以太坊平臺實驗手記

最近帶我師弟做項目,順手衍生了一份實驗手記。我自覺不錯。就放上來了。


以太坊 Go 客戶端的安裝與區塊鏈的導入導出


以下實驗在 Ubuntu 16.04 LTS 中進行,驗證對 Ethereum Go 客戶端(geth)的 1.6.6- stable-10a45cb5 版本有效。其他版本的特性參見 Git Hub 項目主頁 [1]。 在 Ubuntu 上使用 PPA 安裝的命令如下:


sudo apt-get install software-properties-common


sudo add-apt-repository -y ppa:ethereum/ethereum


sudo add-apt-repository -y ppa:ethereum/ethereum-dev


sudo apt-get update


sudo apt-get install ethereum


在使用上述命令安裝後,在控制檯使用 geth --help 命令應當有所迴應,如圖1所示。 需要注意的是,安裝之後若直接運行 geth,則程序將會把所有需要持久化的數據(除 了工作量證明的 Ethash 算法需要生成的有向無環圖)寫入默認的數據文件夾中,在 Linux 下 這個默認的數據文件夾爲~/.ethereum。 即區塊鏈的數據就會被默認存儲在該文件夾下,但在運行 geth 時也可以通過--datadir <data dir> 選項來指定區塊鏈數據的位置。 這些區塊鏈的數據可以進行導入和導出操作,相關的命令如下:


• 升級數據庫: geth upgradedb


• 清除數據庫: geth removedb


• 導入區塊鏈: geth import <filename>


• 導出區塊鏈: geth export <filename> 多說一句,之前提到的用於工作量證明(PoW,Proof of Work)的 Ethash 算法需要生 成的有向無環圖(DAG)將被保存在~/.ethash 目錄下,因而可以被所有的客戶端節點複用, 即只在第一次生成客戶端節點時下載並緩存 DAG,這個過程通常非常漫長,我們後續會提到。


1 圖 1: 安裝後驗證安裝成功

2


節點創建和初始化


首先使用如下命令創建兩個數據文件夾,對應將來我們創建的兩個節點:


mkdir -p ~/BlockChain/miner1


mkdir -p ~/BlockChain/miner2


然後我們編寫一個創世區塊的配置文件genesis.json,內容如下:


{


" nonce" : " 0x0000000000000042" ,


" mixhash" : " 0


x0000000000000000000000000000000000000000000000000000000000000000" ,


" difficulty" : " 0x400" ,


" alloc" : {},


" coinbase" : " 0x0000000000000000000000000000000000000000" ,


" timestamp" : " 0x00" ,


" parentHash" : " 0


x0000000000000000000000000000000000000000000000000000000000000000" ,


" extraData" : " " ,


" gasLimit" : " 0xffffffff" ,


2 " config" : {


" chainId" : 42,


" homesteadBlock" : 0,


" eip155Block" : 0,


" eip158Block" : 0


}


}


其中各項的含義如下:


• nonce:一個 64 位隨機數,用於挖礦,其設置需要滿足以太坊的黃皮書([2])的要求


• mixhash:與 nonce 配合用於挖礦,由上一個區塊的一部分生成的 hash,其設置同樣需 要滿足以太坊的黃皮書的要求


• difficulty:設置當前區塊的難度,如果難度過大,CPU 挖礦就很難,這裏設置較小難度


• coinbase:礦工的賬號,此處可隨便填


• timestamp:設置創世塊的時間戳


• parentHash:上一個區塊的 hash 值,因爲是創世塊,所以這個值是 0


• extraData:額外信息,這裏留空。


• gasLimit:該值設置對 GAS 的消耗總量限制,用來限制區塊能包含的交易信息總和,因 爲我們是私有鏈,所以填最大。


• config:從 geth 1.6 版本開始,所有的創世區塊的配置文件必須包含此項,用於指定鏈 的 id(chainId,也被稱爲 network id),此處我們指定爲 42。


設置好的創世區塊配置文件我們放在~/BlockChain/genesis.json 處,如圖2 所示。 接着使用以下命令初始化節點:


cd ~/BlockChain # 工 作 目 錄 切 換 到BlockChain


geth --datadir miner1 init genesis.json


geth --datadir miner2 init genesis.json


這條命令的作用是以 genesis.json 中的配置初始化兩個節點 miner1 和 miner2,將節點 的數據分別存儲在對應的文件夾下。在使用這創建命令後,控制檯會輸出相應的提示,如圖3, 幾行 INFO 表示我們成功將節點數據寫其中唯一一行 WARN 表示我們還沒有爲這個節點創 建默認用戶,這將在之後完成。


BlockChain 的目錄結構應當如下,其中 geth 文件夾下保存了你建好的私有區塊鏈的數 據庫,而 keystore 則存儲了當前節點中賬戶的數據。


3 圖 2: 創建數據文件夾並編寫創世區塊配置文件


4 圖 3: 初始化並寫進創始區塊


5 圖 4: 初始化並寫進創始區塊後的目錄結構


然後在 contracts 目錄下創建並編寫 SmartToken.sol 文件如下,其中定義了三個合約函 數和一個事件記錄。三個合約函數中,depositToken 是向指定的對象發放一定數量的令牌,並 觸發事件記錄;withdrawToken 是從指定的對象處收回一定數量的令牌,並觸發事件記錄;最 後的 getTokens 是一個常量函數,所以在調用的時候不會有 gas 值的開銷。


