The implementation of each class' serialization/deserialization is no longer passed within a macro. The implementation now lies within a template of form: template <typename T, typename Stream, typename Operation> inline static size_t SerializationOp(T thisPtr, Stream& s, Operation ser_action, int nType, int nVersion) { size_t nSerSize = 0; /* CODE */ return nSerSize; } In cases when codepath should depend on whether or not we are just deserializing (old fGetSize, fWrite, fRead flags) an additional clause can be used: bool fRead = boost::is_same<Operation, CSerActionUnserialize>(); The IMPLEMENT_SERIALIZE macro will now be a freestanding clause added within class' body (similiar to Qt's Q_OBJECT) to implement GetSerializeSize, Serialize and Unserialize. These are now wrappers around the "SerializationOp" template.tags/v0.15.1
@@ -46,13 +46,18 @@ private: | |||
public: | |||
IMPLEMENT_SERIALIZE( | |||
CAddress* pthis = (CAddress*)(this); | |||
IMPLEMENT_SERIALIZE | |||
template <typename T, typename Stream, typename Operation> | |||
inline static size_t SerializationOp(T thisPtr, Stream& s, Operation ser_action, int nType, int nVersion) { | |||
size_t nSerSize = 0; | |||
CAddress* pthis = (CAddress*)(thisPtr); | |||
READWRITE(*pthis); | |||
READWRITE(source); | |||
READWRITE(nLastSuccess); | |||
READWRITE(nAttempts); | |||
) | |||
READWRITE(thisPtr->source); | |||
READWRITE(thisPtr->nLastSuccess); | |||
READWRITE(thisPtr->nAttempts); | |||
return nSerSize; | |||
} | |||
void Init() | |||
{ |
@@ -47,23 +47,27 @@ public: | |||
std::string strReserved; | |||
IMPLEMENT_SERIALIZE | |||
( | |||
READWRITE(this->nVersion); | |||
nVersion = this->nVersion; | |||
READWRITE(nRelayUntil); | |||
READWRITE(nExpiration); | |||
READWRITE(nID); | |||
READWRITE(nCancel); | |||
READWRITE(setCancel); | |||
READWRITE(nMinVer); | |||
READWRITE(nMaxVer); | |||
READWRITE(setSubVer); | |||
READWRITE(nPriority); | |||
READWRITE(LIMITED_STRING(strComment, 65536)); | |||
READWRITE(LIMITED_STRING(strStatusBar, 256)); | |||
READWRITE(LIMITED_STRING(strReserved, 256)); | |||
) | |||
template <typename T, typename Stream, typename Operation> | |||
inline static size_t SerializationOp(T thisPtr, Stream& s, Operation ser_action, int nType, int nVersion) { | |||
size_t nSerSize = 0; | |||
READWRITE(thisPtr->nVersion); | |||
nVersion = thisPtr->nVersion; | |||
READWRITE(thisPtr->nRelayUntil); | |||
READWRITE(thisPtr->nExpiration); | |||
READWRITE(thisPtr->nID); | |||
READWRITE(thisPtr->nCancel); | |||
READWRITE(thisPtr->setCancel); | |||
READWRITE(thisPtr->nMinVer); | |||
READWRITE(thisPtr->nMaxVer); | |||
READWRITE(thisPtr->setSubVer); | |||
READWRITE(thisPtr->nPriority); | |||
READWRITE(LIMITED_STRING(thisPtr->strComment, 65536)); | |||
READWRITE(LIMITED_STRING(thisPtr->strStatusBar, 256)); | |||
READWRITE(LIMITED_STRING(thisPtr->strReserved, 256)); | |||
return nSerSize; | |||
} | |||
void SetNull(); | |||
@@ -83,10 +87,14 @@ public: | |||
} | |||
IMPLEMENT_SERIALIZE | |||
( | |||
READWRITE(vchMsg); | |||
READWRITE(vchSig); | |||
) | |||
template <typename T, typename Stream, typename Operation> | |||
inline static size_t SerializationOp(T thisPtr, Stream& s, Operation ser_action, int nType, int nVersion) { | |||
size_t nSerSize = 0; | |||
READWRITE(thisPtr->vchMsg); | |||
READWRITE(thisPtr->vchSig); | |||
return nSerSize; | |||
} | |||
void SetNull(); | |||
bool IsNull() const; |
@@ -63,12 +63,16 @@ public: | |||
CBloomFilter() : isFull(true), isEmpty(false), nHashFuncs(0), nTweak(0), nFlags(0) {} | |||
IMPLEMENT_SERIALIZE | |||
( | |||
READWRITE(vData); | |||
READWRITE(nHashFuncs); | |||
READWRITE(nTweak); | |||
READWRITE(nFlags); | |||
) | |||
template <typename T, typename Stream, typename Operation> | |||
inline static size_t SerializationOp(T thisPtr, Stream& s, Operation ser_action, int nType, int nVersion) { | |||
size_t nSerSize = 0; | |||
READWRITE(thisPtr->vData); | |||
READWRITE(thisPtr->nHashFuncs); | |||
READWRITE(thisPtr->nTweak); | |||
READWRITE(thisPtr->nFlags); | |||
return nSerSize; | |||
} | |||
void insert(const std::vector<unsigned char>& vKey); | |||
void insert(const COutPoint& outpoint); |
@@ -30,7 +30,16 @@ public: | |||
COutPoint() { SetNull(); } | |||
COutPoint(uint256 hashIn, uint32_t nIn) { hash = hashIn; n = nIn; } | |||
IMPLEMENT_SERIALIZE( READWRITE(FLATDATA(*this)); ) | |||
IMPLEMENT_SERIALIZE | |||
template <typename T, typename Stream, typename Operation> | |||
inline static size_t SerializationOp(T thisPtr, Stream& s, Operation ser_action, int nType, int nVersion) { | |||
size_t nSerSize = 0; | |||
READWRITE(FLATDATA(*thisPtr)); | |||
return nSerSize; | |||
} | |||
void SetNull() { hash = 0; n = (uint32_t) -1; } | |||
bool IsNull() const { return (hash == 0 && n == (uint32_t) -1); } | |||
@@ -85,11 +94,15 @@ public: | |||
CTxIn(uint256 hashPrevTx, uint32_t nOut, CScript scriptSigIn=CScript(), uint32_t nSequenceIn=std::numeric_limits<uint32_t>::max()); | |||
IMPLEMENT_SERIALIZE | |||
( | |||
READWRITE(prevout); | |||
READWRITE(scriptSig); | |||
READWRITE(nSequence); | |||
) | |||
template <typename T, typename Stream, typename Operation> | |||
inline static size_t SerializationOp(T thisPtr, Stream& s, Operation ser_action, int nType, int nVersion) { | |||
size_t nSerSize = 0; | |||
READWRITE(thisPtr->prevout); | |||
READWRITE(thisPtr->scriptSig); | |||
READWRITE(thisPtr->nSequence); | |||
return nSerSize; | |||
} | |||
bool IsFinal() const | |||
{ | |||
@@ -136,7 +149,14 @@ public: | |||
friend bool operator>=(const CFeeRate& a, const CFeeRate& b) { return a.nSatoshisPerK >= b.nSatoshisPerK; } | |||
std::string ToString() const; | |||
IMPLEMENT_SERIALIZE( READWRITE(nSatoshisPerK); ) | |||
IMPLEMENT_SERIALIZE | |||
template <typename T, typename Stream, typename Operation> | |||
inline static size_t SerializationOp(T thisPtr, Stream& s, Operation ser_action, int nType, int nVersion) { | |||
size_t nSerSize = 0; | |||
READWRITE(thisPtr->nSatoshisPerK); | |||
return nSerSize; | |||
} | |||
}; | |||
@@ -157,10 +177,14 @@ public: | |||
CTxOut(int64_t nValueIn, CScript scriptPubKeyIn); | |||
IMPLEMENT_SERIALIZE | |||
( | |||
READWRITE(nValue); | |||
READWRITE(scriptPubKey); | |||
) | |||
template <typename T, typename Stream, typename Operation> | |||
inline static size_t SerializationOp(T thisPtr, Stream& s, Operation ser_action, int nType, int nVersion) { | |||
size_t nSerSize = 0; | |||
READWRITE(thisPtr->nValue); | |||
READWRITE(thisPtr->scriptPubKey); | |||
return nSerSize; | |||
} | |||
void SetNull() | |||
{ | |||
@@ -237,15 +261,23 @@ public: | |||
CTransaction& operator=(const CTransaction& tx); | |||
IMPLEMENT_SERIALIZE( | |||
READWRITE(*const_cast<int32_t*>(&this->nVersion)); | |||
nVersion = this->nVersion; | |||
READWRITE(*const_cast<std::vector<CTxIn>*>(&vin)); | |||
READWRITE(*const_cast<std::vector<CTxOut>*>(&vout)); | |||
READWRITE(*const_cast<uint32_t*>(&nLockTime)); | |||
IMPLEMENT_SERIALIZE | |||
template <typename T, typename Stream, typename Operation> | |||
inline static size_t SerializationOp(T thisPtr, Stream& s, Operation ser_action, int nType, int nVersion) { | |||
size_t nSerSize = 0; | |||
bool fRead = boost::is_same<Operation, CSerActionUnserialize>(); | |||
READWRITE(*const_cast<int32_t*>(&thisPtr->nVersion)); | |||
nVersion = thisPtr->nVersion; | |||
READWRITE(*const_cast<std::vector<CTxIn>*>(&thisPtr->vin)); | |||
READWRITE(*const_cast<std::vector<CTxOut>*>(&thisPtr->vout)); | |||
READWRITE(*const_cast<uint32_t*>(&thisPtr->nLockTime)); | |||
if (fRead) | |||
UpdateHash(); | |||
) | |||
thisPtr->UpdateHash(); | |||
return nSerSize; | |||
} | |||
bool IsNull() const { | |||
return vin.empty() && vout.empty(); | |||
@@ -292,13 +324,20 @@ struct CMutableTransaction | |||
CMutableTransaction(); | |||
CMutableTransaction(const CTransaction& tx); | |||
IMPLEMENT_SERIALIZE( | |||
READWRITE(this->nVersion); | |||
nVersion = this->nVersion; | |||
READWRITE(vin); | |||
READWRITE(vout); | |||
READWRITE(nLockTime); | |||
) | |||
IMPLEMENT_SERIALIZE | |||
template <typename T, typename Stream, typename Operation> | |||
inline static size_t SerializationOp(T thisPtr, Stream& s, Operation ser_action, int nType, int nVersion) { | |||
size_t nSerSize = 0; | |||
READWRITE(thisPtr->nVersion); | |||
nVersion = thisPtr->nVersion; | |||
READWRITE(thisPtr->vin); | |||
READWRITE(thisPtr->vout); | |||
READWRITE(thisPtr->nLockTime); | |||
return nSerSize; | |||
} | |||
/** Compute the hash of this CMutableTransaction. This is computed on the | |||
* fly, as opposed to GetHash() in CTransaction, which uses a cached result. | |||
@@ -318,18 +357,24 @@ public: | |||
CTxOutCompressor(CTxOut &txoutIn) : txout(txoutIn) { } | |||
IMPLEMENT_SERIALIZE(({ | |||
IMPLEMENT_SERIALIZE | |||
template <typename T, typename Stream, typename Operation> | |||
inline static size_t SerializationOp(T thisPtr, Stream& s, Operation ser_action, int nType, int nVersion) { | |||
bool fRead = boost::is_same<Operation, CSerActionUnserialize>(); | |||
size_t nSerSize = 0; | |||
if (!fRead) { | |||
uint64_t nVal = CompressAmount(txout.nValue); | |||
uint64_t nVal = CompressAmount(thisPtr->txout.nValue); | |||
READWRITE(VARINT(nVal)); | |||
} else { | |||
uint64_t nVal = 0; | |||
READWRITE(VARINT(nVal)); | |||
txout.nValue = DecompressAmount(nVal); | |||
thisPtr->txout.nValue = DecompressAmount(nVal); | |||
} | |||
CScriptCompressor cscript(REF(txout.scriptPubKey)); | |||
CScriptCompressor cscript(REF(thisPtr->txout.scriptPubKey)); | |||
READWRITE(cscript); | |||
});) | |||
return nSerSize; | |||
} | |||
}; | |||
/** Undo information for a CTxIn | |||
@@ -382,9 +427,14 @@ public: | |||
// undo information for all txins | |||
std::vector<CTxInUndo> vprevout; | |||
IMPLEMENT_SERIALIZE( | |||
READWRITE(vprevout); | |||
) | |||
IMPLEMENT_SERIALIZE | |||
template <typename T, typename Stream, typename Operation> | |||
inline static size_t SerializationOp(T thisPtr, Stream& s, Operation ser_action, int nType, int nVersion) { | |||
size_t nSerSize = 0; | |||
READWRITE(thisPtr->vprevout); | |||
return nSerSize; | |||
} | |||
}; | |||
@@ -413,15 +463,21 @@ public: | |||
} | |||
IMPLEMENT_SERIALIZE | |||
( | |||
READWRITE(this->nVersion); | |||
nVersion = this->nVersion; | |||
READWRITE(hashPrevBlock); | |||
READWRITE(hashMerkleRoot); | |||
READWRITE(nTime); | |||
READWRITE(nBits); | |||
READWRITE(nNonce); | |||
) | |||
template <typename T, typename Stream, typename Operation> | |||
inline static size_t SerializationOp(T thisPtr, Stream& s, Operation ser_action, int nType, int nVersion) { | |||
size_t nSerSize = 0; | |||
READWRITE(thisPtr->nVersion); | |||
nVersion = thisPtr->nVersion; | |||
READWRITE(thisPtr->hashPrevBlock); | |||
READWRITE(thisPtr->hashMerkleRoot); | |||
READWRITE(thisPtr->nTime); | |||
READWRITE(thisPtr->nBits); | |||
READWRITE(thisPtr->nNonce); | |||
return nSerSize; | |||
} | |||
void SetNull() | |||
{ | |||
@@ -468,10 +524,16 @@ public: | |||
} | |||
IMPLEMENT_SERIALIZE | |||
( | |||
READWRITE(*(CBlockHeader*)this); | |||
READWRITE(vtx); | |||
) | |||
template <typename T, typename Stream, typename Operation> | |||
inline static size_t SerializationOp(T thisPtr, Stream& s, Operation ser_action, int nType, int nVersion) { | |||
size_t nSerSize = 0; | |||
READWRITE(*(CBlockHeader*)thisPtr); | |||
READWRITE(thisPtr->vtx); | |||
return nSerSize; | |||
} | |||
void SetNull() | |||
{ | |||
@@ -516,11 +578,17 @@ struct CBlockLocator | |||
} | |||
IMPLEMENT_SERIALIZE | |||
( | |||
template <typename T, typename Stream, typename Operation> | |||
inline static size_t SerializationOp(T thisPtr, Stream& s, Operation ser_action, int nType, int nVersion) { | |||
size_t nSerSize = 0; | |||
if (!(nType & SER_GETHASH)) | |||
READWRITE(nVersion); | |||
READWRITE(vHave); | |||
) | |||
READWRITE(thisPtr->vHave); | |||
return nSerSize; | |||
} | |||
void SetNull() | |||
{ |
@@ -44,13 +44,18 @@ public: | |||
std::vector<unsigned char> vchOtherDerivationParameters; | |||
IMPLEMENT_SERIALIZE | |||
( | |||
READWRITE(vchCryptedKey); | |||
READWRITE(vchSalt); | |||
READWRITE(nDerivationMethod); | |||
READWRITE(nDeriveIterations); | |||
READWRITE(vchOtherDerivationParameters); | |||
) | |||
template <typename T, typename Stream, typename Operation> | |||
inline static size_t SerializationOp(T thisPtr, Stream& s, Operation ser_action, int nType, int nVersion) { | |||
size_t nSerSize = 0; | |||
READWRITE(thisPtr->vchCryptedKey); | |||
READWRITE(thisPtr->vchSalt); | |||
READWRITE(thisPtr->nDerivationMethod); | |||
READWRITE(thisPtr->nDeriveIterations); | |||
READWRITE(thisPtr->vchOtherDerivationParameters); | |||
return nSerSize; | |||
} | |||
CMasterKey() | |||
{ | |||
// 25000 rounds is just under 0.1 seconds on a 1.86 GHz Pentium M |
@@ -197,10 +197,15 @@ struct CDiskBlockPos | |||
int nFile; | |||
unsigned int nPos; | |||
IMPLEMENT_SERIALIZE( | |||
READWRITE(VARINT(nFile)); | |||
READWRITE(VARINT(nPos)); | |||
) | |||
IMPLEMENT_SERIALIZE | |||
template <typename T, typename Stream, typename Operation> | |||
inline static size_t SerializationOp(T thisPtr, Stream& s, Operation ser_action, int nType, int nVersion) { | |||
size_t nSerSize = 0; | |||
READWRITE(VARINT(thisPtr->nFile)); | |||
READWRITE(VARINT(thisPtr->nPos)); | |||
return nSerSize; | |||
} | |||
CDiskBlockPos() { | |||
SetNull(); | |||
@@ -227,10 +232,15 @@ struct CDiskTxPos : public CDiskBlockPos | |||
{ | |||
unsigned int nTxOffset; // after header | |||
IMPLEMENT_SERIALIZE( | |||
READWRITE(*(CDiskBlockPos*)this); | |||
READWRITE(VARINT(nTxOffset)); | |||
) | |||
IMPLEMENT_SERIALIZE | |||
template <typename T, typename Stream, typename Operation> | |||
inline static size_t SerializationOp(T thisPtr, Stream& s, Operation ser_action, int nType, int nVersion) { | |||
size_t nSerSize = 0; | |||
READWRITE(*(CDiskBlockPos*)thisPtr); | |||
READWRITE(VARINT(thisPtr->nTxOffset)); | |||
return nSerSize; | |||
} | |||
CDiskTxPos(const CDiskBlockPos &blockIn, unsigned int nTxOffsetIn) : CDiskBlockPos(blockIn.nFile, blockIn.nPos), nTxOffset(nTxOffsetIn) { | |||
} | |||
@@ -307,9 +317,14 @@ class CBlockUndo | |||
public: | |||
std::vector<CTxUndo> vtxundo; // for all but the coinbase | |||
IMPLEMENT_SERIALIZE( | |||
READWRITE(vtxundo); | |||
) | |||
IMPLEMENT_SERIALIZE | |||
template <typename T, typename Stream, typename Operation> | |||
inline static size_t SerializationOp(T thisPtr, Stream& s, Operation ser_action, int nType, int nVersion) { | |||
size_t nSerSize = 0; | |||
READWRITE(thisPtr->vtxundo); | |||
return nSerSize; | |||
} | |||
bool WriteToDisk(CDiskBlockPos &pos, const uint256 &hashBlock); | |||
bool ReadFromDisk(const CDiskBlockPos &pos, const uint256 &hashBlock); | |||
@@ -411,24 +426,32 @@ protected: | |||
public: | |||
// serialization implementation | |||
IMPLEMENT_SERIALIZE( | |||
READWRITE(nTransactions); | |||
READWRITE(vHash); | |||
IMPLEMENT_SERIALIZE | |||
template <typename T, typename Stream, typename Operation> | |||
inline static size_t SerializationOp(T thisPtr, Stream& s, Operation ser_action, int nType, int nVersion) { | |||
size_t nSerSize = 0; | |||
bool fRead = boost::is_same<Operation, CSerActionUnserialize>(); | |||
READWRITE(thisPtr->nTransactions); | |||
READWRITE(thisPtr->vHash); | |||
std::vector<unsigned char> vBytes; | |||
if (fRead) { | |||
READWRITE(vBytes); | |||
CPartialMerkleTree &us = *(const_cast<CPartialMerkleTree*>(this)); | |||
CPartialMerkleTree &us = *(const_cast<CPartialMerkleTree*>(thisPtr)); | |||
us.vBits.resize(vBytes.size() * 8); | |||
for (unsigned int p = 0; p < us.vBits.size(); p++) | |||
us.vBits[p] = (vBytes[p / 8] & (1 << (p % 8))) != 0; | |||
us.fBad = false; | |||
} else { | |||
vBytes.resize((vBits.size()+7)/8); | |||
for (unsigned int p = 0; p < vBits.size(); p++) | |||
vBytes[p / 8] |= vBits[p] << (p % 8); | |||
vBytes.resize((thisPtr->vBits.size()+7)/8); | |||
for (unsigned int p = 0; p < thisPtr->vBits.size(); p++) | |||
vBytes[p / 8] |= thisPtr->vBits[p] << (p % 8); | |||
READWRITE(vBytes); | |||
} | |||
) | |||
return nSerSize; | |||
} | |||
// Construct a partial merkle tree from a list of transaction id's, and a mask that selects a subset of them | |||
CPartialMerkleTree(const std::vector<uint256> &vTxid, const std::vector<bool> &vMatch); | |||
@@ -484,15 +507,22 @@ public: | |||
uint64_t nTimeFirst; // earliest time of block in file | |||
uint64_t nTimeLast; // latest time of block in file | |||
IMPLEMENT_SERIALIZE( | |||
READWRITE(VARINT(nBlocks)); | |||
READWRITE(VARINT(nSize)); | |||
READWRITE(VARINT(nUndoSize)); | |||
READWRITE(VARINT(nHeightFirst)); | |||
READWRITE(VARINT(nHeightLast)); | |||
READWRITE(VARINT(nTimeFirst)); | |||
READWRITE(VARINT(nTimeLast)); | |||
) | |||
IMPLEMENT_SERIALIZE | |||
template <typename T, typename Stream, typename Operation> | |||
inline static size_t SerializationOp(T thisPtr, Stream& s, Operation ser_action, int nType, int nVersion) { | |||
size_t nSerSize = 0; | |||
READWRITE(VARINT(thisPtr->nBlocks)); | |||
READWRITE(VARINT(thisPtr->nSize)); | |||
READWRITE(VARINT(thisPtr->nUndoSize)); | |||
READWRITE(VARINT(thisPtr->nHeightFirst)); | |||
READWRITE(VARINT(thisPtr->nHeightLast)); | |||
READWRITE(VARINT(thisPtr->nTimeFirst)); | |||
READWRITE(VARINT(thisPtr->nTimeLast)); | |||
return nSerSize; | |||
} | |||
void SetNull() { | |||
nBlocks = 0; | |||
@@ -756,28 +786,34 @@ public: | |||
} | |||
IMPLEMENT_SERIALIZE | |||
( | |||
template <typename T, typename Stream, typename Operation> | |||
inline static size_t SerializationOp(T thisPtr, Stream& s, Operation ser_action, int nType, int nVersion) { | |||
size_t nSerSize = 0; | |||
if (!(nType & SER_GETHASH)) | |||
READWRITE(VARINT(nVersion)); | |||
READWRITE(VARINT(nHeight)); | |||
READWRITE(VARINT(nStatus)); | |||
READWRITE(VARINT(nTx)); | |||
if (nStatus & (BLOCK_HAVE_DATA | BLOCK_HAVE_UNDO)) | |||
READWRITE(VARINT(nFile)); | |||
if (nStatus & BLOCK_HAVE_DATA) | |||
READWRITE(VARINT(nDataPos)); | |||
if (nStatus & BLOCK_HAVE_UNDO) | |||
READWRITE(VARINT(nUndoPos)); | |||
READWRITE(VARINT(thisPtr->nHeight)); | |||
READWRITE(VARINT(thisPtr->nStatus)); | |||
READWRITE(VARINT(thisPtr->nTx)); | |||
if (thisPtr->nStatus & (BLOCK_HAVE_DATA | BLOCK_HAVE_UNDO)) | |||
READWRITE(VARINT(thisPtr->nFile)); | |||
if (thisPtr->nStatus & BLOCK_HAVE_DATA) | |||
READWRITE(VARINT(thisPtr->nDataPos)); | |||
if (thisPtr->nStatus & BLOCK_HAVE_UNDO) | |||
READWRITE(VARINT(thisPtr->nUndoPos)); | |||
// block header | |||
READWRITE(this->nVersion); | |||
READWRITE(hashPrev); | |||
READWRITE(hashMerkleRoot); | |||
READWRITE(nTime); | |||
READWRITE(nBits); | |||
READWRITE(nNonce); | |||
) | |||
READWRITE(thisPtr->nVersion); | |||
READWRITE(thisPtr->hashPrev); | |||
READWRITE(thisPtr->hashMerkleRoot); | |||
READWRITE(thisPtr->nTime); | |||
READWRITE(thisPtr->nBits); | |||
READWRITE(thisPtr->nNonce); | |||
return nSerSize; | |||
} | |||
uint256 GetBlockHash() const | |||
{ | |||
@@ -976,10 +1012,14 @@ public: | |||
CMerkleBlock(const CBlock& block, CBloomFilter& filter); | |||
IMPLEMENT_SERIALIZE | |||
( | |||
READWRITE(header); | |||
READWRITE(txn); | |||
) | |||
template <typename T, typename Stream, typename Operation> | |||
inline static size_t SerializationOp(T thisPtr, Stream& s, Operation ser_action, int nType, int nVersion) { | |||
size_t nSerSize = 0; | |||
READWRITE(thisPtr->header); | |||
READWRITE(thisPtr->txn); | |||
return nSerSize; | |||
} | |||
}; | |||
@@ -89,9 +89,13 @@ class CNetAddr | |||
friend bool operator<(const CNetAddr& a, const CNetAddr& b); | |||
IMPLEMENT_SERIALIZE | |||
( | |||
READWRITE(FLATDATA(ip)); | |||
) | |||
template <typename T, typename Stream, typename Operation> | |||
inline static size_t SerializationOp(T thisPtr, Stream& s, Operation ser_action, int nType, int nVersion) { | |||
size_t nSerSize = 0; | |||
READWRITE(FLATDATA(thisPtr->ip)); | |||
return nSerSize; | |||
} | |||
}; | |||
class CSubNet | |||
@@ -149,14 +153,19 @@ class CService : public CNetAddr | |||
CService(const struct sockaddr_in6& addr); | |||
IMPLEMENT_SERIALIZE | |||
( | |||
CService* pthis = const_cast<CService*>(this); | |||
READWRITE(FLATDATA(ip)); | |||
unsigned short portN = htons(port); | |||
READWRITE(portN); | |||
if (fRead) | |||
template <typename T, typename Stream, typename Operation> | |||
inline static size_t SerializationOp(T thisPtr, Stream& s, Operation ser_action, int nType, int nVersion) { | |||
bool fRead = boost::is_same<Operation, CSerActionUnserialize>(); | |||
size_t nSerSize = 0; | |||
CService* pthis = const_cast<CService*>(thisPtr); | |||
READWRITE(FLATDATA(thisPtr->ip)); | |||
unsigned short portN = htons(thisPtr->port); | |||
READWRITE(portN); | |||
if (fRead) | |||
pthis->port = ntohs(portN); | |||
) | |||
return nSerSize; | |||
} | |||
}; | |||
typedef CService proxyType; |
@@ -36,12 +36,16 @@ class CMessageHeader | |||
bool IsValid() const; | |||
IMPLEMENT_SERIALIZE | |||
( | |||
READWRITE(FLATDATA(pchMessageStart)); | |||
READWRITE(FLATDATA(pchCommand)); | |||
READWRITE(nMessageSize); | |||
READWRITE(nChecksum); | |||
) | |||
template <typename T, typename Stream, typename Operation> | |||
inline static size_t SerializationOp(T thisPtr, Stream& s, Operation ser_action, int nType, int nVersion) { | |||
size_t nSerSize = 0; | |||
READWRITE(FLATDATA(thisPtr->pchMessageStart)); | |||
READWRITE(FLATDATA(thisPtr->pchCommand)); | |||
READWRITE(thisPtr->nMessageSize); | |||
READWRITE(thisPtr->nChecksum); | |||
return nSerSize; | |||
} | |||
// TODO: make private (improves encapsulation) | |||
public: | |||
@@ -84,19 +88,26 @@ class CAddress : public CService | |||
void Init(); | |||
IMPLEMENT_SERIALIZE | |||
( | |||
CAddress* pthis = const_cast<CAddress*>(this); | |||
CService* pip = (CService*)pthis; | |||
if (fRead) | |||
pthis->Init(); | |||
if (nType & SER_DISK) | |||
READWRITE(nVersion); | |||
if ((nType & SER_DISK) || | |||
(nVersion >= CADDR_TIME_VERSION && !(nType & SER_GETHASH))) | |||
READWRITE(nTime); | |||
READWRITE(nServices); | |||
READWRITE(*pip); | |||
) | |||
template <typename T, typename Stream, typename Operation> | |||
inline static size_t SerializationOp(T thisPtr, Stream& s, Operation ser_action, int nType, int nVersion) { | |||
size_t nSerSize = 0; | |||
bool fRead = boost::is_same<Operation, CSerActionUnserialize>(); | |||
CAddress* pthis = const_cast<CAddress*>(thisPtr); | |||
CService* pip = (CService*)pthis; | |||
if (fRead) | |||
pthis->Init(); | |||
if (nType & SER_DISK) | |||
READWRITE(nVersion); | |||
if ((nType & SER_DISK) || | |||
(nVersion >= CADDR_TIME_VERSION && !(nType & SER_GETHASH))) | |||
READWRITE(thisPtr->nTime); | |||
READWRITE(thisPtr->nServices); | |||
READWRITE(*pip); | |||
return nSerSize; | |||
} | |||
// TODO: make private (improves encapsulation) | |||
public: | |||
@@ -118,10 +129,14 @@ class CInv | |||
CInv(const std::string& strType, const uint256& hashIn); | |||
IMPLEMENT_SERIALIZE | |||
( | |||
READWRITE(type); | |||
READWRITE(hash); | |||
) | |||
template <typename T, typename Stream, typename Operation> | |||
inline static size_t SerializationOp(T thisPtr, Stream& s, Operation ser_action, int nType, int nVersion) { | |||
size_t nSerSize = 0; | |||
READWRITE(thisPtr->type); | |||
READWRITE(thisPtr->hash); | |||
return nSerSize; | |||
} | |||
friend bool operator<(const CInv& a, const CInv& b); | |||
@@ -25,20 +25,27 @@ public: | |||
SendCoinsRecipient recipient; | |||
IMPLEMENT_SERIALIZE | |||
( | |||
RecentRequestEntry* pthis = const_cast<RecentRequestEntry*>(this); | |||
unsigned int nDate = date.toTime_t(); | |||
template <typename T, typename Stream, typename Operation> | |||
inline static size_t SerializationOp(T thisPtr, Stream& s, Operation ser_action, int nType, int nVersion) { | |||
size_t nSerSize = 0; | |||
bool fRead = boost::is_same<Operation, CSerActionUnserialize>(); | |||
RecentRequestEntry* pthis = const_cast<RecentRequestEntry*>(thisPtr); | |||
unsigned int nDate = thisPtr->date.toTime_t(); | |||
READWRITE(pthis->nVersion); | |||
nVersion = pthis->nVersion; | |||
READWRITE(id); | |||
READWRITE(thisPtr->id); | |||
READWRITE(nDate); | |||
READWRITE(recipient); | |||
READWRITE(thisPtr->recipient); | |||
if (fRead) | |||
pthis->date = QDateTime::fromTime_t(nDate); | |||
) | |||
return nSerSize; | |||
} | |||
}; | |||
class RecentRequestEntryLessThan |
@@ -60,8 +60,13 @@ public: | |||
int nVersion; | |||
IMPLEMENT_SERIALIZE | |||
( | |||
SendCoinsRecipient* pthis = const_cast<SendCoinsRecipient*>(this); | |||
template <typename T, typename Stream, typename Operation> | |||
inline static size_t SerializationOp(T thisPtr, Stream& s, Operation ser_action, int nType, int nVersion) { | |||
size_t nSerSize = 0; | |||
bool fRead = boost::is_same<Operation, CSerActionUnserialize>(); | |||
SendCoinsRecipient* pthis = const_cast<SendCoinsRecipient*>(thisPtr); | |||
std::string sAddress = pthis->address.toStdString(); | |||
std::string sLabel = pthis->label.toStdString(); | |||
@@ -75,7 +80,7 @@ public: | |||
nVersion = pthis->nVersion; | |||
READWRITE(sAddress); | |||
READWRITE(sLabel); | |||
READWRITE(amount); | |||
READWRITE(thisPtr->amount); | |||
READWRITE(sMessage); | |||
READWRITE(sPaymentRequest); | |||
READWRITE(sAuthenticatedMerchant); | |||
@@ -89,7 +94,9 @@ public: | |||
pthis->paymentRequest.parse(QByteArray::fromRawData(sPaymentRequest.data(), sPaymentRequest.size())); | |||
pthis->authenticatedMerchant = QString::fromStdString(sAuthenticatedMerchant); | |||
} | |||
) | |||
return nSerSize; | |||
} | |||
}; | |||
/** Interface to Bitcoin wallet from Qt view code. */ |
@@ -22,6 +22,7 @@ | |||
#include <boost/tuple/tuple.hpp> | |||
#include <boost/type_traits/is_fundamental.hpp> | |||
#include <boost/typeof/typeof.hpp> | |||
class CAutoFile; | |||
class CDataStream; | |||
@@ -37,6 +38,14 @@ inline T& REF(const T& val) | |||
return const_cast<T&>(val); | |||
} | |||
// Used to acquire a const pointer "this" and generate a const | |||
// serialization operation from a template | |||
template<typename T> | |||
inline T MAKE_CONST(T val) | |||
{ | |||
return const_cast<const T>(val); | |||
} | |||
/** Get begin pointer of vector (non-const version). | |||
* @note These functions avoid the undefined case of indexing into an empty | |||
* vector, as well as that of indexing after the end of the vector. | |||
@@ -79,48 +88,27 @@ enum | |||
SER_GETHASH = (1 << 2), | |||
}; | |||
#define IMPLEMENT_SERIALIZE(statements) \ | |||
unsigned int GetSerializeSize(int nType, int nVersion) const \ | |||
{ \ | |||
CSerActionGetSerializeSize ser_action; \ | |||
const bool fGetSize = true; \ | |||
const bool fWrite = false; \ | |||
const bool fRead = false; \ | |||
unsigned int nSerSize = 0; \ | |||
ser_streamplaceholder s; \ | |||
assert(fGetSize||fWrite||fRead); /* suppress warning */ \ | |||
s.nType = nType; \ | |||
s.nVersion = nVersion; \ | |||
{statements} \ | |||
return nSerSize; \ | |||
} \ | |||
template<typename Stream> \ | |||
void Serialize(Stream& s, int nType, int nVersion) const \ | |||
{ \ | |||
CSerActionSerialize ser_action; \ | |||
const bool fGetSize = false; \ | |||
const bool fWrite = true; \ | |||
const bool fRead = false; \ | |||
unsigned int nSerSize = 0; \ | |||
assert(fGetSize||fWrite||fRead); /* suppress warning */ \ | |||
{statements} \ | |||
} \ | |||
template<typename Stream> \ | |||
void Unserialize(Stream& s, int nType, int nVersion) \ | |||
{ \ | |||
CSerActionUnserialize ser_action; \ | |||
const bool fGetSize = false; \ | |||
const bool fWrite = false; \ | |||
const bool fRead = true; \ | |||
unsigned int nSerSize = 0; \ | |||
assert(fGetSize||fWrite||fRead); /* suppress warning */ \ | |||
{statements} \ | |||
} | |||
#define READWRITE(obj) (nSerSize += ::SerReadWrite(s, (obj), nType, nVersion, ser_action)) | |||
/* Implement three methods for serializable objects. These are actually wrappers over | |||
* "SerializationOp" template, which implements the body of each class' serialization | |||
* code. Adding "IMPLEMENT_SERIALIZE" in the body of the class causes these wrappers to be | |||
* added as members. */ | |||
#define IMPLEMENT_SERIALIZE \ | |||
size_t GetSerializeSize(int nType, int nVersion) const { \ | |||
ser_streamplaceholder s; \ | |||
s.nType = nType; \ | |||
s.nVersion = nVersion; \ | |||
return SerializationOp(MAKE_CONST(this), s, CSerActionGetSerializeSize(), nType, nVersion); \ | |||
} \ | |||
template<typename Stream> \ | |||
void Serialize(Stream& s, int nType, int nVersion) const { \ | |||
SerializationOp(MAKE_CONST(this), s, CSerActionSerialize(), nType, nVersion); \ | |||
} \ | |||
template<typename Stream> \ | |||
void Unserialize(Stream& s, int nType, int nVersion) { \ | |||
SerializationOp(this, s, CSerActionUnserialize(), nType, nVersion); \ | |||
} | |||
@@ -64,12 +64,16 @@ public: | |||
CKeyPool(const CPubKey& vchPubKeyIn); | |||
IMPLEMENT_SERIALIZE | |||
( | |||
template <typename T, typename Stream, typename Operation> | |||
inline static size_t SerializationOp(T thisPtr, Stream& s, Operation ser_action, int nType, int nVersion) { | |||
size_t nSerSize = 0; | |||
if (!(nType & SER_GETHASH)) | |||
READWRITE(nVersion); | |||
READWRITE(nTime); | |||
READWRITE(vchPubKey); | |||
) | |||
READWRITE(thisPtr->nTime); | |||
READWRITE(thisPtr->vchPubKey); | |||
return nSerSize; | |||
} | |||
}; | |||
/** Address book data */ | |||
@@ -489,16 +493,20 @@ public: | |||
fMerkleVerified = false; | |||
} | |||
IMPLEMENT_SERIALIZE | |||
( | |||
nSerSize += SerReadWrite(s, *(CTransaction*)this, nType, nVersion, ser_action); | |||
nVersion = this->nVersion; | |||
READWRITE(hashBlock); | |||
READWRITE(vMerkleBranch); | |||
READWRITE(nIndex); | |||
) | |||
template <typename T, typename Stream, typename Operation> | |||
inline static size_t SerializationOp(T thisPtr, Stream& s, Operation ser_action, int nType, int nVersion) { | |||
size_t nSerSize = 0; | |||
nSerSize += SerReadWrite(s, *(CTransaction*)thisPtr, nType, nVersion, ser_action); | |||
nVersion = thisPtr->nVersion; | |||
READWRITE(thisPtr->hashBlock); | |||
READWRITE(thisPtr->vMerkleBranch); | |||
READWRITE(thisPtr->nIndex); | |||
return nSerSize; | |||
} | |||
int SetMerkleBranch(const CBlock* pblock=NULL); | |||
@@ -513,7 +521,6 @@ public: | |||
bool AcceptToMemoryPool(bool fLimitFree=true, bool fRejectInsaneFee=true); | |||
}; | |||
/** 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. | |||
*/ | |||
@@ -604,8 +611,13 @@ public: | |||
} | |||
IMPLEMENT_SERIALIZE | |||
( | |||
CWalletTx* pthis = const_cast<CWalletTx*>(this); | |||
template <typename T, typename Stream, typename Operation> | |||
inline static size_t SerializationOp(T thisPtr, Stream& s, Operation ser_action, int nType, int nVersion) { | |||
size_t nSerSize = 0; | |||
bool fRead = boost::is_same<Operation, CSerActionUnserialize>(); | |||
CWalletTx* pthis = const_cast<CWalletTx*>(thisPtr); | |||
if (fRead) | |||
pthis->Init(NULL); | |||
char fSpent = false; | |||
@@ -616,18 +628,18 @@ public: | |||
WriteOrderPos(pthis->nOrderPos, pthis->mapValue); | |||
if (nTimeSmart) | |||
pthis->mapValue["timesmart"] = strprintf("%u", nTimeSmart); | |||
if (thisPtr->nTimeSmart) | |||
pthis->mapValue["timesmart"] = strprintf("%u", thisPtr->nTimeSmart); | |||
} | |||
nSerSize += SerReadWrite(s, *(CMerkleTx*)this, nType, nVersion,ser_action); | |||
nSerSize += SerReadWrite(s, *(CMerkleTx*)thisPtr, nType, nVersion,ser_action); | |||
std::vector<CMerkleTx> vUnused; // Used to be vtxPrev | |||
READWRITE(vUnused); | |||
READWRITE(mapValue); | |||
READWRITE(vOrderForm); | |||
READWRITE(fTimeReceivedIsTxTime); | |||
READWRITE(nTimeReceived); | |||
READWRITE(fFromMe); | |||
READWRITE(thisPtr->mapValue); | |||
READWRITE(thisPtr->vOrderForm); | |||
READWRITE(thisPtr->fTimeReceivedIsTxTime); | |||
READWRITE(thisPtr->nTimeReceived); | |||
READWRITE(thisPtr->fFromMe); | |||
READWRITE(fSpent); | |||
if (fRead) | |||
@@ -636,7 +648,7 @@ public: | |||
ReadOrderPos(pthis->nOrderPos, pthis->mapValue); | |||
pthis->nTimeSmart = mapValue.count("timesmart") ? (unsigned int)atoi64(pthis->mapValue["timesmart"]) : 0; | |||
pthis->nTimeSmart = thisPtr->mapValue.count("timesmart") ? (unsigned int)atoi64(pthis->mapValue["timesmart"]) : 0; | |||
} | |||
pthis->mapValue.erase("fromaccount"); | |||
@@ -644,7 +656,9 @@ public: | |||
pthis->mapValue.erase("spent"); | |||
pthis->mapValue.erase("n"); | |||
pthis->mapValue.erase("timesmart"); | |||
) | |||
return nSerSize; | |||
} | |||
// make sure balances are recalculated | |||
void MarkDirty() | |||
@@ -891,14 +905,18 @@ public: | |||
CWalletKey(int64_t nExpires=0); | |||
IMPLEMENT_SERIALIZE | |||
( | |||
template <typename T, typename Stream, typename Operation> | |||
inline static size_t SerializationOp(T thisPtr, Stream& s, Operation ser_action, int nType, int nVersion) { | |||
size_t nSerSize = 0; | |||
if (!(nType & SER_GETHASH)) | |||
READWRITE(nVersion); | |||
READWRITE(vchPrivKey); | |||
READWRITE(nTimeCreated); | |||
READWRITE(nTimeExpires); | |||
READWRITE(LIMITED_STRING(strComment, 65536)); | |||
) | |||
READWRITE(thisPtr->vchPrivKey); | |||
READWRITE(thisPtr->nTimeCreated); | |||
READWRITE(thisPtr->nTimeExpires); | |||
READWRITE(LIMITED_STRING(thisPtr->strComment, 65536)); | |||
return nSerSize; | |||
} | |||
}; | |||
@@ -925,11 +943,15 @@ public: | |||
} | |||
IMPLEMENT_SERIALIZE | |||
( | |||
template <typename T, typename Stream, typename Operation> | |||
inline static size_t SerializationOp(T thisPtr, Stream& s, Operation ser_action, int nType, int nVersion) { | |||
size_t nSerSize = 0; | |||
if (!(nType & SER_GETHASH)) | |||
READWRITE(nVersion); | |||
READWRITE(vchPubKey); | |||
) | |||
READWRITE(thisPtr->vchPubKey); | |||
return nSerSize; | |||
} | |||
}; | |||
@@ -966,38 +988,43 @@ public: | |||
} | |||
IMPLEMENT_SERIALIZE | |||
( | |||
CAccountingEntry& me = *const_cast<CAccountingEntry*>(this); | |||
template <typename T, typename Stream, typename Operation> | |||
inline static size_t SerializationOp(T thisPtr, Stream& s, Operation ser_action, int nType, int nVersion) { | |||
size_t nSerSize = 0; | |||
bool fRead = boost::is_same<Operation, CSerActionUnserialize>(); | |||
CAccountingEntry& me = *const_cast<CAccountingEntry*>(thisPtr); | |||
if (!(nType & SER_GETHASH)) | |||
READWRITE(nVersion); | |||
// Note: strAccount is serialized as part of the key, not here. | |||
READWRITE(nCreditDebit); | |||
READWRITE(nTime); | |||
READWRITE(LIMITED_STRING(strOtherAccount, 65536)); | |||
READWRITE(thisPtr->nCreditDebit); | |||
READWRITE(thisPtr->nTime); | |||
READWRITE(LIMITED_STRING(thisPtr->strOtherAccount, 65536)); | |||
if (!fRead) | |||
{ | |||
WriteOrderPos(nOrderPos, me.mapValue); | |||
WriteOrderPos(thisPtr->nOrderPos, me.mapValue); | |||
if (!(mapValue.empty() && _ssExtra.empty())) | |||
if (!(thisPtr->mapValue.empty() && thisPtr->_ssExtra.empty())) | |||
{ | |||
CDataStream ss(nType, nVersion); | |||
ss.insert(ss.begin(), '\0'); | |||
ss << mapValue; | |||
ss.insert(ss.end(), _ssExtra.begin(), _ssExtra.end()); | |||
ss << thisPtr->mapValue; | |||
ss.insert(ss.end(), thisPtr->_ssExtra.begin(), thisPtr->_ssExtra.end()); | |||
me.strComment.append(ss.str()); | |||
} | |||
} | |||
READWRITE(LIMITED_STRING(strComment, 65536)); | |||
READWRITE(LIMITED_STRING(thisPtr->strComment, 65536)); | |||
size_t nSepPos = strComment.find("\0", 0, 1); | |||
size_t nSepPos = thisPtr->strComment.find("\0", 0, 1); | |||
if (fRead) | |||
{ | |||
me.mapValue.clear(); | |||
if (std::string::npos != nSepPos) | |||
{ | |||
CDataStream ss(std::vector<char>(strComment.begin() + nSepPos + 1, strComment.end()), nType, nVersion); | |||
CDataStream ss(std::vector<char>(thisPtr->strComment.begin() + nSepPos + 1, thisPtr->strComment.end()), nType, nVersion); | |||
ss >> me.mapValue; | |||
me._ssExtra = std::vector<char>(ss.begin(), ss.end()); | |||
} | |||
@@ -1007,7 +1034,9 @@ public: | |||
me.strComment.erase(nSepPos); | |||
me.mapValue.erase("n"); | |||
) | |||
return nSerSize; | |||
} | |||
private: | |||
std::vector<char> _ssExtra; |
@@ -55,11 +55,15 @@ public: | |||
} | |||
IMPLEMENT_SERIALIZE | |||
( | |||
READWRITE(this->nVersion); | |||
nVersion = this->nVersion; | |||
READWRITE(nCreateTime); | |||
) | |||
template <typename T, typename Stream, typename Operation> | |||
inline static size_t SerializationOp(T thisPtr, Stream& s, Operation ser_action, int nType, int nVersion) { | |||
size_t nSerSize = 0; | |||
READWRITE(thisPtr->nVersion); | |||
nVersion = thisPtr->nVersion; | |||
READWRITE(thisPtr->nCreateTime); | |||
return nSerSize; | |||
} | |||
void SetNull() | |||
{ |