0
0
Fork 0
mirror of https://github.com/bitcoin/bitcoin.git synced 2025-02-08 10:31:50 -05:00

Merge #18317: Serialization improvements step 6 (all except wallet/gui)

f9ee0f37c2 Add comments to CustomUintFormatter (Pieter Wuille)
4eb5643e35 Convert everything except wallet/qt to new serialization (Pieter Wuille)
2b1f85e8c5 Convert blockencodings_tests to new serialization (Pieter Wuille)
73747afbbe Convert merkleblock to new serialization (Pieter Wuille)
d06fedd1bc Add SER_READ and SER_WRITE for read/write-dependent statements (Russell Yanofsky)
6f9a1e5ad0 Extend CustomUintFormatter to support enums (Russell Yanofsky)
769ee5fa00 Merge BigEndian functionality into CustomUintFormatter (Pieter Wuille)

Pull request description:

  The next step of changes from #10785.

  This:
  * Adds support for enum serialization to `CustomUintFormatter`, used in `CAddress` for service flags.
  * Merges `BigEndian` into `CustomUintFormatter`, used in `CNetAddr` for port numbers.
  * Converts everything (except wallet and gui) to use the new serialization framework.

ACKs for top commit:
  MarcoFalke:
    re-ACK f9ee0f37c2, only change is new documentation commit for CustomUintFormatter 📂
  ryanofsky:
    Code review ACK f9ee0f37c2. Just new commit adding comment since last review
  jonatack:
    Code review re-ACK f9ee0f37c2 only change since last review is an additional commit adding Doxygen documentation for `CustomUintFormatter`.

Tree-SHA512: e7a0a36afae592d5a4ff8c81ae04d858ac409388e361f2bc197d9a78abca45134218497ab2dfd6d031e0cce0ca586cf857077b7c6ce17fccf67e2d367c1b6cd4
This commit is contained in:
MarcoFalke 2020-05-20 07:30:21 -04:00
commit 448bdff263
No known key found for this signature in database
GPG key ID: CE2B75697E69A548
22 changed files with 155 additions and 301 deletions

View file

@ -20,9 +20,7 @@
struct nontrivial_t { struct nontrivial_t {
int x; int x;
nontrivial_t() :x(-1) {} nontrivial_t() :x(-1) {}
ADD_SERIALIZE_METHODS SERIALIZE_METHODS(nontrivial_t, obj) { READWRITE(obj.x); }
template <typename Stream, typename Operation>
inline void SerializationOp(Stream& s, Operation ser_action) {READWRITE(x);}
}; };
static_assert(!IS_TRIVIALLY_CONSTRUCTIBLE<nontrivial_t>::value, static_assert(!IS_TRIVIALLY_CONSTRUCTIBLE<nontrivial_t>::value,
"expected nontrivial_t to not be trivially constructible"); "expected nontrivial_t to not be trivially constructible");

View file

@ -92,12 +92,13 @@ private:
friend class PartiallyDownloadedBlock; friend class PartiallyDownloadedBlock;
static const int SHORTTXIDS_LENGTH = 6;
protected: protected:
std::vector<uint64_t> shorttxids; std::vector<uint64_t> shorttxids;
std::vector<PrefilledTransaction> prefilledtxn; std::vector<PrefilledTransaction> prefilledtxn;
public: public:
static constexpr int SHORTTXIDS_LENGTH = 6;
CBlockHeader header; CBlockHeader header;
// Dummy for deserialization // Dummy for deserialization

View file

@ -64,15 +64,7 @@ public:
CBloomFilter(const unsigned int nElements, const double nFPRate, const unsigned int nTweak, unsigned char nFlagsIn); CBloomFilter(const unsigned int nElements, const double nFPRate, const unsigned int nTweak, unsigned char nFlagsIn);
CBloomFilter() : nHashFuncs(0), nTweak(0), nFlags(0) {} CBloomFilter() : nHashFuncs(0), nTweak(0), nFlags(0) {}
ADD_SERIALIZE_METHODS; SERIALIZE_METHODS(CBloomFilter, obj) { READWRITE(obj.vData, obj.nHashFuncs, obj.nTweak, obj.nFlags); }
template <typename Stream, typename Operation>
inline void SerializationOp(Stream& s, Operation ser_action) {
READWRITE(vData);
READWRITE(nHashFuncs);
READWRITE(nTweak);
READWRITE(nFlags);
}
void insert(const std::vector<unsigned char>& vKey); void insert(const std::vector<unsigned char>& vKey);
void insert(const COutPoint& outpoint); void insert(const COutPoint& outpoint);

