使用Geth 構建以太坊區塊鏈並模擬挖礦過程


使用Geth 構建以太坊區塊鏈並模擬挖礦過程

Go-ethereum 是以太坊官方的一個Golang 實現,我們可以使用Geth 工具來創建創世區塊並啟動區塊鏈,使用Clef 實現以太坊錢包的功能,以及使用evm、puppeth 用來以太坊開發。本次我們使用Geth,在兩台Host 上,創建一條以太坊區塊鏈和兩個賬戶,並進行區塊鏈的一些基本操作。

我的網絡環境中,Host1 的IP 地址為192.168.0.100,Host2 的IP 地址為192.168.0.180

本文絕大多數參考資料來源於Geth Documentation,在官方的文檔里可以找到諸如Geth 安裝使用、如何產生私有區塊鏈、JSON-RPC APIs 的使用方法等,

1. 獲得 Geth

Geth 在各個平台都可用,直接從https://geth.ethereum.org/docs/install-and-build/installing-geth 獲取即可

在Windows 上,安裝Geth,我們會獲得幾個可執行程序:

    Directory: C:\Users\sun\Desktop\geth

Mode                 LastWriteTime         Length Name
----                 -------------         ------ ----
-a---          2020/12/11    16:17       50280980 abigen.exe
-a---          2020/12/11    16:17       48783481 bootnode.exe
-a---          2020/12/11    16:17       63922102 clef.exe
-a---          2020/12/11    16:18       49921889 evm.exe
-a---          2020/12/11    16:18       67456679 geth.exe
-a---          2020/12/11    16:18       26165842 puppeth.exe
-a---          2020/12/11    16:18        2512896 rlpdump.exe

其中Geth 理論上已經被寫進Path,在任何位置打開shell 都可用。

2. 准備

新建一個privatechain1文件夾,用來保存我們第一個區塊鏈。geth需要一個創世配置文件genisis.json,來創建區塊鏈,例如:

{
  "config": {
    "chainId": 10086,
    "homesteadBlock": 0,
    "eip150Block": 0,
    "eip155Block": 0,
    "eip158Block": 0,
    "byzantiumBlock": 0,
    "constantinopleBlock": 0,
    "petersburgBlock": 0,
    "ethash": {}
  },
  "difficulty": "1",
  "gasLimit": "80000",
  "alloc": {}
}

此處我們定義chainID 為10086,使用PoW 共識機制,挖礦難度為1,沒有初始資產

有關genesis.json 的詳細格式可以參考:創世區塊配置文件genesis.json的格式解讀

3. 啟動

創建好genesis.json后,就可以根據該配置創建區塊鏈:

geth init --datadir . genesis.json 

--datadir參數指定區塊鏈相關文件的放置目錄

image-20210126005956163

隨后啟動區塊鏈:

geth --networkid 191 --nodiscover --http --http.addr "0.0.0.0" --http.port 8545 --http.api personal,eth,net,web3 --allow-insecure-unlock --datadir . console

啟動參數較多,分別為:

--networkid 網絡ID。只有當NetworkID,ChainID,創世區塊全部相同時,才是同一條區塊鏈

--nodiscover 由於本次為實驗環境,而且只有兩台Host,我們可以關閉自動發現,手動添加Peers

--http 該區塊鏈使用http協議。除了http,還可以使用websocket

--http.addr 監聽地址,由於之后要在兩台Host上傳輸數據,因此此處為0.0.0.0

--http.port 默認端口為8545

--http.api 可以允許使用http進行的一些操作,后續會詳解

--allow-insecure-unlock 由於在本地做測試,為了方便不會配置https證書,加上這個參數可以在非HTTPS的環境下解鎖賬戶

--datadir 指定區塊鏈數據所在的目錄

console 打開控制台

有關詳細的Geth 啟動參數,可以參閱Geth Command-line Options

啟動成功后,會打開一個web3控制台,類似這樣:

image-20210126010045961

在Host2上重復上述操作,啟動相同的區塊鏈。

