摘要:本文首發(fā)于深入淺出區(qū)塊鏈社區(qū)原文鏈接以太坊創(chuàng)世區(qū)塊與鏈配置載入分析,原文已更新,請(qǐng)讀者前往原文閱讀。以太坊允許通過(guò)創(chuàng)世配置文件來(lái)初始化創(chuàng)世區(qū)塊,也可使用選擇使用內(nèi)置的多個(gè)網(wǎng)絡(luò)環(huán)境的創(chuàng)世配置。再準(zhǔn)備兩個(gè)以太坊賬戶,以便在創(chuàng)世時(shí)存入資產(chǎn)。
本文首發(fā)于深入淺出區(qū)塊鏈社區(qū)
原文鏈接:以太坊創(chuàng)世區(qū)塊與鏈配置載入分析,原文已更新,請(qǐng)讀者前往原文閱讀。
創(chuàng)世區(qū)塊作為第零個(gè)區(qū)塊,其他區(qū)塊直接或間接引用到創(chuàng)世區(qū)塊。因此節(jié)點(diǎn)啟動(dòng)之初必須載入正確的創(chuàng)世區(qū)塊信息,且不得任意修改。
以太坊允許通過(guò)創(chuàng)世配置文件來(lái)初始化創(chuàng)世區(qū)塊,也可使用選擇使用內(nèi)置的多個(gè)網(wǎng)絡(luò)環(huán)境的創(chuàng)世配置。默認(rèn)使用以太坊主網(wǎng)創(chuàng)世配置。
創(chuàng)世配置文件如果你需要搭建以太坊私有鏈,那么了解創(chuàng)世配置是必須的,否則你大可不關(guān)心創(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" } } }
根據(jù)配置用途可分為三大類:
鏈配置
config項(xiàng)是定義鏈配置,會(huì)影響共識(shí)協(xié)議,雖然鏈配置對(duì)創(chuàng)世影響不大,但新區(qū)塊的出塊規(guī)則均依賴鏈配置。
創(chuàng)世區(qū)塊頭信息配置
nonce:隨機(jī)數(shù),對(duì)應(yīng)創(chuàng)世區(qū)塊 Nonce 字段。
timestamp:UTC時(shí)間戳,對(duì)應(yīng)創(chuàng)世區(qū)塊 Time字段。
extraData:額外數(shù)據(jù),對(duì)應(yīng)創(chuàng)世區(qū)塊 Extra 字段。
gasLimit:必填,燃料上限,對(duì)應(yīng)創(chuàng)世區(qū)塊 GasLimit 字段。
difficulty:必填,難度系數(shù),對(duì)應(yīng)創(chuàng)世區(qū)塊 Difficulty 字段。搭建私有鏈時(shí),需要根據(jù)情況選擇合適的難度值,以便調(diào)整出塊。
minHash:一個(gè)哈希值,對(duì)應(yīng)創(chuàng)世區(qū)塊的MixDigest字段。和 nonce 值一起證明在區(qū)塊上已經(jīng)進(jìn)行了足夠的計(jì)算。
coinbase:一個(gè)地址,對(duì)應(yīng)創(chuàng)世區(qū)塊的Coinbase字段。
初始賬戶資產(chǎn)配置
alloc 項(xiàng)是創(chuàng)世中初始賬戶資產(chǎn)配置。在生成創(chuàng)世區(qū)塊時(shí),將此數(shù)據(jù)集中的賬戶資產(chǎn)寫入?yún)^(qū)塊中,相當(dāng)于預(yù)挖礦。這對(duì)開發(fā)測(cè)試和私有鏈非常好用,不需要挖礦就可以直接為任意多個(gè)賬戶分配資產(chǎn)。
自定義創(chuàng)世如果你計(jì)劃部署以太坊私有網(wǎng)絡(luò)或者一個(gè)獨(dú)立的測(cè)試環(huán)境,那么需要自定義創(chuàng)世,并初始化它。為了統(tǒng)一溝通,推薦先在用戶根目錄創(chuàng)建一個(gè)文件夾 deepeth,以做為《以太坊設(shè)計(jì)與實(shí)現(xiàn)》電子書學(xué)習(xí)工作目錄。
mkdir $HOME/deepeth && cd $HOME/deepeth
再準(zhǔn)備兩個(gè)以太坊賬戶,以便在創(chuàng)世時(shí)存入資產(chǎn)。
geth --datadir $HOME/deepeth account new
因?yàn)槭菍W(xué)習(xí)使用,推薦使用統(tǒng)一密碼 foobar,執(zhí)行兩次命令,創(chuàng)建好兩個(gè)賬戶。這里使用 --datadir 參數(shù)指定以太坊運(yùn)行時(shí)數(shù)據(jù)存放目錄,是讓大家將數(shù)據(jù)統(tǒng)一存放在一個(gè)本課程學(xué)習(xí)文件夾中。
再將下面配置內(nèi)容保存到 $HOME/deepeth/genesis.json 文件,其中 alloc 項(xiàng)替換成剛剛創(chuàng)建的兩個(gè)以太坊賬戶地址。
{ "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í)行成功后,便可啟動(dòng)該私有鏈:
geth --maxpeers 0 --datadir $HOME/deepeth console
執(zhí)行如下命令,可以查看到前面創(chuàng)建的兩個(gè)賬戶,均已有資產(chǎn):
eth.getBalance(eth.accounts[0]) // 18446744073709551615 eth.getBalance(eth.accounts[1]) // 18446744073709551615
至此,我們已完成創(chuàng)世定制版。
內(nèi)置的創(chuàng)世配置上面我已完成自定義創(chuàng)世,但以太坊作為去中心平臺(tái),需要許多節(jié)點(diǎn)一起參與。僅僅為了測(cè)試,多個(gè)節(jié)點(diǎn)來(lái)搭建私有鏈比較麻煩。如果希望和別人一起聯(lián)調(diào),或者需要在測(cè)試網(wǎng)絡(luò)中測(cè)試DAPP時(shí),該怎么辦呢?那么,可使用以太坊測(cè)試網(wǎng)絡(luò)。以太坊公開的測(cè)試網(wǎng)絡(luò)有 5 個(gè),目前仍在運(yùn)行的有 4 個(gè),具體見下表格。
測(cè)試網(wǎng) | 共識(shí)機(jī)制 | 出塊間隔 | 提供方 | 上線時(shí)間 | 備注 | 狀態(tài) |
---|---|---|---|---|---|---|
Morden | PoW | 以太坊官方 | 2015.7 | 因難度炸彈被迫退役 | stopped | |
Ropsten | PoW | 30秒 | 以太坊官方 | 2016.11 | 接替Morden | running |
Kovan | PoA | 4秒 | 以太坊錢包Parity開發(fā)團(tuán)隊(duì) | 2017.3 | 不支持geth | running |
Rinkeby | PoA | 15秒 | 以太坊官方 | 2017.4 | 最常用,只支持geth | running |
Sokol | PoA | 5秒 | 以太坊官方POA.network團(tuán)隊(duì) | 2017.12 | 不支持geth | running |
G?rli | PoA | 15秒 | 以太坊柏林社區(qū) | 2018.9 | 首個(gè)以太坊2.0實(shí)驗(yàn)場(chǎng) | running |
支持 geth 的3個(gè)測(cè)試網(wǎng)絡(luò)的創(chuàng)世配置已內(nèi)置在以太坊代碼中,具體見 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{}
當(dāng)然不會(huì)缺以太坊主網(wǎng)創(chuàng)世配置,也是 geth 運(yùn)行的默認(rèn)配置。
// DefaultGenesisBlock returns the Ethereum main net genesis block. func DefaultGenesisBlock() *Genesis{}
如果你不想自定義創(chuàng)世配置文件用于開發(fā)測(cè)試,那么以太坊也提供一份專用于本地開發(fā)的配置。
// DeveloperGenesisBlock returns the "geth --dev" genesis block. Note, this must // be seeded with the func DeveloperGenesisBlock(period uint64, faucet common.Address) *Genesis
運(yùn)行 geth --dev console 可臨時(shí)運(yùn)行使用。但如果需要長(zhǎng)期使用此模式,則需要指定 datadir。
geth --dev --datadir $HOME/deepeth/dev console
首次運(yùn)行 dev 模式會(huì)自動(dòng)創(chuàng)建一個(gè)空密碼的賬戶,并開啟挖礦。當(dāng)有新交易時(shí),將立刻打包出塊。
geth 創(chuàng)世區(qū)塊加載流程在運(yùn)行 geth 時(shí)需根據(jù)配置文件加載創(chuàng)世配置以及創(chuàng)世區(qū)塊,并校驗(yàn)其合法性。如果配置信息隨意變更,易引起共識(shí)校驗(yàn)不通過(guò)等問(wèn)題。只有在加載并檢查通過(guò)時(shí),才能繼續(xù)運(yùn)行程序。
上圖是一個(gè)簡(jiǎn)要流程,下面分別講解“加載創(chuàng)世配置”和“安裝創(chuàng)世區(qū)塊”兩個(gè)子流程。
加載創(chuàng)世配置應(yīng)使用哪種創(chuàng)世配置,由用戶在啟動(dòng) geth 時(shí)決定。下圖是創(chuàng)世配置選擇流程圖:
通過(guò) geth 命令參數(shù)可選擇不同網(wǎng)絡(luò)配置,可以通過(guò) networkid 選擇,也可使用網(wǎng)絡(luò)名稱啟用。
使用 networkid:
不同網(wǎng)絡(luò)使用不同ID標(biāo)識(shí)。
1=Frontier,主網(wǎng)環(huán)境,是默認(rèn)選項(xiàng)。
2=Morden 測(cè)試網(wǎng)絡(luò),但已禁用。
3=Ropsten 測(cè)試網(wǎng)絡(luò)。
4=Rinkeby 測(cè)試網(wǎng)絡(luò)。
直接使用網(wǎng)絡(luò)名稱:
testnet: Ropsten 測(cè)試網(wǎng)絡(luò)。
rinkeby: Rinkeby 測(cè)試網(wǎng)絡(luò)。
goerli: G?rli 測(cè)試網(wǎng)絡(luò)。
dev: 本地開發(fā)環(huán)境。
geth 啟動(dòng)時(shí)根據(jù)不同參數(shù)選擇加載不同網(wǎng)絡(luò)配置,并對(duì)應(yīng)不同網(wǎng)絡(luò)環(huán)境。如果不做任何選擇,雖然在此不會(huì)做出選擇,但在后面流程中會(huì)默認(rèn)使用主網(wǎng)配置。
安裝創(chuàng)世區(qū)塊上面已初步選擇創(chuàng)世配置,而這一步則根據(jù)配置加載或者初始化創(chuàng)世單元。下圖是處理流程:
首先,需要從數(shù)據(jù)庫(kù)中根據(jù)區(qū)塊高度 0 讀取創(chuàng)世區(qū)塊哈希。如果不存在則說(shuō)明本地屬于第一次啟動(dòng),直接使用運(yùn)行時(shí)創(chuàng)世配置來(lái)構(gòu)建創(chuàng)世區(qū)塊。屬于首次,還需要存儲(chǔ)創(chuàng)世區(qū)塊和鏈配置。
如果存在,則需要使用運(yùn)行時(shí)創(chuàng)世配置構(gòu)建創(chuàng)世區(qū)塊并和本次已存儲(chǔ)的創(chuàng)世區(qū)塊哈希進(jìn)行對(duì)比。一旦不一致,則返回錯(cuò)誤,不得繼續(xù)。
隨后,還需要檢查鏈配置。先從數(shù)據(jù)庫(kù)獲取鏈配置,如果不存在,則無(wú)需校驗(yàn)直接使用運(yùn)行時(shí)鏈配置。否則,需要檢查運(yùn)行時(shí)鏈配置是否正確,只有正確時(shí)才能替換更新。但有一個(gè)例外:主網(wǎng)配置不得隨意更改,由代碼控制而非人為指定。
總的來(lái)說(shuō),以太坊默認(rèn)使用主網(wǎng)配置,只有在首次運(yùn)行時(shí)才創(chuàng)建和存儲(chǔ)創(chuàng)世區(qū)塊,其他時(shí)候僅僅用于校驗(yàn)。而鏈配置除主網(wǎng)外則在規(guī)則下可隨時(shí)變更。
構(gòu)建創(chuàng)建區(qū)塊上面我們已知曉總體流程,這里再細(xì)說(shuō)下以太坊是如何根據(jù)創(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)//? }
上面代碼是根據(jù)創(chuàng)世配置生成創(chuàng)世區(qū)塊的代碼邏輯,細(xì)節(jié)如下:
? 創(chuàng)世區(qū)塊無(wú)父塊,從零初始化全新的 state(后續(xù)文章會(huì)詳細(xì)講解 state對(duì)象)。
? 遍歷配置中 Alloc 項(xiàng)賬戶集合數(shù)據(jù),直接寫入 state 中。
這里不單可以設(shè)置 balance,還可以設(shè)置 code、nonce 以及任意多個(gè) storage 數(shù)據(jù)。
意味著創(chuàng)世時(shí)便可以直接部署智能合約。例如下面配置則在創(chuàng)世時(shí)部署了一個(gè)名為093f59f1d91017d30d8c2caa78feb5beb0d2cfaf 的智能合約。
"alloc": { "093f59f1d91017d30d8c2caa78feb5beb0d2cfaf": { "balance": "0xffffffffffffffff", "nonce": "0x3", "code":"0x606060", "storage":{ "11bbe8db4e347b4e8c937c1c8370e4b5ed33adb3db69cbdb7a38e1e50b1b82fa":"1234ff" } } }
? 將賬戶數(shù)據(jù)寫入 state 后,便可以計(jì)算出 state 數(shù)據(jù)的默克爾樹的根值,稱之為 StateRoot。
此值記錄在區(qū)塊頭 Root 字段中。
? 創(chuàng)世配置的一部分配置,則直接映射到區(qū)塊頭中,完成創(chuàng)世區(qū)塊頭的構(gòu)建。
? 因?yàn)?GasLimit 和 Difficulty 直接影響到下一個(gè)區(qū)塊出塊處理。
因此未設(shè)置時(shí)使用默認(rèn)配置(Difficulty=131072,GasLimit=4712388)。
? 提交 state,將 state 數(shù)據(jù)提交到底層的內(nèi)存 trie 數(shù)據(jù)中。
? 將內(nèi)存 trie 數(shù)據(jù)更新到 db 中。
這是多余的一步,因?yàn)樘峤坏綌?shù)據(jù)庫(kù)是由外部進(jìn)行,這里只需要負(fù)責(zé)生成區(qū)塊。
? 利用區(qū)塊頭創(chuàng)建區(qū)塊,且區(qū)塊中無(wú)交易記錄。
深入淺出區(qū)塊鏈 - 系統(tǒng)學(xué)習(xí)區(qū)塊鏈,學(xué)區(qū)塊鏈都在這里,打造最好的區(qū)塊鏈技術(shù)博客。
文章版權(quán)歸作者所有,未經(jīng)允許請(qǐng)勿轉(zhuǎn)載,若此文章存在違規(guī)行為,您可以聯(lián)系管理員刪除。
轉(zhuǎn)載請(qǐng)注明本文地址:http://www.ezyhdfw.cn/yun/24645.html
摘要:運(yùn)行以太坊私有網(wǎng)絡(luò)以太坊以的形式來(lái)標(biāo)識(shí)一個(gè)網(wǎng)絡(luò),推薦使用的形式去指定,主網(wǎng)絡(luò)的是默認(rèn)的,如果你想要建立私有網(wǎng)絡(luò),你可以指定一個(gè)新的網(wǎng)絡(luò)。 運(yùn)行以太坊私有網(wǎng)絡(luò) network ID 以太坊以 netWorkID的形式來(lái)標(biāo)識(shí)一個(gè)網(wǎng)絡(luò),推薦使用--networkid的形式去指定,主網(wǎng)絡(luò)的networkid是1(默認(rèn)的),如果你想要建立私有網(wǎng)絡(luò),你可以指定一個(gè)新的網(wǎng)絡(luò)id。 創(chuàng)建創(chuàng)世區(qū)塊 創(chuàng)世...
摘要:原文地址石匠的為了測(cè)試以太坊智能合約,最方便的是在本地搭建一個(gè)以太坊私有鏈。網(wǎng)絡(luò)在連接到其他節(jié)點(diǎn)的時(shí)候會(huì)用到,以太坊公網(wǎng)的網(wǎng)絡(luò)是,為了不與公有鏈網(wǎng)絡(luò)沖突,運(yùn)行私有鏈節(jié)點(diǎn)的時(shí)候要指定自己的網(wǎng)絡(luò)。當(dāng)設(shè)置為表示使用發(fā)布該鏈。 原文地址: 石匠的blog 為了測(cè)試以太坊智能合約,最方便的是在本地搭建一個(gè)以太坊私有鏈。在mac上搭建環(huán)境主要需要以下步驟。 geth安裝 geth是go-ether...
摘要:本文首發(fā)于深入淺出區(qū)塊鏈社區(qū)原文鏈接如何搭建以太坊私有鏈原文已更新,請(qǐng)讀者前往原文閱讀在開發(fā)以太坊時(shí),很多時(shí)候需要搭建一條以太坊私有鏈,通過(guò)本文一起看看如何在上進(jìn)行搭建。 本文首發(fā)于深入淺出區(qū)塊鏈社區(qū)原文鏈接:如何搭建以太坊私有鏈原文已更新,請(qǐng)讀者前往原文閱讀 在開發(fā)以太坊時(shí),很多時(shí)候需要搭建一條以太坊私有鏈,通過(guò)本文一起看看如何在Mac上進(jìn)行搭建。 寫在前面 閱讀本文前,你應(yīng)該對(duì)以太...
摘要:本文所搭建的環(huán)境是在上的開發(fā)環(huán)境,其他操作系統(tǒng)上與此非常相似,依然有參考價(jià)值。作為一枚區(qū)塊鏈開發(fā)工程師,本地的開發(fā)環(huán)境是必不可少的。因?yàn)槲覀兪撬接墟?,所以可以寫的大一些,方便開發(fā)測(cè)試。 本文所搭建的環(huán)境是在 Mac 上的開發(fā)環(huán)境,其他操作系統(tǒng)上與此非常相似,依然有參考價(jià)值。 作為一枚區(qū)塊鏈開發(fā)工程師,本地的開發(fā)環(huán)境是必不可少的。我們首先看看需要哪些工具: go-ethereum so...
摘要:本文所搭建的環(huán)境是在上的開發(fā)環(huán)境,其他操作系統(tǒng)上與此非常相似,依然有參考價(jià)值。作為一枚區(qū)塊鏈開發(fā)工程師,本地的開發(fā)環(huán)境是必不可少的。因?yàn)槲覀兪撬接墟?,所以可以寫的大一些,方便開發(fā)測(cè)試。 本文所搭建的環(huán)境是在 Mac 上的開發(fā)環(huán)境,其他操作系統(tǒng)上與此非常相似,依然有參考價(jià)值。 作為一枚區(qū)塊鏈開發(fā)工程師,本地的開發(fā)環(huán)境是必不可少的。我們首先看看需要哪些工具: go-ethereum so...
閱讀 2953·2021-11-23 09:51
閱讀 3473·2021-11-22 09:34
閱讀 3376·2021-10-27 14:14
閱讀 1599·2019-08-30 15:55
閱讀 3408·2019-08-30 15:54
閱讀 1130·2019-08-30 15:52
閱讀 1944·2019-08-30 12:46
閱讀 2899·2019-08-29 16:11