go-ethereum學習筆記(一)


前言

本篇文章簡單介紹使用go-ethereum鏈接以太坊的主網和測試網以及一些基礎開發須知,着重介紹如何搭建一個私網的以太坊,至於以太坊應用開發,有機會的話,將在後面的文章中重點介紹。node

本篇文章中包含筆者花費大量心血理解並整理的配置和參數說明資料,望能夠爲諸位道友提供一些幫助。git

安裝

Go Ethereum能夠安裝的操做系統平臺有Mac OS X,Windows以及Linux/Unix。詳情請看Installation Instructionsgithub

這裏介紹在Linux上,從go-ethereum源碼構建的安裝流程。官方提到的Linux/Unix平臺包括Ubuntu,Arch和FreeBSD。這裏以Ubuntu爲例。golang

編譯環境準備

編譯環境要求有 GoC編譯程序。安裝方法以下:web

apt-get install -y build-essential golang
複製代碼

獲取源碼並編譯

獲取源碼

切換到你準備編譯go-ethereum源碼的目錄,執行命令:算法

git clone https://github.com/ethereum/go-ethereum
複製代碼

上述命令會clone go-ethereum的主幹分支代碼,該分支代碼是持續開發代碼,若是想要使用發佈代碼,參見go-ethereum release。這裏以當時最新的發佈代碼 v1.8.7 爲例:docker

  1. 下載代碼
wget https://github.com/ethereum/go-ethereum/archive/v1.8.7.tar.gz
複製代碼
  1. 解壓
tar zxvf v1.8.7.tar.gz
複製代碼

將解壓後的代碼移動到你準備編譯go-ethereum源碼的目錄。編程

編譯源碼

當你準備好go-ethereum的源碼後,進入go-ethereum源碼工程頂級目錄,執行命令:json

make geth
複製代碼

(推薦)若是你想要編譯出全部工具,執行:bootstrap

make all
複製代碼

編譯完成後,全部工具能夠在 build/bin 目錄下找到,將這些二進制文件取出來放到你選好的安裝目錄,或者就在原來的位置放着,這裏我放到 /opt/xingweidong/eth/bin 目錄下,接下來根據你的喜愛設置系統環境變量,添加以下內容:

export ETH_HOME=/opt/xingweidong/eth
export PATH=$PATH:$ETH_HOME/bin
複製代碼

別忘了使用 source /etc/profile 或者其餘你喜歡的方法更新你的環境變量信息。

運行geth

geth命令,主要的Ethereum CLI客戶端,是Ethereum網(main-, test- 或 private網)的入口,有能力做爲一個full node(默認)存檔節點(保留全部歷史數據)或者一個light node(現場檢索數據)節點運行。經由暴露在HTTP, WebSocket 或 IPC傳輸的頂部的JSON RPC端點,它能夠被其餘過程用做Ethereum網的網關。

提示:查看 geth 全部命令行選項使用 geth --help 或者查看 CLI Wiki page

Ethereum main網的full node

目前爲止,大多數狀況是人們想要簡單地與Ethereum網進行交互:建立帳戶;轉移資金;部署並與合約交互。對於這種特殊的使用狀況,用戶不關心之前的歷史數據,因此咱們能快速的同步當前的Ethereum網狀態。執行命令:

geth console
複製代碼

命令做用:

  • 開始 geth 進入快速同步模式(默認模式,可使用 --syncmode 選項改變同步模式),因爲它爲了不處理整個Ethereum網的歷史數據,會下載大量的事務數據,因此會佔用大量CPU資源。
  • 啓動 Geth 內在的交互式 JavaScript console,(經由 console 子命令)經過這個,你能調用全部官方 web3 methods 以及Geth本身的 management APIs。這個也是可選的,若是你離開,你能使用 geth attach 鏈接一個已經存在的 Geth 實例。

Ethereum test網的full node

向開發者過渡,若是你想要創造合約,你幾乎確定想要在沒有任何真實資金的狀況下作到這一點,直到你掌握整個系統。換句話說,代替鏈接到Ethereum main網,你會想要加入到一個 test網,它是和 main網徹底等價的,只須要:

geth --testnet console
複製代碼

console子命令與上面的含義徹底相同而且它們在一個測試網上也一樣有用。若是你跳到這一步,請看上面對它們的解釋。

