比特币源码(v0.01)区块序列化过程

比特币源码(v0.01)区块序列化过程

比特币中,区块序列化存储到区块文件(格式:blkxxxxx.dat)中,序列化过程【1】-【13】如下:

class CBlock
{
public:
	// header
	int nVersion;
	uint256 hashPrevBlock;
	uint256 hashMerkleRoot;
	unsigned int nTime;
	unsigned int nBits;
	unsigned int nNonce;
	
	// network and disk
	vector<CTransaction> vtx;
	
	// memory only
	mutable vector<uint256> vMerkleTree;
	
	//[7]
	//序列化宏调用:用宏定义部分替换
	IMPLEMENT_SERIALIZE
	(
		READWRITE(this->nVersion);
		nVersion = this->nVersion;
		READWRITE(hashPrevBlock);
		READWRITE(hashMerkleRoot);
		READWRITE(nTime);
		READWRITE(nBits);
		READWRITE(nNonce);
		
		// ConnectBlock depends on vtx being last so it can calculate offset
		if (!(nType & (SER_GETHASH | SER_BLOCKHEADERONLY)))
		    READWRITE(vtx);
		else if (fRead)
		    const_cast<CBlock*>(this)->vtx.clear();
	)
	
	//[2]
	//序列化存储到硬盘中
	bool WriteToDisk(bool fWriteTransactions, unsigned int& nFileRet, unsigned int& nBlockPosRet)
	{
		// Open history file to append
		CAutoFile fileout = AppendBlockFile(nFileRet);
		
		if (!fileout)
		return error("CBlock::WriteToDisk() : AppendBlockFile failed");
		
		if (!fWriteTransactions)
		fileout.nType |= SER_BLOCKHEADERONLY;
		
		// Write index header
		unsigned int nSize = fileout.GetSerializeSize(*this);
		fileout << FLATDATA(pchMessageStart) << nSize;
		
		// Write block
		nBlockPosRet = ftell(fileout);
		if (nBlockPosRet == -1)
		return error("CBlock::WriteToDisk() : ftell failed");
		
		//[3]
		//实例序列化
		fileout << *this;
		
		return true;
	}
}

//序列化宏定义开始,替换CBlock类中的IMPLEMENT_SERIALIZE宏
//#define IMPLEMENT_SERIALIZE(statements)  start
unsigned int GetSerializeSize(int nType=0, int nVersion=VERSION) const  
{                                           
	CSerActionGetSerializeSize ser_action;  
	
	const bool fGetSize = true;             
	const bool fWrite = false;              
	const bool fRead = false;               
	unsigned int nSerSize = 0;              
	ser_streamplaceholder s;                
	s.nType = nType;                        
	s.nVersion = nVersion;                  
	
	//READWRITE(obj);调用宏READWRITE,结果如下:
	nSerSize += ::SerReadWrite(s, this->nVersion, nType, nVersion, ser_action);
	nSerSize += ::SerReadWrite(s, hashPrevBlock, nType, nVersion, ser_action);
	nSerSize += ::SerReadWrite(s, hashMerkleRoot, nType, nVersion, ser_action);
	nSerSize += ::SerReadWrite(s, nTime, nType, nVersion, ser_action);
	nSerSize += ::SerReadWrite(s, nBits, nType, nVersion, ser_action);
	nSerSize += ::SerReadWrite(s, nNonce, nType, nVersion, ser_action);
		
	if (!(nType & (SER_GETHASH | SER_BLOCKHEADERONLY)))
            nSerSize += ::SerReadWrite(s, vtx, nType, nVersion, ser_action);
        else if (fRead)
            const_cast<CBlock*>(this)->vtx.clear();                                  
	
	return nSerSize;                        
}     
                 
//[8]                     
template<typename Stream>                   
void Serialize(Stream& s, int nType=0, int nVersion=VERSION) const  
{                                           
	CSerActionSerialize ser_action;        
	 
	const bool fGetSize = false;            
	const bool fWrite = true;               
	const bool fRead = false;               
	unsigned int nSerSize = 0;              

	//[9]
	//READWRITE(obj);调用宏READWRITE,结果如下:
	nSerSize += ::SerReadWrite(s, this->nVersion, nType, nVersion, ser_action);
	nSerSize += ::SerReadWrite(s, hashPrevBlock, nType, nVersion, ser_action);
	nSerSize += ::SerReadWrite(s, hashMerkleRoot, nType, nVersion, ser_action);
	nSerSize += ::SerReadWrite(s, nTime, nType, nVersion, ser_action);
	nSerSize += ::SerReadWrite(s, nBits, nType, nVersion, ser_action);
	nSerSize += ::SerReadWrite(s, nNonce, nType, nVersion, ser_action);
		
	if (!(nType & (SER_GETHASH | SER_BLOCKHEADERONLY)))
            nSerSize += ::SerReadWrite(s, vtx, nType, nVersion, ser_action);
        else if (fRead)
            const_cast<CBlock*>(this)->vtx.clear();                      
}                                           

