區塊鏈之以太坊初體驗——以太坊平臺學習總結

各類媒體和技術專家也對該技術的應用前景、對應用領域顛覆性的意義進行了大量的報道和描述,區塊鏈技術會像互聯網技術一樣改變現有傳統領域。業界也不乏技術實踐的先行者,像R3區塊鏈聯盟、以太坊等,在平臺實現、技術應用方面已經有了很多的嘗試。

640?wx_fmt=jpeg&tp=webp&wxfrom=5&wx_lazy


近期,因爲工作需要,對以太坊、區塊鏈等技術和概念進行了學習和研究。本文是作者對前一段時間學習、工作實踐和同事交流的一個知識整理。


區塊鏈DISCOVERY

區塊鏈是一種基於點對點(peer-to-peer)網絡、分佈式的共享賬簿技術。

640?wx_fmt=jpeg&tp=webp&wxfrom=5&wx_lazy


通俗地理解,區塊鏈就是一個公共的、去中心化的數據庫,每個節點(full node)上都保存有一份全量的一模一樣的數據,在一筆交易數據提交到區塊鏈網絡時,各個節點(node,也叫礦工)開始基於該交易信息進行數據塊的計算,只有第一個被計算出並按照某種共識機制得其他的節點確認的數據塊勝出,從而被添加到鏈上,該過程也叫算力競爭。後續數據塊的計算都會基於前一個塊的數據的hash值進行。


而區塊鏈技術被寄予厚望的原因正是,該技術的應用可以改變目前中心化的交易機制(目前,個人和組織的交易行爲都是基於一個可信任的、中心化的機構來開展的,比如跨境結算,需要通過國際清算銀行等中間機構才能完成交易),幫助人們構建一種可信任的、去中心化的交易機制,交易當事方不需要經過第三方機構而直接完成交易。


這樣降低交易的複雜度和中間費用,提高商業效率。同時,區塊鏈通過分佈式存儲、公私鑰加密等技術保證了交易數據的安全、可追溯、不可篡改性。


以太坊DISCOVERY

以太坊是一個基於區塊鏈技術的開源平臺,通過它可以非常容易地構建去中心化的應用(Dapp)。在底層,以太坊基於區塊鏈技術,實現了數據的去中心化、分佈式存儲和信息交換的信任問題。同時,以太坊實現了一個叫Ethereum Virtual Machine(EVM)的運行時環境,類似JVM,它的主要工作是執行智能合約(該概念下面會介紹)的字節碼。

640?wx_fmt=jpeg&tp=webp&wxfrom=5&wx_lazy


在以太坊中也有挖礦的概念,每一筆交易只有通過網絡中的礦工進行挖礦才能提交到以太坊區塊鏈中。


  • 以太幣

類似比特幣,以太坊平臺上的數字貨幣,英文縮寫ETH。


  • Gas

用戶提交給EVM執行交易或智能合約時,需要支付的費用,由以太幣按一定的比例轉而來,當用戶中的以太幣不足以支付Gas時,EVM會停止執行提交的交易或者智能合約。


  • 賬戶

在以太坊中有兩類賬戶:

  1. 外部賬戶(externally owned account,EOA)

    用戶可以通過地址和私鑰對賬戶進行操作。EOA可以在以太坊控制檯中通過命令來創建,或者通過IPC方式由外部調用api來創建;


  2. 智能合約(smart contract)

    它在以太坊中的作用有:

    1)維護數據存儲

    2)實現複雜的訪問控制策略

    3)爲其他合約提供方法調用。

    但是智能合約無法自己執行其中的邏輯或者方法,只能由EOA或者其他合約發起調用。

    在以太坊平臺,智能合約的編程語言有Solidity(文件擴展名以.sol結尾)和Serpent(文件擴展名以.se結尾),但目前現在最流行而且最穩定的要算是Solidity。


  • 賬戶在區塊鏈中的存儲結構

以太坊賬戶的所有信息也存儲在在區塊鏈的結構中,如下圖: 