然而,指定 --testnet 將從新配置你的 Geth 實例一小部分:

  • 代替使用默認數據目錄(例如Linux上的 ~/.ethereum),Geth將會深刻一層目錄建立 testnet 子文件夾(在Linux上是 ~/.ethereum/testnet)。注意,在OSX和Linux上,這也意味着鏈接一個運行的testnet節點要求使用一個自定義的端點,由於 geth attach 默認將鏈接一個生產節點。例如:geth attach /testnet/geth.ipc。Windows用戶不受影響。
  • 代替鏈接 Ethereum main網,客戶端將鏈接到一個 test網,使用不一樣的P2P bootnodes,不一樣的網絡ID和創世狀態。

注意:儘管有一些內部安全措施防止main網和test網的交易互換,你也應該確認老是爲測試資產和真實資產使用分開的帳戶。除非你手動移動帳戶,Geth將默認正確分開兩個網絡,而且在它們之間將不會有任何帳戶可用。

Rinkeby test網的full node

上述測試網絡是基於ethash工做證實共識算法的跨客戶端網絡。所以,因爲網絡的低難度/安全性,它有必定的額外開銷,而且更容易受到重組攻擊。Go Ethereum還支持鏈接到稱爲Rinkeby的權威證實測試網絡(由社區成員運營)。這個網絡更輕,更安全,但只受到go-ethereum的支持。

geth --rinkeby console
複製代碼

配置

代替傳遞大量選項給 geth 二進制,你能傳遞一個配置文件經由:

geth --config /path/to/your_config.toml
複製代碼

爲了理解這個文件的寫法,你能使用 dumpconfig 子命令export你的現有配置:

geth --your-favourite-flags dumpconfig
eg:geth --testnet dumpconfig
複製代碼

注意:這個只在 geth v1.6.0以及以上版本有效。

Docker quick start

經過使用Docker,你能夠在你的機器上快速啓動Ethereum並運行:

docker run -d --name ethereum-node -v /Users/alice/ethereum:/root \
           -p 8545:8545 -p 30303:30303 \
           ethereum/client-go
複製代碼

上述命令將以快速同步模式啓動geth,並具備1GB的DB內存容量。它也將在你的home目錄下建立一個永久捲來儲存你的區塊鏈和映射的默認端口。還有一個 alpine 標籤可用於image的精簡版本。

若是你想要從其餘容器或主機訪問RPC,不要忘了 --rpcaddr 0.0.0.0。默認狀況下,geth 綁定本地接口而且不可從外訪問RPC端點。

可編程接口 Geth nodes

做爲一個開發者,你將想要及早開始經由你本身的程序而不是手動控制檯與Geth和Ethereum網交互。爲此,Geth已經內置支持一個基於APIs(standard APIsGeth specific APIs)的JSON-RPC。它可以經由HTTP, WebSockets 和 IPC (unix sockets on unix based platforms, and named pipes on Windows)暴露。

IPC接口默認是激活的並暴露全部Geth支持的APIs,然而HTTP 和 WS接口須要手動激活而且因爲安全緣由只能暴露一個APIs子集。這些能夠根據你的須要打開或關閉並被配置。

詳情請看 Programatically interfacing Geth nodes

操做一個私網

維護你本身的私網是十分複雜的,由於在一個正規的網絡中,大量配置的獲取和受權須要手動設置。下面,咱們創建一個簡單的私網以太坊。

說明:爲了使下面建立私網以太坊的步驟更加直白,筆者將默認使用如下的geth選項值(請自行查看選項含義):

  • --datadir /root/privatenet/.ethereum
  • --config config/privatenet.toml

在開始以前,筆者先介紹一下如何建立以太坊帳戶:

  • 建立主網以太坊帳戶,執行命令:
geth account new
複製代碼
  • 建立私網以太坊帳戶,執行命令:
geth --datadir /root/privatenet/.ethereum account new
複製代碼

按照提示輸入帳戶密碼便可。

注意:建立私網以太坊帳戶時,務必指定 --datadir 選項,不然會默認建立主網以太坊帳戶。

定義一個私有的創世狀態

首先,你須要創造你的網絡的全部節點須要意識到並贊成的創世狀態。這個由一個小JSON文件組成(例如,稱它爲 genesis.json):

{
  "config": {
        "chainId": 15,
        "homesteadBlock": 0,
        "eip155Block": 0,
        "eip158Block": 0
    },
  "alloc"      : {},
  "coinbase"   : "0x0000000000000000000000000000000000000000",
  "difficulty" : "0x20000",
  "extraData"  : "",
  "gasLimit"   : "0x2fefd8",
  "nonce"      : "0x0000000000001993",
  "mixhash"    : "0x0000000000000000000000000000000000000000000000000000000000000000",
  "parentHash" : "0x0000000000000000000000000000000000000000000000000000000000000000",
  "timestamp"  : "0x00"
}
複製代碼

