比特幣源碼(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);
}
發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章