bitcoin源码分析 – 区块数据

Block — 数据

区块数据结构

block.h block.cpp

class CBlockHeader
{
public:
    // header
    int32_t nVersion;
    uint256 hashPrevBlock;
    uint256 hashMerkleRoot;
    uint32_t nTime;
    uint32_t nBits;
    uint32_t nNonce;

nTime表示时间戳, 如果当前区块的时间戳大于前11个区块的平均时间戳, 并且小于网络调整时间(Network Adjust Time)+2小时, 则认为该时间戳是有效的; 网络调整时间是指与之连接的所有节点的平均时间。
Adjust Time相关源码可以参考: NetMsgType::VERSION AddTimeData相关部分。

nBits即target, 表示挖矿难度。
nNonce表示随机数, 用来产生hash。

class CBlock : public CBlockHeader
{
public:
    // network and disk
    std::vector<CTransactionRef> vtx;
struct CBlockLocator
{
    std::vector<uint256> vHave;

uint256为Block唯一标示, 高度在某些场合下也可以标示Block, 但不唯一。
此结构用来获取hashBlock集合, 在CChain里和CWalletDB里等用到。

chain.h chain.cpp

class CBlockIndex
{
public:
    //! pointer to the hash of the block, if any. Memory is owned by this CBlockIndex
    const uint256* phashBlock;

    //! pointer to the index of the predecessor of this block
    CBlockIndex* pprev;

    //! pointer to the index of some further predecessor of this block
    CBlockIndex* pskip;

    //! height of the entry in the chain. The genesis block has height 0
    int nHeight;

    //! Which # file this block is stored in (blk?????.dat)
    int nFile;

    //! Byte offset within blk?????.dat where this block's data is stored
    unsigned int nDataPos;

    //! Byte offset within rev?????.dat where this block's undo data is stored
    unsigned int nUndoPos;

    //! (memory only) Total amount of work (expected number of hashes) in the chain up to and including this block
    arith_uint256 nChainWork;

    //! Number of transactions in this block.
    //! Note: in a potential headers-first mode, this number cannot be relied upon
    unsigned int nTx;

    //! (memory only) Number of transactions in the chain up to and including this block.
    //! This value will be non-zero only if and only if transactions for this block and all its parents are available.
    //! Change to 64-bit type when necessary; won't happen before 2030
    unsigned int nChainTx;

    //! Verification status of this block. See enum BlockStatus
    uint32_t nStatus;

    //! block header
    int32_t nVersion;
    uint256 hashMerkleRoot;
    uint32_t nTime;
    uint32_t nBits;
    uint32_t nNonce;

    //! (memory only) Sequential id assigned to distinguish order in which blocks are received.
    int32_t nSequenceId;

