比特币源码(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);
}