以太坊区块链 (区块的资料结构)


以太坊的资料储存可以分为 3 种:

  • 状态资料: 以太坊帐户相关的状态资料,使用 StateDB 储存与管理帐户,每一个帐户都是一个 StateObject。

  • 区块链: 以太坊的核心资料,跟 bitcoin 很像但又有一点进化。

  • 底层资料: 储存全部的以太坊资料,以 key-value 的形式存于 LevelDB 中。


  • Tips:

    以太坊资料储存在 LevelDB 中。

    LevelDB 是 Google 推出的一款 key-value database。

    目前以太坊中共有 3 个 LevelDB,分别是 BlockDB, StateDB, ExtrasDB。

    • BlockDB: 保存区块主体内容 (包括区块头部,与区块体)。
    • StateDB: 保存帐号状态资料。
    • ExtrasDB: 保存交易收据资料以其其他辅助资料。

    以太坊资料结构

    下图中是以太坊在 1.0 版本 PoW 时代的资料结构示意图,有部分栏位在 2.0 PoS 时代已被移除,我会在后续单独解释每一个栏位时注明。

    状态资料

    状态资料以 MPT 的形式储存在 StateDB 中。MPT 是兼具 Merkle Tree & Patricia Tree 特点的一种新的树状资料结构。

    MPT 特点:

    • 可以储存任意长度的 key-value pairs。
    • 具备 Merkle Tree 的特点,可以用于节点快速校验。
    • 能够很快速的根据 key 查到 value。

    MPT 中包含 shortNode,fullNode,valueNode 还有 hashNode 这四种节点。

    shortNode 与 fullNode 是分枝节点,他们可以有个自的子节点。但要注意 shortNode 只能有一个子节点,而 fullNode 可以有多个。

    valueNode 与 hashNode 是叶子节点。valueNode 用于储存资料,值为从 root 节点到当前节点的路径上所有节点的 key 之合。hashNode 用于储存资料库中其他节点的 hash 值。

    区块链

    ETH 区块链的结构有 2 点与 BTC 区块链相同:

  • ETH 区块链也是由父区块的 hash 值将区块连接在一起(指向前一个区块的指针)。

  • ETH 区块链也是由区块头跟区块体组成。区块头与区块体结构如下:

  • 上图中出现的名词说明:

    • ParentHash: 父区块的 Hash 值。

    • CoinBase: 币基地址,矿工的钱包地址(挖出区块的奖励接收者)。

    • UncleHash(适用于 PoW,以太坊 2.0 中已移除): 当前区块引用的叔叔区块集合的 Merkle 数根 Hash。叔叔区块是曾经以太坊 Pow 时期的特色之一。

      当两个矿工几乎同时挖出新区块时,由于网络传播的延迟,部分矿工可能首先接收到 A 矿工的区块,另一些矿工可能先接收到 B 矿工的区块。结果是网络中暂时出现两条区块链分支。

      矿工们通常会遵循它们首先收到的区块,并将其视为主链的一部分,然后矿工们开始继续在所接收的区块上进行挖矿,形成两个分支各自延续的情况。

      比特币解决分叉的方式:

      • 长链原则(Longest Chain Rule):

        • 比特币协议规定,节点会认为工作量证明(Proof of Work)最长的链是正确的主链。

        • 当新的区块被加入其中一条链后,该链变得更长,其它节点会切换到该更长的链。

      • 孤块(Orphan Block):

        • 较短的链(即未被选择的链)上的区块称为「孤块」,不再被网络承认。孤块中的交易会返回到内存池中,等待重新被打包到主链的区块中。
      • 处理孤块的影响:

        • 交易不丢失:被包含在孤块中的交易(未在其他区块中确认的交易)会被返回到网络的内存池中,等待其他矿工再次打包。

        • 矿工的损失:挖出孤块的矿工无法获得该区块的区块奖励和交易手续费。

        • 网络一致性:一旦网络回到单一主链,所有节点达成共识,分叉自然消失。

      当两个矿工几乎同时挖出区块时,比特币网络会暂时分叉,但基于「长链原则」,最终一条分支会被选为主链,另一条分支成为孤块而被放弃。这种机制保证了区块链的一致性和安全性。

      以太坊解决分叉的方式:

      以太坊的叔叔块是指那些被有效挖出但未成为主链一部分的区块,与比特币中的「孤块」不同,叔叔块仍然能获得一定的区块奖励。

      以太坊遇到暂时性分岔处理过程如下:

    • 确认主链:

      如果出现暂时分叉,矿工最终会选择基于「长链原则」的主链。

    • 叔叔块奖励:

      被排除在主链之外的叔叔块仍然可以提交到网络,并获得一定比例的奖励(离主链越近的叔叔块奖励越高)。包含叔叔块的主链区块的矿工也能获得额外的奖励 (一个主链区块最多可以有 2 个 叔叔块,多少还是要限制一下产量)。

    • 网络一致性:

      因为叔叔块仍然有价值,矿工的算力竞争不会完全浪费,这减少了因分叉导致的资源浪费。

    • Root: StateDB 中 MPT 的树根 Hash 值。MPT 中存有所有以太坊帐户资料。

    • TxHash: 交易集合的 Merkle 数根 Hash,所有交易打包到一个区块中后会形成这个树根。

    • ReceiptHash: 纪录所有收据资料的 MPT 树根 Hash 值,Receipt 中的纪录包含交易被包在哪个区块,这笔交易花费多少 Gas,以及一些交易 log。

    • Bloom: 用于快速搜寻与判断一个 log 是否存在于 Receipt 中。

      补充:Bloom Filter 是一种空间效率很高的数据结构,用于快速检索特定事件是否在交易执行日誌(Logs)中。

    • Difficulty(适用于 PoW,以太坊 2.0 中已移除): Pow 共识算法中挖矿难度的 factor。

    • Nonce(适用于 PoW,以太坊 2.0 中已移除): 它是矿工通过不断变化来满足挖矿条件的随机数,与 MixHash 一起证明工作量的合法性。

    • MixHash(适用于 PoW,以太坊 2.0 中已移除): 挖矿计算过程中生成的最终随机值,用于验证这个区块是否满足 PoW 要求。

    • Number: 区块编号。

    • Time: 生成区块的时间戳。

    • GasLimit: 该区块可容纳的最大 Gas 量,防止单一区块因过多交易导致处理过于缓慢。

    • GasUsed: 区块中实际消耗的 Gas,通常低于或等于 GasLimit。

    • extraData: 留给区块的建立者纪录自定义讯息,长度小于 32 bytes。

    交易 (Tx) 由下几个参数组成:

    • GasPrice: Gas 的价格,单位是 wei,GasPrice 越高越优先被矿工打包。

    • GasLimit: 设置执行合约或交易的资源使用上限,防止无法完成交易时资源浪费。

    • Recipient: 交易收据。

    • Amount: 交易金额。

    • Payload: 包含执行合约的具体资料,对于部署智能合约的交易尤为重要。

    • R,S,V: 用户请求交易的签名。