以太坊创世区块与链配置载入分析

原文链接
请大家前往深入浅出区块链主站, 获取最新内容。

创世区块作为第零个区块,其他区块直接或间接引用到创世区块。因此节点启动之初必须载入正确的创世区块信息,且不得任意修改。

以太坊允许通过创世配置文件来初始化创世区块,也可使用选择使用内置的多个网络环境的创世配置。默认使用以太坊主网创世配置。

创世配置文件

如果你需要搭建以太坊私有链,那么了解创世配置是必须的,否则你大可不关心创世配置。下面是一份 JSON 格式的创世配置示例:

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

根据配置用途可分为三大类:

  1. 链配置
    config项是定义链配置,会影响共识协议,虽然链配置对创世影响不大,但新区块的出块规则均依赖链配置。
  2. 创世区块头信息配置
    • nonce:随机数,对应创世区块 Nonce 字段。
    • timestamp:UTC时间戳,对应创世区块 Time字段。
    • extraData:额外数据,对应创世区块 Extra 字段。
    • gasLimit必填,燃料上限,对应创世区块 GasLimit 字段。
    • difficulty必填,难度系数,对应创世区块 Difficulty 字段。搭建私有链时,需要根据情况选择合适的难度值,以便调整出块。
    • minHash:一个哈希值,对应创世区块的MixDigest字段。和 nonce 值一起证明在区块上已经进行了足够的计算。
    • coinbase:一个地址,对应创世区块的Coinbase字段。
  3. 初始账户资产配置
    alloc 项是创世中初始账户资产配置。在生成创世区块时,将此数据集中的账户资产写入区块中,相当于预挖矿。这对开发测试和私有链非常好用,不需要挖矿就可以直接为任意多个账户分配资产。

自定义创世

如果你计划部署以太坊私有网络或者一个独立的测试环境,那么需要自定义创世,并初始化它。为了统一沟通,推荐先在用户根目录创建一个文件夹 deepeth,以做为《以太坊设计与实现》电子书学习工作目录。

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

再准备两个以太坊账户,以便在创世时存入资产。

geth --datadir $HOME/deepeth account new

因为是学习使用,推荐使用统一密码 foobar,执行两次命令,创建好两个账户。这里使用 --datadir 参数指定以太坊运行时数据存放目录,是让大家将数据统一存放在一个本课程学习文件夹中。

再将下面配置内容保存到 $HOME/deepeth/genesis.json 文件,其中 alloc 项替换成刚刚创建的两个以太坊账户地址。

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

然后,执行 geth 子命令 init 初始化创世区块。

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

执行成功后,便可启动该私有链:

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

执行如下命令,可以查看到前面创建的两个账户,均已有资产:

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

至此,我们已完成创世定制版。

内置的创世配置

上面我已完成自定义创世,但以太坊作为去中心平台,需要许多节点一起参与。仅仅为了测试,多个节点来搭建私有链比较麻烦。如果希望和别人一起联调,或者需要在测试网络中测试DAPP时,该怎么办呢?那么,可使用以太坊测试网络。以太坊公开的测试网络有 5 个,目前仍在运行的有 4 个,具体见下表格。

测试网 共识机制 出块间隔 提供方 上线时间 备注 状态
Morden PoW 以太坊官方 2015.7 因难度×××被迫退役 stopped
Ropsten PoW 30秒 以太坊官方 2016.11 接替Morden running
Kovan PoA 4秒 以太坊钱包Parity开发团队 2017.3 不支持geth running
Rinkeby PoA 15秒 以太坊官方 2017.4 最常用,只支持geth running
Sokol PoA 5秒 以太坊官方POA.network团队 2017.12 不支持geth running
G?rli PoA 15秒 以太坊柏林社区 2018.9 首个以太坊2.0实验场 running

支持 geth 的3个测试网络的创世配置已内置在以太坊代码中,具体见 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{}

当然不会缺以太坊主网创世配置,也是 geth 运行的默认配置。

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

如果你不想自定义创世配置文件用于开发测试,那么以太坊也提供一份专用于本地开发的配置。


// 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 模式会自动创建一个空密码的账户,并开启挖矿。当有新交易时,将立刻打包出块。

geth 创世区块加载流程

在运行 geth 时需根据配置文件加载创世配置以及创世区块,并校验其合法性。如果配置信息随意变更,易引起共识校验不通过等问题。只有在加载并检查通过时,才能继续运行程序。

<img src="https://img.learnblockchain.cn/2019/04/07_20190407101509.png" width="400px" alt="创世加载流程">

上图是一个简要流程,下面分别讲解“加载创世配置”和“安装创世区块”两个子流程。

加载创世配置

