Ethereum Genesis block and chain configuration loading analysis

Time:2019-11-26

This article starts with the block chain community
Original link: Ethereum Genesis block and chain configuration loading analysis, the original has been updated, please go to the original for reading.

As the zero block, other blocks directly or indirectly refer to the genesis block. Therefore, at the beginning of node startup, the correct creation block information must be loaded and cannot be modified arbitrarily.

Ethereum allows initialization of the creation block through the creation profile, or the creation configuration using multiple built-in network environments. By default, the Ethereum master network creation configuration is used.

Genesis profile

If you need to build the Ethereum private chain, it is necessary to understand the creation configuration, otherwise you may not care about the creation configuration. The following is an example of creation configuration in JSON format:

{
    "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"
        }
    }
}

According to the configuration purpose, it can be divided into three categories:

  1. Chain configuration

configItem is to define the chain configuration, which will affect the consensus agreement. Although the chain configuration has little impact on genesis, the outbound rules of new blocks all depend on the chain configuration.

  1. Configuration of block information in Chuangshi District

    • nonce: random number, corresponding to Genesis blockNonceField.
    • timestamp: UTC timestamp, corresponding to Genesis blockTimeField.
    • extraData: additional data, corresponding to Genesis blockExtraField.
    • gasLimitMust fill, fuel cap, corresponding to Genesis blockGasLimitField.
    • difficultyMust fill, difficulty coefficient, corresponding to Genesis blockDifficultyField. When building a private chain, it is necessary to select the appropriate difficulty value according to the situation, so as to adjust the block.
    • minHash: a hash value corresponding to theMixDigestField. Together with the nonce value, it is proved that enough computation has been done on the block.
    • coinbase: an address corresponding to theCoinbaseField.
  2. Initial account asset allocation

allocItem is the initial account asset allocation in Genesis. When the genesis block is generated, the account assets in this data set are written into the block, which is equivalent to pre mining. This is very useful for development testing and the private chain. You can allocate assets directly to any number of accounts without mining.

Custom genesis

If you plan to deploy the Ethereum private network or a stand-alone test environment, you need to customize genesis and initialize it. For unified communication, it is recommended to create a folder in the root directory of the user firstdeepeth, as the e-book learning working directory of Ethereum design and implementation.

mkdir $HOME/deepeth && cd $HOME/deepeth

Prepare two more Ethereum accounts to deposit assets at creation time.

geth --datadir $HOME/deepeth account new

Because it’s for learning to use, unified password is recommended.foobar, execute the command twice to create two accounts. Use here--datadirParameter specifies the data storage directory of Ethereum runtime, which allows you to store the data in a learning folder of this course.

Then save the following configuration content to$HOME/deepeth/genesis.jsonDocuments, whereallocReplace with the two Ethereum account addresses you just created.

{
    "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"
        }
    }
}

Then, execute the geth subcommand init to initialize the creation block.

geth  --datadir $HOME/deepeth init genesis.json

After successful execution, the private chain can be started:

geth --maxpeers 0 --datadir $HOME/deepeth  console

Execute the following command to view the two accounts created previously, both of which have assets:

eth.getBalance(eth.accounts[0])
// 18446744073709551615
eth.getBalance(eth.accounts[1])
// 18446744073709551615

So far, we have completed the customized version of Genesis.

Built in Genesis configuration

I have finished the custom creation above, but Ethereum as a decentralized platform needs many nodes to participate together. Just for testing, it’s difficult to build a private chain with multiple nodes. What to do if you want to conduct joint debugging with others or need to test DAPP in the test network? Then, you can use Ethereum to test the network. There are 5 open test networks of Ethereum, and 4 are still running. See the table below for details.

Test network Consensus mechanism Out block interval provider On-line time Remarks state
Morden PoW Ethereum official 2015.7 Forced to retire due to difficulty bomb stopped
Ropsten PoW 30 seconds Ethereum official 2016.11 Replace Morden running
Kovan PoA 4 seconds Parity development team of Ethereum Wallet 2017.3 Geth not supported running
Rinkeby PoA 15 seconds Ethereum official 2017.4 Most commonly used, only geth is supported running
Sokol PoA 5 seconds Official poa.network team of Ethereum 2017.12 Geth not supported running
Görli PoA 15 seconds Ethereum Berlin community 2018.9 The first Ethereum 2.0 experimental field running

The creation configuration of the three test networks supporting geth has been built into the Ethereum code. For details, seecore/genesis.goDocument:

// 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{}

Of course, it will not lack the creation configuration of the Ethereum main network, which is also the default configuration for geth operation.

// DefaultGenesisBlock returns the Ethereum main net genesis block.
func DefaultGenesisBlock() *Genesis{}

If you don’t want to customize the genesis profile for development testing, Ethereum also provides a configuration dedicated to local development.


// DeveloperGenesisBlock returns the 'geth --dev' genesis block. Note, this must
// be seeded with the
func DeveloperGenesisBlock(period uint64, faucet common.Address) *Genesis

