本篇文章簡單介紹使用go-ethereum鏈接以太坊的主網和測試網以及一些基礎開發須知,着重介紹如何搭建一個私網的以太坊,至於以太坊應用開發,有機會的話,將在後面的文章中重點介紹。node
本篇文章中包含筆者花費大量心血理解並整理的配置和參數說明資料,望能夠爲諸位道友提供一些幫助。git
Go Ethereum能夠安裝的操做系統平臺有Mac OS X,Windows以及Linux/Unix。詳情請看Installation Instructions。github
這裏介紹在Linux上,從go-ethereum源碼構建的安裝流程。官方提到的Linux/Unix平臺包括Ubuntu,Arch和FreeBSD。這裏以Ubuntu爲例。golang
編譯環境要求有 Go 和 C編譯程序。安裝方法以下: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
wget https://github.com/ethereum/go-ethereum/archive/v1.8.7.tar.gz
複製代碼
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命令,主要的Ethereum CLI客戶端,是Ethereum網(main-, test- 或 private網)的入口,有能力做爲一個full node(默認)存檔節點(保留全部歷史數據)或者一個light node(現場檢索數據)節點運行。經由暴露在HTTP, WebSocket 或 IPC傳輸的頂部的JSON RPC端點,它能夠被其餘過程用做Ethereum網的網關。
提示:查看 geth 全部命令行選項使用 geth --help 或者查看 CLI Wiki page。
目前爲止,大多數狀況是人們想要簡單地與Ethereum網進行交互:建立帳戶;轉移資金;部署並與合約交互。對於這種特殊的使用狀況,用戶不關心之前的歷史數據,因此咱們能快速的同步當前的Ethereum網狀態。執行命令:
geth console
複製代碼
命令做用:
向開發者過渡,若是你想要創造合約,你幾乎確定想要在沒有任何真實資金的狀況下作到這一點,直到你掌握整個系統。換句話說,代替鏈接到Ethereum main網,你會想要加入到一個 test網,它是和 main網徹底等價的,只須要:
geth --testnet console
複製代碼
console子命令與上面的含義徹底相同而且它們在一個測試網上也一樣有用。若是你跳到這一步,請看上面對它們的解釋。
然而,指定 --testnet 將從新配置你的 Geth 實例一小部分:
注意:儘管有一些內部安全措施防止main網和test網的交易互換,你也應該確認老是爲測試資產和真實資產使用分開的帳戶。除非你手動移動帳戶,Geth將默認正確分開兩個網絡,而且在它們之間將不會有任何帳戶可用。
上述測試網絡是基於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,你能夠在你的機器上快速啓動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和Ethereum網交互。爲此,Geth已經內置支持一個基於APIs(standard APIs 和 Geth 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選項值(請自行查看選項含義):
在開始以前,筆者先介紹一下如何建立以太坊帳戶:
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節點,其餘節點可使用它在你的網絡或因特網中找到彼此。乾淨的方式是配置並運行一個獨立的bootnode:
bootnode -genkey 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 去處理交易併爲你創造新塊。
公共Ethereum網的mining是一個複雜的任務,由於它惟一可行的是使用GPUs,要求一個OpenCL 或 CUDA激活 ethminer 實例。更多信息請查閱 EtherMining subreddit和 Genoil 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實例:
miner.start(4)
複製代碼
miner.stop()
複製代碼
更多Mining相關信息,請參看Mining
至此,私網以太坊搭建完成,感謝閱讀!
原創不易,與君共勉!