參數說明(下表是筆者參考go-ethereum源碼README和ethereum_yellow_paper整理所得,若有錯誤,請幫忙指正):

參數 描述
alloc 能夠預置帳號以及帳號的以太幣數量
coinbase 區塊受益者地址,能夠設置成已存在的帳戶。後面挖出的區塊的受益者將是挖掘出那個區塊的帳戶(礦工)
difficulty 表明當前區塊的難度等級(十六進制),這裏定義創世區塊的難度等級,難度等級越高,挖礦越難。後面生成的區塊難度等級根據前一個區塊的難度等級和時間戳計算獲得
extraData 一個包含這個區塊相關數據的字節數組,任意填寫。必須是32位之內
gasLimit 執行這個事務應該被使用的gas的最大量。這個在任何計算被作以前是預付的,而且在以後不會增長
nonce 表明從這個地址發送的事務數目,或者在關聯代碼的帳戶狀況下,這表明這個帳戶創造的合約數目。(在Yellow Paper中對nonce有多處描述,這裏選擇了4.1章節的描述,)
mixhash 一個256位的hash,由nonce合併,證實在這個區塊上已經執行足夠量的計算
parentHash 前一個(父級)區塊的header的keccak256算法hash
timestamp 這個區塊開始的Unix的time()和合理輸出

上面這些域應該能夠知足大多數需求,不過咱們建議改變 nonce 爲一些隨機值,這樣你就能阻止不知名的遠程節點訪問你。若是你想要爲了更早測試,預儲備一些帳戶,你能在 alloc 域進行帳戶配置:

"alloc": {
  "0x0000000000000000000000000000000000000001": {"balance": "111111111"},
  "0x0000000000000000000000000000000000000002": {"balance": "222222222"}
}
複製代碼

隨着創世狀態定義在上面的JSON文件,你應該在啓動每一個節點以前,優先初始化它,以確認全部區塊鏈參數被正確設置:

geth --datadir /root/privatenet/.ethereum init genesis.json
複製代碼

啓動bootstrap

當全部你想要運行的節點初始化到指望的創世狀態,你將須要開始一個bootstrap節點,其餘節點可使用它在你的網絡或因特網中找到彼此。乾淨的方式是配置並運行一個獨立的bootnode:

  1. 每一個ethereum節點,包括一個bootnode,經過一個enode標識符聯繫。這些標識符源自一個key。因而你將須要給bootnode這樣一個key。由於咱們當前沒有這樣的key,因此咱們能夠在bootnode啓動前生成一個key(並存儲它到一個文件):
bootnode -genkey bootnode.key
複製代碼
  1. 爲了bootnode每次啓動都使用相同的enode,須要在bootnode啓動時指定一個key:
bootnode -nodekey bootnode.key
複製代碼

當bootnode上線,它將展現一個 enode URL,例如:

INFO [05-09|01:47:05] UDP listener up                          self=enode://75535ebac1f5b2a644edb134dbe91c6c288353be1a5301864edae529630b35c5ff0c0ae9e07b2bcdef578c3ac1b72b2cda105c061c2c77067f1fd8ec54d852b7@[::]:30301
複製代碼

其餘節點可使用這個 enode URL 鏈接它並交換對等信息。確認用你的外部訪問IP替換展現的IP地址信息(極可能是 [::])去獲得真正的 enode URL。例如:

enode://75535ebac1f5b2a644edb134dbe91c6c288353be1a5301864edae529630b35c5ff0c0ae9e07b2bcdef578c3ac1b72b2cda105c061c2c77067f1fd8ec54d852b7@192.168.1.214:30301
複製代碼

保存這個準確的 enode URL 到你的一個文本中或者其餘什麼地方,下面須要用到。

注意:你也可使用徹底成熟的Geth節點做爲引導節點,但這是不太推薦的方式。

定義一個配置文件

爲了成員節點啓動時使用的配置一致,須要寫一個配置文件,例如 privatenet.toml(參考自 testnet 的配置, 執行命令 geth --testnet dumpconfig 可見):

# Note: this config doesn't contain the genesis block.

[Eth]
NetworkId = 3369
DatabaseCache = 768
GasPrice = 18000000000

[Eth.Ethash]
CacheDir = "ethash"
CachesInMem = 2
CachesOnDisk = 3
DatasetDir = "/root/privatenet/.ethash"
DatasetsInMem = 1
DatasetsOnDisk = 2

[Eth.TxPool]
NoLocals = false
Journal = "transactions.rlp"
Rejournal = 3600000000000
PriceLimit = 1
PriceBump = 10
AccountSlots = 16
GlobalSlots = 4096
AccountQueue = 64
GlobalQueue = 1024
Lifetime = 10800000000000

