Skip to content
MathxH Chen edited this page Aug 23, 2018 · 8 revisions

区块

概述

源文件
block.h CBlock

区块的数据结构


区块在源码中以类CBlock表现,与比特币底层的区块不一样的是,它不分区块的header和body两部分。CBlock的数据字段都作为类成员,作为一个整体, 以下是区块的各个字段,在block.h文件中能查到:

    uint16  nVersion; // 版本号,目前区块版本为 0x0001
    uint16  nType; // 类型,区分创世纪块、主链区块、业务区块和业务子区块
    uint32  nTimeStamp; // 时间戳,采用UTC秒单位
    uint256 hashPrev; // 前一区块的hash
    uint256 hashMerkle; // Merkle tree的根
    std::vector<uint8> vchProof;  // 用于校验共识合法性数据
    CTransaction txMint; // 出块奖励交易
    std::vector<CTransaction> vtx; // 区块打包的所有交易
    std::vector<uint8> vchSig;// 区块签名
  1. nType字段表明区块的类型,分为区分创世纪块、主链区块、业务区块和业务子区块,以C++ 中的enum class表示:
    enum
    {
        BLOCK_GENESIS    = 0xffff,  // 创世区块
        BLOCK_ORIGIN     = 0xff00,  // 分支的起始区块
        BLOCK_PRIMARY    = 0x0001,  // 主链区块
        BLOCK_SUBSIDIARY = 0x0002,  // 业务子区块
        BLOCK_EXTENDED   = 0x0004,  // 业务区块
    };
  1. hashMerkle字段,表示Merkle tree root。用于快速验证交易是否合法。它的值是通过对vtx字段里的所有交易的Hash两两结合Hash,递归迭代的Hash计算出的值,Hash算法是blake2b算法。构建Merkle tree的算法在block.h中的函数中:
uint256 BuildMerkleTree(std::vector<uint256>& vMerkleTree) const // 函数返回Merkle tree root的值
  1. vchProof字段为了校验共识合法性数据,与比特币区块不一样的地方是,这个字段很容易与比特币区块头中的nonce随机数字段混淆,其实它的意义与nonce 完全不一样。 比特币区块头中的nonce随机数是矿池中的矿机,不停的生成随机数,使随机数的Hash的结果与难度目标是否一样,如果为真,那么最先计算出来的矿机就有了出块的权利,由这台矿机来打包网络中的新交易。

  2. txMint字段,相当于比特币中的Coinbase交易,就是打包费用,给矿机的。

  3. vchSig字段,区块签名 vchSig 使用 txMint 输出地址进行签名,签名数据段包含除 vchSig 以外所有字段。

CBlock类提供的主要方法


  1. 设置区块为空。
void SetNull();
  1. 判断区块是否为空。
bool IsNull() const;
  1. 判断区块是否是起源区块。
bool IsOrigin() const;

起源区块的意思就是分支的最开始的那一块区块,主链的创世区块也是一种起源区块。

  1. 判断区块是否是主链区块。
bool IsPrimary() const;
  1. 判断区块是否是PoW共识算法生成的块。是通过矿机费用的交易类型判断的,如果出块交易的类型是Pow,那么此区块就是Pow块
    bool IsProofOfWork() const
    {
        return (txMint.nType == CTransaction::TX_WORK);
    }
  1. 得到块的信标
uint64 GetBlockBeacon(int idx = 0) const;

该方法得到的信标值用来参与BlockIndex的计算,BlockIndex是块链以文件的方式存储到节点本地,通过BlockIndex与块关联上,提高在块文件中 查找block的效率。

  1. 得到块的Trust值
uint64 GetBlockTrust() const;

该方法得到的Trust值用来参与BlockIndex的计算,同上。

  1. 构建Merkle Tree,并返回Merkle Tree root
    uint256 BuildMerkleTree(std::vector<uint256>& vMerkleTree) const; // 返回Merkle Tree的root
    
    uint256 CalcMerkleTreeRoot() const
    {
        std::vector<uint256> vMerkleTree; //临时存放树的节点的vector对象,用于辅助计算Merkle tree root
        return BuildMerkleTree(vMerkleTree);
    }

对Merkle Tree的详细理解,可以参考这篇文章

  1. 得到区块的Hash.
    uint256 GetHash() const
    {
        walleve::CWalleveBufStream ss;
        ss << nVersion << nType << nTimeStamp << hashPrev << hashMerkle << vchProof << txMint;
        return multiverse::crypto::CryptoHash(ss.GetData(),ss.GetSize());
    }

计算除去vtx,vchSig字段外所有字段的Hash,就是一个区块的Hash。

整理者 日期
Shaohan Chen 2018.08.08