应使用哪种创世配置,由用户在启动 geth 时决定。下图是创世配置选择流程图:br/>![以太坊创世配置选择流程图](https://img.learnblockchain.cn/2019/04/[email protected])
通过 geth 命令参数可选择不同网络配置,可以通过 networkid 选择,也可使用网络名称启用。

  1. 使用 networkid:
    不同网络使用不同ID标识。

    • 1=Frontier,主网环境,是默认选项。
    • 2=Morden 测试网络,但已禁用。
    • 3=Ropsten 测试网络。
    • 4=Rinkeby 测试网络。
  2. 直接使用网络名称:
    • testnet: Ropsten 测试网络。
    • rinkeby: Rinkeby 测试网络。
    • goerli: G?rli 测试网络。
    • dev: 本地开发环境。

geth 启动时根据不同参数选择加载不同网络配置,并对应不同网络环境。如果不做任何选择,虽然在此不会做出选择,但在后面流程中会默认使用主网配置。

安装创世区块

上面已初步选择创世配置,而这一步则根据配置加载或者初始化创世单元。下图是处理流程:

首先,需要从数据库中根据区块高度 0 读取创世区块哈希。如果不存在则说明本地属于第一次启动,直接使用运行时创世配置来构建创世区块。属于首次,还需要存储创世区块和链配置。

如果存在,则需要使用运行时创世配置构建创世区块并和本次已存储的创世区块哈希进行对比。一旦不一致,则返回错误,不得继续。

随后,还需要检查链配置。先从数据库获取链配置,如果不存在,则无需校验直接使用运行时链配置。否则,需要检查运行时链配置是否正确,只有正确时才能替换更新。但有一个例外:主网配置不得随意更改,由代码控制而非人为指定。

总的来说,以太坊默认使用主网配置,只有在首次运行时才创建和存储创世区块,其他时候仅仅用于校验。而链配置除主网外则在规则下可随时变更。

构建创建区块

上面我们已知晓总体流程,这里再细说下以太坊是如何根据创世配置生成创世区块。核心代码位于 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)//?
}

上面代码是根据创世配置生成创世区块的代码逻辑,细节如下:

  • ? 创世区块无父块,从零初始化全新的 state(后续文章会详细讲解 state对象)。
  • ? 遍历配置中 Alloc 项账户集合数据,直接写入 state 中。
    这里不单可以设置 balance,还可以设置 codenonce 以及任意多个 storage 数据。
    意味着创世时便可以直接部署智能合约。例如下面配置则在创世时部署了一个名为093f59f1d91017d30d8c2caa78feb5beb0d2cfaf 的智能合约。
    "alloc": {
            "093f59f1d91017d30d8c2caa78feb5beb0d2cfaf": {
                "balance": "0xffffffffffffffff",
                "nonce": "0x3",
                "code":"0x606060",
                "storage":{
                "11bbe8db4e347b4e8c937c1c8370e4b5ed33adb3db69cbdb7a38e1e50b1b82fa":"1234ff"
                }
            }
    }
  • ? 将账户数据写入 state 后,便可以计算出 state 数据的默克尔树的根值,称之为 StateRoot
    此值记录在区块头 Root 字段中。
  • ? 创世配置的一部分配置,则直接映射到区块头中,完成创世区块头的构建。
  • ? 因为 GasLimitDifficulty 直接影响到下一个区块出块处理。
    因此未设置时使用默认配置(Difficulty=131072,GasLimit=4712388)。
  • ? 提交 state,将 state 数据提交到底层的内存 trie 数据中。
  • ? 将内存 trie 数据更新到 db 中。
    这是多余的一步,因为提交到数据库是由外部进行,这里只需要负责生成区块。
  • ? 利用区块头创建区块,且区块中无交易记录。

深入浅出区块链 - 系统学习区块链,学区块链都在这里,打造最好的区块链技术博客。

原文地址:https://blog.51cto.com/13457438/2384805

时间: 2024-10-07 22:11:00

以太坊创世区块与链配置载入分析的相关文章

F3D系统开发以太坊Fomo3D区块链模式

Fomo3D(F3D)以太坊ETH底层技术系统开发空气-陳洋1 5 0 1*3 1 5 1*7 4 0电T微.现代经济体系正在朝着分布式.点对点.网络化的结构进行演化.分布式账本技术吸收了现代密码学.安全通讯.可信计算.对等网络和博弈论的研究成果,尝试构建一个分布式.防篡改.异构多活和灵活定制的计算架构,以求支撑数字经济时代的业务需求.分布式账本技术还处于它的早期阶段,我们可以将其视为一种"组合式创新"(Combinatorial Innovation),运用创新经济学的理论研究它的应

EOS和以太坊那个区块链平台更好?