View file

@ -16,13 +16,7 @@ struct FlatFilePos
int nFile; int nFile;
unsigned int nPos; unsigned int nPos;
ADD_SERIALIZE_METHODS; SERIALIZE_METHODS(FlatFilePos, obj) { READWRITE(VARINT_MODE(obj.nFile, VarIntMode::NONNEGATIVE_SIGNED), VARINT(obj.nPos)); }
template <typename Stream, typename Operation>
inline void SerializationOp(Stream& s, Operation ser_action) {
READWRITE(VARINT_MODE(nFile, VarIntMode::NONNEGATIVE_SIGNED));
READWRITE(VARINT(nPos));
}
FlatFilePos() : nFile(-1), nPos(0) {} FlatFilePos() : nFile(-1), nPos(0) {}

View file

@ -39,14 +39,7 @@ struct DBVal {
uint256 header; uint256 header;
FlatFilePos pos; FlatFilePos pos;
ADD_SERIALIZE_METHODS; SERIALIZE_METHODS(DBVal, obj) { READWRITE(obj.hash, obj.header, obj.pos); }
template <typename Stream, typename Operation>
inline void SerializationOp(Stream& s, Operation ser_action) {
READWRITE(hash);
READWRITE(header);
READWRITE(pos);
}
}; };
struct DBHeightKey { struct DBHeightKey {
@ -78,17 +71,14 @@ struct DBHashKey {
explicit DBHashKey(const uint256& hash_in) : hash(hash_in) {} explicit DBHashKey(const uint256& hash_in) : hash(hash_in) {}
ADD_SERIALIZE_METHODS; SERIALIZE_METHODS(DBHashKey, obj) {
template <typename Stream, typename Operation>
inline void SerializationOp(Stream& s, Operation ser_action) {
char prefix = DB_BLOCK_HASH; char prefix = DB_BLOCK_HASH;
READWRITE(prefix); READWRITE(prefix);
if (prefix != DB_BLOCK_HASH) { if (prefix != DB_BLOCK_HASH) {
throw std::ios_base::failure("Invalid format for block filter index DB hash key"); throw std::ios_base::failure("Invalid format for block filter index DB hash key");
} }
READWRITE(hash); READWRITE(obj.hash);
} }
}; };

View file

@ -21,12 +21,10 @@ struct CDiskTxPos : public FlatFilePos
{ {
unsigned int nTxOffset; // after header unsigned int nTxOffset; // after header
ADD_SERIALIZE_METHODS; SERIALIZE_METHODS(CDiskTxPos, obj)
{
template <typename Stream, typename Operation> READWRITEAS(FlatFilePos, obj);
inline void SerializationOp(Stream& s, Operation ser_action) { READWRITE(VARINT(obj.nTxOffset));
READWRITEAS(FlatFilePos, *this);
READWRITE(VARINT(nTxOffset));
} }
CDiskTxPos(const FlatFilePos &blockIn, unsigned int nTxOffsetIn) : FlatFilePos(blockIn.nFile, blockIn.nPos), nTxOffset(nTxOffsetIn) { CDiskTxPos(const FlatFilePos &blockIn, unsigned int nTxOffsetIn) : FlatFilePos(blockIn.nFile, blockIn.nPos), nTxOffset(nTxOffsetIn) {

View file

@ -9,6 +9,24 @@
#include <consensus/consensus.h> #include <consensus/consensus.h>
std::vector<unsigned char> BitsToBytes(const std::vector<bool>& bits)
{
std::vector<unsigned char> ret((bits.size() + 7) / 8);
for (unsigned int p = 0; p < bits.size(); p++) {
ret[p / 8] |= bits[p] << (p % 8);
}
return ret;
}
std::vector<bool> BytesToBits(const std::vector<unsigned char>& bytes)
{
std::vector<bool> ret(bytes.size() * 8);
for (unsigned int p = 0; p < ret.size(); p++) {
ret[p] = (bytes[p / 8] & (1 << (p % 8))) != 0;
}
return ret;
}
CMerkleBlock::CMerkleBlock(const CBlock& block, CBloomFilter* filter, const std::set<uint256>* txids) CMerkleBlock::CMerkleBlock(const CBlock& block, CBloomFilter* filter, const std::set<uint256>* txids)
{ {
header = block.GetBlockHeader(); header = block.GetBlockHeader();

View file

@ -13,6 +13,10 @@
#include <vector> #include <vector>
// Helper functions for serialization.
std::vector<unsigned char> BitsToBytes(const std::vector<bool>& bits);
std::vector<bool> BytesToBits(const std::vector<unsigned char>& bytes);
/** Data structure that represents a partial merkle tree. /** Data structure that represents a partial merkle tree.
* *
* It represents a subset of the txid's of a known block, in a way that * It represents a subset of the txid's of a known block, in a way that
@ -81,27 +85,14 @@ protected:
public: public:
/** serialization implementation */ SERIALIZE_METHODS(CPartialMerkleTree, obj)
ADD_SERIALIZE_METHODS; {
READWRITE(obj.nTransactions, obj.vHash);
template <typename Stream, typename Operation> std::vector<unsigned char> bytes;
inline void SerializationOp(Stream& s, Operation ser_action) { SER_WRITE(obj, bytes = BitsToBytes(obj.vBits));
READWRITE(nTransactions); READWRITE(bytes);
READWRITE(vHash); SER_READ(obj, obj.vBits = BytesToBits(bytes));
std::vector<unsigned char> vBytes; SER_READ(obj, obj.fBad = false);
if (ser_action.ForRead()) {
READWRITE(vBytes);
CPartialMerkleTree &us = *(const_cast<CPartialMerkleTree*>(this));
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);
READWRITE(vBytes);
}
} }
/** Construct a partial merkle tree from a list of transaction ids, and a mask that selects a subset of them */ /** Construct a partial merkle tree from a list of transaction ids, and a mask that selects a subset of them */
@ -157,13 +148,7 @@ public:
CMerkleBlock() {} CMerkleBlock() {}
ADD_SERIALIZE_METHODS; SERIALIZE_METHODS(CMerkleBlock, obj) { READWRITE(obj.header, obj.txn); }
template <typename Stream, typename Operation>
inline void SerializationOp(Stream& s, Operation ser_action) {
READWRITE(header);
READWRITE(txn);
}
private: private:
// Combined constructor to consolidate code // Combined constructor to consolidate code

View file

@ -99,12 +99,7 @@ class CNetAddr
friend bool operator!=(const CNetAddr& a, const CNetAddr& b) { return !(a == b); } friend bool operator!=(const CNetAddr& a, const CNetAddr& b) { return !(a == b); }
friend bool operator<(const CNetAddr& a, const CNetAddr& b); friend bool operator<(const CNetAddr& a, const CNetAddr& b);
ADD_SERIALIZE_METHODS; SERIALIZE_METHODS(CNetAddr, obj) { READWRITE(obj.ip); }
template <typename Stream, typename Operation>
inline void SerializationOp(Stream& s, Operation ser_action) {
READWRITE(ip);
}
friend class CSubNet; friend class CSubNet;
}; };
@ -136,14 +131,7 @@ class CSubNet
friend bool operator!=(const CSubNet& a, const CSubNet& b) { return !(a == b); } friend bool operator!=(const CSubNet& a, const CSubNet& b) { return !(a == b); }
friend bool operator<(const CSubNet& a, const CSubNet& b); friend bool operator<(const CSubNet& a, const CSubNet& b);
ADD_SERIALIZE_METHODS; SERIALIZE_METHODS(CSubNet, obj) { READWRITE(obj.network, obj.netmask, obj.valid); }
template <typename Stream, typename Operation>
inline void SerializationOp(Stream& s, Operation ser_action) {
READWRITE(network);
READWRITE(netmask);
READWRITE(valid);
}
}; };
/** A combination of a network address (CNetAddr) and a (TCP) port */ /** A combination of a network address (CNetAddr) and a (TCP) port */
@ -171,13 +159,7 @@ class CService : public CNetAddr
CService(const struct in6_addr& ipv6Addr, unsigned short port); CService(const struct in6_addr& ipv6Addr, unsigned short port);
explicit CService(const struct sockaddr_in6& addr); explicit CService(const struct sockaddr_in6& addr);
ADD_SERIALIZE_METHODS; SERIALIZE_METHODS(CService, obj) { READWRITE(obj.ip, Using<BigEndianFormatter<2>>(obj.port)); }
template <typename Stream, typename Operation>
inline void SerializationOp(Stream& s, Operation ser_action) {
READWRITE(ip);
READWRITE(WrapBigEndian(port));
}
}; };
bool SanityCheckASMap(const std::vector<bool>& asmap); bool SanityCheckASMap(const std::vector<bool>& asmap);