Functiongeth --dev consoleIt can be used for temporary operation. However, if you need to use this mode for a long time, you need to specifydatadir

geth --dev --datadir $HOME/deepeth/dev console

Running dev mode for the first time will automatically create an account with an empty password and enable mining. When there is a new deal, it will be packaged immediately.

Geth creation block loading process

When running geth, you need to load the genesis configuration and the genesis block according to the configuration file, and verify its validity. If the configuration information is changed at will, it is easy to cause consensus verification failure and other problems. You can continue running the program only if it has been loaded and checked.

<imghttps://img.learnblockchain.cn/2019/04/07_20190407101509.png&quot” rel=”nofollow noreferrer”>https://img.learnblockchain.c…; width=”400px”>

The above figure is a brief process, and the following two subprocesses are explained respectively: “load Genesis configuration” and “install Genesis block”.

Load Genesis configuration

Which creation configuration should be used is determined by the user when starting geth. The following figure is the flow chart of Chuangshi configuration selection:
Ethereum Genesis block and chain configuration loading analysis
Through the geth command parameter, you can select different network configurations, and through thenetworkidSelect, or enable with network name.

  1. Using networkid:
    Different networks use different IDs.

    • 1 = frontier, primary network environment, is the default option.
    • 2 = morden tests the network, but it is disabled.
    • 3 = ropsten test network.
    • 4 = rinkeby test network.
  2. Use network name directly:

    • Testnet: ropsten tests the network.
    • Rinkeby: rinkeby tests the network.
    • Goerli: G ö RLI tests the network.
    • Dev: local development environment.

When geth is started, different network configurations are loaded according to different parameters and corresponding to different network environments. If no choice is made, although no choice will be made here, the main network configuration will be used by default in the later process.

Install Chuangshi block

The creation configuration has been initially selected above, and this step loads or initializes the creation unit according to the configuration. The following figure shows the processing flow:

Ethereum Genesis block and chain configuration loading analysis

First, we need to read the genesis block hash from the database according to the block height 0. If it does not exist, it means that it is the first time to start locally. Use the runtime creation configuration directly to build the creation block. For the first time, it also needs to store the configuration of Genesis block and chain.

If it exists, you need to use the runtime creation configuration to build the creation block and compare it with the hash of the creation block stored this time. Once inconsistent, an error is returned and cannot continue.

Subsequently, you also need to check the chain configuration. Get the chain configuration from the database first. If it doesn’t exist, you don’t need to verify to use the runtime chain configuration directly. Otherwise, you need to check whether the runtime chain configuration is correct, and only when it is correct can you replace the update. However, there is an exception: the configuration of the main network shall not be changed at will, and shall be controlled by code rather than specified by people.

In general, Ethereum uses the main network configuration by default, and only creates and stores the creation block when it is first running, and only uses it for verification in other times. In addition to the main network, the chain configuration can be changed at any time under the rules.

Build create block

We know the overall process above. Here we will talk about how Ethereum generates the creation block according to the creation configuration. Core code incore/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)//❽
}

The above code is the code logic to generate the genesis block according to the genesis configuration. The details are as follows:

  • ❶ Chuangshi block has no parent block, initializing a new one from zerostate(the following articles will explain in detailstateObject.
  • ❷ traversal configurationAllocItem account collection data, written directly to state.
    Not only can we set it herebalance, you can also setcodenonceAnd any number ofstorageData.
    It means that smart contracts can be deployed directly at the time of creation. For example, the following configuration deploys a configuration named093f59f1d91017d30d8c2caa78feb5beb0d2cfafSmart contract for.

    "alloc": {
            "093f59f1d91017d30d8c2caa78feb5beb0d2cfaf": {
                "balance": "0xffffffffffffffff",
                "nonce": "0x3",
                "code":"0x606060",
                "storage":{
                "11bbe8db4e347b4e8c937c1c8370e4b5ed33adb3db69cbdb7a38e1e50b1b82fa":"1234ff"
                }
            }
    }
  • ❸ after the account data is written into the state, the root value of the Merkel tree of the state data can be calculated, which is calledStateRoot
    This value is recorded in the block headerRootField.
  • ❹ some configurations of the creation configuration are mapped directly to the block head to complete the construction of the creation block head.
  • Because ofGasLimitandDifficultyDirectly affect the next block out processing.
    Therefore, the default configuration is used when it is not set (difficultly = 131072, gaslimit = 4712388).
  • ❻❻❻❻❻❻❻❻❻❻❻❻❻❻❻❻❻❻.
  • ❼ update memory trie data to DB.

This is an extra step, because the commit to the database is done externally, and only the block is generated here.

  • ❽❽❽❽❽❽❽❽❽❽❽❽❽❽❽❽❽.

Go deep and understand the blockchain system learning blockchain. All the blockchains are here to create the best blockchain technology blog.