不同於比特幣,在以太坊的區塊鏈結構中,不僅包含了對前一個區塊的引用信息、區塊號、交易和時間戳等信息,它還包含了所有以太坊賬戶的信息,存儲在以“STATE_ROOT”爲根節點的一棵Patricia樹(“a specialized kind of Merkle tree”)上。該根節點的值是對整棵數上保存的數據進行hash計算得出。


從圖中可以看出,每個賬戶節點中包含四類信息:

  1. NONCE--記錄從該賬戶發起的交易數;

  2. BALANCE--記錄該賬戶餘額;

  3. CODEHASH--智能合約賬戶的代碼hash值並指向合約代碼,如果爲EOA則該值爲空;

  4. STORAGE_ROOT--另一棵Patricia樹的根節點,智能合約賬戶的內部數據存儲空間,當合約賬戶調用suicide()方法時,該值將被置爲null。


智能合約開發環境搭建DISCOVERY

爲了便於智能合約的開發和測試,需要在本地電腦搭建一個以太坊開發環境。本文接下來將介紹如何使用Truffle+Testrpc來搭建環境。


Testrpc的介紹和使用

Testrpc是基於node.js開發的以太坊客戶端,整個blockchain的數據駐留在內存空間,testrpc可以模擬一個geth客戶端的行爲,包括所有的RPC api,發送給testrpc的交易會被馬上處理而不需要等待挖礦時間,讓基於以太坊的開發測試工作更加方便快速。


Testrpc安裝。在命令行終端輸入“npm install -g ethereumjs-testrpc”,等待完成即可。


啓動Testrpc。輸入命令”testrpc”即可,啓動完成後,出現下圖信息:

640?wx_fmt=png&tp=webp&wxfrom=5&wx_lazy=


從中我們可以看到,testrpc在啓動時默認創建了多個賬號,並開放了rpc端口8545。


Truffle介紹

Truffle是一個基於以太坊的智能合約開發工具,支持對合約代碼的單元測試,非常適合TDD。同時它內置了智能合約編譯器,只要使用腳本命令就可以輕鬆完成合約的編譯、動態庫鏈接、部署、測試等工作,大大簡化了智能合約的開發生命週期。


Truffle的安裝非常簡單,只要在終端輸入命令“sudo npm install -g truffle”,等待安裝完成即可。


使用Truffle開發智能合約的過程如下(如何編寫合約及solidity語法不在本文範圍):

  • 使用testrpc開啓一個以太坊節點

  • 創建一個工程目錄,並初始化

mkdir myProject

cd myProject

truffle init


初始化完成後,Truffle在工程目錄下默認會生成一個叫MetaCoin的智能合約demo及其測試文件,目錄結構如下:

640?wx_fmt=png&tp=webp&wxfrom=5&wx_lazy=


各目錄含義:

app/:存放前端javascript文件和stylesheets文件,在開發Dapps時使用;

contracts/:智能合約文件的存放目錄;

migrations/:存放部署腳本;

test/:存放智能合約測試文件;

truffle.js:truffle的主配置文件,在該文件中可以指定以太坊客戶端地址和rpc端口,network_id等;


1. 編寫智能合約文件並編譯,比如有個Multiply.sol,將其放入contracts目錄下,執行命令“truffle complie”,代碼片段如下:


2. 部署合約,執行命令“truffle deploy”,或者發佈合約到以太坊客戶端,在migrations目錄下增加部署文件,比如3_deploy_multiply.js 文件,修改truffle.js中相關rpc的配置,執行命令“truffle migrate”,終端打印如下信息,表示成功發佈;

640?wx_fmt=png&tp=webp&wxfrom=5&wx_lazy=


3. 編寫測試文件,保存爲multiply.js,並放入test目錄下(代碼如下),執行命令“truffle test”:

640?wx_fmt=png&tp=webp&wxfrom=5&wx_lazy=


執行結果如下:

640?wx_fmt=png&tp=webp&wxfrom=5&wx_lazy=


智能合約的外部調用DISCOVERY

