當前位置:
首頁 > 最新 > 動手編寫一個以太坊智能合約

動手編寫一個以太坊智能合約

如何部署、調用智能合約

1

RPC

之前的章節中講到了怎麼寫、部署合約以及與合約互動(點擊閱讀上一章節)。現在該講講與以太坊網路和智能合約溝通的細節了。

一個以太坊節點提供一個RPC界面。這個界面給Dapp(去中心化應用)訪問以太坊區塊鏈的許可權和節點提供的功能,比如編譯智能合約代碼,它用JSON-RPC 2.0規範(不支持提醒和命名的參數) 的子集作為序列化協議,在HTTP和IPC (linux/OSX上的unix域介面,在Windows上叫pipe』s)上可用。

2

慣例

RPC界面會使用一些慣例,但它們不是JSON-RPC 2.0規範的一部分,這些慣例如下:

數字是十六進位編碼。做這個決定是因為有些語言對運行極大的數字沒有或有很少的限制。為了防止這些錯誤數字類型是十六進位編碼,由開發者來分析這些數字並正確處理它們。在維基頁百科查看十六進位編碼章節查看案例。

默認區塊數字。幾個RPC 方法接受區塊數字。在一些情況下,給出區塊數字是不可能的或者不太方便。在那樣的情況下,默認區塊數字可以是以下字元串中的一個[」earliest」, 「latest」, 「pending」]。在維基頁面可查看使用默認區塊參數的RPC方法列表。

3

部署合約

我們會通過不同的步驟來部署下面的合約,但只用到RPC界面。

contract Multiply7 {

event Print(uint);

function multiply(uint input) returns (uint) {

Print(input

*

7);

return input

*

7;

}

}

要做的第一件事是確保HTTP RPC界面可用。這意味著我們在開始為geth供應—rpc標誌,為eth提供-j標誌。在這個例子中,用的是私有開發鏈上的geth節點。通過這種方法,我們就不需要真實網路上的以太幣了。

> geth --rpc --dev --mine --minerthreads 1 --unlock 0 console 2>>geth.log

這會在http://localhost:8545上啟動HTTP RPC界面。

注意:geth支持CORS查看—rpccorsdomain標誌了解更多。

我們可以通過用curl檢索coinbase地址和餘額來證明界面正在運行。請注意這些例子中的數據在你本地的節點上會有所不同。如果你想要試試這些參數,視情況替換需要的參數。

> curl --data {"jsonrpc":"2.0","method":"eth_coinbase", "id":1} localhost:8545

{"id":1,"jsonrpc":"2.0","result":["0xeb85a5557e5bdc18ee1934a89d8bb402398ee26a"]}

> curl --data {"jsonrpc":"2.0","method":"eth_getBalance", "params": ["0xeb85a5557e5bdc18ee1934a89d8bb402398ee26a"], "id":2} localhost:8545

{"id":2,"jsonrpc":"2.0","result":"0x1639e49bba16280000"}

記不記得前面說過數字是十六進位編碼?在這個情況下,餘額作為十六進位字元串以Wei的形式返還。如果希望餘額作為數字以太幣為單位,可以從控制台用web3,示例如下:

現在我們在私有開發鏈上有一些以太幣,就可以部署合約了。第一步是驗證solidity編譯器可用,可以用eth_getCompilers RPC method方法來檢索可用的編譯器,示例如下:

> curl --data {"jsonrpc":"2.0","method": "eth_getCompilers", "id": 3} localhost:8545

{"id":3,"jsonrpc":"2.0","result":["Solidity"]}

我們可以看到solidity編譯器可用。

下一步是把Multiply7合約編譯到可以發送給以太坊虛擬機的位元組代碼中,示例如下:

現在我們有了編譯代碼,需要決定花多少gas去部署它。RPC界面有eth_estimateGas方法,會給我們一個預估數量,如下:

> curl --data {"jsonrpc":"2.0","method": "eth_estimateGas", "params": [{"from": "0xeb85a5557e5bdc18ee1934a89d8bb402398ee26a", "data": "0x6060604052605f8060106000396000f3606060405260e060020a6000350463c6888fa18114601a575b005b60586004356007810260609081526000907f24abdb5865df5079dcc5ac590ff6f01d5c16edbc5fab4e195d9febd1114503da90602090a15060070290565b5060206060f3"}], "id": 5} localhost:8545

{"id":5,"jsonrpc":"2.0","result":"0xb8a9"}

最後部署合約。

> curl --data {"jsonrpc":"2.0","method": "eth_sendTransaction", "params": [{"from": "0xeb85a5557e5bdc18ee1934a89d8bb402398ee26a", "gas": "0xb8a9", "data": "0x6060604052605f8060106000396000f3606060405260e060020a6000350463c6888fa18114601a575b005b60586004356007810260609081526000907f24abdb5865df5079dcc5ac590ff6f01d5c16edbc5fab4e195d9febd1114503da90602090a15060070290565b5060206060f3"}], "id": 6} localhost:8545