View file

@ -35,16 +35,7 @@ public:
m_coins_count(coins_count), m_coins_count(coins_count),
m_nchaintx(nchaintx) { } m_nchaintx(nchaintx) { }
ADD_SERIALIZE_METHODS; SERIALIZE_METHODS(SnapshotMetadata, obj) { READWRITE(obj.m_base_blockhash, obj.m_coins_count, obj.m_nchaintx); }
template <typename Stream, typename Operation>
inline void SerializationOp(Stream& s, Operation ser_action)
{
READWRITE(m_base_blockhash);
READWRITE(m_coins_count);
READWRITE(m_nchaintx);
}
}; };
#endif // BITCOIN_NODE_UTXO_SNAPSHOT_H #endif // BITCOIN_NODE_UTXO_SNAPSHOT_H

View file

@ -48,12 +48,7 @@ public:
CFeeRate& operator+=(const CFeeRate& a) { nSatoshisPerK += a.nSatoshisPerK; return *this; } CFeeRate& operator+=(const CFeeRate& a) { nSatoshisPerK += a.nSatoshisPerK; return *this; }
std::string ToString() const; std::string ToString() const;
ADD_SERIALIZE_METHODS; SERIALIZE_METHODS(CFeeRate, obj) { READWRITE(obj.nSatoshisPerK); }
template <typename Stream, typename Operation>
inline void SerializationOp(Stream& s, Operation ser_action) {
READWRITE(nSatoshisPerK);
}
}; };
#endif // BITCOIN_POLICY_FEERATE_H #endif // BITCOIN_POLICY_FEERATE_H

