日韩性视频-久久久蜜桃-www中文字幕-在线中文字幕av-亚洲欧美一区二区三区四区-撸久久-香蕉视频一区-久久无码精品丰满人妻-国产高潮av-激情福利社-日韩av网址大全-国产精品久久999-日本五十路在线-性欧美在线-久久99精品波多结衣一区-男女午夜免费视频-黑人极品ⅴideos精品欧美棵-人人妻人人澡人人爽精品欧美一区-日韩一区在线看-欧美a级在线免费观看

歡迎訪問 生活随笔!

生活随笔

當前位置: 首頁 > 编程资源 > 编程问答 >内容正文

编程问答

在geth客户端调用已部署的智能合约

發(fā)布時間:2025/3/15 编程问答 23 豆豆
生活随笔 收集整理的這篇文章主要介紹了 在geth客户端调用已部署的智能合约 小編覺得挺不錯的,現(xiàn)在分享給大家,幫大家做個參考.

什么是合約?

合約是代碼(它的功能)和數(shù)據(jù)(它的狀態(tài))的集合,存在于以太坊區(qū)塊鏈的特定地址。 合約賬戶能夠在彼此之間傳遞信息,進行圖靈完備的運算。合約依靠被稱作以太坊虛擬機(EVM) 字節(jié)代碼(以太坊特有的二進制格式)上的區(qū)塊鏈運行。

合約很典型地用諸如Solidity等高級語言寫成,然后編譯成字節(jié)代碼上傳到區(qū)塊鏈上。

也有其他語言可以用于編寫智能合約如Serpent和LLL,在下一節(jié)會進一步闡述。去中心化應(yīng)用開發(fā)資源列出了綜合的開發(fā)環(huán)境,幫助你用這些語言開發(fā)的開發(fā)者工具,提供測試和部署支持等功能。

以太坊高級語言

合約依靠被稱作以太坊虛擬機(EVM) 字節(jié)代碼(以太坊特有的二進制格式)上的區(qū)塊鏈運行。然而,合約是很典型地用諸如Solidity等高級語言寫成的,它會用以太坊虛擬機編譯器編譯成字節(jié)代碼上傳到區(qū)塊鏈。

