1. 程式人生 > >第一行代碼:以太坊(1)-創建自己的私有區塊鏈

第一行代碼:以太坊(1)-創建自己的私有區塊鏈

list 建立 ini 立即生效 file 初始 頭節點 壓縮包 線程

本文會利用以太坊客戶端(geth)搭建一個私有區塊鏈,並在這個私有區塊鏈上挖礦,通過本文的案例,讀者可以更深入理解區塊鏈、以太坊、挖礦的理論。

通過閱讀本文,您可以:

  • 掌握搭建以太坊開發環境的方法
  • 掌握geth的基本使用方法
  • 了解如何啟動JavaScript控制臺
  • 掌握建立一個私有區塊鏈的步驟
  • 掌握如何在私有區塊鏈上挖礦

1. 以太坊(Ethereum)開發環境搭建

在玩以太坊之前,首先要搭建以太坊的開發環境。第一步就是安裝geth。那麽geth是什麽呢?geth(或稱為go-ethereum)是以太坊節點的一個實現。也就是說,geth是一個客戶端,用於連接以太坊網絡。從geth的名 字可以看出,geth是用go語言實現的一個以太坊節點。那麽為什麽需要這個節點呢?

這是因為以太坊網絡由多個節點組成,這些節點可能是用不同技術實現的。如geth就是官方的以太坊節點。通過這些節點可以用命令行方式直接訪問區塊鏈網絡,如廣播交易,發布智能合約等,但對於大多數用戶來說,都是非程序員出身,讓他們通過命令行方式去操作以太坊網絡是不可能的,所以就要求有圖形化的操作界面來操作以太坊網絡。但geth這樣的節點是做不到的,因此,就需要像web3.js,web3.py這樣的程序庫,再配合JavaScript、Python實現可視化的以太坊客戶端,但這些庫是無法直接連接進以太坊網絡的,他們只能連接像geth這樣的以太坊節點,然後通過一塔發節點訪問以太坊網絡,所以geth其實同時起到客戶端和服務端的作用。也就是說,geth是以太坊網絡的客戶端,是web3.js的服務端。

安裝geth也非常容易,可以直接到下面的官網下載不同平臺的geth安裝程序。

https://ethereum.github.io/go-ethereum/downloads

訪問上面的Url,會看到頁面上面顯示如下圖所示的下載按鈕。

技術分享圖片

目前geth的最新版本是1.8.3,支持Linux、Mac OS X和Windows平臺,讀者可以根據實際情況下載相應平臺的geth安裝程序,也可以直接下載源代碼(最後一個按鈕),然後編譯和安裝geth,不過這種方式只適合於專業人員,對於初學者,並不推薦使用這種方式。

(1)安裝Windows版geth

Windows版安裝程序是一個exe文件(geth-windows-amd64-1.8.3-329ac18e.exe或類似的文件名),直接雙擊安裝即可。雙擊該文件會顯示如下圖所示的安裝界面。

技術分享圖片

單擊“I Agree”按鈕會顯示如下圖所示的選擇組件界面。

技術分享圖片

建議讀者將Geth和Development tools都選上,否則在用到相關工具時還需要安裝。然後單擊“Next”按鈕進入下一個安裝界面。該界面主要用於指定geth的安裝目錄,默認安裝目錄是“C:\Program Files\Geth”,如果讀者不想將geth安裝到這個目錄,可以修改成其他目錄,如“D:\geth”效果如下圖所示。

技術分享圖片

接下來單擊“Install”按鈕開始安裝geth。安裝的過程會顯示當前安裝進度的百分比,直到最後顯示“Completed”,表示已經安裝成功,如下圖所示。最後單擊“Close”按鈕關閉安裝界面。

技術分享圖片

Windows版的geth其實就是一些exe文件,如下圖所示。其中geth.exe是本書主要使用的工具。

技術分享圖片

安裝完geth後,最好將geth.exe文件所在的目錄加到PATH環境變量中,這樣在任何目錄下就都可以使用geth.exe文件。

(2)安裝Mac OS X版geth

Mac OS X版安裝程序是一個壓縮文件(geth-darwin-amd64-1.8.3-329ac18e.tar.gz或類似的名字),將該壓縮文件解壓,會發現只有一個geth可執行文件,如下圖所示。

