以太坊系列---Block核心数据结构

在Ethereum的世界里,数据的最终存储形式是[k,v]键值对,目前使用的[k,v]型底层数据库是LevelDB;所有与交易,操作相关的数据,其呈现的集合形式是Block(Header);如果以Block为单位链接起来,则构成更大粒度的BlockChain(HeaderChain);若以Block作切割,那么Transaction和Contract就是更小的粒度;所有交易或操作的结果,将以各个个体账户的状态(state)存在,账户的呈现形式是stateObject,所有账户的集合受StateDB管理。下图描绘了上述各数据单元的层次关系:
另一方面,上述数据单元如Block,stateObject,StateDB等,均大量使用Merkle-PatriciaTrie(MPT)数据结构以组织和管理[k,v]型数据。利用MPT高效的分段哈希验证机制和灵活的节点(Node)插入/载入设计,调用方均可快速且高效的实现对数据的插入、删除、更新、压缩和加密。

Block和Header

Block结构体基本可分为Header和Body两个部分

Header是Block的核心,注意到它的成员变量全都是公共的,这使得它可以很方便的向调用者提供关于Block属性的操作。Header的成员变量全都很重要,值得细细理解:

  • ParentHash:指向父区块(parentBlock)的指针。除了创世块(Genesis Block)外,每个区块有且只有一个父区块。
  • Coinbase:挖掘出这个区块的作者地址。在每次执行交易时系统会给与一定补偿的Ether,这笔金额就是发给这个地址的。
  • UncleHash:Block结构体的成员uncles的RLP哈希值。uncles是一个Header数组,它的存在,颇具匠心。
  • Root:StateDB中的“state Trie”的根节点的RLP哈希值。Block中,每个账户以stateObject对象表示,账户以Address为唯一标示,其信息在相关交易(Transaction)的执行中被修改。所有账户对象可以逐个插入一个Merkle-PatricaTrie(MPT)结构里,形成“state Trie”。
  • TxHash: Block中 “tx Trie”的根节点的RLP哈希值。Block的成员变量transactions中所有的tx对象,被逐个插入一个MPT结构,形成“tx Trie”。
  • ReceiptHash:Block中的 “Receipt Trie”的根节点的RLP哈希值。Block的所有Transaction执行完后会生成一个Receipt数组,这个数组中的所有Receipt被逐个插入一个MPT结构中,形成”Receipt Trie”。
  • Bloom:Bloom过滤器(Filter),用来快速判断一个参数Log对象是否存在于一组已知的Log集合中。
  • **Difficulty:区块的难度。Block的Difficulty由共识算法基于parentBlock的Time和Difficulty计算得出,它会应用在区块的‘挖掘’阶段。
  • Number:区块的序号。Block的Number等于其父区块Number +1。
  • Time:区块“应该”被创建的时间。由共识算法确定,一般来说,要么等于parentBlock.Time + 10s,要么等于当前系统时间。
  • GasLimit:区块内所有Gas消耗的理论上限。该数值在区块创建时设置,与父区块有关。具体来说,根据父区块的GasUsed同GasLimit * 2/3的大小关系来计算得出。
  • GasUsed:区块内所有Transaction执行时所实际消耗的Gas总和。
  • Nonce:一个64bit的哈希数,它被应用在区块的”挖掘”阶段,并且在使用中会被修改。

Root,TxHash和ReceiptHash,分别取自三个MPT类型对象:stateTrie, txTrie, 和receiptTrie的根节点哈希值。
receiptTrie 必须在Block的所有交易执行完成才能生成;txTrie 理论上只需tx数组transactions即可,不过依然被限制在所有交易执行完后才生成;最有趣的是stateTrie,由于它存储了所有账户的信息,比如余额,发起交易次数,虚拟机指令数组等等,所以随着每次交易的执行,stateTrie 其实一直在变化,这就使得Root值也在变化中。

Bloom:日志布隆过滤器 2048bit 256字节
用户可以通过传递下面的参数来查找指定的Log,开始的区块号,结束的区块号, 根据合约 Addresses指定的地址过滤,根据指定的Topics来过滤。

BlockChain

type BlockChain struct {
    config *params.ChainConfig // chain & network configuration

    hc            *HeaderChain      // 只包含了区块头的区块链
    chainDb       ethdb.Database    // 底层数据库
    rmLogsFeed    event.Feed        // 下面是很多消息通知的组件
    chainFeed     event.Feed
    chainSideFeed event.Feed
    chainHeadFeed event.Feed
    logsFeed      event.Feed
    scope         event.SubscriptionScope
    genesisBlock  *types.Block      // 创世区块

    mu      sync.RWMutex // global mutex for locking chain operations
    chainmu sync.RWMutex // blockchain insertion lock
    procmu  sync.RWMutex // block processor lock

    checkpoint       int          // checkpoint counts towards the new checkpoint
    currentBlock     *types.Block //  当前的区块头
    currentFastBlock *types.Block // 当前的快速同步的区块头.

    stateCache   state.Database // State database to reuse between imports (contains state cache)
    bodyCache    *lru.Cache     // Cache for the most recent block bodies
    bodyRLPCache *lru.Cache     // Cache for the most recent block bodies in RLP encoded format
    blockCache   *lru.Cache     // Cache for the most recent entire blocks
    futureBlocks *lru.Cache     // 暂时还不能插入的区块存放位置.

    quit    chan struct{} // blockchain quit channel
    running int32         // running must be called atomically
    // procInterrupt must be atomically called
    procInterrupt int32          // interrupt signaler for block processing
    wg            sync.WaitGroup // chain processing wait group for shutting down

    engine    consensus.Engine  // 一致性引擎
    processor Processor // block processor interface  // 区块处理器接口
    validator Validator // block and state validator interface // 区块和状态验证器接口
    vmConfig  vm.Config //虚拟机的配置

    badBlocks *lru.Cache // Bad block cache  错误区块的缓存.
}

小结

以太坊的账号模型相对于比特币UTXO模型更加复杂。需要维护日志,StateDB,账号余额等数据,值得去深入学习使用。

  • Block结构体主要分为Header和Body,Header相对轻量,涵盖了Block的所有属性,包括特征标示,前向指针,和内部数据集的验证哈希值等;Body相对重量,持有内部数据集。每个Block的Header部分,Body部分,以及一些特征属性,都以[k,v]形式单独存储在底层数据库中。
  • BlockChain管理Block组成的一个单向链表,HeaderChain管理Header组成的单向链表,并且BlockChain持有HeaderChain。在做插入/删除/查找时,要注意回溯,以及数据库中相应的增删。
  • Merkle-PatriciaTrie(MPT)数据结构用来组织管理[k,v]型数据,它设计了灵活多变的节点体系和编码格式,既融合了多种原型结构的优点,又兼顾了业务需求和运行效率。
  • StateDB作为本地存储模块,它面向业务模型,又连接底层数据库,内部利用两极缓存机制来存储和更新所有代表“账户”的stateObject对象。
  • stateObject除了管理着账户余额等信息之外,也用了类似的两级缓存机制来存储和更新所有的State数据。

猜你喜欢

转载自blog.csdn.net/niyuelin1990/article/details/80423823