pragma solidity ^0.4.0;


contract SmartToken {


mapping(address => uint) tokens;


event OnValueChanged(address indexed _from, uint _value);


function depositToken(address recipient, uint value) returns (bool


success) {


tokens[recipient] += value;


OnValueChanged(recipient, tokens[recipient]);


return true;


}


function withdrawToken(address recipient, uint value) returns (bool


success) {


if ((tokens[recipient] - value) < 0) {


tokens[recipient] = 0;


} else {


tokens[recipient] -= value;


}


OnValueChanged(recipient, tokens[recipient]);


return true;


}


function getTokens(address recipient) constant returns (uint value) {


return tokens[recipient];


}


}


接着通過修改migrations/2_deploy_contracts.js 修改部署配置相關的代碼,修改 後的代碼如下:


23 圖 23: 使用 truffle 編譯部署的結果


部署成功後我們可以在 truffle 控制檯中查看合約地址與 ABI 接口信息(這裏的 ABI 用 JSON 表示,如圖24):


truffle console


# 進 入truffle控 制 臺


SmartToken.address


# 查看地址


JSON.stringify(SmartToken.abi) # 查 看abi, JSON格 式


.exit


# 退 出truffle控 制 臺


25 圖 24: 查看合約被部署的地址與 JSON 格式的 ABI 接口信息


8


通過 Mist 客戶端查看和測試合約


最後我們通過 Mist 這個客戶端來查看和測試合約,直接從圖形界面點擊之前安裝好的 Mist 客戶端,他會自己找到默認路徑下的 geth.ipc 文件,然後以該文件對應的節點的身份登 錄並獲取賬戶信息,即會以 miner1 的第一個賬戶的身份登錄 Mist 瀏覽器。


打開 Mist 瀏覽器最初的界面會如圖25所示,由於 miner1 節點正在挖礦,你會看到默認 賬戶的以太幣不斷增加。


26 圖 25: Mist 自動登錄後的錢包界面,可以看到當前登錄的 miner1 節點上的兩個賬戶,下面的 ADD ACCOUNT 提供了增加賬戶的選項,這實際只是對我們之前控制檯創建賬戶命令做的 上層封裝


點擊上面的 SEND 標籤,可以從 WALLET 切換到交易的界面,如圖26,從這裏可以看 到,以太坊的客戶端 Mist 實際也就是對我們 JS 控制檯中的命令進行了封裝。Mist 這個客戶 端本來也就是被設計成給普通用戶參與以太幣交易的。


27 圖 26: Mist 的交易界面,其實就是對我們之前在 JS 控制檯中交易的封裝 我們也可以點擊初始界面的 CONTRACTS 標籤,切換到合約界面,大致的狀況如圖27所 示,我們可以看到他提供了部署合約和查看合約的選項。


28 圖 27: 合約相關界面


而從合約界面上 Mist 也提供了部署合約的選項,如果我們點擊 DEPLOY NEW CON- TRACT 則會進入圖28 所示的界面,可以看到他在這個客戶端中提供了一個 Solidity 的編輯 器,能夠供普通用戶編寫合約代碼部署到當前節點。


29 圖 28: 點擊 DEPLOY NEW CONTRACT 進入的部署合約的界面


而如果我們在之前的合約界面點擊 WATCH CONTRACT,則會彈出圖29 所示界面,我 們輸入之前從 truffle 控制檯得來的合約地址、合約名、以及 JSON 格式的接口,就可以查看 和運行之前編寫的智能合約了。


30 圖 29: Mist 中輸入之前部署好的智能合約信息


我們點擊我們輸入的智能合約的圖標,會進入圖30所示界面,其中因爲 getTokens 是一個 const 函數,所以執行時不會花費 gas,我們在左側輸入地址即可查詢,我們這裏輸入 miner2 的第二個賬戶的地址,查看其初始令牌數爲 0。接着我們在右側選擇 Deposit Token 這個函 數,然後輸入 miner2 的第二個賬戶的地址,Value 填入 1234,並看到右下方合約的執行者是 miner1 的主賬戶(默認第一個賬戶),我們點擊圖中的 EXECUTE 按鈕。


31 圖 30: 查看 miner2 的第二個賬戶最開始的令牌數量,然後準備用 miner1 的第一個賬戶執行 合約函數,發放 1234 個令牌給 miner2 的第二個賬戶


按下 EXECUTE 按鈕後,我們能看到一個確認執行合約的彈窗(圖31),需要輸入當前合 約執行人的密碼,我們輸入後點擊 SEND TRANSACTION。


32 圖 31: 輸入密碼確認合約 之後可以看到, 確認執行的彈窗消失後回到執行合約的界面32,我們可以看到左側的 miner2 的第二個賬戶的令牌數量變爲 1234。 33 圖 32: 合約執行結束後,再查看 miner2 的第二個賬戶的令牌數量,發現已經從 0 變成了 1234


我們再下拉,勾選上圖33中的 Watch contract events 之後就可以看到之前的 deposit 操 作觸發的事件也被永久記錄下來了。


34 圖 33: 下面關於合約函數執行後觸發的函數會自動增加

參考文獻



[1] https://github.com/ethereum/go-ethereum.


[2] http://gavwood.com/Paper.pdf.


[3] https://github.com/ethereum/go-ethereum/wiki/JavaScript-Console.


圖暫時沒放上去了,pdf版如果需要,可以在下面評論區留言。

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