是CBlock
的父类,所以先介绍CBlockHeader
,这个类是区块头的数据结构
uint256
: 256-bit opaque blob.
blob
:binary large objects.
字段尺寸 | 描述 | 数据类型 | 说明 |
---|---|---|---|
4 | nVersion | int32_t | block的版本信息,基于创建该区块的软件版本 |
32 | hashPrevBlock | uint256 | 该区块前一区块的hash值 |
32 | hashMerkleRoot | uint256 | 与该区块相关的全部交易的hash(Merkle树),Merkle树是hash的二叉树,在比特币中使用两次SHA-256算法来生成Merkle树 |
4 | nTime | uint32_t | 记录block创建时间的时间戳 |
4 | nBits | uint32_t | 创建block的计算难度 |
4 | nNonce | uint32_t | 用于生成这一block的Nonce值 |
主要看下这段代码的数据结构,函数比较简单
//block.h
/*网络中的节点将新的交易收集到块中,把他们散列到哈希树(Merkle树)中,然后遍历随机数以使得块的hash值满足工作量证明要求 *当节点找到满足要求的一个随机数,就把块广播给其节点,并添加到区块链上,每个区块的第一个交易都是coinbase交易。*/
class CBlockHeader
{
public:
// header
int32_t nVersion;
uint256 hashPrevBlock;
uint256 hashMerkleRoot;
uint32_t nTime;
uint32_t nBits;
uint32_t nNonce;
CBlockHeader()
{
SetNull();
}
ADD_SERIALIZE_METHODS;
template <typename Stream, typename Operation>
inline void SerializationOp(Stream& s, Operation ser_action, int nType, int nVersion) {
READWRITE(this->nVersion);
READWRITE(hashPrevBlock);
READWRITE(hashMerkleRoot);
READWRITE(nTime);
READWRITE(nBits);
READWRITE(nNonce);
}
void SetNull()
{
nVersion = 0;
hashPrevBlock.SetNull();
hashMerkleRoot.SetNull();
nTime = 0;
nBits = 0;
nNonce = 0;
}
bool IsNull() const
{
return (nBits == 0);
}
uint256 GetHash() const;
int64_t GetBlockTime() const
{
return (int64_t)nTime;
}
};
##GetHash()
//1. blocp.cpp
uint256 CBlockHeader::GetHash() const
{
return SerializeHash(*this);
}
//2. hash.h
/** Compute the 256-bit hash of an object's serialization. */
template<typename T>
uint256 SerializeHash(const T& obj, int nType=SER_GETHASH, int nVersion=PROTOCOL_VERSION)
{
CHashWriter ss(nType, nVersion);
ss << obj;
return ss.GetHash();
}
//3. class CHashWriter
// invalidates the object
uint256 GetHash() {
uint256 result;
ctx.Finalize((unsigned char*)&result);//ctx是v
return result;
}
可以看到对区块获取hash值是使用区块头的数据计算所得,不包括交易容器vtx,当然区块的hash与交易是有关的 ,hashMerkleRoot是区块头的一部分,该成员变量由函数BlockMerkleRoot
计算所得,用到的参数是block.vtx,也就是交易部分
//merkle.h
/* * Compute the Merkle root of the transactions in a block. * *mutated is set to true if a duplicated subtree was found. */
uint256 BlockMerkleRoot(const CBlock& block, bool* mutated = NULL);
关于merkle树,可以参考src/consensus/目录下的merkle.cpp的注释
CBlock公有继承类CBlockHeader
字段尺寸 | 描述 | 数据类型 | 说明 |
---|---|---|---|
80 | CBlockHeader | 区块头 | |
vtx | vector<CTransaction> | 所有的交易 | |
fChecked | mutable bool | 交易是否验证过并构成Merkle树 |
//block.h
class CBlock : public CBlockHeader
{
public:
// network and disk
std::vector<CTransaction> vtx;
// memory only
mutable bool fChecked;
CBlock()
{
SetNull();
}
CBlock(const CBlockHeader &header)
{
SetNull();
*((CBlockHeader*)this) = header;
}
ADD_SERIALIZE_METHODS;
template <typename Stream, typename Operation>
inline void SerializationOp(Stream& s, Operation ser_action, int nType, int nVersion) {
READWRITE(*(CBlockHeader*)this);
READWRITE(vtx);
}
void SetNull()
{
CBlockHeader::SetNull();
vtx.clear();
fChecked = false;
}
CBlockHeader GetBlockHeader() const
{
CBlockHeader block;
block.nVersion = nVersion;
block.hashPrevBlock = hashPrevBlock;
block.hashMerkleRoot = hashMerkleRoot;
block.nTime = nTime;
block.nBits = nBits;
block.nNonce = nNonce;
return block;
}
std::string ToString() const;
};
区块链是树状结构,从根部的起源块开始,每个块可能具有多个候选者作为下一个块。 块索引可能有多个pprev指向它,但最多其中一个可以是当前活动分支的一部分。
class CBlockIndex
{
public:
//! pointer to the hash of the block, if any. Memory is owned by this CBlockIndex
const uint256* phashBlock;//指向区块hash的指针
//! 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
unsigned int nStatus;
//! block header 区块头
int nVersion;
uint256 hashMerkleRoot;
unsigned int nTime;
unsigned int nBits;
unsigned int nNonce;
//! (memory only) Sequential id assigned to distinguish order in which blocks are received.
uint32_t nSequenceId;
···
对比上面两个类,可以看到CBlock是纯数据(区块的交易数据和区块头),而CBlockIndex则包含区块链相关的信息(例如指向父区块的指针,在区块链上的高度等等)
CChain chainActive;
chainActive是定义在main.cpp的全局变量,代表的是当前有最大累计工作量的分支,可以看到CChain是有一个数组保存CBlockIndex*,并且重写了一些操作符,方便检索到任意高度的区块。
/** An in-memory indexed chain of blocks. */
class CChain {
private:
std::vector<CBlockIndex*> vChain;
public:
/** Returns the index entry for the genesis block of this chain, or NULL if none. */
CBlockIndex *Genesis() const {
return vChain.size() > 0 ? vChain[0] : NULL;
}
/** Returns the index entry for the tip of this chain, or NULL if none. */
CBlockIndex *Tip() const {
return vChain.size() > 0 ? vChain[vChain.size() - 1] : NULL;
}
/** Returns the index entry at a particular height in this chain, or NULL if no such height exists. */
CBlockIndex *operator[](int nHeight) const {
if (nHeight < 0 || nHeight >= (int)vChain.size())
return NULL;
return vChain[nHeight];
}
/** Compare two chains efficiently. */
friend bool operator==(const CChain &a, const CChain &b) {
return a.vChain.size() == b.vChain.size() &&
a.vChain[a.vChain.size() - 1] == b.vChain[b.vChain.size() - 1];
}
/** Efficiently check whether a block is present in this chain. */
bool Contains(const CBlockIndex *pindex) const {
return (*this)[pindex->nHeight] == pindex;
}
/** Find the successor of a block in this chain, or NULL if the given index is not found or is the tip. */
CBlockIndex *Next(const CBlockIndex *pindex) const {
if (Contains(pindex))
return (*this)[pindex->nHeight + 1];
else
return NULL;
}
/** Return the maximal height in the chain. Is equal to chain.Tip() ? chain.Tip()->nHeight : -1. */
int Height() const {
return vChain.size() - 1;
}
/** Set/initialize a chain with a given tip. */
void SetTip(CBlockIndex *pindex);
/** Return a CBlockLocator that refers to a block in this chain (by default the tip). */
CBlockLocator GetLocator(const CBlockIndex *pindex = NULL) const;
/** Find the last common block between this chain and a block index entry. */
const CBlockIndex *FindFork(const CBlockIndex *pindex) const;
};
下面来看继承自类CTransaction的两个类
一个交易带有一个能把它连接到区块链上的 merkle 分支
/** A transaction with a merkle branch linking it to the block chain. */
class CMerkleTx : public CTransaction
{
private:
/** Constant used in hashBlock to indicate tx has been abandoned */
static const uint256 ABANDON_HASH;
public:
uint256 hashBlock;
/* An nIndex == -1 means that hashBlock (in nonzero) refers to the earliest * block in the chain we know this or any in-wallet dependency conflicts * with. Older clients interpret nIndex == -1 as unconfirmed for backward * compatibility. */
int nIndex;
CMerkleTx()
{
Init();
}
CMerkleTx(const CTransaction& txIn) : CTransaction(txIn)
{
Init();
}
void Init()
{
hashBlock = uint256();
nIndex = -1;
}
ADD_SERIALIZE_METHODS;
template <typename Stream, typename Operation>
inline void SerializationOp(Stream& s, Operation ser_action, int nType, int nVersion) {
std::vector<uint256> vMerkleBranch; // For compatibility with older versions.
READWRITE(*(CTransaction*)this);
nVersion = this->nVersion;
READWRITE(hashBlock);
READWRITE(vMerkleBranch);
READWRITE(nIndex);
}
int SetMerkleBranch(const CBlock& block);
/** * Return depth of transaction in blockchain: * <0 : conflicts with a transaction this deep in the blockchain * 0 : in memory pool, waiting to be included in a block * >=1 : this many blocks deep in the main chain */
int GetDepthInMainChain(const CBlockIndex* &pindexRet) const;
int GetDepthInMainChain() const { const CBlockIndex *pindexRet; return GetDepthInMainChain(pindexRet); }
bool IsInMainChain() const { const CBlockIndex *pindexRet; return GetDepthInMainChain(pindexRet) > 0; }
int GetBlocksToMaturity() const;
/** Pass this transaction to the mempool. Fails if absolute fee exceeds absurd fee. */
bool AcceptToMemoryPool(bool fLimitFree, const CAmount nAbsurdFee, CValidationState& state);
bool hashUnset() const { return (hashBlock.IsNull() || hashBlock == ABANDON_HASH); }
bool isAbandoned() const { return (hashBlock == ABANDON_HASH); }
void setAbandoned() { hashBlock = ABANDON_HASH; }
};
这个类可以方便的验证一个交易是否属于一个区块。
包含大量附加信息的交易,只有(这笔交易)所有者关心。 它包括将其链接回块链所需的任何未记录的事务。
//wallet.h
/** * A transaction with a bunch of additional info that only the owner cares about. * It includes any unrecorded transactions needed to link it back to the block chain. */
class CWalletTx : public CMerkleTx
{
private:
const CWallet* pwallet;
public:
mapValue_t mapValue;
std::vector<std::pair<std::string, std::string> > vOrderForm;
unsigned int fTimeReceivedIsTxTime;
unsigned int nTimeReceived; //!< time received by this node
unsigned int nTimeSmart;
char fFromMe;
std::string strFromAccount;
int64_t nOrderPos; //!< position in ordered transaction list
···