在某些應用場景下,爲了接入以太坊區塊鏈,業務系統需要調用以太坊客戶端的api,將用戶的交易數據發送給以太坊平臺。以太坊客戶端已經爲外部系統提供了RPC和IPC兩種api調用方式。


以RPC方式爲例,使用curl命令請求的格式如下:

調用客戶端命令:

假設我們要調用客戶端命令eth.getBalance(),查詢地址爲0x407的賬號的餘額,命令如下:

curl --data '{"jsonrpc":"2.0","method":"eth_getBalance","params":["0x407", "latest"],"id":1}' localhost:8123


其中:jsonrpc字段指定JSON-RPC版本號,method字段指定需要調用的api方法名,params字段爲傳送的參數,id爲消息標識字段;


調用合約方法:

假設目前有部署的智能合約,地址爲0x6ff93,我們要調用的合約方法簽名爲multiply(uint256),傳入的參數值爲6,那麼調用命令的格式如下:



其中,from爲扣除GAS的賬戶地址,to爲智能合約部署的地址,data爲調用方法的簽名和傳入參數,編碼方式爲:

“0x”+sha3(“multiply(uint256)”).substring(0,8)+to_32bit_Hex_str(6)


to_32bit_Hex_str()方法的實現會依據不同的變量類型而有不同,具體規則可以參考Ethereum Contract ABI 文檔(HERE)。


從上面的示例可以看出,從外部對智能合約的調用需要進行復雜的編碼。萬幸,目前以太坊官方提供了使用javascript語言實現的web3.js模塊,對RPC和IPC兩種調用方式d都進行了封裝,對外提供了簡潔的接口,使用非常方便。


下面本文將使用web3.js模塊在nodejs環境下實現對智能合約的調用,並向外提供RESTful的api。詳情如下:

系統環境:

Ubuntu14.04.4+Node V5.1.1;


需要引入的Node模塊

express、web3、net,可以使用npm命令安裝依賴;


主要代碼片段

引入模塊依賴

640?wx_fmt=png&tp=webp&wxfrom=5&wx_lazy=


設置RPC和IPC連接對象

640?wx_fmt=png&tp=webp&wxfrom=5&wx_lazy=


調用以太坊客戶端方法,查詢指定賬戶的餘額

640?wx_fmt=png&tp=webp&wxfrom=5&wx_lazy=


新建以太坊賬戶,該方法必須使用IPC api的調用方式

640?wx_fmt=png&tp=webp&wxfrom=5&wx_lazy=


新建合約對象,其中contractData爲合約代碼編譯後的16進制字符串


調用智能合約方法

640?wx_fmt=png&tp=webp&wxfrom=5&wx_lazy=


開啓http server

640?wx_fmt=png&tp=webp&wxfrom=5&wx_lazy=


最後使用node啓動服務,看到“Example app listening at http://:::9090”服務就啓動成功了。這樣用戶便可通過RESTful的http請求來與以太坊客戶端進行交互,並調用智能合約。


結束語

本篇文章是我對最近一段時間學習的以太坊平臺和區塊鏈技術的總結,主要介紹了以太坊平臺的一些基本概念、智能合約本地開發環境的搭建和外部系統調用智能合約api開發介紹3個方面的內容,即當是一次以太坊區塊鏈知識的歸納梳理,也當是一次知識的分享交流。


由於學習的時間有限,文中難免有理解不到位得地方,還請大家指正!同時,非常感謝公司其他同事對我在學習以太坊平臺中的幫助,讓我受益匪淺!最後,文中也引用和參考了很多官網的資料和網友的文章,在此獻上真摯的謝意!


參考資料:

  1. https://blog.ethereum.org/2015/06/26/state-tree-pruning/

  2. https://blog.ethereum.org/2014/02/18/ethereum-scalability-and-decentralization-updates/

  3. http://gavwood.com/Paper.pdf

  4. http://truffle.readthedocs.org/en/latest/

  5. https://github.com/ethereumjs/testrpc

  6. http://www.ethdocs.org/en/latest/

  7. https://solidity.readthedocs.io/en/latest/


發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章