技術分享圖片

如果要想下載Mac OS X版的geth相關工具,可以到圖2-1所示頁面下方選擇相應的操作系統,下載Tools壓縮包或安裝程序(點擊Geth&Tools 1.8.3即可下載相應操作系統的Tools),如下圖所示。為了使用方便,可以將geth所在的路徑加到/etc/profile文件的PATH變量中,然後執行source /etc/profile命令,讓配置立即生效。這樣在任何目錄下都可以使用geth。

技術分享圖片

在Mac OS X下還可以使用brew命令安裝以太坊開發環境。

brew tap ethereum/ethereum
brew install ethereum

讀者可以選擇自己喜歡的方式在Mac OS X下安裝以太坊開發環境。

(3)安裝Linux版geth

Linux版的geth與Mac OS X版的geth差不多,安裝程序同樣是一個壓縮文件(geth-linux-amd64-1.8.3-329ac18e.tar.gz或類似的文件名),將該壓縮文件復制到Linux的某個目錄,然後在Console中進入該目錄,執行如下的命令對該文件解壓。

tar zxvf geth-linux-amd64-1.8.3-329ac18e.tar.gz

解壓後,仍然只有一個geth可執行文件,這個可執行文件是靜態編譯的,在任何Linux發行版上都可以獨立執行。

在Linux下安裝完geth後,最好將geth文件所在的路徑添加到PATH變量中,設置的方法與Mac OS X類似。

2. 使用geth命令創建以太坊賬戶

安裝完geth,需要測試一下,可以在控制臺輸入geth version命令(用於查看geth的版本信息),如果輸出類似下圖所示的信息,表示geth已經安裝成功。

技術分享圖片

在Windows下執行geth version命令,也會得到與圖2-9類似的版本信息,只是部分信息稍有差異,如下圖所示。

技術分享圖片

使用geth的第一步就是創建賬戶。以太坊的賬戶用40位十六進制的地址表示,如下面的十六進制數就是一個標準的以太坊賬戶地址(前面的0x表示十六進制)。

0x24924f33a9c49d312a8d885ade76ece76b315982

第一次使用geth時,geth中沒有任何賬戶,所以首先需要使用geth命令創建以太坊賬戶。在創建以太坊賬戶之前,可以使用下面的命令查看以太坊當前的賬戶。

geth account list

執行上面的命令,會顯示如下圖所示的信息,很明顯,沒有任何賬戶。

技術分享圖片

現在使用geth account new命令創建以太坊賬戶,在創建的過程中要求輸入賬戶的密碼。如果最後輸出了一個以太坊地址,就說明賬戶創建成功了,如下圖所示。該地址就是以太坊賬戶。

技術分享圖片

可以使用同樣的方法多創建幾個以太坊賬戶。然後使用geth account list命令查看以太坊當前的賬戶,會得到如下圖所示的查詢結果。根據查詢結果顯示,以太坊當前有3個賬戶。

技術分享圖片

3. 刪除以太坊賬戶

geth並沒有直接提供刪除以太坊賬戶的命令,不過可以通過刪除賬戶本地文件的方式刪除以太坊賬戶(因為每一個以太坊賬戶對應一個文件)。根據上圖所示的以太坊賬戶信息,可以得知賬戶文件的存儲路徑如下:

/Users/lining/Library/Ethereum/keystore

進入該目錄,會看到如下圖所示的3個文件,分別對應上一節建立的3個以太坊賬戶。如果要刪除某個以太坊賬戶,只需要刪除對應的文件即可,然後再次執行geth account
list命令,會發現與文件對應的以太坊賬戶消失了。

技術分享圖片

在Windows中的操作與Mac OS X相同,只是保存賬戶文件的路徑不同。在Windows下使用同樣的方式創建3個以太坊賬戶,然後使用geth account list命令列出所有的賬戶,如下圖所示。

技術分享圖片

從上圖所示的賬戶信息可知,保存賬戶文件的路徑如下:

C:\Users\androidguy\AppData\Roaming\Ethereum\keystore

其中androidguy是Windows用戶名,請將其改成自己機器的用戶名。

4. geth JavaScript控制臺