template<typename Stream>                   
void Unserialize(Stream& s, int nType=0, int nVersion=VERSION)  
{                                           
	CSerActionUnserialize ser_action;      
	 
	const bool fGetSize = false;            
	const bool fWrite = false;              
	const bool fRead = true;                
	unsigned int nSerSize = 0;              
	
	//READWRITE(obj);调用宏READWRITE,结果如下:
	nSerSize += ::SerReadWrite(s, this->nVersion, nType, nVersion, ser_action);
	nSerSize += ::SerReadWrite(s, hashPrevBlock, nType, nVersion, ser_action);
	nSerSize += ::SerReadWrite(s, hashMerkleRoot, nType, nVersion, ser_action);
	nSerSize += ::SerReadWrite(s, nTime, nType, nVersion, ser_action);
	nSerSize += ::SerReadWrite(s, nBits, nType, nVersion, ser_action);
	nSerSize += ::SerReadWrite(s, nNonce, nType, nVersion, ser_action);
		
	if (!(nType & (SER_GETHASH | SER_BLOCKHEADERONLY)))
            nSerSize += ::SerReadWrite(s, vtx, nType, nVersion, ser_action);
        else if (fRead)
            const_cast<CBlock*>(this)->vtx.clear();                                 
}
//#define IMPLEMENT_SERIALIZE(statements)  end
//序列化宏定义结束

//宏READWRITE开始
//#define READWRITE(obj)      (nSerSize += ::SerReadWrite(s, (obj), nType, nVersion, ser_action))
//多态(ser_action)
template<typename Stream, typename T>
inline unsigned int SerReadWrite(Stream& s, const T& obj, int nType, int nVersion, CSerActionGetSerializeSize ser_action)
{
    return ::GetSerializeSize(obj, nType, nVersion);
}

//[10]
template<typename Stream, typename T>
inline unsigned int SerReadWrite(Stream& s, const T& obj, int nType, int nVersion, CSerActionSerialize ser_action)
{
    ::Serialize(s, obj, nType, nVersion);
	
    return 0;
}

template<typename Stream, typename T>
inline unsigned int SerReadWrite(Stream& s, T& obj, int nType, int nVersion, CSerActionUnserialize ser_action)
{
    ::Unserialize(s, obj, nType, nVersion);
	
    return 0;
}
//宏READWRITE结束

//[12]
#define WRITEDATA(s, obj)   s.write((char*)&(obj), sizeof(obj))
#define READDATA(s, obj)    s.read((char*)&(obj), sizeof(obj))

//多态
inline unsigned int GetSerializeSize(signed int a,     int, int=0) { return sizeof(a); }
inline unsigned int GetSerializeSize(unsigned int a,   int, int=0) { return sizeof(a); }

//[11]
template<typename Stream> inline void Serialize(Stream& s, signed int a,     int, int=0) { WRITEDATA(s, a); }
template<typename Stream> inline void Serialize(Stream& s, unsigned int a,   int, int=0) { WRITEDATA(s, a); }

template<typename Stream> inline void Unserialize(Stream& s, signed int& a,     int, int=0) { READDATA(s, a); }
template<typename Stream> inline void Unserialize(Stream& s, unsigned int& a,   int, int=0) { READDATA(s, a); }

//类型为类
template<typename T>
inline unsigned int GetSerializeSize(const T& a, long nType, int nVersion=VERSION)
{
    	return a.GetSerializeSize((int)nType, nVersion);
}

template<typename Stream, typename T>
inline void Serialize(Stream& os, const T& a, long nType, int nVersion=VERSION)
{
    	a.Serialize(os, (int)nType, nVersion);
}

template<typename Stream, typename T>
inline void Unserialize(Stream& is, T& a, long nType, int nVersion=VERSION)
{
    	a.Unserialize(is, (int)nType, nVersion);
}

//[1]
//构造block,然后序列化
//......
//block.WriteToDisk(!fClient, nFile, nBlockPos)
//调用block.Serialize方法

//[4]
//序列化,重载操作符<<
//序列化区块时,此时,T为CBlock类
template<typename T>
CAutoFile& operator<<(const T& obj)
{
	// Serialize to this stream
	if (!file)
		throw std::ios_base::failure("CAutoFile::operator<< : file handle is NULL");
	
	//[5]
	//调用多态方法
	::Serialize(*this, obj, nType, nVersion);
	
	return (*this);
}

//[6]
//此时,T为CBlock类
template<typename Stream, typename T>
inline void Serialize(Stream& os, const T& a, long nType, int nVersion=VERSION)
{
	//调用CBlock类中的Serialize方法:
	//调用block.Serialize方法
    	a.Serialize(os, (int)nType, nVersion);
}

//[13]
CAutoFile& write(const char* pch, int nSize)
{
	if (!file)
		throw std::ios_base::failure("CAutoFile::write : file handle is NULL");
	
	if (fwrite(pch, 1, nSize, file) != nSize)
		setstate(ios::failbit, "CAutoFile::write : write failed");
	
	return (*this);
}

//[12]
//CDataStream类
template<typename Stream>
void Serialize(Stream& s, int nType=0, int nVersion=VERSION) const
{
	// Special case: stream << stream concatenates like stream += stream
	if (!vch.empty())
		s.write((char*)&vch[0], vch.size() * sizeof(vch[0]));
}

//[13]
CDataStream& write(const char* pch, int nSize)
{
	// Write to the end of the buffer
	assert(nSize >= 0);
	vch.insert(vch.end(), pch, pch + nSize);
	
	return (*this);
}
发布了60 篇原创文章 · 获赞 24 · 访问量 2万+

猜你喜欢

转载自blog.csdn.net/bjgpdn/article/details/105058252