4. 操作

4.1 新用戶

此時geth的任務已完成,我們開始使用 JSON RPC APIs 進行操作。

> eth.accounts
[]

可以看到目前還沒有任何賬戶,新建一個賬戶:

輸入personal.newAccount(),然后輸入兩次密碼即可

image-20210126011045656

可以看到我們的新賬戶地址為:0xf1d65f66658a3dfa86b689ce084fd3234fc3b691,並且在keystore目錄下生成了一個文件。

再次查看eth.accounts,剛剛創建的新用戶已出現:

> eth.accounts
["0xf1d65f66658a3dfa86b689ce084fd3234fc3b691"]

在Host2上重復上述操作,創建另一個新用戶:

==============================================
               Shell on Host2
==============================================

> eth.accounts
["0xf228360fbf872e4aca7f930a60b18c6f1f6ca19e"]

4.2 添加Peers

盡管兩台Host現在運行同一條區塊鏈,但由於我們預先關閉了peers自動發現,因此目前並沒有Peers。在Host1上查看:

> admin.peers
[]

要添加在Host1上添加Host2,我們需要得到Host2的網絡地址。在Host2的控制台中向上翻,找到區塊鏈啟動時,出現的一個Strated P2P networking 信息:

INFO [01-26|01:02:40.182] Started P2P networking                   self="enode://c81e35213c6fd2824dafdd174b24aa0bb36e7ce935819d2ecf22a19a53aea5e760caf32e20bf3818ab129eb89efaa33ed841a542cd7ea973b60e2b95ef3953c5@127.0.0.1:30303?discport=0"

其中self的值就是Host2的網絡地址,注意應該將127.0.0.1改為192.168.0.180

enode://c81e35213c6fd2824dafdd174b24aa0bb36e7ce935819d2ecf22a19a53aea5e760caf32e20bf3818ab129eb89efaa33ed841a542cd7ea973b60e2b95ef3953c5@192.168.0.180:30303?discport=0

回到Host1,執行以下操作:

admin.addPeer("enode://c81e35213c6fd2824dafdd174b24aa0bb36e7ce935819d2ecf22a19a53aea5e760caf32e20bf3818ab129eb89efaa33ed841a542cd7ea973b60e2b95ef3953c5@192.168.0.180:30303?discport=0")

一段時間后,發現peercount=1,再次查看peers

image-20210126012808444

如果此步遲遲不能發現新Peer,可以嘗試在Host2上添加Host1

4.3 挖礦

在以太坊中,每挖出一個新區塊,礦工將會獲得一定的獎勵。獎勵將會流入coinbase賬戶中。如果genesis.json沒有指定默認的coinbase賬戶,則會流入eth.accounts[0]中。下面我們開始模擬挖礦過程。

要使用某一個賬戶進行挖礦、交易等操作,首先需要解鎖賬戶,方便起見,給Host1上的第一個賬戶地址設一個變量sender:

> sender = eth.accounts[0]
"0xf1d65f66658a3dfa86b689ce084fd3234fc3b691"
> personal.unlockAccount(sender)
Unlock account 0xf1d65f66658a3dfa86b689ce084fd3234fc3b691
Passphrase: 
true

然后開始挖礦:

miner.start(1)

其中參數1指進程數,可按Host性能設置。由於我們在genesis.json中將difficulty設置得很小,理論上不會消耗很多時間。挖礦開始后,不斷提示Generating DAG in progress,當percentage到達100%時,會看到挖掘出新區塊。

image-20210126123306584

Host1會將挖到的區塊作為交易銷售出去,在區塊鏈上留下交易痕跡

來到Host2,會發現Host1提交的新區塊被同步

image-20210126123348629

適時停止挖礦:

miner.stop()

在Host1上查看賬戶sender的賬戶余額:

> miner.stop()
null
> eth.getBalance(sender)
34000000000000000000

查看目前區塊鏈上挖出區塊數量,在Host1和Host2上理論上應該出現相同的結果:

> eth.blockNumber
17

這個數字和之前顯示的INFO最后一個挖出的區塊number對應:

INFO [01-26|12:34:00.697] 🔨 mined potential block                  number=17 hash="5ac61c…ee83ca"

4.4 轉賬

Host1上的第一個賬戶0xf1d65f66658a3dfa86b689ce084fd3234fc3b691,變量名為sender

Host2上的第一個賬戶0xf228360fbf872e4aca7f930a60b18c6f1f6ca19e,設置新的變量名為receiver

> receiver = "0xf228360fbf872e4aca7f930a60b18c6f1f6ca19e"

設置轉賬的amount,轉出1個ETH,在以太坊上進行交易,需要將ETH 單位轉為Wei 單位:

> amount = web3.toWei(1, "ether")

執行sendTransaction 操作:

> eth.sendTransaction({from: sender, to: receiver, value: amount})

如果出現Error: authentication needed: password or unlock,可能時時間過長,sender 賬戶又被加鎖,重新解鎖即可。

image-20210126135810955

sendTransaction 執行之后,Host2 中的receiver 賬戶並不會立刻受到1ETH(即1000000000000000000Wei),之前提到過,要在區塊鏈中留下數據,必須通過挖礦產生新區塊,提交到區塊鏈中。因此要使轉賬生效,我們需要開始挖礦,將交易數據打包到新區塊中。

在此之前,先來看一下等待隊列中的交易,輸入eth.pendingTransactions

image-20210126140340739

其中包含兩個新參數gas 和gasPrice,是需要付給確認這筆交易的礦工的工資。

開始挖礦:

> miner.start(1)

挖到第一個區塊就可以停止挖礦了:

> miner.stop()

在Host1 上挖到了新區塊:

INFO [01-26|13:59:12.443] 🔨 mined potential block                  number=18 hash="675837…edf7ca"
INFO [01-26|13:59:13.060] Successfully sealed new block            number=19 sealhash="58e4be…89b373" hash="15d1f0…7ca475" elapsed=638.999ms
INFO [01-26|13:59:13.060] 🔗 block reached canonical chain          number=12 hash="7c0bcf…76cec9"
INFO [01-26|13:59:13.088] Commit new mining work                   number=20 sealhash="18f1a8…de77c4" uncles=0 txs=0 gas=0     fees=0       elapsed=28.006ms

在Host2 上找到這個已經同步來的區塊:

INFO [01-26|13:59:13.690] Imported new chain segment               blocks=1 txs=1 mgas=0.021 elapsed=7.991ms  mgasps=2.628 number=18 hash="675837…edf7ca" dirty=4.72KiB

此時在Host2 上查看receiver 的余額:

> receiver = "0xf228360fbf872e4aca7f930a60b18c6f1f6ca19e"
> eth.getBalance(receiver)
1000000000000000000

在Host1 上查看sender 余額:

> eth.getBalance(sender)
43000000000000000000

5. 總結

該篇章中我們使用Geth 生成了一條區塊鏈,並在兩個Host 上,用兩個用戶完成了挖礦和轉賬操作。下一篇章我們會着重理解以太坊的工作方式,入門智能合約。

作為以太坊初學者,本文很可能有概念理解上的錯誤,歡迎各位批評指正。

📖其他參考資料:

區塊鏈入門(3):在以太坊私有網絡中建立節點集群,並發生交易 - 88911562 - 博客園 (cnblogs.com)

私有鏈挖礦的時候,這個generating DAG好慢 有什么方法加快這個速度-鏈客區塊鏈技術開發者社區 (liankexing.com)

以太坊基本概念與實驗環境搭建 · float's blog (gitee.io)


免責聲明!

本站轉載的文章為個人學習借鑒使用,本站對版權不負任何法律責任。如果侵犯了您的隱私權益,請聯系本站郵箱yoyou2525@163.com刪除。



 
粵ICP備18138465號   © 2018-2025 CODEPRJ.COM