[Eth.GPO]
Blocks = 20
Percentile = 60

[Shh]
MaxMessageSize = 1048576
MinimumAcceptedPOW = 2e-01

[Node]
DataDir = "/root/privatenet/.ethereum"
IPCPath = "geth.ipc"
HTTPPort = 8545
HTTPVirtualHosts = ["localhost"]
HTTPModules = ["net", "web3", "eth", "shh"]
WSPort = 8546
WSModules = ["net", "web3", "eth", "shh"]

[Node.P2P]
MaxPeers = 25
NoDiscovery = false
BootstrapNodes = ["enode://75535ebac1f5b2a644edb134dbe91c6c288353be1a5301864edae529630b35c5ff0c0ae9e07b2bcdef578c3ac1b72b2cda105c061c2c77067f1fd8ec54d852b7@1 92.168.1.214:30301"]StaticNodes = []
TrustedNodes = []
ListenAddr = ":30303"
EnableMsgEvents = false

[Dashboard]
Host = "localhost"
Port = 8080
Refresh = 5000000000
複製代碼

配置說明(下表是筆者參考geth參數說明和go-ethereum相關配置項代碼整理所得,若有錯誤,請幫忙指正):

配置項 對應參數 說明
Eth NetworkId --networkid value Network標識符(integer類型,1=Frontier,2=Morden(disused),3=Ropsten,4=Rinkeby),默認爲1。若是創建在私網上,使用另外的任意值,好比:3369
Eth DatabaseCache null (我的理解)爲database申請的系統內存,單位爲MB,最小值和默認值是16MB
Eth GasPrice --gasprice 「18000000000」 接受挖掘事務的最低gas價格。可能指miner的報酬
Eth.Ethash CacheDir --ethash.cachedir 存儲ethash證實緩存的目錄(默認在 datadir 目錄裏)
Eth.Ethash CachesInMem --ethash.cachesinmem value 保留在內存中的最新ethash緩存的數目(每16MB)(默認:2)。
Eth.Ethash CachesOnDisk --ethash.cachesondisk value 保留在磁盤中的最新ethash緩存的數目(每16MB)(默認:3)。
Eth.Ethash DatasetDir --ethash.dagdir "/home/karalabe/.ethash" 存儲ethash挖掘DAGs的目錄(默認在home目錄裏)
Eth.Ethash DatasetsInMem --ethash.dagsinmem value 保留在內存中的最新ethash挖掘DAGs(每1+GB)(默認:1)。
Eth.Ethash DatasetsOnDisk --ethash.dagsondisk value 保留在磁盤中的最新ethash挖掘DAGs(每1+GB)(默認:2)。
Eth.TxPool NoLocals --txpool.nolocals 免除本地提交事務的費用
Eth.TxPool Journal --txpool.journal value 用於節點重啓的本地事務磁盤日誌(默認:"transactions.rlp")
Eth.TxPool Rejournal --txpool.rejournal value 從新生成本地事務日誌的時間間隔(默認:1h0m0s)
Eth.TxPool PriceLimit --txpool.pricelimit value 強制接歸入池的最小gas價格限制(默認:1)
Eth.TxPool PriceBump --txpool.pricebump value 替代一個已經存在的事務的價格碰撞百分比(默認:10)
Eth.TxPool AccountSlots --txpool.accountslots value 每一個帳戶擔保的可執行事務時隙的最小數目(默認:16)
Eth.TxPool GlobalSlots --txpool.globalslots value 全部帳戶的可執行事務時隙的最大數目(默認:4096)
Eth.TxPool AccountQueue --txpool.accountqueue value 每一個帳戶許可的非可執行事務時隙的最大數目(默認:64)
Eth.TxPool GlobalQueue --txpool.globalqueue 全部帳戶的非可執行事務時隙的最大數目(默認:1024)
Eth.TxPool Lifetime --txpool.lifetime value 非可執行事務的排隊最大時間(默認:3h0m0s)
Eth.GPO Blocks --gpoblocks value 檢查gas價格的最新區塊的數目(默認:10)
Eth.GPO Percentile --gpopercentile value 建議的gas價格是一組最新事務gas價格的百分位(默認:50)
Shh MaxMessageSize --shh.maxmessagesize value 可接受的最大信息大小(默認:1048576)
Shh MinimumAcceptedPOW --shh.pow value 可接受的最小POW(默認:0.2)
Node DataDir --datadir "/home/karalabe/.ethereum" databases和keystore的數據目錄
Node IPCPath --ipcpath datadir裏的IPC socket/pipe的文件名
Node HTTPPort --rpcport value HTTP-RPC服務監聽端口(默認:8545)
Node HTTPVirtualHosts --rpcaddr value HTTP-RPC服務監聽接口(默認:"localhost")
Node HTTPModules null 經由HTTP RPC接口暴露的API modules列表
Node WSPort --wsport value WS-RPC 服務監聽端口(默認:8546)
Node WSModules null 經由websocket RPC接口暴露的API modules列表,若是modules是空的,全部指向public的RPC API端點將會被暴露
Node.P2P MaxPeers --maxpeers value network peers的最大數目(若是設置爲0,network失效)(默認:25)
Node.P2P NoDiscovery --nodiscover 使peer發現機制無效(手動peer添加)。這裏設置爲false,以便使用這個配置文件的新節點能夠被發現
Node.P2P BootstrapNodes --bootnodes value 逗號分割的P2P discovery bootstrap enode URLs(對於 light servers,設置 v4+v5 代替)。將上面啓動bootnodes時獲取的enode URL替換IP後添加到這裏
Node.P2P BootstrapNodesV5 --bootnodesv5 value 逗號分割的P2P v5 discovery bootstrap enode URLs(light server,light nodes)
Node.P2P StaticNodes null 配置做爲static nodes的節點enode URLs列表
Node.P2P TrustedNodes null 配置做爲trusted nodes的節點enode URLs列表
Node.P2P ListenAddr --port network監聽端口(默認:30303)
Node.P2P EnableMsgEvents null 若是EnableMsgEvents被設置,服務器將發出PeerEvents,不管一個peer什麼時候發送或接收一條信息
Dashboard Host null 啓動dashboard服務的主機接口,若是這個域爲空,則沒有dashboard將被啓動
Dashboard Port null 啓動dashboard服務的TCP端口數字。默認0值是有效的,並將使用一個隨機端口數字(用於臨時節點)
Dashboard Refresh null 數據更新的刷新速率,chartEntry將被常常收集