geth可以通過JavaScript控制臺和JavaScript代碼訪問以太坊網絡。只需要執行geth console命令,就可以啟動JavaScript控制臺,在該控制臺可以直接輸入JavaScript代碼,按Enter鍵會執行輸入的JavaScript代碼,不過有一個問題,就是geth命令同時也負責同步區塊,以及其他工作,這樣會產生大量的日誌信息,這些日誌信息會與JavaScript代碼交替出現,非常煩人。效果如下圖所示。

技術分享圖片

為了不讓日誌信息在JavaScript控制臺輸出,可以使用下面的命令啟動JavaScript控制臺,其中2表示日誌管道,也就是將日誌信息直接輸出到geth.log文件。

geth console 2>>geth.log

執行上面的命令,會進入JavaScript控制臺,在控制臺中,除了輸入的JavaScript代碼和執行結果外,什麽都不會輸出,效果如下圖所示。

技術分享圖片

在Windows下使用同樣的操作會得到與Mac OS X下完全一樣的效果,如下圖所示。

技術分享圖片

JavaScript控制臺並不是簡簡單單用來執行JavaScript代碼的,其實這個控制臺可以通過web3.js API直接訪問以太坊網絡。web3.js就是一套API,支持Web和Node.js。可能很多讀者看到這些估計有些懵,一下拋出這麽多概念,又是web3.js,又是Node.js。這些技術會在本書後面詳細介紹,本節只要知道在JavaScript控制臺可以使用JavaScript代碼訪問以太坊網絡就可以了。如果使用geth console命令進入JavaScript控制臺,並不需要單獨安裝web3.js,直接就可以使用web3.js的API。

在JavaScript控制臺中內置了很多JavaScript對象,其中web3就是其中最重要的對象。當啟動JavaScript控制臺後,這些對象會自動創建,可以直接使用。例如,可以直接在JavaScript控制臺中執行下面的JavaScript代碼。

str = web3.fromAscii(‘ethereum‘)   //  將‘ethereum‘按ASCII轉換為十六進制數
web3.toDecimal(‘0xa‘)           //  將十六進制數(0xa)轉換為十進制數
//  判斷地址是否有效
isAddress = web3.isAddress("0x8888f1f195afa192cfee860698584c030f4c9db1");

這些命令執行的效果如下圖所示。在Windows中的JavaScript控制臺也會得到完全相同的效果。

技術分享圖片

使用web3.js API的方式有很多,除了在JavaScript控制臺中使用web3.js API外,至少還可以在下面的環境中使用web3.js。

• 瀏覽器

• Node.js

• IPython

• Jupyter Notebook

5. 建立私有區塊鏈與挖礦

本節會利用geth命令創建一個私有區塊鏈,然後自己挖礦,可以通過這個操作過程更深入理解以太坊和區塊鏈的概念。

創建私有區塊鏈的步驟如下:

(1)建立創世塊

區塊鏈是由若幹個區塊組成的。在私有鏈啟動後,需要為區塊鏈創建第一個區塊(創世塊),相當於數據結構中鏈表的頭節點。不過以太坊並不知道如何創建這個創世塊,需要我們告訴以太坊如何創建,因此,首先需要建立一個創世塊的描述文件,這個描述文件是JSON格式的,本例起名為block.json,代碼如下:

block.json文件

文件位置:src/chapter2/block.json


{
    "config":
    {
        "chainId":15,
        "homesteadBlock":0
    },
    "difficulty":"20",
    "gasLimit":"2100000",
    "alloc":{
        "7df9a875a174b3bc565e6424a0050ebc1b2d1d82":{"balance":"300000"},
        "f41c74c9ae680c1aa78f42e5647a62f353b7bdde":{"balance":"400000"}
    }
}

一個完整的區塊描述文件非常復雜,本例只對區塊進行了一些基本設置,這些設置項的描述如下:

• chainId:指定了獨立的區塊鏈網絡 ID。網絡 ID
在連接到其他節點的時候會用到,以太坊公網的網絡 ID 是 1,為了不與公有鏈網絡沖突,運行私有鏈節點的時候要指定自己的網絡 ID。不同 ID 網絡的節點無法相互連接。

• homesteadBlock:以太坊推出的第2個主要的區塊發行版本,Frontier是第1個推出的區塊發行版本(也是測試版本)。建議使用homesteadBlock,這裏的0表示有效。