    //! (memory only) Maximum nTime in the chain up to and including this block.
    unsigned int nTimeMax;

可见, CBlockIndex既包含了blockheader, 又对应了block的持久化数据。

class CChain {
private:
    std::vector<CBlockIndex*> vChain;

区块形成链条。

其它

class CBlockFileInfo
{
public:
    unsigned int nBlocks;      //!< number of blocks stored in file
    unsigned int nSize;        //!< number of used bytes of block file
    unsigned int nUndoSize;    //!< number of used bytes in the undo file
    unsigned int nHeightFirst; //!< lowest height of block in file
    unsigned int nHeightLast;  //!< highest height of block in file
    uint64_t nTimeFirst;       //!< earliest time of block in file
    uint64_t nTimeLast;        //!< latest time of block in file

class CDiskBlockIndex : public CBlockIndex
{
public:
    uint256 hashPrev;

CBlockFileInfo与CDiskBlockIndex对应持久化数据。

区块与交易硬盘数据

block数据

目录:blocks/blk******.dat, rev******.dat(回滚数据)
大小:180G左右(2018/05)
读写:ReadBlockFromDisk WriteBlockToDisk OpenBlockFile FlushBlockFile UndoReadFromDisk UndoWriteToDisk

block index数据

目录:blocks/index/*.ldb
大小:80M左右(2018/05)
读写:CBlockTreeDB (std::unique_ptr<CBlockTreeDB> pblocktree)
)

utxo数据

目录:chainstate/*.ldb
大小:2.8G 左右(2018/05)
读写:CCoinsViewDB (std::unique_ptr<CCoinsViewDB> pcoinsdbview)

transaction index数据(-txindex=1选项产生)

目录: indexes/txindex/*.ldb
读写:TxIndexDB (std::unique_ptr<TxIndex> g_txindex)

区块与交易内存数据

Cache分配

init Step 7: load block chain:
在64位机器上,total cache 默认为1800M, 32位机器1024M
其中,nBlockTreeDBCache=1800/8M=225M

剩下的1800M-225M=1575M里面:
25%-50%作为nCoinDBCache
剩下的作为nCoinCacheUsage

nMempoolSizeMax=300*1000000=300M

block index database —-nBlockTreeDBCache
chain state database —-nCoinDBCache
in-memory UTXO set —— nCoinCacheUsage
unused mempool space——nMempoolSizeMax

std::unique_ptr<CCoinsViewDB> pcoinsdbview;
std::unique_ptr<CCoinsViewCache> pcoinsTip;

std::unique_ptr<CBlockTreeDB> pblocktree;

BlockIndex缓存数据

CChainState 存放BlockIndex缓存数据

class CChainState {
public:
	CChain chainActive;
	BlockMap mapBlockIndex;
} g_chainstate;

typedef std::unordered_map<uint256, CBlockIndex*, BlockHasher> BlockMap;
CChain: std::vector<CBlockIndex*> vChain;

init LoadBlockIndex会加载所有index数据到mapBlockIndex 。

交易缓存数据

CTxMemPool 存放交易缓存数据, 准确地说CTxMemPool stores valid-according-to-the-current-best-chain transactions that may be included in the next block.

CTxMemPool mempool(&feeEstimator);
LoadMempool(ThreadImport里调用, 读入mempool.dat)
DumpMempool(ShutDown里调用, 写入mempool.dat)
AcceptToMemoryPool(主要是NetMsgType::TX消息)

class CTxMemPool
{
typedef boost::multi_index_container<
        CTxMemPoolEntry,
        boost::multi_index::indexed_by<
            // sorted by txid
            boost::multi_index::hashed_unique<mempoolentry_txid, SaltedTxidHasher>,
            // sorted by fee rate
            boost::multi_index::ordered_non_unique<
                boost::multi_index::tag<descendant_score>,
                boost::multi_index::identity<CTxMemPoolEntry>,
                CompareTxMemPoolEntryByDescendantScore
            >,
            // sorted by entry time
            boost::multi_index::ordered_non_unique<
                boost::multi_index::tag<entry_time>,
                boost::multi_index::identity<CTxMemPoolEntry>,
                CompareTxMemPoolEntryByEntryTime
            >,
            // sorted by fee rate with ancestors
            boost::multi_index::ordered_non_unique<
                boost::multi_index::tag<ancestor_score>,
                boost::multi_index::identity<CTxMemPoolEntry>,
                CompareTxMemPoolEntryByAncestorFee
            >
        >
    > indexed_transaction_set;

    mutable CCriticalSection cs;
    indexed_transaction_set mapTx GUARDED_BY(cs);
class CTxMemPoolEntry
{
private:
    CTransactionRef tx;
    CAmount nFee;              //!< Cached to avoid expensive parent-transaction lookups
    size_t nTxWeight;          //!< ... and avoid recomputing tx weight (also used for GetTxSize())
    size_t nUsageSize;         //!< ... and total memory usage
    int64_t nTime;             //!< Local time when entering the mempool
    unsigned int entryHeight;  //!< Chain height when entering the mempool
    bool spendsCoinbase;       //!< keep track of transactions that spend a coinbase
    int64_t sigOpCost;         //!< Total sigop cost
    int64_t feeDelta;          //!< Used for determining the priority of the transaction for mining in a block
    LockPoints lockPoints;     //!< Track the height and time at which tx was final

    // Information about descendants of this transaction that are in the
    // mempool; if we remove this transaction we must remove all of these
    // descendants as well.
    uint64_t nCountWithDescendants;  //!< number of descendant transactions
    uint64_t nSizeWithDescendants;   //!< ... and size
    CAmount nModFeesWithDescendants; //!< ... and total fees (all including us)

    // Analogous statistics for ancestor transactions
    uint64_t nCountWithAncestors;
    uint64_t nSizeWithAncestors;
    CAmount nModFeesWithAncestors;
    int64_t nSigOpCostWithAncestors;
/**
 * CCoinsView that brings transactions from a mempool into view.
 * It does not check for spendings by memory pool transactions.
 * Instead, it provides access to all Coins which are either unspent in the
 * base CCoinsView, or are outputs from any mempool transaction!
 * This allows transaction replacement to work as expected, as you want to
 * have all inputs "available" to check signatures, and any cycles in the
 * dependency graph are checked directly in AcceptToMemoryPool.
 * It also allows you to sign a double-spend directly in signrawtransaction,
 * as long as the conflicting transaction is not yet confirmed.
 */
class CCoinsViewMemPool : public CCoinsViewBacked
{
protected:
    const CTxMemPool& mempool;
public:
    CCoinsViewMemPool(CCoinsView* baseIn, const CTxMemPool& mempoolIn);
    bool GetCoin(const COutPoint &outpoint, Coin &coin) const override;
};

UTXO缓存数据

CCoinsViewCache 存放UTXO缓存数据

class CCoinsViewCache : public CCoinsViewBacked
{
protected:
	mutable uint256 hashBlock;
	mutable CCoinsMap cacheCoins;
private:
    CCoinsMap::iterator FetchCoin(const COutPoint &outpoint) const;


typedef std::unordered_map<COutPoint, CCoinsCacheEntry, SaltedOutpointHasher> CCoinsMap;

/**
 * A UTXO entry.
 *
 * Serialized format:
 * - VARINT((coinbase ? 1 : 0) | (height << 1))
 * - the non-spent CTxOut (via CTxOutCompressor)
 */
class Coin
{
public:
    //! unspent transaction output
    CTxOut out;

    //! whether containing transaction was a coinbase
    unsigned int fCoinBase : 1;

    //! at which height this containing transaction was included in the active block chain
    uint32_t nHeight : 31;

struct CCoinsCacheEntry
{
    Coin coin; // The actual cached data.
    unsigned char flags;

Leave a Reply

Your email address will not be published. Required fields are marked *

This site uses Akismet to reduce spam. Learn how your comment data is processed.