摘要:本文首發(fā)于深入淺出區(qū)塊鏈社區(qū)原文鏈接以太坊創(chuàng)世區(qū)塊與鏈配置載入分析,原文已更新,請讀者前往原文閱讀。以太坊允許通過創(chuàng)世配置文件來初始化創(chuàng)世區(qū)塊,也可使用選擇使用內置的多個網絡環(huán)境的創(chuàng)世配置。再準備兩個以太坊賬戶,以便在創(chuàng)世時存入資產。
本文首發(fā)于深入淺出區(qū)塊鏈社區(qū)
原文鏈接:以太坊創(chuàng)世區(qū)塊與鏈配置載入分析,原文已更新,請讀者前往原文閱讀。
創(chuàng)世區(qū)塊作為第零個區(qū)塊,其他區(qū)塊直接或間接引用到創(chuàng)世區(qū)塊。因此節(jié)點啟動之初必須載入正確的創(chuàng)世區(qū)塊信息,且不得任意修改。
以太坊允許通過創(chuàng)世配置文件來初始化創(chuàng)世區(qū)塊,也可使用選擇使用內置的多個網絡環(huán)境的創(chuàng)世配置。默認使用以太坊主網創(chuàng)世配置。
創(chuàng)世配置文件如果你需要搭建以太坊私有鏈,那么了解創(chuàng)世配置是必須的,否則你大可不關心創(chuàng)世配置。下面是一份 JSON 格式的創(chuàng)世配置示例:
{ "config": { "chainId": 1, "homesteadBlock": 1150000, "daoForkBlock": 1920000, "daoForkSupport": true, "eip150Block": 2463000, "eip150Hash": "0x2086799aeebeae135c246c65021c82b4e15a2c451340993aacfd2751886514f0", "eip155Block": 2675000, "eip158Block": 2675000, "byzantiumBlock": 4370000, "constantinopleBlock": 7280000, "petersburgBlock": 7280000, "ethash": {} }, "nonce": "0x42", "timestamp": "0x0", "extraData": "0x11bbe8db4e347b4e8c937c1c8370e4b5ed33adb3db69cbdb7a38e1e50b1b82fa", "gasLimit": "0x1388", "difficulty": "0x400000000", "mixHash": "0x0000000000000000000000000000000000000000000000000000000000000000", "coinbase": "0x0000000000000000000000000000000000000000", "number": "0x0", "gasUsed": "0x0", "parentHash": "0x0000000000000000000000000000000000000000000000000000000000000000", "alloc": { "000d836201318ec6899a67540690382780743280": { "balance": "0xad78ebc5ac6200000" }, "001762430ea9c3a26e5749afdb70da5f78ddbb8c": { "balance": "0xad78ebc5ac6200000" } } }
根據配置用途可分為三大類:
鏈配置
config項是定義鏈配置,會影響共識協(xié)議,雖然鏈配置對創(chuàng)世影響不大,但新區(qū)塊的出塊規(guī)則均依賴鏈配置。
創(chuàng)世區(qū)塊頭信息配置
nonce:隨機數,對應創(chuàng)世區(qū)塊 Nonce 字段。
timestamp:UTC時間戳,對應創(chuàng)世區(qū)塊 Time字段。
extraData:額外數據,對應創(chuàng)世區(qū)塊 Extra 字段。
gasLimit:必填,燃料上限,對應創(chuàng)世區(qū)塊 GasLimit 字段。
difficulty:必填,難度系數,對應創(chuàng)世區(qū)塊 Difficulty 字段。搭建私有鏈時,需要根據情況選擇合適的難度值,以便調整出塊。
minHash:一個哈希值,對應創(chuàng)世區(qū)塊的MixDigest字段。和 nonce 值一起證明在區(qū)塊上已經進行了足夠的計算。
coinbase:一個地址,對應創(chuàng)世區(qū)塊的Coinbase字段。
初始賬戶資產配置
alloc 項是創(chuàng)世中初始賬戶資產配置。在生成創(chuàng)世區(qū)塊時,將此數據集中的賬戶資產寫入區(qū)塊中,相當于預挖礦。這對開發(fā)測試和私有鏈非常好用,不需要挖礦就可以直接為任意多個賬戶分配資產。
自定義創(chuàng)世如果你計劃部署以太坊私有網絡或者一個獨立的測試環(huán)境,那么需要自定義創(chuàng)世,并初始化它。為了統(tǒng)一溝通,推薦先在用戶根目錄創(chuàng)建一個文件夾 deepeth,以做為《以太坊設計與實現》電子書學習工作目錄。
mkdir $HOME/deepeth && cd $HOME/deepeth
再準備兩個以太坊賬戶,以便在創(chuàng)世時存入資產。
geth --datadir $HOME/deepeth account new
因為是學習使用,推薦使用統(tǒng)一密碼 foobar,執(zhí)行兩次命令,創(chuàng)建好兩個賬戶。這里使用 --datadir 參數指定以太坊運行時數據存放目錄,是讓大家將數據統(tǒng)一存放在一個本課程學習文件夾中。
再將下面配置內容保存到 $HOME/deepeth/genesis.json 文件,其中 alloc 項替換成剛剛創(chuàng)建的兩個以太坊賬戶地址。
{ "config": { "chainId": 8888, "homesteadBlock": 0, "daoForkBlock": 0, "daoForkSupport": true, "eip150Block": 0, "eip155Block": 0, "eip158Block": 0, "byzantiumBlock": 0, "constantinopleBlock": 0, "petersburgBlock": 0, "ethash": {} }, "nonce": "0x42", "timestamp": "0x0", "extraData": "0x11bbe8db4e347b4e8c937c1c8370e4b5ed33adb3db69cbdb7a38e1e50b1b82fa", "gasLimit": "0x1388", "difficulty": "0x1", "alloc": { "093f59f1d91017d30d8c2caa78feb5beb0d2cfaf": { "balance": "0xffffffffffffffff" }, "ddf7202cbe0aaed1c2d5c4ef05e386501a054406": { "balance": "0xffffffffffffffff" } } }
然后,執(zhí)行 geth 子命令 init 初始化創(chuàng)世區(qū)塊。
geth --datadir $HOME/deepeth init genesis.json
執(zhí)行成功后,便可啟動該私有鏈:
geth --maxpeers 0 --datadir $HOME/deepeth console
執(zhí)行如下命令,可以查看到前面創(chuàng)建的兩個賬戶,均已有資產:
eth.getBalance(eth.accounts[0]) // 18446744073709551615 eth.getBalance(eth.accounts[1]) // 18446744073709551615
至此,我們已完成創(chuàng)世定制版。
內置的創(chuàng)世配置上面我已完成自定義創(chuàng)世,但以太坊作為去中心平臺,需要許多節(jié)點一起參與。僅僅為了測試,多個節(jié)點來搭建私有鏈比較麻煩。如果希望和別人一起聯(lián)調,或者需要在測試網絡中測試DAPP時,該怎么辦呢?那么,可使用以太坊測試網絡。以太坊公開的測試網絡有 5 個,目前仍在運行的有 4 個,具體見下表格。
測試網 | 共識機制 | 出塊間隔 | 提供方 | 上線時間 | 備注 | 狀態(tài) |
---|---|---|---|---|---|---|
Morden | PoW | 以太坊官方 | 2015.7 | 因難度炸彈被迫退役 | stopped | |
Ropsten | PoW | 30秒 | 以太坊官方 | 2016.11 | 接替Morden | running |
Kovan | PoA | 4秒 | 以太坊錢包Parity開發(fā)團隊 | 2017.3 | 不支持geth | running |
Rinkeby | PoA | 15秒 | 以太坊官方 | 2017.4 | 最常用,只支持geth | running |
Sokol | PoA | 5秒 | 以太坊官方POA.network團隊 | 2017.12 | 不支持geth | running |
G?rli | PoA | 15秒 | 以太坊柏林社區(qū) | 2018.9 | 首個以太坊2.0實驗場 | running |
支持 geth 的3個測試網絡的創(chuàng)世配置已內置在以太坊代碼中,具體見 core/genesis.go 文件:
// DefaultTestnetGenesisBlock returns the Ropsten network genesis block. func DefaultTestnetGenesisBlock() *Genesis{} // DefaultRinkebyGenesisBlock returns the Rinkeby network genesis block. func DefaultRinkebyGenesisBlock() *Genesis // DefaultGoerliGenesisBlock returns the G?rli network genesis block. func DefaultGoerliGenesisBlock() *Genesis{}
當然不會缺以太坊主網創(chuàng)世配置,也是 geth 運行的默認配置。
// DefaultGenesisBlock returns the Ethereum main net genesis block. func DefaultGenesisBlock() *Genesis{}
如果你不想自定義創(chuàng)世配置文件用于開發(fā)測試,那么以太坊也提供一份專用于本地開發(fā)的配置。
// DeveloperGenesisBlock returns the "geth --dev" genesis block. Note, this must // be seeded with the func DeveloperGenesisBlock(period uint64, faucet common.Address) *Genesis
運行 geth --dev console 可臨時運行使用。但如果需要長期使用此模式,則需要指定 datadir。
geth --dev --datadir $HOME/deepeth/dev console
首次運行 dev 模式會自動創(chuàng)建一個空密碼的賬戶,并開啟挖礦。當有新交易時,將立刻打包出塊。
geth 創(chuàng)世區(qū)塊加載流程在運行 geth 時需根據配置文件加載創(chuàng)世配置以及創(chuàng)世區(qū)塊,并校驗其合法性。如果配置信息隨意變更,易引起共識校驗不通過等問題。只有在加載并檢查通過時,才能繼續(xù)運行程序。
上圖是一個簡要流程,下面分別講解“加載創(chuàng)世配置”和“安裝創(chuàng)世區(qū)塊”兩個子流程。
加載創(chuàng)世配置應使用哪種創(chuàng)世配置,由用戶在啟動 geth 時決定。下圖是創(chuàng)世配置選擇流程圖:
通過 geth 命令參數可選擇不同網絡配置,可以通過 networkid 選擇,也可使用網絡名稱啟用。
使用 networkid:
不同網絡使用不同ID標識。
1=Frontier,主網環(huán)境,是默認選項。
2=Morden 測試網絡,但已禁用。
3=Ropsten 測試網絡。
4=Rinkeby 測試網絡。
直接使用網絡名稱:
testnet: Ropsten 測試網絡。
rinkeby: Rinkeby 測試網絡。
goerli: G?rli 測試網絡。
dev: 本地開發(fā)環(huán)境。
geth 啟動時根據不同參數選擇加載不同網絡配置,并對應不同網絡環(huán)境。如果不做任何選擇,雖然在此不會做出選擇,但在后面流程中會默認使用主網配置。
安裝創(chuàng)世區(qū)塊上面已初步選擇創(chuàng)世配置,而這一步則根據配置加載或者初始化創(chuàng)世單元。下圖是處理流程:
首先,需要從數據庫中根據區(qū)塊高度 0 讀取創(chuàng)世區(qū)塊哈希。如果不存在則說明本地屬于第一次啟動,直接使用運行時創(chuàng)世配置來構建創(chuàng)世區(qū)塊。屬于首次,還需要存儲創(chuàng)世區(qū)塊和鏈配置。
如果存在,則需要使用運行時創(chuàng)世配置構建創(chuàng)世區(qū)塊并和本次已存儲的創(chuàng)世區(qū)塊哈希進行對比。一旦不一致,則返回錯誤,不得繼續(xù)。
隨后,還需要檢查鏈配置。先從數據庫獲取鏈配置,如果不存在,則無需校驗直接使用運行時鏈配置。否則,需要檢查運行時鏈配置是否正確,只有正確時才能替換更新。但有一個例外:主網配置不得隨意更改,由代碼控制而非人為指定。
總的來說,以太坊默認使用主網配置,只有在首次運行時才創(chuàng)建和存儲創(chuàng)世區(qū)塊,其他時候僅僅用于校驗。而鏈配置除主網外則在規(guī)則下可隨時變更。
構建創(chuàng)建區(qū)塊上面我們已知曉總體流程,這里再細說下以太坊是如何根據創(chuàng)世配置生成創(chuàng)世區(qū)塊。核心代碼位于 core/genesis.go:229。
func (g *Genesis) ToBlock(db ethdb.Database) *types.Block{ if db == nil { db = rawdb.NewMemoryDatabase() } statedb, _ := state.New(common.Hash{}, state.NewDatabase(db))//? for addr, account := range g.Alloc { //? statedb.AddBalance(addr, account.Balance) statedb.SetCode(addr, account.Code) statedb.SetNonce(addr, account.Nonce) for key, value := range account.Storage { statedb.SetState(addr, key, value) } } root := statedb.IntermediateRoot(false)//? head := &types.Header{//? Number: new(big.Int).SetUint64(g.Number), Nonce: types.EncodeNonce(g.Nonce), Time: g.Timestamp, ParentHash: g.ParentHash, Extra: g.ExtraData, GasLimit: g.GasLimit, GasUsed: g.GasUsed, Difficulty: g.Difficulty, MixDigest: g.Mixhash, Coinbase: g.Coinbase, Root: root, } //? if g.GasLimit == 0 { head.GasLimit = params.GenesisGasLimit } if g.Difficulty == nil { head.Difficulty = params.GenesisDifficulty } statedb.Commit(false)//? statedb.Database().TrieDB().Commit(root, true)//? return types.NewBlock(head, nil, nil, nil)//? }
上面代碼是根據創(chuàng)世配置生成創(chuàng)世區(qū)塊的代碼邏輯,細節(jié)如下:
? 創(chuàng)世區(qū)塊無父塊,從零初始化全新的 state(后續(xù)文章會詳細講解 state對象)。
? 遍歷配置中 Alloc 項賬戶集合數據,直接寫入 state 中。
這里不單可以設置 balance,還可以設置 code、nonce 以及任意多個 storage 數據。
意味著創(chuàng)世時便可以直接部署智能合約。例如下面配置則在創(chuàng)世時部署了一個名為093f59f1d91017d30d8c2caa78feb5beb0d2cfaf 的智能合約。
"alloc": { "093f59f1d91017d30d8c2caa78feb5beb0d2cfaf": { "balance": "0xffffffffffffffff", "nonce": "0x3", "code":"0x606060", "storage":{ "11bbe8db4e347b4e8c937c1c8370e4b5ed33adb3db69cbdb7a38e1e50b1b82fa":"1234ff" } } }
? 將賬戶數據寫入 state 后,便可以計算出 state 數據的默克爾樹的根值,稱之為 StateRoot。
此值記錄在區(qū)塊頭 Root 字段中。
? 創(chuàng)世配置的一部分配置,則直接映射到區(qū)塊頭中,完成創(chuàng)世區(qū)塊頭的構建。
? 因為 GasLimit 和 Difficulty 直接影響到下一個區(qū)塊出塊處理。
因此未設置時使用默認配置(Difficulty=131072,GasLimit=4712388)。
? 提交 state,將 state 數據提交到底層的內存 trie 數據中。
? 將內存 trie 數據更新到 db 中。
這是多余的一步,因為提交到數據庫是由外部進行,這里只需要負責生成區(qū)塊。
? 利用區(qū)塊頭創(chuàng)建區(qū)塊,且區(qū)塊中無交易記錄。
深入淺出區(qū)塊鏈 - 系統(tǒng)學習區(qū)塊鏈,學區(qū)塊鏈都在這里,打造最好的區(qū)塊鏈技術博客。
文章版權歸作者所有,未經允許請勿轉載,若此文章存在違規(guī)行為,您可以聯(lián)系管理員刪除。
轉載請注明本文地址:http://specialneedsforspecialkids.com/yun/24645.html
摘要:原文地址石匠的為了測試以太坊智能合約,最方便的是在本地搭建一個以太坊私有鏈。網絡在連接到其他節(jié)點的時候會用到,以太坊公網的網絡是,為了不與公有鏈網絡沖突,運行私有鏈節(jié)點的時候要指定自己的網絡。當設置為表示使用發(fā)布該鏈。 原文地址: 石匠的blog 為了測試以太坊智能合約,最方便的是在本地搭建一個以太坊私有鏈。在mac上搭建環(huán)境主要需要以下步驟。 geth安裝 geth是go-ether...
摘要:本文首發(fā)于深入淺出區(qū)塊鏈社區(qū)原文鏈接如何搭建以太坊私有鏈原文已更新,請讀者前往原文閱讀在開發(fā)以太坊時,很多時候需要搭建一條以太坊私有鏈,通過本文一起看看如何在上進行搭建。 本文首發(fā)于深入淺出區(qū)塊鏈社區(qū)原文鏈接:如何搭建以太坊私有鏈原文已更新,請讀者前往原文閱讀 在開發(fā)以太坊時,很多時候需要搭建一條以太坊私有鏈,通過本文一起看看如何在Mac上進行搭建。 寫在前面 閱讀本文前,你應該對以太...
摘要:本文所搭建的環(huán)境是在上的開發(fā)環(huán)境,其他操作系統(tǒng)上與此非常相似,依然有參考價值。作為一枚區(qū)塊鏈開發(fā)工程師,本地的開發(fā)環(huán)境是必不可少的。因為我們是私有鏈,所以可以寫的大一些,方便開發(fā)測試。 本文所搭建的環(huán)境是在 Mac 上的開發(fā)環(huán)境,其他操作系統(tǒng)上與此非常相似,依然有參考價值。 作為一枚區(qū)塊鏈開發(fā)工程師,本地的開發(fā)環(huán)境是必不可少的。我們首先看看需要哪些工具: go-ethereum so...
摘要:本文所搭建的環(huán)境是在上的開發(fā)環(huán)境,其他操作系統(tǒng)上與此非常相似,依然有參考價值。作為一枚區(qū)塊鏈開發(fā)工程師,本地的開發(fā)環(huán)境是必不可少的。因為我們是私有鏈,所以可以寫的大一些,方便開發(fā)測試。 本文所搭建的環(huán)境是在 Mac 上的開發(fā)環(huán)境,其他操作系統(tǒng)上與此非常相似,依然有參考價值。 作為一枚區(qū)塊鏈開發(fā)工程師,本地的開發(fā)環(huán)境是必不可少的。我們首先看看需要哪些工具: go-ethereum so...
閱讀 2892·2021-11-23 09:51
閱讀 3403·2021-11-22 09:34
閱讀 3304·2021-10-27 14:14
閱讀 1503·2019-08-30 15:55
閱讀 3344·2019-08-30 15:54
閱讀 1066·2019-08-30 15:52
閱讀 1887·2019-08-30 12:46
閱讀 2844·2019-08-29 16:11