显然,你已经听说过两个最受欢迎的智能合约区块链,但想知道EOS与以太坊之中哪个更好?或许你想比较一下两种技术?好吧,你来对了地方,因为我要告诉你你需要知道的一切! 在这个EOS vs Ethereum指南中,我将首先解释每个项目的基础知识,然后概述每个区块链的执行情况.这将包括交易时间,交易费用和可扩展性等内容. 之后,我将简要介绍如何在没有第三方的情况下验证交易.这将包括以太坊使用的工作量证明(Proof of Work)与EOS使用的股份授权证明(Delegated Proof of Sta

Flume-NG源码分析-整体结构及配置载入分析

在 http://flume.apache.org 上下载flume-1.6.0版本,将源码导入到Idea开发工具后如下图所示: 一.主要模块说明 flume-ng-channels 里面包含了filechannel,jdbcchannel,kafkachannel,memorychannel通道的实现. flume-ng-clients 实现了log4j相关的几个Appender,使得log4j的日志输出可以直接发送给flume-agent:其中有一个LoadBalancingLog4jApp

(转)写文章 以太坊(Ethereum)创世揭秘 以太坊(Ethereum)创世揭秘

什么是以太坊(Ethereum) 以太坊(Ethereum)是一个基于区块链技术,允许任何人构建和使用去中心化应用的区块链平台.像比特币一样,以太坊是开源的,并由来自全世界的支持者们共同维护.与比特币仅提供了有限功能的脚本不同,以太坊提供了一个"图灵完备"的虚拟机,称为以太坊虚拟机(Ethereum Virtual Machine),简称EVM,用户可以在EVM上创建智能合约(Smart Contract).以太坊平台中的通用货币为以太币(Ether),简称ETH,以太币可用于账号间的

PoW挖矿算法原理及其在比特币、以太坊中的实现

PoW,全称Proof of Work,即工作量证明,又称挖矿.大部分公有链或虚拟货币,如比特币.以太坊,均基于PoW算法,来实现其共识机制.即根据挖矿贡献的有效工作,来决定货币的分配.? 比特币区块 ? 比特币区块由区块头和该区块所包含的交易列表组成.区块头大小为80字节,其构成包括:? 4字节:版本号 32字节:上一个区块的哈希值 32字节:交易列表的Merkle根哈希值 4字节:当前时间戳 4字节:当前难度值 4字节:随机数Nonce值? 此80字节长度的区块头,即为比特币Pow算法的输入

第一行代码:以太坊(1)-创建自己的私有区块链

本文会利用以太坊客户端(geth)搭建一个私有区块链,并在这个私有区块链上挖矿,通过本文的案例,读者可以更深入理解区块链.以太坊.挖矿的理论. 通过阅读本文,您可以: 掌握搭建以太坊开发环境的方法 掌握geth的基本使用方法 了解如何启动JavaScript控制台 掌握建立一个私有区块链的步骤 掌握如何在私有区块链上挖矿 1. 以太坊(Ethereum)开发环境搭建 在玩以太坊之前,首先要搭建以太坊的开发环境.第一步就是安装geth.那么geth是什么呢?geth(或称为go-ethereum)

如何从零开始学习区块链技术——推荐从以太坊开发DApp开始

很多人迷惑于区块链和以太坊,不知如何学习,本文简单说了一下学习的一些方法和资源. 一. 以太坊和区块链的关系 从区块链历史上来说,先诞生了比特币,当时并没有区块链这个技术和名词,然后业界从比特币中提取了技术架构和体系,称之为区块链技术.从比特币提取的区块链技术称之为区块链1.0时代,那个时候的应用主要以电子货币和去中心化交易为主,比如各种山寨币.而以太坊将区块链带入了2.0的时代,区块链2.0不是推翻了1.0,而是在1.0的基础上实现了区块知晓.价值知晓.图灵完备,并进行了细节优化,从而形成了以

爆炒区块链3.0概念,EOS想超ETH(以太坊),没那么简单!

2017年6月25日,EOS开始上线众筹,时间为一年!也就是说,EOS众筹结束时间要到2018年6月.自EOS众筹以来,炒得最多的就是区块链3.0概念,比如要超越以太坊,要做真正的区块链操作系统-- 那么,这个目前还在概念中的EOS,真的可以取代以太坊吗?我们一起来看看. 一.从以太坊说起 Ethereum(以太坊)是由俄罗斯人Vitalik Buterin于2014年创建的开源区块链平台,用户可以使用它来创建和发布去中心化的应用程序.Ethereum可以用来编程,分散,担保和交易任何事物:投票

一文读懂比特币、以太币和区块链

8年,比特币创造一个神话——价格上涨近300万倍,国内价格一度突破2万元.在这场神话中,不同的人看到了不同的故事.投机者看到了赚钱的机会,技术极客看到了改变未来的技术,传统金融机构则或许看到了一个不断成长的幽灵…… 今天,星河研究院谈点轻松的内容,介绍一下电子支付行业最火的两个兄弟比特币.以太坊及其底层的区块链技术.它们真的能重塑世界经济吗?看完这篇文章之后,希望你能得到自己的答案. 比特币诞生,革命的开始? 提到电子支付行业,我们最先想到的要么是支付宝要么是微信.其实,在这两个巨头背后,还有两