原文:How To Write, Deploy, and Interact with Ethereum Smart Contracts on a Private Blockchain
作者:jack_schultz
翻譯:無阻我飛揚
摘要:本文作者以極長的篇幅給出了在私人區塊鏈上編寫、部署以及與以太坊進行互動的智能合約的較為完整的代碼、相關細節步驟、使用者介面等。作者是希望藉助他這篇文章,大家可以自行在私人以太坊區塊鏈上編寫並部署一個智能合約,以下是譯文。
最後,你會建立出一個私人以太坊專用區塊鏈,串連兩個不同的節點作為peers,編寫並編譯一個智能合約,有一個允許使用者提出問題的Web介面,在區塊鏈上部署問題,然後讓使用者來回答。
如果希望對欄位有一個完整的解釋,看看這個堆疊溢位的解答。這個案例中的difficulty是很低的,因為不希望在測試網路上等待很長的時間,區塊才能被挖掘出來,然後gasLimit 的值高到允許區塊中的一個節點可以完成的工作量能夠處理每個交易。
去開啟一個終端,確保geth(以太坊用戶端)以任何適用於你的作業系統的方式進行安裝,然後cd(dos命令)到儲存genesis.json的檔案夾。運行以下命令,將初始化該節點的區塊鏈。
$ geth --datadir "/Users/USERNAME/Library/PrivEth" init genesis.json
-datadir指定區塊鏈所有資料的位置。在Mac作業系統上,預設是 ~/Library/Ethereum目錄。由於有多個節點在運行,所以不能讓它們共用相同的資料檔案夾,因此需要具體指定。Linux和Windows機器具有不同的預設datadir,所以請查看這些資料一般應該位於何處。
用genesis.json檔案運行完初始化命令之後,去檢查那個--datadir目錄,會看到一堆檔案,所以隨意四處看看吧。現在沒有必要,但是最終還是要去看看。
對於這樣一個區塊鏈,需要多個節點。要使區塊鏈成為peers,它們需要擁有相同的創始檔案。所以要從同一個目錄運行和上面相同的命令,但是這次使用了不同的datadir。
geth --datadir "/Users/USERNAME/Library/PrivEth2" init genesis.json
1 2 這裡所有的代碼,將在同一個目錄下工作。代碼是一樣的,但是使用命令列選項,可以通過命令列參數區分這些進程。
初始化兩個節點的鏈。
1 2 這裡還有更多的選擇。
-networkid與genesis.json檔案中的類似,在這裡所需要做的是確保不使用網路ID 1-4。
-port指定.ipc檔案將要用到的連接埠。這就是使用web3.js庫串連資料庫的方式,預設連接埠是30303。所以將它保留在那個地區,但這是第一個節點,所以它的連接埠是30301。
nodiscover告訴geth最初不要找peers。這一點在這個案例中確實很重要。這是一個私人網路。不希望節點在沒有指定的情況下嘗試串連到其它節點,不希望這些節點在沒有告訴它們的情況下被發現。
在第一個geth節點啟動並執行情況下,在有第二個—datadir的不同終端運行相同的命令,節點在不同的連接埠上運行。
好難過。這是我們期望的,在非1-4網路ID和nodiscover的標誌上啟動控制台。這意味著需要告知每個節點用特定的命令串連到另一個節點。通過分享enode 地址的方式來做。
> admin.nodeInfo.enode“enode:// 13b835d68917bd4970502b53d8125db1e124b466f6473361c558ea481e31ce4197843ec7d8684011b15ce63def5eeb73982d04425af3a0b6f3437a030878c8a9 @ [:]:30301 discport = 0”
這是geth用來串連到不同節點的enode資訊,在這些不同的節點它們能夠分享交易和成功挖掘資訊。
要使用這個URL串連節點,需要調用addPeer函數。
如果要複製從其中一個節點admin.nodeInfo.enode的傳回值,請在另一個節點中運行以下命令。
> admin.addPeer(“enode:// 13b835d68917bd4970502b53d8125db1e124b466f6473361c558ea481e31ce4197843ec7d8684011b15ce63def5eeb73982d04425af3a0b6f3437a030878c8a9 @ [::]:30301。discport = 0”)
這告知一個節點如何到達另一個節點,並請求另一個節點串連起來,它們都將成為彼此的peers。如需檢驗,請在兩個節點上運行admin.peers命令,將看到它們串連在一起。代碼如下:
> admin.peers[{caps: ["eth/63"],id: "99bf59fe629dbea3cb3da94be4a6cff625c40da21dfffacddc4f723661aa1aa77cd4fb7921eb437b0d5e9333c01ed57bfc0d433b9f718a2c95287d3542f2e9a8",name: "Geth/v1.7.1-stable-05101641/darwin-amd64/go1.9.1",network: { localAddress: "[::1]:30301", remoteAddress: "[::1]:50042"},protocols: { eth: { difficulty: 935232, head: "0x8dd2dc7968328c8bbd5aacc53f87e590a469e5bde3945bee0f6ae13392503d17", version: 63 }}}]
要添加peer,只需要告訴一個節點串連到另一個節點,然後檢查另一個節點,就會看到如下輸出:
現在從另一個節點的coinbase帳戶複製地址,並回到未解鎖的帳戶節點
> hisAddress = "0x846774a81e8e48379c6283a3aa92e9036017172a"
在此之後,sendTransaction命令有點簡單。
> eth.sendTransaction({from: eth.coinbase, to: hisAddress, value: 100000000})INFO [12-09|10:29:36] Submitted transaction fullhash=0x776689315d837b5f0d9220dc7c0e7315ef45907e188684a6609fde8fcd97dd57 recipient=0x846774A81E8E48379C6283a3Aa92E9036017172A"0x776689315d837b5f0d9220dc7c0e7315ef45907e188684a6609fde8fcd97dd57"
還有一件需要注意的事,而且會很容易混淆的,就是為什麼這些數位值有那麼多0。這是因為值是用wei來表示的,所以不必處理可能在不同系統上引起問題的浮點數。這將與gas(一個與計算步驟大致相當的測量法。每筆交易都需要包括一個Gas限制和一個願意為每個Gas支付的費用;礦工可以選擇進行交易和收費)一起發揮作用 ,需要開始指定合約部署和交易。
如果想知道用這個值發送了多少以太幣,命令如下:
> web3.fromWei(100000000,'ether')“0.0000000001”
要使交易發送,並且看到不同餘額的差異,需要在節點中啟動礦工,然後在挖掘了一個區塊後停止,現在檢查餘額以查看變化。
> miner.start()...............> miner.stop()> web3.eth.getBalance(eth.coinbase)59999999999900000000> web3.eth.getBalance(hisAddress)100000000
接下來看看下面的這張巨幅圖片。同樣,節點1在左邊,節點2在右邊。所以首先檢查每個節點上各自coinbase賬戶的餘額。在節點1上,複製節點2的地址,發送交易,然後從接收到提交的交易的節點登入,接著開始挖掘。會發現節點8 有txs=1,這意味著它在那個區塊挖掘了一筆交易。再多挖幾個區塊以後,停止挖掘。檢查節點1的帳戶餘額。有12個區塊,每個區塊獎勵5以太幣,但後來卻付出了100000000wei。
現在,回到節點2,檢查其coinbase帳戶的餘額,餘額是0。然後,記得重新啟動過節點1的控制台,並沒有將兩個節點設定為peers。因此,列印節點1的enode,作為一個peer將其添到節點2。在添加peer後,會看到節點2接收到錯過的塊,包括1個交易。然後再次檢查餘額,發現它有100000000Wei。