{"id":6,"jsonrpc":"2.0","result":"0x3a90b5face52c4c5f30d507ccf51b0209ca628c6824d0532bcd6283df7c08

交易由節點接受,交易散表被返還。我們可以用這個散表來跟蹤交易。

下一步是決定部署合約的地址。每個執行的交易都會創建一個接收。這個接收包含交易的各種信息,比如交易被包含在哪個區塊,以太坊虛擬機用掉多少gas。如果交易創建了一個合約,它也會包含合約地址。我們可以用eth_getTransactionReceipt RPC方法檢索接收,示例如下:

> curl --data {"jsonrpc":"2.0","method": "eth_getTransactionReceipt", "params": ["0x3a90b5face52c4c5f30d507ccf51b0209ca628c6824d0532bcd6283df7c08a7c"], "id": 7} localhost:8545

{"id":7,"jsonrpc":"2.0","result":{"transactionHash":"0x3a90b5face52c4c5f30d507ccf51b0209ca628c682

可以看到,合約在0x6ff93b4b46b41c0c3c9baee01c255d3b4675963d上被創建。如果你得到了零而不是接收,說明還沒有被納入區塊。這時,要檢查看看你的礦工是否在運行,然後重新試一遍。

4

和智能合約互動

現在已經部署了合約,我們可以和它互動了。有兩種方法進行互動,即發送交易或像5.7.6節說明的那樣調用。在本節的例子中,將會發送交易到合約的multiply方法里。

在我們的實例中,需要具體說明from、to 和data參數。From是我們賬戶的公共地址,to是合約地址,Data參數有一點複雜,它包括了規定調用哪個方法和哪個參數的負載量。這就需要ABI發揮作用了,ABI規定了如何為以太坊虛擬機規定和編碼數據。

負載量的位元組是功能選擇符,規定了調用哪個方法。它取Keccak散表的頭4個位元組,涵蓋功能名稱參數類型,並進行十六進位編碼。multiply功能接受一個參數。示例如下:

> web3.sha3("multiply(uint256)").substring(0, 8)

"c6888fa1"

下一步是編碼參數。我們只有一個unit256,假定提供了值6。ABI有一個章節規定了編碼uint位元組的方法,如下:

int: enc(X) is the big-endian two』s complement encoding of X, padded on the higher-oder (left) side with 0xff for negative X and with zero 位元組s for positive X such that the length is a multiple of 32 bytes.

它會編碼到0000000000000000000000000000000000000000000000000000000000000006。

將功能選擇符和編碼參數結合起來,數據就會變成0xc6888fa10000000000000000000000000000000000000000000000000000000000000006。

我們來試一下:

> curl --data {"jsonrpc":"2.0","method": "eth_sendTransaction", "params": [{"from": "0xeb85a5557e5bdc18ee1934a89d8bb402398ee26a", "to": "0x6ff93b4b46b41c0c3c9baee01c255d3b4675963d", "data": "0xc6888fa10000000000000000000000000000000000000000000000000000000000000006"}], "id": 8} localhost:8545

{"id":8,"jsonrpc":"2.0","result":"0x759cf065cbc22e9d779748dc53763854e5376eea07409e590c990eafc0869

由於我們發送了交易,於是有交易散表返回。如果檢索接收,可以看到一些新內容,如下:

{

blockHash: "0xbf0a347307b8c63dd8c1d3d7cbdc0b463e6e7c9bf0a35be40393588242f01d55",

blockNumber: 268,

contractAddress: null,

cumulativeGasUsed: 22631,

gasUsed: 22631,

logs: [{

address: "0x6ff93b4b46b41c0c3c9baee01c255d3b4675963d",

blockHash: "0xbf0a347307b8c63dd8c1d3d7cbdc0b463e6e7c9bf0a35be40393588242f01d55",

blockNumber: 268,

data: "0x000000000000000000000000000000000000000000000000000000000000002a",

logIndex: 0,

topics: ["0x24abdb5865df5079dcc5ac590ff6f01d5c16edbc5fab4e195d9febd1114503da"],

transactionHash: "0x759cf065cbc22e9d779748dc53763854e5376eea07409e590c990eafc0869d74",

transactionIndex: 0

}],

transactionHash: "0x759cf065cbc22e9d779748dc53763854e5376eea07409e590c990eafc0869d74",

transactionIndex: 0

}

接收包含一個日誌。日誌由以太坊虛擬機在交易執行時生成,包含接收。如果我們看Multiply功能,可以看到列印事件和輸入次數7一起被提出。由於列印事件的參數是uint256,因此可以根據ABI規則對它進行編碼,這樣就會得到預期的十進位42。

> web3.sha3("Print(uint256)")

"24abdb5865df5079dcc5ac590ff6f01d5c16edbc5fab4e195d9febd1114503da"

這只是對一些最常見任務的簡單介紹。在RPC維基頁面查看可用RPC方法的完整列表。

5

Web3.js

正如在之前的案例所見,使用JSON-RPC界面相當單調乏味且容易出錯,尤其是在處理ABI的時候。Web3.js是Javascript庫,它的目標是提供更友好的界面,減少出錯機會。

用web3部署Multiply7合約看起來是這樣:

var source = contract Multiply7 { event Print(uint); function multiply(uint input) returns (uint) { Print(input

var compiled = web3.eth.compile.solidity(source);

var code = compiled.Multiply7.code;

var abi = compiled.Multiply7.info.abiDefinition;

web3.eth.contract(abi).new(, function (err, contract) {

if (!err && contract.address)

console.log("deployed on:", contract.address);

}

);

deployed on: 0x0ab60714033847ad7f0677cc7514db48313976e2

裝載一個部署的合約,發送交易:

註冊一個回調,列印事件創建日誌的時候會被調用。


點擊展開全文

喜歡這篇文章嗎?立刻分享出去讓更多人知道吧!

本站內容充實豐富,博大精深,小編精選每日熱門資訊,隨時更新,點擊「搶先收到最新資訊」瀏覽吧!


請您繼續閱讀更多來自 區塊鏈大本營 的精彩文章:

深入淺出談以太坊智能合約

TAG:區塊鏈大本營 |