View file

@ -33,17 +33,7 @@ public:
SetNull(); SetNull();
} }
ADD_SERIALIZE_METHODS; SERIALIZE_METHODS(CBlockHeader, obj) { READWRITE(obj.nVersion, obj.hashPrevBlock, obj.hashMerkleRoot, obj.nTime, obj.nBits, obj.nNonce); }
template <typename Stream, typename Operation>
inline void SerializationOp(Stream& s, Operation ser_action) {
READWRITE(this->nVersion);
READWRITE(hashPrevBlock);
READWRITE(hashMerkleRoot);
READWRITE(nTime);
READWRITE(nBits);
READWRITE(nNonce);
}
void SetNull() void SetNull()
{ {
@ -89,12 +79,10 @@ public:
*(static_cast<CBlockHeader*>(this)) = header; *(static_cast<CBlockHeader*>(this)) = header;
} }
ADD_SERIALIZE_METHODS; SERIALIZE_METHODS(CBlock, obj)
{
template <typename Stream, typename Operation> READWRITEAS(CBlockHeader, obj);
inline void SerializationOp(Stream& s, Operation ser_action) { READWRITE(obj.vtx);
READWRITEAS(CBlockHeader, *this);
READWRITE(vtx);
} }
void SetNull() void SetNull()
@ -131,14 +119,12 @@ struct CBlockLocator
explicit CBlockLocator(const std::vector<uint256>& vHaveIn) : vHave(vHaveIn) {} explicit CBlockLocator(const std::vector<uint256>& vHaveIn) : vHave(vHaveIn) {}
ADD_SERIALIZE_METHODS; SERIALIZE_METHODS(CBlockLocator, obj)
{
template <typename Stream, typename Operation>
inline void SerializationOp(Stream& s, Operation ser_action) {
int nVersion = s.GetVersion(); int nVersion = s.GetVersion();
if (!(s.GetType() & SER_GETHASH)) if (!(s.GetType() & SER_GETHASH))
READWRITE(nVersion); READWRITE(nVersion);
READWRITE(vHave); READWRITE(obj.vHave);
} }
void SetNull() void SetNull()

View file