在你的操做目錄建立config文件夾,將寫好的配置文件privatenet.toml移動到config目錄裏。

啓動你的成員節點

以太坊的成員節點,之間是徹底對等的,每一個節點均可以有多個帳戶。

啓動私網以太坊的成員節點:

geth --config config/privatenet.toml
複製代碼

鏈接到剛剛啓動的或者已經在運行的node,開始一個交互式JavaScript環境:

geth attach privatenet/.ethereum/geth.ipc
複製代碼

官方說明: 當bootnode運轉起來而且外部可達(你能嘗試 telnet 去確認它的確可達),開始隨後的Geth節點,爲了對等發現,經由 --bootnodes 選項指向bootnode。保持你的私網的數據目錄單獨將極可能是明智的選擇,因此也指定一個自定義的 --datadir 選項。

geth --datadir=path/to/custom/data/folder --bootnodes=<bootnode-enode-url-from-above>
複製代碼

注意:由於你的網絡將被從main和test網徹底切除,因此你將須要配置一個 miner 去處理交易併爲你創造新塊。

運行一個私有的miner

公共Ethereum網的mining是一個複雜的任務,由於它惟一可行的是使用GPUs,要求一個OpenCL 或 CUDA激活 ethminer 實例。更多信息請查閱 EtherMining subredditGenoil miner 倉庫。

然而在一個私網的設置,一個單一的 CPU miner實例是足夠知足實際需求的,由於它不須要沉重的資源(考慮到運行在一個單一的線程上,也不須要多個)就能在一個正確的間隔內生產一個穩定的區塊流(stable stream of blocks)。爲mining開始一個Geth實例,指定你一般使用的選項運行它,經過如下方法擴展:

geth --config config/privatenet.toml --mine --minerthreads=1 --etherbase=0x0000000000000000000000000000000000000000
複製代碼

這將開始mining區塊並在一個單一CPU線程上交易,存入全部事件到一個 --etherbase 選項指定的帳戶,若是不指定帳戶,則會默認指定當前節點上的第一個帳戶。你能進一步調節mining,經過(--targetgaslimit)改變默認gas限制區塊而且在(--gasprice)處接受價格交易。

另外,也能夠在交互式JavaScript環境中控制mining實例:

  • 開始一個4線程的mining實例:
miner.start(4)
複製代碼
  • 中止mining實例:
miner.stop()
複製代碼

更多Mining相關信息,請參看Mining

至此,私網以太坊搭建完成,感謝閱讀!


原創不易,與君共勉!

文章最新地址

相關文章
相關標籤/搜索