下面是開發(fā)者可以用來為以太坊寫智能合約的高級語言。

  • Solidity?
    Solidity是和JavaScript相似的語言,你可以用它來開發(fā)合約并編譯成以太坊虛擬機字節(jié)代碼。它目前是以太坊最受歡迎的語言。
  • Serpent?
    Serpent是和Python類似的語言,可以用于開發(fā)合約編譯成以太坊虛擬機字節(jié)代碼。它力求簡潔, 將低級語言在效率方面的優(yōu)點和編程風格的操作簡易相結(jié)合,同時合約編程增加了獨特的領(lǐng)域特定功能。Serpent用LLL編譯。
  • LLL?
    Lisp Like Language (LLL)是和Assembly類似的低級語言。它追求極簡;本質(zhì)上只是直接對以太坊虛擬機的一點包裝。
  • Mutan (棄用)?
    Mutan是個靜態(tài)類型,由Jeffrey Wilcke 開發(fā)設(shè)計的C類語言。它已經(jīng)不再受到維護。
  • 寫合約

    沒有Hello World程序,語言就不完整。Solidity在以太坊環(huán)境內(nèi)操作,沒有明顯的“輸出”字符串的方式。我們能做的最接近的事就是用日志記錄事件來把字符串放進區(qū)塊鏈,示例如下:

    contract HelloWorld { event Print(string out); function() { Print("Hello, World!"); } }
    • 1
    • 2
    • 3
    • 4

    每次執(zhí)行時,這個合約都會在區(qū)塊鏈創(chuàng)建一個日志入口,印著“Hello,World!”參數(shù)。?
    另請參閱:Solidity docs里有更多寫Solidity代碼的示例和指導(dǎo)。

    編譯合約

    solidity合約的編譯可以通過很多機制完成。

    • 通過命令行使用solc編譯器實現(xiàn)。
    • 在geth或eth提供的javascript控制臺使用web3.eth.compile.solidity (這仍然需要安裝solc 編譯器)實現(xiàn)。
    • 通過在線Solidity實時編譯器實現(xiàn)。
    • 通過建立solidity合約的Meteor dapp Cosmo實現(xiàn)。
    • 通過Mix IDE實現(xiàn)。
    • 通過以太坊錢包實現(xiàn)。

    注意:關(guān)于solc和編譯Solidity合約代碼的更多信息可在此查看。

    1. 在geth設(shè)置solidity編譯器

    如果你啟動了geth節(jié)點,就可以查看哪個編譯器可用。示例如下:

    \> web3.eth.getCompilers(); ["lll", "solidity", "serpent"]
    • 1
    • 2

    這一指令會返回到顯示當前哪個編譯器可用的字符串。?
    注意:solc編譯器和cpp- ethereum一起安裝。或者,你可以自己創(chuàng)建。?
    如果你的solc可執(zhí)行文件不在標準位置,可以用—solc標志為solc可執(zhí)行文件指定一個定制路線。示例如下:

    $ geth --solc /usr/local/bin/solc
    • 1

    或者你可以通過控制臺在執(zhí)行期間設(shè)置這個選項:

    \> admin.setSolc("/usr/local/bin/solc") solc, the solidity compiler commandline interface Version: 0.2.2-02bb315d/.-Darwin/appleclang/JIT linked to libethereum-1.2.0-8007cef0/.-Darwin/appleclang/JIT path: /usr/local/bin/solc
    • 1
    • 2
    • 3
    • 4

    2. 編譯一個簡單合約

    讓我們來編譯一個簡單的合約源,示例如下:

    source = "contract test { function multiply(uint a) returns(uint d) { return a * 7; } }"
    • 1

    這個合約提供了一個單一方法multiply,它和一個正整數(shù)a調(diào)用并返回到a*7。

    下面準備在geth JS控制臺用eth.compile.solidity()編譯solidity代碼:

    \> contract = eth.compile.solidity(source).test { code: '605280600c6000396000f3006000357c010000000000000000000000000000000000000000000000000000000090048063c6888fa114602e57005b60376004356041565b8060005260206000f35b6000600782029050604d565b91905056', info: { language: 'Solidity', languageVersion: '0', compilerVersion: '0.9.13', abiDefinition: [{ constant: false, inputs: [{ name: 'a', type: 'uint256' } ], name: 'multiply', outputs: [{ name: 'd', type: 'uint256' } ], type: 'function' } ], userDoc: { methods: { } }, developerDoc: { methods: { } }, source: 'contract test { function multiply(uint a) returns(uint d) { return a * 7; } }' } }
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    • 14
    • 15
    • 16
    • 17
    • 18
    • 19
    • 20
    • 21
    • 22
    • 23
    • 24
    • 25
    • 26
    • 27
    • 28
    • 29
    • 30
    • 31
    • 32
    • 33

    注意:編譯器通過RPC因此也能通過web3.js,對瀏覽器內(nèi)任何通過RPC/IPC連接到geth的Dapp可用。

    下面的例子會向你展示如何通過JSON-RPC接合geth來使用編譯器。

    \$ geth --datadir ~/eth/ --loglevel 6 --logtostderr=true --rpc --rpcport 8100 --rpccorsdomain ' * ' --mine console 2>> ~/eth/eth.log $ curl -X POST --data '{"jsonrpc":"2.0","method":"eth_compileSolidity","params":["contract test {
    • 1
    • 2

    單源編譯器輸出會給出你合約對象,每個都代表一個單獨的合約。eth.compile.solidity 的實際返還值是合約名字到合約對象的映射。由于合約名字是test,eth.compile.solidity(source).test會給出包含下列領(lǐng)域的測試合約對:

    • Code:編譯的以太坊虛擬機字節(jié)代碼。
    • Info:從編譯器輸出的額外元數(shù)據(jù)。
    • Source:源代碼。
    • Language:合約語言 (Solidity,Serpent,LLL)。
    • LanguageVersion:合約語言版本。
    • compilerVersion:用于編譯這個合約的solidity編譯器版本。
    • abiDefinition:應(yīng)用的二進制界面定義。
    • userDoc:用戶的NatSpec Doc。
    • developerDoc:開發(fā)者的NatSpec Doc。

    編譯器輸出的直接結(jié)構(gòu)化(到code和info)反映了兩種非常不同的部署路徑。編譯的以太坊虛擬機代碼和一個合約創(chuàng)建交易被發(fā)送到區(qū)塊,剩下的(info)在理想狀態(tài)下會存活在去中心化云上,公開驗證的元數(shù)據(jù)則執(zhí)行區(qū)塊鏈上的代碼。

    如果你的源包含多個合約,輸出會包括每個合約一個入口,對應(yīng)的合約信息對象可以用作為屬性名稱的合約名字檢索到。你可以通過檢測當前的GlobalRegistrar代碼來試一下:

    contracts = eth.compile.solidity(globalRegistrarSrc)
    • 1

    創(chuàng)建和部署合約

    開始閱讀這一節(jié)之前,確保你有解鎖的賬戶和一些資金。

    現(xiàn)在在區(qū)塊鏈上創(chuàng)建一個合約,方法是用上一章節(jié)的以太坊虛擬機代碼作為數(shù)據(jù)給空地址發(fā)送交易。示例如下:

    注意:用在線Solidity實時編譯器或Mix IDE程序會更容易完成。

    var primaryAddress = eth.accounts[0] var abi = [{ constant: false, inputs: [{ name: 'a', type: 'uint256' } ] var MyContract = eth.contract(abi) var contract = MyContract.new(arg1, arg2, ..., {from: primaryAddress, data: evmByteCodeFromPrevio
    • 1
    • 2
    • 3
    • 4

    所有的二進制數(shù)據(jù)都以十六進制的格式序列化。十六進制字符串總會有一個十六進制前綴0x。

    注意:注意arg1, arg2, …是合約構(gòu)造函數(shù)參數(shù),以備它要接受參數(shù)。如果合約不需要構(gòu)造函數(shù)參數(shù),就可以忽略這些參數(shù)。

    值得指出的是,這一步驟需要你支付執(zhí)行。一旦交易成功進入到區(qū)塊,你的賬戶余額(你作為發(fā)送方放在from領(lǐng)域)會根據(jù)以太坊虛擬機的gas規(guī)則被扣減。一段時間以后,你的交易會在一個區(qū)塊中出現(xiàn),確認它帶來的狀態(tài)是共識。你的合約現(xiàn)在存在于區(qū)塊鏈上。

    以不同步的方式做同樣的事看起來是這樣:

    MyContract.new([arg1, arg2, ...,]{from: primaryAccount, data: evmCode}, function(err, contract) { if (!err && contract.address) console.log(contract.address); });
    • 1
    • 2
    • 3
    • 4

    與合約互動

    與合約互動典型的做法是用諸如eth.contract()功能的抽象層,它會返回到j(luò)avascript對象,和所有可用的合約功能一起,作為可調(diào)用的javascript功能。

    描述合約可用功能的標準方式是ABI定義。這個對象是一個字符串,它描述了調(diào)用簽名和每個可用合約功能的返回值。示例如下:

    var Multiply7 = eth.contract(contract.info.abiDefinition); var myMultiply7 = Multiply7.at(address);
    • 1
    • 2

    現(xiàn)在ABI中具體說明的所有功能調(diào)用都在合約實例中可用。你可以用兩種方法中的一種來調(diào)用這些合約實例上的方法。

    \> myMultiply7.multiply.sendTransaction(3, {from: address}) "0x12345" > myMultiply7.multiply.call(3) 21
    • 1
    • 2
    • 3
    • 4

    當用sendTransaction被調(diào)用的時候,功能調(diào)用通過發(fā)送交易來執(zhí)行。需要花費以太幣來發(fā)送,調(diào)用會永久記錄在區(qū)塊鏈上。用這種方式進行的調(diào)用返回值是交易散表。

    當用call被調(diào)用的時候,功能在以太坊虛擬機被本地執(zhí)行,功能返回值和功能一起返回。用這種方式進行的調(diào)用不會記錄在區(qū)塊鏈上,因此也不會改變合約內(nèi)部狀態(tài)。這種調(diào)用方式被稱為恒定功能調(diào)用。以這種方式進行的調(diào)用不花費以太幣。

    如果你只對返回值感興趣,那么你應(yīng)該用call。如果你只關(guān)心合約狀態(tài)的副作用,就應(yīng)該用sendTransaction。

    在上面的例子中,不會產(chǎn)生副作用,因此sendTransaction只會燒gas,增加宇宙的熵。

    合約元數(shù)據(jù)

    在之前的章節(jié)中,揭示了怎樣在區(qū)塊鏈上創(chuàng)建合約。現(xiàn)在來處理剩下的編譯器輸出,合約元數(shù)據(jù)或者說合約信息。

    在與不是你創(chuàng)建的合約互動時,你可能會想要文檔或者查看源代碼。合約作者被鼓勵提供這樣的可見信息,他們可以在區(qū)塊鏈上登記或者借助第三方服務(wù),比如說EtherChain。管理員API為所有選擇登記的合約提供便利的方法來獲取這個捆綁。示例如下:

    // get the contract info for contract address to do manual verification var info = admin.getContractInfo(address) // lookup, fetch, decode var source = info.source; var abiDef = info.abiDefinition
    • 1
    • 2
    • 3
    • 4

    這項工作的潛在機制是:

    • 合約信息被可以公開訪問的URI上傳到可辨認的地方。
    • 任何人都可以只知道合約地址就找到是什么URI。

    僅通過2個步驟的區(qū)塊鏈注冊就可以實現(xiàn)這些要求。第一步是在被稱作HashReg的合約中用內(nèi)容散表注冊合約代碼(散表)。第二步是在UrlHint合約用內(nèi)容散表注冊一個url。這些注冊合約是Frontier版本的一部分,已經(jīng)參與到Homestead中。

    要知道合約地址來查詢url,獲取實際合約元數(shù)據(jù)信息包,使用這一機制就足夠了。

    如果你是個盡職的合約創(chuàng)建者,請遵循以下步驟:

  • 將合約本身部署到區(qū)塊鏈
  • 獲取合約信息json文件
  • 將合約信息json文件部署到你選擇的任意url
  • 注冊代碼散表 ->內(nèi)容散表 -> url
  • JS API通過提供助手把這個過程變得非常容易。 調(diào)用admin.register從合約中提取信息,在指定文件中寫出json序列,運算文件的內(nèi)容散表,最終將這個內(nèi)容散表注冊到合約代碼散表。一旦將那個文件部署到任意url,你就能用admin.registerUrl來注冊url 和你區(qū)塊鏈上的內(nèi)容散表(注意,一旦固定的內(nèi)容選址模式被用作文件商店,url-hint不再必要了) 。

    source = "contract test { function multiply(uint a) returns(uint d) { return a * 7; } }" // compile with solc contract = eth.compile.solidity(source).test // create contract object var MyContract = eth.contract(contract.info.abiDefinition) // extracts info from contract, save the json serialisation in the given file, contenthash = admin.saveInfo(contract.info, "~/dapps/shared/contracts/test/info.json")// send off the contract to the blockchain MyContract.new({from: primaryAccount, data: contract.code}, function(error, contract){ if(!error && contract.address) { // calculates the content hash and registers it with the code hash in `HashReg` // it uses address to send the transaction. // returns the content hash that we use to register a url admin.register(primaryAccount, contract.address, contenthash) // here you deploy ~/dapps/shared/contracts/test/info.json to a url admin.registerUrl(primaryAccount, hash, url) } });
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    • 14
    • 15
    • 16
    • 17
    • 18
    • 19

    測試合約和交易

    在為交易和合約排除故障時,你通常會需要一些低級的測試策略。這一章節(jié)將介紹一些你可以用到的排錯工作和做法。為了測試合約和交易而不產(chǎn)生實際的后果,最好在私有區(qū)塊鏈上測試。這可以通過配置一個替代網(wǎng)絡(luò)ID (選擇一個特別的數(shù)字)和/或不能用的端點來實現(xiàn)。推薦做法是,為了測試你用一個替代數(shù)據(jù)目錄和端口,這樣就不會意外地和實時運行的節(jié)點沖突(假定用默認運行。在虛擬機排錯模式開啟geth,推薦性能分析和最高的日志冗余級別):

    geth --datadir ~/dapps/testing/00/ --port 30310 --rpcport 8110 --networkid 4567890 --nodiscover -
    • 1

    提交交易之前,你需要創(chuàng)建私有測試鏈(參閱測試網(wǎng)絡(luò)相關(guān)章節(jié)),示例如下:

    // create account. will prompt for password personal.newAccount(); // name your primary account, will often use it primary = eth.accounts[0]; // check your balance (denominated in ether) balance = web3.fromWei(eth.getBalance(primary), "ether");
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    // assume an existing unlocked primary account primary = eth.accounts[0]; // mine 10 blocks to generate ether // starting miner miner.start(4); // sleep for 10 blocks (this can take quite some time). admin.sleepBlocks(10); // then stop mining (just not to burn heat in vain) miner.stop(); balance = web3.fromWei(eth.getBalance(primary), "ether");
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10

    創(chuàng)建交易之后,你可以用下面的命令來強制運行:

    miner.start(1);?
    admin.sleepBlocks(1);?
    miner.stop();

    你也可以用以下命令查看即將發(fā)生的交易:

    // shows transaction pool?
    txpool.status?
    // number of pending txs?
    eth.getBlockTransactionCount(“pending”);?
    // print all pending txs?
    eth.getBlock(“pending”, true).transactions

    如果你提交合約創(chuàng)建交易,可以檢查想要的代碼是否實際上嵌入到當前的區(qū)塊鏈:

    txhash = eth.sendTansaction({from:primary, data: code}) //... mining contractaddress = eth.getTransactionReceipt(txhash); eth.getCode(contractaddress)
    • 1
    • 2
    • 3
    • 4

    http://blog.csdn.net/MisshqZzz/article/details/77834856

    總結(jié)

    以上是生活随笔為你收集整理的在geth客户端调用已部署的智能合约的全部內(nèi)容,希望文章能夠幫你解決所遇到的問題。

    如果覺得生活随笔網(wǎng)站內(nèi)容還不錯,歡迎將生活随笔推薦給好友。