您好,登錄后才能下訂單哦!
本篇內(nèi)容介紹了“以太坊智能合約入門知識點有哪些”的有關(guān)知識,在實際案例的操作過程中,不少人都會遇到這樣的困境,接下來就讓小編帶領(lǐng)大家學(xué)習(xí)一下如何處理這些情況吧!希望大家仔細(xì)閱讀,能夠?qū)W有所成!
以太坊智能合約是存放在以太坊區(qū)塊鏈具有特定地址的代碼(它的功能)和數(shù)據(jù)(它的狀態(tài))集合。智能合約賬戶之間可以相互傳遞消息以實現(xiàn)圖靈完備運算。 智能合約以以太坊特定的二進(jìn)制字節(jié)碼通過以太坊虛擬機(EVM)運行于區(qū)塊鏈上。
以太坊智能合約通常是以名為 Solidity 的高級語言編寫,并被編譯為字節(jié)碼上傳到區(qū)塊鏈上。
Solidity是一種類似JavaScript的語言,允許你開發(fā)智能合約并可以被編譯成EVM字節(jié)碼,現(xiàn)在已經(jīng)是以太坊的旗艦語言并且是最流行的。
沒有實現(xiàn)Hello World程序的語言是不完整的,在以太坊的環(huán)境中,Solidity沒有一個明確的方式可以”輸出”一個字符串。 最接近的方式就是實用日志事件將一個字符串放入?yún)^(qū)塊鏈中:
contract HelloWorld { event Print(string out); function() { Print("Hello, World!"); } }
這條合約每次執(zhí)行后,會通過Print并帶有”Hello World”參數(shù),將一條日志放入?yún)^(qū)塊鏈中。
可以通過多種形式的機制對solidity開發(fā)的以太坊 智能合約的編譯。
通過命令行使用 solc
編譯器。
通過 geth
或 eth``(仍需安裝 ``solc
編譯器) 提供的javascript控制臺使用 web3.eth.compile.solidity
。
通過 實時在線編譯器.
通過 Ethereum Wallet.
如果你啟動了 geth
節(jié)點,你可以通過如下命令來檢查哪些編譯器可以使用。
> web3.eth.getCompilers(); ["lll", "solidity", "serpent"]
這個命令返回當(dāng)前可用的編譯器的字符串?dāng)?shù)組。
Note
solc
編譯器同 cpp-ethereum
一起被安裝,作為替代方案,你可以自己編譯 。
如果你的 solc
執(zhí)行檔不在指定的標(biāo)準(zhǔn)路徑下,你可以通過 --solc
參數(shù)指定 solc
的執(zhí)行路徑。
$ geth --solc /usr/local/bin/solc
同樣的,你可以通過命令行在運行時執(zhí)行這個操作:
> 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
我們來編譯一個簡單的合約代碼:
> source = "contract test { function multiply(uint a) returns(uint d) { return a * 7; } }"
這個合約提供了一個名為 multiply 的函數(shù),輸入一個正整數(shù) a
返回結(jié)果 a * 7
。
你已經(jīng)準(zhǔn)備好了編譯solidity代碼的環(huán)境,使用 geth
的JS命令臺 eth.compile.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; } }' } }
Note
編譯器支持RPC <[https://github.com/ethereum/wiki/wiki/JSON-RPC](https://github.com/ethereum/wiki/wiki/JSON-RPC)>
__ ,因此你可以使用web3.js 并通過RPC/IPC連接到 geth
。
下面的例子顯示了如何通過使用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 { function multiply(uint a) returns(uint d) { return a * 7; } }"],"id":1}' http://127.0.0.1:8100
編譯器為源代碼中的每個單獨的合約生成一個合約對象,命令 eth.compile.solidity
會返回合約名和合約對象的映射。這個例子中我們的合約名為 test
,所以命令 eth.compile.solidity(source).test
會返回名為test的合約對象,并包含如下相關(guān)域: code
:編譯生成的以太坊虛擬機字節(jié)碼 info
:編譯器輸出的額外元數(shù)據(jù) source
:源代碼 language
:合約使用的編程語言(Solidity, Serpent, LLL) languageVersion
:合約語言的版本號 compilerVersion
:編譯合約代碼所使用編譯器的版本號 abiDefinition
:應(yīng)用程序二進(jìn)制接口定義 userDoc
:提供給用戶的 [NatSpec Doc] developerDoc
:提供給開發(fā)者的 [NatSpec Doc]
編譯器最直觀的輸出結(jié)構(gòu)(code
和 info
)反應(yīng)出兩個完全不同的 部署路徑 ,編譯出的EVMcode會給發(fā)給區(qū)塊鏈上特定交易,剩下的(info)會存放在去中心化的區(qū)塊鏈云端作為完善代碼的元數(shù)據(jù)。
如果你的源代碼包含多個合約,那么輸出會包含每一個合約的入口信息,合約的展開信息可以通過名字來獲取,你可以通過查看當(dāng)前的GlobalRegistrar合約來嘗試一下效果:
contracts = eth.compile.solidity(globalRegistrarSrc)
在開始這個章節(jié)前,請確保你有一個解鎖的賬戶并且里面有一些資金。
你現(xiàn)在可以通過前面章節(jié)的EVM代碼來向一個空地址 發(fā)起一筆交易 。
Note
這個可以通過更容易的方式完成,也就是通過 實時在線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: evmByteCodeFromPreviousSection})
所有的二進(jìn)制數(shù)據(jù)都會被序列化為十六進(jìn)制格式,十六進(jìn)制的字符串總是以 0x
作為前綴。
Note
請注意 arg1, arg2, ...
是合約的構(gòu)造參數(shù),可以接受任何輸入,如果合約不需要任何構(gòu)造參數(shù)那么這些參數(shù)可以被忽略。
值得指出的是執(zhí)行這些步驟你需要支付一些費用,一旦的交易被打包進(jìn)區(qū)塊,你賬戶的余額會根據(jù)以太坊虛擬機的瓦斯費用規(guī)則進(jìn)行扣除,經(jīng)過一些時間,你的交易會出現(xiàn)在一個狀態(tài)被確認(rèn)是一致的區(qū)塊中,你的合約現(xiàn)在已經(jīng)存在于區(qū)塊鏈中。
異步執(zhí)行這些步驟的方法如下:
MyContract.new([arg1, arg2, ...,]{from: primaryAccount, data: evmCode}, function(err, contract) { if (!err && contract.address) console.log(contract.address); });
通常使用抽象層 eth.contract() 來完成與合約的交互,該函數(shù)返回一個JavaScript對象,該對象包含了所有可以被JavaScript調(diào)用的合約函數(shù)。
描述合約可用函數(shù)的標(biāo)準(zhǔn)方法是 ABI定義,這個對象是一個數(shù)組,該數(shù)組包含了每一個可用合約函數(shù)的調(diào)用簽名和返回值。
var Multiply7 = eth.contract(contract.info.abiDefinition); var myMultiply7 = Multiply7.at(address);
現(xiàn)在所有ABI中定義的函數(shù)都可以在合約實例中使用了,你可以通過如下兩種方法之一來進(jìn)行調(diào)用:
> myMultiply7.multiply.sendTransaction(3, {from: address}) "0x12345" > myMultiply7.multiply.call(3) 21
當(dāng)使用 sendTransaction
時,通過發(fā)送一個交易來調(diào)用函數(shù)。這種方式會消耗以太幣,同時調(diào)用會永久被紀(jì)錄在區(qū)塊鏈中,這種方式的返回值就是交易的哈希值。
當(dāng)使用 call
時,函數(shù)會在本地的虛擬機(EVM)上執(zhí)行,調(diào)用的返回值就是函數(shù)的返回值。這種方式的調(diào)用不會被紀(jì)錄在區(qū)塊鏈中,因此也不會改變合約的內(nèi)部狀態(tài),這種方式被稱為常量函數(shù)調(diào)用。這種調(diào)用方式不會消耗以太幣。
只關(guān)心返回值的情況下你應(yīng)該使用 call
,如果你關(guān)心合約的狀態(tài)變化那么就使用 sendTransaction
。
在上面的例子中,不涉及改變合約狀態(tài),因此 sendTransaction
調(diào)用只會白白燃燒燃料(gas)增加宇宙的熵。
在上個章節(jié)我們解釋了如何在區(qū)塊鏈上創(chuàng)建合約,接下來我們處理編譯器輸出的內(nèi)容,合約元數(shù)據(jù)或者合約信息。
當(dāng)與一個你還沒有創(chuàng)建的合約進(jìn)行交互時,你可能想要說明文檔或者查看其源代碼。合約作者被鼓勵通過區(qū)塊鏈或者第三方機構(gòu)的服務(wù)來注冊此類信息,例如: EtherChain 。API admin
為注冊了這類信息的合約提供了便利的方法來查看。
// 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
這項工作生效的基本機制是:
合約信息被上傳到一個公共可訪問的位置地址 URI 上
知道合約地址任何人都可以找到相關(guān)的 URI
這些合約信息通過兩步區(qū)塊鏈注冊被打包: * 第一步:稱為 HashReg
的合約通過內(nèi)容哈希來注冊合約代碼。 * 第二步:稱為 UrlHint
的合約通過內(nèi)容哈希來注冊url。 這些 注冊合約 被作為前沿(Frontier)版本的一部分,同時被帶入到家園(Homestead)版本中。
使用這個結(jié)構(gòu),只需要知道合約的地址,然后獲取到url,進(jìn)而獲取合約相關(guān)的所有元數(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
在區(qū)塊鏈上注冊你的內(nèi)容哈希url(如果使用固定內(nèi)容尋址模型作為文檔存儲那么rul-hint就不是必需的了)。
source = "contract test { function multiply(uint a) returns(uint d) { return a * 7; } }" // 使用solc來編譯 contract = eth.compile.solidity(source).test // 創(chuàng)建合約對象 var MyContract = eth.contract(contract.info.abiDefinition) // 合約的摘要信息,序列化到指定的json文件中 contenthash = admin.saveInfo(contract.info, "~/dapps/shared/contracts/test/info.json") // 合約發(fā)送到區(qū)塊鏈上 MyContract.new({from: primaryAccount, data: contract.code}, function(error, contract){ if(!error && contract.address) { // 計算內(nèi)容哈希并且將其通過 `HashReg` 注冊為代碼哈希 // 使用地址來發(fā)送交易 // 返回我們用來注冊url的內(nèi)容哈希 admin.register(primaryAccount, contract.address, contenthash) // 將 ~/dapps/shared/contracts/test/info.json 部署到一個url上 admin.registerUrl(primaryAccount, hash, url) } });
通常要對合約和交易進(jìn)行測試和調(diào)試,這個章節(jié)我們來介紹幾種調(diào)試工具和實踐方法。為了測試合約和交易,并且避免產(chǎn)生真實的影響,你最好在一條私有區(qū)塊鏈上進(jìn)行操作,這可以通過配置網(wǎng)絡(luò)ID(選擇一個獨一無二的整數(shù))來實現(xiàn),并且不需要其他對等節(jié)點。推薦的做法是為測試設(shè)置其他的數(shù)據(jù)目錄和端口,以避免可能的來自其他節(jié)點的影響(假設(shè)使用默認(rèn)的參數(shù)運行)。通過調(diào)試模式來運行 geth
,并設(shè)置最高級別的日志:
geth --datadir ~/dapps/testing/00/ --port 30310 --rpcport 8110 --networkid 4567890 --nodiscover --maxpeers 0 --vmdebug --verbosity 6 --pprof --pprofport 6110 console 2>> ~/dapp/testint/00/00.log
提交任何交易前,你需要設(shè)置好你的測試鏈,詳細(xì)內(nèi)容請查看: <cite >test-networks</cite>
// 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"); // 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");
創(chuàng)建交易后你可以強制執(zhí)行它們,如下:
miner.start(1); admin.sleepBlocks(1); miner.stop();
可以通過如下來檢查未驗證的交易:
// shows transaction pool txpool.status // number of pending txs eth.getBlockTransactionCount("pending"); // print all pending txs eth.getBlock("pending", true).transactions
如果提交了交易創(chuàng)建合約,你可以檢查所需代碼是否已經(jīng)插入到當(dāng)前的區(qū)塊中:
txhash = eth.sendTansaction({from:primary, data: code}) //... mining contractaddress = eth.getTransactionReceipt(txhash); eth.getCode(contractaddress)
“以太坊智能合約入門知識點有哪些”的內(nèi)容就介紹到這里了,感謝大家的閱讀。如果想了解更多行業(yè)相關(guān)的知識可以關(guān)注億速云網(wǎng)站,小編將為大家輸出更多高質(zhì)量的實用文章!
免責(zé)聲明:本站發(fā)布的內(nèi)容(圖片、視頻和文字)以原創(chuàng)、轉(zhuǎn)載和分享為主,文章觀點不代表本網(wǎng)站立場,如果涉及侵權(quán)請聯(lián)系站長郵箱:is@yisu.com進(jìn)行舉報,并提供相關(guān)證據(jù),一經(jīng)查實,將立刻刪除涉嫌侵權(quán)內(nèi)容。