1. 程式人生 > >動手編寫一個以太坊智慧合約

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

本文節選自圖書《區塊鏈開發指南》,本書由 申屠青春 主編,宋波、張鵬、汪曉明、季宙棟、左川民 聯合編著。
區塊鏈相關約稿、文章糾錯、尋求報道等可郵件聯絡 [email protected]

如何部署、呼叫智慧合約

RPC

之前的章節中講到了怎麼寫、部署合約以及與合約互動。現在該講講與以太坊網路和智慧合約溝通的細節了。

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

慣例

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

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

  • 預設區塊數字。幾個RPC 方法接受區塊數字。在一些情況下,給出區塊數字是不可能的或者不太方便。在那樣的情況下,預設區塊數字可以是以下字串中的一個[”earliest”, “latest”, “pending”]。在維基頁面可檢視使用預設區塊引數的RPC方法列表。

部署合約

我們會通過不同的步驟來部署下面的合約,但只用到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

注意: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,示例如下:

\> web3.fromWei("0x1639e49bba16280000", "ether")
"410"

現在我們在私有開發鏈上有一些以太幣,就可以部署合約了。第一步是驗證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合約編譯到可以傳送給以太坊虛擬機器的位元組程式碼中,示例如下:

\> curl --data '{"jsonrpc":"2.0","method": "eth_compileSolidity", "params": ["contract Multiply7 { event Print(uint); function multiply(uint input) returns (uint) { Print(input
{"id":4,"jsonrpc":"2.0","result":{"Multiply7":{"code":"0x6060604052605f8060106000396000f360606040

現在我們有了編譯程式碼,需要決定花多少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上被建立。如果你得到了零而不是接收,說明還沒有被納入區塊。這時,要檢檢視看你的礦工是否在執行,然後重新試一遍。

和智慧合約互動

現在已經部署了合約,我們可以和它互動了。有兩種方法進行互動,即傳送交易或呼叫。在本節的例子中,將會發送交易到合約的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<M>: 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方法的完整列表。

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({from: "0xeb85a5557e5bdc18ee1934a89d8bb402398ee26a", data: code}, function (err, contract) {
if (!err && contract.address)
console.log("deployed on:", contract.address);
}
);
deployed on: 0x0ab60714033847ad7f0677cc7514db48313976e2

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

var source = 'contract Multiply7 { event Print(uint); function multiply(uint input) returns (uint) { Print(input
var compiled = web3.eth.compile.solidity(source);
var Multiply7 = web3.eth.contract(compiled.Multiply7.info.abiDefinition);
var multi = Multiply7.at("0x0ab60714033847ad7f0677cc7514db48313976e2")
multi.multiply.sendTransaction(6, {from: "0xeb85a5557e5bdc18ee1934a89d8bb402398ee26a"})

註冊一個回撥,列印事件建立日誌的時候會被呼叫。

multi.Print(function(err, data) { console.log(JSON.stringify(data)) })
{"address":"0x0ab60714033847ad7f0677cc7514db48313976e2","args": {"":"21"},"blockHash":"0x259c7dc0

在web3.js維基頁面可檢視更多資訊。

控制檯

geth控制檯提供命令列介面和Javascript執行時間。它可以連線到本地或遠端的geth或eth節點。它會裝載使用者能使用的web3.js庫,從而方便使用者從控制檯通過web3.js部署智慧合約,並和智慧合約互動。實際上Web3.js章節的例子可以被複制進控制檯並且呼叫。

檢視合約與交易

有幾個可用的線上區塊鏈瀏覽器,能讓你查詢以太坊區塊鏈,它們分別是:

  • EtherChain
  • EtherCamp
  • EtherScan

其他可檢視節點或交易的資源

  • EtherNodes :節點的地理分配,由客戶端區分。
  • EtherListen:實時以太坊交易可視器和可聽器。

智慧合約案例實戰

以太坊是區塊鏈開發領域最好的程式設計平臺,而truffle是以太坊(Ethereum)最受歡迎的一個開發框架,這也是介紹truffle的原因。實戰是最重要的事情,這篇文章不講原理,只搭建環境,執行第一個區塊鏈程式(Dapp)。

1. 安裝truffle

安裝truffle的命令如下:

$ npm install -g truffle

2. 依賴環境

可用的系統包括:Windows、Linux和Mac OS X,推薦Mac OS X,不建議使用Windows,會碰到各種各樣的問題,很可能導致放棄。首先,訪問https://nodejs.org 官方網站下載安裝NodeJS。

此外,需要安裝Ethereum客戶端,來支援JSON RPC API呼叫。

安裝命令如下:

$ npm install -g ethereumjs-testrpc

3. 新建第一個專案

通過以下命令新建一個專案:

$ mkdir zhaoxi
$ cd zhaoxi
$ truffle init

預設會生成一個MetaCoin的demo,可以從這個demo中學習truffle的架構。

專案的目錄結構如圖5-3所示。

這裡寫圖片描述
圖5-3 專案的目錄結構

專案所有檔案的目錄如圖5-4所示。

這裡寫圖片描述
圖5-4 專案檔案目錄目錄結構

現在,通過以下命令編譯專案。

$ truffle compile

圖5-5是執行以上命令後的結果。

這裡寫圖片描述
圖5-5 Truffle compile執行結果圖

下面介紹部署專案的方式。

部署之前先啟動TestRPC,命令如下:

$ testrpc 
$ truffle deploy(在Truffle 2.0以上版本中,命令變成了:truffle migrate)

圖5-6是執行truffle deploy後的結果。

這裡寫圖片描述
圖5-6 truffle deploy執行結果圖

$ truffle migrate migrate的執行結果見圖5-7。

這裡寫圖片描述
圖5-7 truffle migrate migrate執行結果圖

現在,可以啟動服務了,命令如下:

$ truffle serve

圖5-8是truffle serve執行結果圖

這裡寫圖片描述
圖5-8 truffle serve執行結果圖

啟動服務後,可以在瀏覽器訪問專案了,地址是:http://localhost:8080/ ,網頁介面如圖5-9所示。

這裡寫圖片描述
圖5-9智慧合約執行介面

好了,第一個區塊鏈程式跑起來了,後面可以不斷地實踐深入學習了。

這裡寫圖片描述

相關推薦

動手編寫一個智慧合約

本文節選自圖書《區塊鏈開發指南》,本書由 申屠青春 主編,宋波、張鵬、汪曉明、季宙棟、左川民 聯合編著。 區塊鏈相關約稿、文章糾錯、尋求報道等可郵件聯絡 [email protected] 如何部署、呼叫智慧合約 RPC 之前的

如何通過solc編譯solidity編寫智慧合約

solc:solidity的編譯器 solidity編寫的以太坊智慧合約可通過命令列編譯工具solc來進行編譯,成為以太坊虛擬機器中的程式碼。solc編譯後最終部署到鏈上形成我們所見到的各種智慧合約。 作為一個solidity命令列編譯工具,我們來看看官網都

編寫除錯智慧合約/blockchain

一、        智慧合約IDE簡介     目前以太坊上支援三種語言編寫智慧合約,     Solidity:類似JavaScript,這是以太坊官方推薦語言,也是最流行的智慧合約語言。具體用法參加Solidity文件,地址:https://solidity

智慧合約學習筆記:網頁互動

沒搞過web程式,花了幾天研究一下,總算是搞懂了網頁與以太坊節點的互動流程。 網頁與智慧合約互動,需要使用web3.js,它實現了通用JSON PRC規範,通過JSON RPC協議與以太坊節點進行互動。除了js以外,以太坊還提供了Java、Python等語言的API,對於沒有提供API的語言

智慧合約學習筆記:使用Truffle框架開發部署智慧合約

truffle是一個智慧合約的開發框架,具體的就不介紹了,我們主要是說說怎麼使用這個框架來進行智慧合約的開發,官網戳這裡。 文章目錄 #安裝 首先我們要先安裝npm和truffle,安裝命令如下 sudo apt install npm sudo n

智慧合約學習筆記:開發流程及工具鏈使用

本文主要介紹開發流程和工具鏈的使用,安裝過程百度上有好多,這裡就不贅述了 網上隨便找了一個智慧合約的例子,咱們來做一個投票系統,先用傳統的中心化方案去實現,然後在過度到區塊鏈1.0,最後再用區塊鏈2.0,感受一下開發思想的不同。 業務分析 傳統

區塊鏈技術進階-深入詳解智慧合約語言 solidity(含原始碼)-熊麗兵-專題視訊課程...

區塊鏈技術進階-深入詳解以太坊智慧合約語言 solidity(含原始碼)—103人已學習 課程介紹         區塊鏈開發技術進階-深入詳解以太坊智慧合約語言 solidity視訊培訓教程:本課

iOS應用程式如何呼叫智慧合約

以太坊智慧合約有各種各樣的用例,但到目前為止,從你的iOS應用程式中呼叫它們非常困難。不過如果使用以太坊iOS開發套件和EtherKit,這種情況會改善很多,你可以立即開始使用。在本教程結束時,你將能夠呼叫其ABI(應用程式二進位制介面)中定義的任何公共合約函式。 對於這個專案,我們將使

如何實現一鍵呼叫智慧合約

今天有人問如何用按鈕呼叫智慧合約,我不知道在哪裡找,所以我決定寫這個,很快就可以。 在這篇文章中,我將給出一個簡單但有希望有效的演示,說明JavaScript開發人員如何建立一個能夠呼叫智慧合約的網頁,並通過單擊即可向其匯款(以太幣)。 要做到這一點,使用者將需要使用支援Web

olidity語言開發智慧合約中的繼承

我們已經探索了很多主題,在編寫智慧合約時我們發現經常使用相同的模式:例如,智慧合約具有在建構函式中設定的所有者,然後生成修改器以便僅讓所有者使用一些功能。如果我們制定實施這些功能的基礎合約並在未來的智慧合約中重複使用它們那該怎麼辦?你一定猜得到,我們將使用繼承。 在Solidity中,繼承與經典的面向物

web3j教程:java使用web3j開發智慧合約交易

從廣義上講,有web3j支援三種類型的以太坊交易: 1.以太幣從一方交易到另一方 2.建立一個智慧合約 3.與智慧合約交易 為了進行這些交易,必須有以太幣(以太坊區塊鏈的代幣)存在於交易發生的以太坊賬戶中。這是為了支付gas成本,這是為支付參與交易的以太坊客戶端的交

java如何在Spring Boot中用web3j開始開發智慧合約

通過Spring的依賴注入將web3j整合到Spring Boot應用程式中。此處提供了示例應用程式: 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

關於智慧合約在專案實戰過程中的設計及經驗總結(1)

此文已由作者蘇州授權網易雲社群釋出。 歡迎訪問網易雲社群,瞭解更多網易技術產品運營經驗 1.智慧合約的概述 近幾年,區塊鏈概念的大風吹遍了全球各地,有的人覺得這是一個大風口,有的人覺得他是個泡沫。眾所周知,比特幣是區塊鏈1.0,而以太坊被稱為了區塊鏈2.0,而區塊鏈1.0和2.0最主要的差別就在於以太坊擁有

關於智慧合約在專案實戰過程中的設計及經驗總結(2)

此文已由作者蘇州授權網易雲社群釋出。 歡迎訪問網易雲社群,瞭解更多網易技術產品運營經驗 7.智慧合約經驗分享 1)智慧合約開發的工具的問題 古人云“工欲善其事必先利其器”,同意良好的智慧合約的開發工具對智慧合約的開發效率有極大的提升。以下是一些比較好的智慧合約的開發組合: &nb

智慧合約的奇幻漂流

“A smart contract is a computer program executed in a secure environment that directly controls digital assets.” – Vitalik Buterin 作為以太坊

區塊鏈開發(二)部署並執行第一個智慧合約

        網路上不少部署智慧合約的文章,但是都有一個共同的特點,就是採用命令列的方式來部署,先是建立SOLC的編譯環境,然後部署Geth或者Eth節點,然後一步一步生成錢包、ABI、合約地址進行部署,對初學者來說晦澀難懂而且容易失敗,本文主要介紹如何在圖形化介面下一鍵部

WEB頁面訪問智慧合約--使用Web3

準備工作  使用remix IDE開發智慧合約程式碼,並部署合約到測試鏈上。請參考《使用remix釋出智慧合約》  安裝Ganache,使用Ganache模擬一個以太坊坊節點。請參考《Ganache模擬以太坊區塊鏈節點》 Web3簡介 Web3JS是

智慧合約的編譯器使用

注意 本節不適用於solcjs,即使在命令列模式下使用也不適用。 Solidity儲存庫的構建目標之一是solidity solc命令列編譯器。使用為您提供所有選項的說明。編譯器可以生成各種輸出,範圍從簡單的二進位制檔案和抽象語法樹(解析樹)上的彙編到氣體使用的

智慧合約的兩種資料分離模式(部署可升級式智慧合約

重要! 做資料分離推薦使用2018年後的的Geth版本,即v1.8以上。在genesis.json創世檔案的配置config裡需新增拜占庭Block,如下: "config": {     "chainId": 1,     "homesteadBlock": 0,   

智慧合約部署前的環境搭建

Chrome瀏覽器安裝 安裝curl sudo apt-get install curl 安裝npm 安裝 curl -L https://npmjs.org/install.sh | sudo sh 修改源 npm con