• difficulty:挖礦的難易程度,該值越小,挖礦越容易。也就是說,該值越小,挖礦需要的算力越小,在測試時,建議設置一個比較小的值,否則挖礦會需要很長時間。

• gasLimit:挖每個區塊需要消耗資源的上限,gas與以太幣(ether)一樣,都是以太坊中的單位。之所以將gas與ether分開,是為了防止ether的波動對挖每個區塊消耗資源的影響。

• alloc:為了測試挖礦,臨時分配的賬戶,其中balance表示當前賬戶的余額,單位是Wei。

(2)初始化區塊鏈

這一步需要使用如下的命令對區塊鏈進行初始化。

geth init block.json --datadir test

其中test表示與區塊鏈相關數據保存的目錄,本例test與block.json文件在同一個目錄下。執行上面的命令後,會在當前block.json文件所在的目錄生成一個test子目錄。test子目錄的結構如下圖所示。

技術分享圖片

很明顯,在test目錄下面還有兩個子目錄:geth和keystore。其中geth目錄保存了同步區塊鏈以及相關的數據,keystore目錄保存了賬戶文件。由於私有鏈剛創建,還沒有創建賬戶,所以keystore目錄為空。
如果在Windows下執行前面初始化區塊鏈的命令,會得到與Mac OS X下完全一樣的結果。讀者可以自己在Windows做實驗。

(3)啟動以太坊客戶端(geth)

在這一步使用下面的命令啟動以太坊客戶端(進入JavaScript控制臺)。其中datadir命令行參數表示geth會使用test目錄保存相關文件。

geth --datadir test console

(4) 將賬戶與礦工綁定

負責挖礦的賬戶稱為礦工。miner是JavaScript控制臺中內置的礦工對象,在Java可以使用下面的命令將block.json文件中的兩個地址中的一個與miner對象綁定。

miner.setEtherbase("0x7df9a875a174b3bc565e6424a0050ebc1b2d1d82")

(5)開始挖礦

在開始挖礦之前,可以使用下面的命令查一下兩個臨時賬號的余額。

eth.getBalance("0x7df9a875a174b3bc565e6424a0050ebc1b2d1d82")
eth.getBalance("0xf41c74c9ae680c1aa78f42e5647a62f353b7bdde")

查詢結果分別是300000和400000。現在礦工(miner)已經和余額為300000的賬戶綁定,接下來在JavaScript控制臺執行如下的代碼開始挖礦。

miner.start()

執行這行代碼後,就會開始挖礦,如果要停止挖礦,需要在JavaScript控制臺執行如下的代碼。

miner.stop()

停止挖礦後,可以執行下面的代碼查詢當前區塊鏈中的區塊數,其中eth是JavaScript控制臺內建的對象。在本例中一共挖了36個區塊,也就是目前在網絡中有一條由36個區塊組成的區塊鏈。

eth.blockNumber

再次使用下面的代碼查詢兩個臨時賬戶的余額。

eth.getBalance("0x7df9a875a174b3bc565e6424a0050ebc1b2d1d82")
eth.getBalance("0xf41c74c9ae680c1aa78f42e5647a62f353b7bdde")

我們會發現與礦工(miner)綁定的賬戶的余額變多了,多出的余額就是挖礦的獎勵(以太幣),如下圖所示。

技術分享圖片

在Windows下執行同樣的命令會獲得相同的結果(挖了30個區塊),如下圖所示。

技術分享圖片

(6)控制挖礦數量

有時需要控制挖礦數量,也就是說,挖到指定數量的區塊後自動終止挖礦,要達到這個目的,需要在JavaScript控制臺執行下面的命令。

miner.start(3);
admin.sleepBlocks(10);
miner.stop();

其中start方法的參數表示挖礦使用的線程,默認值是CPU內核的數量,如CPU是雙核的,那麽線程數就是2。sleepBlocks方法的參數表示要挖的區塊數,本例是10個區塊。如果還沒有挖完10個區塊,那麽sleepBlocks方法會處於阻塞狀態,直到挖完10個區塊,會繼續執行下面的代碼,也就是miner.stop(),這時挖礦就會結束。

第一行代碼:以太坊(1)-創建自己的私有區塊鏈