@ -26,13 +26,7 @@ public:
COutPoint(): n(NULL_INDEX) { } COutPoint(): n(NULL_INDEX) { }
COutPoint(const uint256& hashIn, uint32_t nIn): hash(hashIn), n(nIn) { } COutPoint(const uint256& hashIn, uint32_t nIn): hash(hashIn), n(nIn) { }
ADD_SERIALIZE_METHODS; SERIALIZE_METHODS(COutPoint, obj) { READWRITE(obj.hash, obj.n); }
template <typename Stream, typename Operation>
inline void SerializationOp(Stream& s, Operation ser_action) {
READWRITE(hash);
READWRITE(n);
}
void SetNull() { hash.SetNull(); n = NULL_INDEX; } void SetNull() { hash.SetNull(); n = NULL_INDEX; }
bool IsNull() const { return (hash.IsNull() && n == NULL_INDEX); } bool IsNull() const { return (hash.IsNull() && n == NULL_INDEX); }
@ -103,14 +97,7 @@ public:
explicit CTxIn(COutPoint prevoutIn, CScript scriptSigIn=CScript(), uint32_t nSequenceIn=SEQUENCE_FINAL); explicit CTxIn(COutPoint prevoutIn, CScript scriptSigIn=CScript(), uint32_t nSequenceIn=SEQUENCE_FINAL);
CTxIn(uint256 hashPrevTx, uint32_t nOut, CScript scriptSigIn=CScript(), uint32_t nSequenceIn=SEQUENCE_FINAL); CTxIn(uint256 hashPrevTx, uint32_t nOut, CScript scriptSigIn=CScript(), uint32_t nSequenceIn=SEQUENCE_FINAL);
ADD_SERIALIZE_METHODS; SERIALIZE_METHODS(CTxIn, obj) { READWRITE(obj.prevout, obj.scriptSig, obj.nSequence); }
template <typename Stream, typename Operation>
inline void SerializationOp(Stream& s, Operation ser_action) {
READWRITE(prevout);
READWRITE(scriptSig);
READWRITE(nSequence);
}
friend bool operator==(const CTxIn& a, const CTxIn& b) friend bool operator==(const CTxIn& a, const CTxIn& b)
{ {
@ -143,13 +130,7 @@ public:
CTxOut(const CAmount& nValueIn, CScript scriptPubKeyIn); CTxOut(const CAmount& nValueIn, CScript scriptPubKeyIn);
ADD_SERIALIZE_METHODS; SERIALIZE_METHODS(CTxOut, obj) { READWRITE(obj.nValue, obj.scriptPubKey); }
template <typename Stream, typename Operation>
inline void SerializationOp(Stream& s, Operation ser_action) {
READWRITE(nValue);
READWRITE(scriptPubKey);
}
void SetNull() void SetNull()
{ {

View file

@ -46,16 +46,7 @@ public:
std::string GetCommand() const; std::string GetCommand() const;
bool IsValid(const MessageStartChars& messageStart) const; bool IsValid(const MessageStartChars& messageStart) const;
ADD_SERIALIZE_METHODS; SERIALIZE_METHODS(CMessageHeader, obj) { READWRITE(obj.pchMessageStart, obj.pchCommand, obj.nMessageSize, obj.pchChecksum); }
template <typename Stream, typename Operation>
inline void SerializationOp(Stream& s, Operation ser_action)
{
READWRITE(pchMessageStart);
READWRITE(pchCommand);
READWRITE(nMessageSize);
READWRITE(pchChecksum);
}
char pchMessageStart[MESSAGE_START_SIZE]; char pchMessageStart[MESSAGE_START_SIZE];
char pchCommand[COMMAND_SIZE]; char pchCommand[COMMAND_SIZE];
@ -343,23 +334,19 @@ public:
void Init(); void Init();
ADD_SERIALIZE_METHODS; SERIALIZE_METHODS(CAddress, obj)
template <typename Stream, typename Operation>
inline void SerializationOp(Stream& s, Operation ser_action)
{ {
if (ser_action.ForRead()) SER_READ(obj, obj.Init());
Init();
int nVersion = s.GetVersion(); int nVersion = s.GetVersion();
if (s.GetType() & SER_DISK) if (s.GetType() & SER_DISK) {
READWRITE(nVersion); READWRITE(nVersion);
}
if ((s.GetType() & SER_DISK) || if ((s.GetType() & SER_DISK) ||
(nVersion >= CADDR_TIME_VERSION && !(s.GetType() & SER_GETHASH))) (nVersion >= CADDR_TIME_VERSION && !(s.GetType() & SER_GETHASH))) {
READWRITE(nTime); READWRITE(obj.nTime);
uint64_t nServicesInt = nServices; }
READWRITE(nServicesInt); READWRITE(Using<CustomUintFormatter<8>>(obj.nServices));
nServices = static_cast<ServiceFlags>(nServicesInt); READWRITEAS(CService, obj);
READWRITEAS(CService, *this);
} }
ServiceFlags nServices; ServiceFlags nServices;
@ -395,14 +382,7 @@ public:
CInv(); CInv();
CInv(int typeIn, const uint256& hashIn); CInv(int typeIn, const uint256& hashIn);
ADD_SERIALIZE_METHODS; SERIALIZE_METHODS(CInv, obj) { READWRITE(obj.type, obj.hash); }
template <typename Stream, typename Operation>
inline void SerializationOp(Stream& s, Operation ser_action)
{
READWRITE(type);
READWRITE(hash);
}
friend bool operator<(const CInv& a, const CInv& b); friend bool operator<(const CInv& a, const CInv& b);

View file

@ -49,18 +49,13 @@ struct CCoin {
uint32_t nHeight; uint32_t nHeight;
CTxOut out; CTxOut out;
ADD_SERIALIZE_METHODS;
CCoin() : nHeight(0) {} CCoin() : nHeight(0) {}
explicit CCoin(Coin&& in) : nHeight(in.nHeight), out(std::move(in.out)) {} explicit CCoin(Coin&& in) : nHeight(in.nHeight), out(std::move(in.out)) {}
template <typename Stream, typename Operation> SERIALIZE_METHODS(CCoin, obj)
inline void SerializationOp(Stream& s, Operation ser_action)
{ {
uint32_t nTxVerDummy = 0; uint32_t nTxVerDummy = 0;
READWRITE(nTxVerDummy); READWRITE(nTxVerDummy, obj.nHeight, obj.out);
READWRITE(nHeight);
READWRITE(out);
} }
}; };

View file

@ -18,13 +18,7 @@ struct KeyOriginInfo
return std::equal(std::begin(a.fingerprint), std::end(a.fingerprint), std::begin(b.fingerprint)) && a.path == b.path; return std::equal(std::begin(a.fingerprint), std::end(a.fingerprint), std::begin(b.fingerprint)) && a.path == b.path;
} }
ADD_SERIALIZE_METHODS; SERIALIZE_METHODS(KeyOriginInfo, obj) { READWRITE(obj.fingerprint, obj.path); }
template <typename Stream, typename Operation>
inline void SerializationOp(Stream& s, Operation ser_action)
{
READWRITE(fingerprint);
READWRITE(path);
}
void clear() void clear()
{ {

View file

@ -412,12 +412,7 @@ public:
CScript(std::vector<unsigned char>::const_iterator pbegin, std::vector<unsigned char>::const_iterator pend) : CScriptBase(pbegin, pend) { } CScript(std::vector<unsigned char>::const_iterator pbegin, std::vector<unsigned char>::const_iterator pend) : CScriptBase(pbegin, pend) { }
CScript(const unsigned char* pbegin, const unsigned char* pend) : CScriptBase(pbegin, pend) { } CScript(const unsigned char* pbegin, const unsigned char* pend) : CScriptBase(pbegin, pend) { }
ADD_SERIALIZE_METHODS; SERIALIZE_METHODS(CScript, obj) { READWRITEAS(CScriptBase, obj); }
template <typename Stream, typename Operation>
inline void SerializationOp(Stream& s, Operation ser_action) {
READWRITEAS(CScriptBase, *this);
}
explicit CScript(int64_t b) { operator<<(b); } explicit CScript(int64_t b) { operator<<(b); }
explicit CScript(opcodetype b) { operator<<(b); } explicit CScript(opcodetype b) { operator<<(b); }

View file

@ -190,6 +190,8 @@ template<typename X> const X& ReadWriteAsHelper(const X& x) { return x; }
#define READWRITE(...) (::SerReadWriteMany(s, ser_action, __VA_ARGS__)) #define READWRITE(...) (::SerReadWriteMany(s, ser_action, __VA_ARGS__))
#define READWRITEAS(type, obj) (::SerReadWriteMany(s, ser_action, ReadWriteAsHelper<type>(obj))) #define READWRITEAS(type, obj) (::SerReadWriteMany(s, ser_action, ReadWriteAsHelper<type>(obj)))
#define SER_READ(obj, code) ::SerRead(s, ser_action, obj, [&](Stream& s, typename std::remove_const<Type>::type& obj) { code; })
#define SER_WRITE(obj, code) ::SerWrite(s, ser_action, obj, [&](Stream& s, const Type& obj) { code; })
/** /**
* Implement three methods for serializable objects. These are actually wrappers over * Implement three methods for serializable objects. These are actually wrappers over
@ -518,7 +520,16 @@ struct VarIntFormatter
} }
}; };
template<int Bytes> /** Serialization wrapper class for custom integers and enums.
*
* It permits specifying the serialized size (1 to 8 bytes) and endianness.
*
* Use the big endian mode for values that are stored in memory in native
* byte order, but serialized in big endian notation. This is only intended
* to implement serializers that are compatible with existing formats, and
* its use is not recommended for new data structures.
*/
template<int Bytes, bool BigEndian = false>
struct CustomUintFormatter struct CustomUintFormatter
{ {
static_assert(Bytes > 0 && Bytes <= 8, "CustomUintFormatter Bytes out of range"); static_assert(Bytes > 0 && Bytes <= 8, "CustomUintFormatter Bytes out of range");
@ -527,52 +538,31 @@ struct CustomUintFormatter
template <typename Stream, typename I> void Ser(Stream& s, I v) template <typename Stream, typename I> void Ser(Stream& s, I v)
{ {
if (v < 0 || v > MAX) throw std::ios_base::failure("CustomUintFormatter value out of range"); if (v < 0 || v > MAX) throw std::ios_base::failure("CustomUintFormatter value out of range");
uint64_t raw = htole64(v); if (BigEndian) {
s.write((const char*)&raw, Bytes); uint64_t raw = htobe64(v);
s.write(((const char*)&raw) + 8 - Bytes, Bytes);
} else {
uint64_t raw = htole64(v);
s.write((const char*)&raw, Bytes);
}
} }
template <typename Stream, typename I> void Unser(Stream& s, I& v) template <typename Stream, typename I> void Unser(Stream& s, I& v)
{ {
static_assert(std::numeric_limits<I>::max() >= MAX && std::numeric_limits<I>::min() <= 0, "CustomUintFormatter type too small"); using U = typename std::conditional<std::is_enum<I>::value, std::underlying_type<I>, std::common_type<I>>::type::type;
static_assert(std::numeric_limits<U>::max() >= MAX && std::numeric_limits<U>::min() <= 0, "Assigned type too small");
uint64_t raw = 0; uint64_t raw = 0;
s.read((char*)&raw, Bytes); if (BigEndian) {
v = le64toh(raw); s.read(((char*)&raw) + 8 - Bytes, Bytes);
v = static_cast<I>(be64toh(raw));
} else {
s.read((char*)&raw, Bytes);
v = static_cast<I>(le64toh(raw));
}
} }
}; };
/** Serialization wrapper class for big-endian integers. template<int Bytes> using BigEndianFormatter = CustomUintFormatter<Bytes, true>;
*
* Use this wrapper around integer types that are stored in memory in native
* byte order, but serialized in big endian notation. This is only intended
* to implement serializers that are compatible with existing formats, and
* its use is not recommended for new data structures.
*
* Only 16-bit types are supported for now.
*/
template<typename I>
class BigEndian
{
protected:
I& m_val;
public:
explicit BigEndian(I& val) : m_val(val)
{
static_assert(std::is_unsigned<I>::value, "BigEndian type must be unsigned integer");
static_assert(sizeof(I) == 2 && std::numeric_limits<I>::min() == 0 && std::numeric_limits<I>::max() == std::numeric_limits<uint16_t>::max(), "Unsupported BigEndian size");
}
template<typename Stream>
void Serialize(Stream& s) const
{
ser_writedata16be(s, m_val);
}
template<typename Stream>
void Unserialize(Stream& s)
{
m_val = ser_readdata16be(s);
}
};
/** Formatter for integers in CompactSize format. */ /** Formatter for integers in CompactSize format. */
struct CompactSizeFormatter struct CompactSizeFormatter
@ -626,9 +616,6 @@ public:
} }
}; };
template<typename I>
BigEndian<I> WrapBigEndian(I& n) { return BigEndian<I>(n); }
/** Formatter to serialize/deserialize vector elements using another formatter /** Formatter to serialize/deserialize vector elements using another formatter
* *
* Example: * Example:
@ -1124,6 +1111,28 @@ inline void SerReadWriteMany(Stream& s, CSerActionUnserialize ser_action, Args&&
::UnserializeMany(s, args...); ::UnserializeMany(s, args...);
} }
template<typename Stream, typename Type, typename Fn>
inline void SerRead(Stream& s, CSerActionSerialize ser_action, Type&&, Fn&&)
{
}
template<typename Stream, typename Type, typename Fn>
inline void SerRead(Stream& s, CSerActionUnserialize ser_action, Type&& obj, Fn&& fn)
{
fn(s, std::forward<Type>(obj));
}
template<typename Stream, typename Type, typename Fn>
inline void SerWrite(Stream& s, CSerActionSerialize ser_action, Type&& obj, Fn&& fn)
{
fn(s, std::forward<Type>(obj));
}
template<typename Stream, typename Type, typename Fn>
inline void SerWrite(Stream& s, CSerActionUnserialize ser_action, Type&&, Fn&&)
{
}
template<typename I> template<typename I>
inline void WriteVarInt(CSizeComputer &s, I n) inline void WriteVarInt(CSizeComputer &s, I n)
{ {

View file

@ -132,24 +132,7 @@ public:
return base.GetShortID(txhash); return base.GetShortID(txhash);
} }
ADD_SERIALIZE_METHODS; SERIALIZE_METHODS(TestHeaderAndShortIDs, obj) { READWRITE(obj.header, obj.nonce, Using<VectorFormatter<CustomUintFormatter<CBlockHeaderAndShortTxIDs::SHORTTXIDS_LENGTH>>>(obj.shorttxids), obj.prefilledtxn); }
template <typename Stream, typename Operation>
inline void SerializationOp(Stream& s, Operation ser_action) {
READWRITE(header);
READWRITE(nonce);
size_t shorttxids_size = shorttxids.size();
READWRITE(VARINT(shorttxids_size));
shorttxids.resize(shorttxids_size);
for (size_t i = 0; i < shorttxids.size(); i++) {
uint32_t lsb = shorttxids[i] & 0xffffffff;
uint16_t msb = (shorttxids[i] >> 32) & 0xffff;
READWRITE(lsb);
READWRITE(msb);
shorttxids[i] = (uint64_t(msb) << 32) | uint64_t(lsb);
}
READWRITE(prefilledtxn);
}
}; };
BOOST_AUTO_TEST_CASE(NonCoinbasePreforwardRTTest) BOOST_AUTO_TEST_CASE(NonCoinbasePreforwardRTTest)

View file

@ -331,24 +331,26 @@ struct StringContentsSerializer {
} }
StringContentsSerializer& operator+=(const StringContentsSerializer& s) { return *this += s.str; } StringContentsSerializer& operator+=(const StringContentsSerializer& s) { return *this += s.str; }
ADD_SERIALIZE_METHODS; template<typename Stream>
void Serialize(Stream& s) const
{
for (size_t i = 0; i < str.size(); i++) {
s << str[i];
}
}
template <typename Stream, typename Operation> template<typename Stream>
inline void SerializationOp(Stream& s, Operation ser_action) { void Unserialize(Stream& s)
if (ser_action.ForRead()) { {
str.clear(); str.clear();
char c = 0; char c = 0;
while (true) { while (true) {
try { try {
READWRITE(c); s >> c;
str.push_back(c); str.push_back(c);
} catch (const std::ios_base::failure&) { } catch (const std::ios_base::failure&) {
break; break;
}
} }
} else {
for (size_t i = 0; i < str.size(); i++)
READWRITE(str[i]);
} }
} }
}; };

View file

@ -29,15 +29,13 @@ public:
memcpy(charstrval, charstrvalin, sizeof(charstrval)); memcpy(charstrval, charstrvalin, sizeof(charstrval));
} }
ADD_SERIALIZE_METHODS; SERIALIZE_METHODS(CSerializeMethodsTestSingle, obj)
{
template <typename Stream, typename Operation> READWRITE(obj.intval);
inline void SerializationOp(Stream& s, Operation ser_action) { READWRITE(obj.boolval);
READWRITE(intval); READWRITE(obj.stringval);
READWRITE(boolval); READWRITE(obj.charstrval);
READWRITE(stringval); READWRITE(obj.txval);
READWRITE(charstrval);
READWRITE(txval);
} }
bool operator==(const CSerializeMethodsTestSingle& rhs) bool operator==(const CSerializeMethodsTestSingle& rhs)
@ -54,11 +52,10 @@ class CSerializeMethodsTestMany : public CSerializeMethodsTestSingle
{ {
public: public:
using CSerializeMethodsTestSingle::CSerializeMethodsTestSingle; using CSerializeMethodsTestSingle::CSerializeMethodsTestSingle;
ADD_SERIALIZE_METHODS;
template <typename Stream, typename Operation> SERIALIZE_METHODS(CSerializeMethodsTestMany, obj)
inline void SerializationOp(Stream& s, Operation ser_action) { {
READWRITE(intval, boolval, stringval, charstrval, txval); READWRITE(obj.intval, obj.boolval, obj.stringval, obj.charstrval, obj.txval);
} }
}; };

View file

@ -36,19 +36,7 @@ struct CoinEntry {
char key; char key;
explicit CoinEntry(const COutPoint* ptr) : outpoint(const_cast<COutPoint*>(ptr)), key(DB_COIN) {} explicit CoinEntry(const COutPoint* ptr) : outpoint(const_cast<COutPoint*>(ptr)), key(DB_COIN) {}
template<typename Stream> SERIALIZE_METHODS(CoinEntry, obj) { READWRITE(obj.key, obj.outpoint->hash, VARINT(obj.outpoint->n)); }
void Serialize(Stream &s) const {
s << key;
s << outpoint->hash;
s << VARINT(outpoint->n);
}
template<typename Stream>
void Unserialize(Stream& s) {
s >> key;
s >> outpoint->hash;
s >> VARINT(outpoint->n);
}
}; };
} }