aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--src/bench/prevector.cpp4
-rw-r--r--src/blockencodings.h3
-rw-r--r--src/bloom.h10
-rw-r--r--src/flatfile.h8
-rw-r--r--src/index/blockfilterindex.cpp16
-rw-r--r--src/index/txindex.cpp10
-rw-r--r--src/merkleblock.cpp18
-rw-r--r--src/merkleblock.h41
-rw-r--r--src/netaddress.h24
-rw-r--r--src/node/utxo_snapshot.h11
-rw-r--r--src/policy/feerate.h7
-rw-r--r--src/primitives/block.h30
-rw-r--r--src/primitives/transaction.h25
-rw-r--r--src/protocol.h42
-rw-r--r--src/rest.cpp9
-rw-r--r--src/script/keyorigin.h8
-rw-r--r--src/script/script.h7
-rw-r--r--src/serialize.h93
-rw-r--r--src/test/blockencodings_tests.cpp19
-rw-r--r--src/test/dbwrapper_tests.cpp36
-rw-r--r--src/test/serialize_tests.cpp23
-rw-r--r--src/txdb.cpp14
22 files changed, 156 insertions, 302 deletions
diff --git a/src/bench/prevector.cpp b/src/bench/prevector.cpp
index 00e5d7e7a0..42b351a72d 100644
--- a/src/bench/prevector.cpp
+++ b/src/bench/prevector.cpp
@@ -20,9 +20,7 @@
struct nontrivial_t {
int x;
nontrivial_t() :x(-1) {}
- ADD_SERIALIZE_METHODS
- template <typename Stream, typename Operation>
- inline void SerializationOp(Stream& s, Operation ser_action) {READWRITE(x);}
+ SERIALIZE_METHODS(nontrivial_t, obj) { READWRITE(obj.x); }
};
static_assert(!IS_TRIVIALLY_CONSTRUCTIBLE<nontrivial_t>::value,
"expected nontrivial_t to not be trivially constructible");
diff --git a/src/blockencodings.h b/src/blockencodings.h
index 377ac3a1a6..9ec1beeaf7 100644
--- a/src/blockencodings.h
+++ b/src/blockencodings.h
@@ -92,12 +92,13 @@ private:
friend class PartiallyDownloadedBlock;
- static const int SHORTTXIDS_LENGTH = 6;
protected:
std::vector<uint64_t> shorttxids;
std::vector<PrefilledTransaction> prefilledtxn;
public:
+ static constexpr int SHORTTXIDS_LENGTH = 6;
+
CBlockHeader header;
// Dummy for deserialization
diff --git a/src/bloom.h b/src/bloom.h
index 9173b80d66..9307257852 100644
--- a/src/bloom.h
+++ b/src/bloom.h
@@ -64,15 +64,7 @@ public:
CBloomFilter(const unsigned int nElements, const double nFPRate, const unsigned int nTweak, unsigned char nFlagsIn);
CBloomFilter() : nHashFuncs(0), nTweak(0), nFlags(0) {}
- ADD_SERIALIZE_METHODS;
-
- template <typename Stream, typename Operation>
- inline void SerializationOp(Stream& s, Operation ser_action) {
- READWRITE(vData);
- READWRITE(nHashFuncs);
- READWRITE(nTweak);
- READWRITE(nFlags);
- }
+ SERIALIZE_METHODS(CBloomFilter, obj) { READWRITE(obj.vData, obj.nHashFuncs, obj.nTweak, obj.nFlags); }
void insert(const std::vector<unsigned char>& vKey);
void insert(const COutPoint& outpoint);
diff --git a/src/flatfile.h b/src/flatfile.h
index 60b3503cc3..04f6373a24 100644
--- a/src/flatfile.h
+++ b/src/flatfile.h
@@ -16,13 +16,7 @@ struct FlatFilePos
int nFile;
unsigned int nPos;
- ADD_SERIALIZE_METHODS;
-
- template <typename Stream, typename Operation>
- inline void SerializationOp(Stream& s, Operation ser_action) {
- READWRITE(VARINT_MODE(nFile, VarIntMode::NONNEGATIVE_SIGNED));
- READWRITE(VARINT(nPos));
- }
+ SERIALIZE_METHODS(FlatFilePos, obj) { READWRITE(VARINT_MODE(obj.nFile, VarIntMode::NONNEGATIVE_SIGNED), VARINT(obj.nPos)); }
FlatFilePos() : nFile(-1), nPos(0) {}
diff --git a/src/index/blockfilterindex.cpp b/src/index/blockfilterindex.cpp
index c3ce8d7af0..f2c3d66ebd 100644
--- a/src/index/blockfilterindex.cpp
+++ b/src/index/blockfilterindex.cpp
@@ -39,14 +39,7 @@ struct DBVal {
uint256 header;
FlatFilePos pos;
- ADD_SERIALIZE_METHODS;
-
- template <typename Stream, typename Operation>
- inline void SerializationOp(Stream& s, Operation ser_action) {
- READWRITE(hash);
- READWRITE(header);
- READWRITE(pos);
- }
+ SERIALIZE_METHODS(DBVal, obj) { READWRITE(obj.hash, obj.header, obj.pos); }
};
struct DBHeightKey {
@@ -78,17 +71,14 @@ struct DBHashKey {
explicit DBHashKey(const uint256& hash_in) : hash(hash_in) {}
- ADD_SERIALIZE_METHODS;
-
- template <typename Stream, typename Operation>
- inline void SerializationOp(Stream& s, Operation ser_action) {
+ SERIALIZE_METHODS(DBHashKey, obj) {
char prefix = DB_BLOCK_HASH;
READWRITE(prefix);
if (prefix != DB_BLOCK_HASH) {
throw std::ios_base::failure("Invalid format for block filter index DB hash key");
}
- READWRITE(hash);
+ READWRITE(obj.hash);
}
};
diff --git a/src/index/txindex.cpp b/src/index/txindex.cpp
index 5bbe6ad1df..4626395ef0 100644
--- a/src/index/txindex.cpp
+++ b/src/index/txindex.cpp
@@ -21,12 +21,10 @@ struct CDiskTxPos : public FlatFilePos
{
unsigned int nTxOffset; // after header
- ADD_SERIALIZE_METHODS;
-
- template <typename Stream, typename Operation>
- inline void SerializationOp(Stream& s, Operation ser_action) {
- READWRITEAS(FlatFilePos, *this);
- READWRITE(VARINT(nTxOffset));
+ SERIALIZE_METHODS(CDiskTxPos, obj)
+ {
+ READWRITEAS(FlatFilePos, obj);
+ READWRITE(VARINT(obj.nTxOffset));
}
CDiskTxPos(const FlatFilePos &blockIn, unsigned int nTxOffsetIn) : FlatFilePos(blockIn.nFile, blockIn.nPos), nTxOffset(nTxOffsetIn) {
diff --git a/src/merkleblock.cpp b/src/merkleblock.cpp
index 4ac6219886..8072b12119 100644
--- a/src/merkleblock.cpp
+++ b/src/merkleblock.cpp
@@ -9,6 +9,24 @@
#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)
{
header = block.GetBlockHeader();
diff --git a/src/merkleblock.h b/src/merkleblock.h
index e641c8aa94..b2d2828784 100644
--- a/src/merkleblock.h
+++ b/src/merkleblock.h
@@ -13,6 +13,10 @@
#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.
*
* It represents a subset of the txid's of a known block, in a way that
@@ -81,27 +85,14 @@ protected:
public:
- /** serialization implementation */
- ADD_SERIALIZE_METHODS;
-
- template <typename Stream, typename Operation>
- inline void SerializationOp(Stream& s, Operation ser_action) {
- READWRITE(nTransactions);
- READWRITE(vHash);
- std::vector<unsigned char> vBytes;
- 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);
- }
+ SERIALIZE_METHODS(CPartialMerkleTree, obj)
+ {
+ READWRITE(obj.nTransactions, obj.vHash);
+ std::vector<unsigned char> bytes;
+ SER_WRITE(obj, bytes = BitsToBytes(obj.vBits));
+ READWRITE(bytes);
+ SER_READ(obj, obj.vBits = BytesToBits(bytes));
+ SER_READ(obj, obj.fBad = false);
}
/** 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() {}
- ADD_SERIALIZE_METHODS;
-
- template <typename Stream, typename Operation>
- inline void SerializationOp(Stream& s, Operation ser_action) {
- READWRITE(header);
- READWRITE(txn);
- }
+ SERIALIZE_METHODS(CMerkleBlock, obj) { READWRITE(obj.header, obj.txn); }
private:
// Combined constructor to consolidate code
diff --git a/src/netaddress.h b/src/netaddress.h
index d8f19deffe..e640c07d32 100644
--- a/src/netaddress.h
+++ b/src/netaddress.h
@@ -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);
- ADD_SERIALIZE_METHODS;
-
- template <typename Stream, typename Operation>
- inline void SerializationOp(Stream& s, Operation ser_action) {
- READWRITE(ip);
- }
+ SERIALIZE_METHODS(CNetAddr, obj) { READWRITE(obj.ip); }
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);
- ADD_SERIALIZE_METHODS;
-
- template <typename Stream, typename Operation>
- inline void SerializationOp(Stream& s, Operation ser_action) {
- READWRITE(network);
- READWRITE(netmask);
- READWRITE(valid);
- }
+ SERIALIZE_METHODS(CSubNet, obj) { READWRITE(obj.network, obj.netmask, obj.valid); }
};
/** 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);
explicit CService(const struct sockaddr_in6& addr);
- ADD_SERIALIZE_METHODS;
-
- template <typename Stream, typename Operation>
- inline void SerializationOp(Stream& s, Operation ser_action) {
- READWRITE(ip);
- READWRITE(WrapBigEndian(port));
- }
+ SERIALIZE_METHODS(CService, obj) { READWRITE(obj.ip, Using<BigEndianFormatter<2>>(obj.port)); }
};
bool SanityCheckASMap(const std::vector<bool>& asmap);
diff --git a/src/node/utxo_snapshot.h b/src/node/utxo_snapshot.h
index 702a0cbe53..c8b4d60fd0 100644
--- a/src/node/utxo_snapshot.h
+++ b/src/node/utxo_snapshot.h
@@ -35,16 +35,7 @@ public:
m_coins_count(coins_count),
m_nchaintx(nchaintx) { }
- ADD_SERIALIZE_METHODS;
-
- template <typename Stream, typename Operation>
- inline void SerializationOp(Stream& s, Operation ser_action)
- {
- READWRITE(m_base_blockhash);
- READWRITE(m_coins_count);
- READWRITE(m_nchaintx);
- }
-
+ SERIALIZE_METHODS(SnapshotMetadata, obj) { READWRITE(obj.m_base_blockhash, obj.m_coins_count, obj.m_nchaintx); }
};
#endif // BITCOIN_NODE_UTXO_SNAPSHOT_H
diff --git a/src/policy/feerate.h b/src/policy/feerate.h
index c040867965..61fa80c130 100644
--- a/src/policy/feerate.h
+++ b/src/policy/feerate.h
@@ -48,12 +48,7 @@ public:
CFeeRate& operator+=(const CFeeRate& a) { nSatoshisPerK += a.nSatoshisPerK; return *this; }
std::string ToString() const;
- ADD_SERIALIZE_METHODS;
-
- template <typename Stream, typename Operation>
- inline void SerializationOp(Stream& s, Operation ser_action) {
- READWRITE(nSatoshisPerK);
- }
+ SERIALIZE_METHODS(CFeeRate, obj) { READWRITE(obj.nSatoshisPerK); }
};
#endif // BITCOIN_POLICY_FEERATE_H
diff --git a/src/primitives/block.h b/src/primitives/block.h
index 750d42efbc..fd8fc8b868 100644
--- a/src/primitives/block.h
+++ b/src/primitives/block.h
@@ -33,17 +33,7 @@ public:
SetNull();
}
- ADD_SERIALIZE_METHODS;
-
- 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);
- }
+ SERIALIZE_METHODS(CBlockHeader, obj) { READWRITE(obj.nVersion, obj.hashPrevBlock, obj.hashMerkleRoot, obj.nTime, obj.nBits, obj.nNonce); }
void SetNull()
{
@@ -89,12 +79,10 @@ public:
*(static_cast<CBlockHeader*>(this)) = header;
}
- ADD_SERIALIZE_METHODS;
-
- template <typename Stream, typename Operation>
- inline void SerializationOp(Stream& s, Operation ser_action) {
- READWRITEAS(CBlockHeader, *this);
- READWRITE(vtx);
+ SERIALIZE_METHODS(CBlock, obj)
+ {
+ READWRITEAS(CBlockHeader, obj);
+ READWRITE(obj.vtx);
}
void SetNull()
@@ -131,14 +119,12 @@ struct CBlockLocator
explicit CBlockLocator(const std::vector<uint256>& vHaveIn) : vHave(vHaveIn) {}
- ADD_SERIALIZE_METHODS;
-
- template <typename Stream, typename Operation>
- inline void SerializationOp(Stream& s, Operation ser_action) {
+ SERIALIZE_METHODS(CBlockLocator, obj)
+ {
int nVersion = s.GetVersion();
if (!(s.GetType() & SER_GETHASH))
READWRITE(nVersion);
- READWRITE(vHave);
+ READWRITE(obj.vHave);
}
void SetNull()
diff --git a/src/primitives/transaction.h b/src/primitives/transaction.h
index 58b3e8aedc..4514db578a 100644
--- a/src/primitives/transaction.h
+++ b/src/primitives/transaction.h
@@ -26,13 +26,7 @@ public:
COutPoint(): n(NULL_INDEX) { }
COutPoint(const uint256& hashIn, uint32_t nIn): hash(hashIn), n(nIn) { }
- ADD_SERIALIZE_METHODS;
-
- template <typename Stream, typename Operation>
- inline void SerializationOp(Stream& s, Operation ser_action) {
- READWRITE(hash);
- READWRITE(n);
- }
+ SERIALIZE_METHODS(COutPoint, obj) { READWRITE(obj.hash, obj.n); }
void SetNull() { hash.SetNull(); 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);
CTxIn(uint256 hashPrevTx, uint32_t nOut, CScript scriptSigIn=CScript(), uint32_t nSequenceIn=SEQUENCE_FINAL);
- ADD_SERIALIZE_METHODS;
-
- template <typename Stream, typename Operation>
- inline void SerializationOp(Stream& s, Operation ser_action) {
- READWRITE(prevout);
- READWRITE(scriptSig);
- READWRITE(nSequence);
- }
+ SERIALIZE_METHODS(CTxIn, obj) { READWRITE(obj.prevout, obj.scriptSig, obj.nSequence); }
friend bool operator==(const CTxIn& a, const CTxIn& b)
{
@@ -143,13 +130,7 @@ public:
CTxOut(const CAmount& nValueIn, CScript scriptPubKeyIn);
- ADD_SERIALIZE_METHODS;
-
- template <typename Stream, typename Operation>
- inline void SerializationOp(Stream& s, Operation ser_action) {
- READWRITE(nValue);
- READWRITE(scriptPubKey);
- }
+ SERIALIZE_METHODS(CTxOut, obj) { READWRITE(obj.nValue, obj.scriptPubKey); }
void SetNull()
{
diff --git a/src/protocol.h b/src/protocol.h
index 8e1b8c588e..0bf9f1d7b5 100644
--- a/src/protocol.h
+++ b/src/protocol.h
@@ -46,16 +46,7 @@ public:
std::string GetCommand() const;
bool IsValid(const MessageStartChars& messageStart) const;
- ADD_SERIALIZE_METHODS;
-
- template <typename Stream, typename Operation>
- inline void SerializationOp(Stream& s, Operation ser_action)
- {
- READWRITE(pchMessageStart);
- READWRITE(pchCommand);
- READWRITE(nMessageSize);
- READWRITE(pchChecksum);
- }
+ SERIALIZE_METHODS(CMessageHeader, obj) { READWRITE(obj.pchMessageStart, obj.pchCommand, obj.nMessageSize, obj.pchChecksum); }
char pchMessageStart[MESSAGE_START_SIZE];
char pchCommand[COMMAND_SIZE];
@@ -343,23 +334,19 @@ public:
void Init();
- ADD_SERIALIZE_METHODS;
-
- template <typename Stream, typename Operation>
- inline void SerializationOp(Stream& s, Operation ser_action)
+ SERIALIZE_METHODS(CAddress, obj)
{
- if (ser_action.ForRead())
- Init();
+ SER_READ(obj, obj.Init());
int nVersion = s.GetVersion();
- if (s.GetType() & SER_DISK)
+ if (s.GetType() & SER_DISK) {
READWRITE(nVersion);
+ }
if ((s.GetType() & SER_DISK) ||
- (nVersion >= CADDR_TIME_VERSION && !(s.GetType() & SER_GETHASH)))
- READWRITE(nTime);
- uint64_t nServicesInt = nServices;
- READWRITE(nServicesInt);
- nServices = static_cast<ServiceFlags>(nServicesInt);
- READWRITEAS(CService, *this);
+ (nVersion >= CADDR_TIME_VERSION && !(s.GetType() & SER_GETHASH))) {
+ READWRITE(obj.nTime);
+ }
+ READWRITE(Using<CustomUintFormatter<8>>(obj.nServices));
+ READWRITEAS(CService, obj);
}
ServiceFlags nServices;
@@ -395,14 +382,7 @@ public:
CInv();
CInv(int typeIn, const uint256& hashIn);
- ADD_SERIALIZE_METHODS;
-
- template <typename Stream, typename Operation>
- inline void SerializationOp(Stream& s, Operation ser_action)
- {
- READWRITE(type);
- READWRITE(hash);
- }
+ SERIALIZE_METHODS(CInv, obj) { READWRITE(obj.type, obj.hash); }
friend bool operator<(const CInv& a, const CInv& b);
diff --git a/src/rest.cpp b/src/rest.cpp
index 5f99e26bad..1d381696d1 100644
--- a/src/rest.cpp
+++ b/src/rest.cpp
@@ -49,18 +49,13 @@ struct CCoin {
uint32_t nHeight;
CTxOut out;
- ADD_SERIALIZE_METHODS;
-
CCoin() : nHeight(0) {}
explicit CCoin(Coin&& in) : nHeight(in.nHeight), out(std::move(in.out)) {}
- template <typename Stream, typename Operation>
- inline void SerializationOp(Stream& s, Operation ser_action)
+ SERIALIZE_METHODS(CCoin, obj)
{
uint32_t nTxVerDummy = 0;
- READWRITE(nTxVerDummy);
- READWRITE(nHeight);
- READWRITE(out);
+ READWRITE(nTxVerDummy, obj.nHeight, obj.out);
}
};
diff --git a/src/script/keyorigin.h b/src/script/keyorigin.h
index 467605ce46..a318ff0f9d 100644
--- a/src/script/keyorigin.h
+++ b/src/script/keyorigin.h
@@ -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;
}
- ADD_SERIALIZE_METHODS;
- template <typename Stream, typename Operation>
- inline void SerializationOp(Stream& s, Operation ser_action)
- {
- READWRITE(fingerprint);
- READWRITE(path);
- }
+ SERIALIZE_METHODS(KeyOriginInfo, obj) { READWRITE(obj.fingerprint, obj.path); }
void clear()
{
diff --git a/src/script/script.h b/src/script/script.h
index 773ffbb985..b61581767f 100644
--- a/src/script/script.h
+++ b/src/script/script.h
@@ -412,12 +412,7 @@ public:
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) { }
- ADD_SERIALIZE_METHODS;
-
- template <typename Stream, typename Operation>
- inline void SerializationOp(Stream& s, Operation ser_action) {
- READWRITEAS(CScriptBase, *this);
- }
+ SERIALIZE_METHODS(CScript, obj) { READWRITEAS(CScriptBase, obj); }
explicit CScript(int64_t b) { operator<<(b); }
explicit CScript(opcodetype b) { operator<<(b); }
diff --git a/src/serialize.h b/src/serialize.h
index fe53eeed31..af75c50ff9 100644
--- a/src/serialize.h
+++ b/src/serialize.h
@@ -190,6 +190,8 @@ template<typename X> const X& ReadWriteAsHelper(const X& x) { return x; }
#define READWRITE(...) (::SerReadWriteMany(s, ser_action, __VA_ARGS__))
#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
@@ -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
{
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)
{
if (v < 0 || v > MAX) throw std::ios_base::failure("CustomUintFormatter value out of range");
- uint64_t raw = htole64(v);
- s.write((const char*)&raw, Bytes);
+ if (BigEndian) {
+ 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)
{
- 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;
- s.read((char*)&raw, Bytes);
- v = le64toh(raw);
+ if (BigEndian) {
+ 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.
- *
- * 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);
- }
-};
+template<int Bytes> using BigEndianFormatter = CustomUintFormatter<Bytes, true>;
/** Formatter for integers in CompactSize format. */
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
*
* Example:
@@ -1124,6 +1111,28 @@ inline void SerReadWriteMany(Stream& s, CSerActionUnserialize ser_action, 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>
inline void WriteVarInt(CSizeComputer &s, I n)
{
diff --git a/src/test/blockencodings_tests.cpp b/src/test/blockencodings_tests.cpp
index 8694891a51..14cf1a4a76 100644
--- a/src/test/blockencodings_tests.cpp
+++ b/src/test/blockencodings_tests.cpp
@@ -132,24 +132,7 @@ public:
return base.GetShortID(txhash);
}
- ADD_SERIALIZE_METHODS;
-
- 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);
- }
+ SERIALIZE_METHODS(TestHeaderAndShortIDs, obj) { READWRITE(obj.header, obj.nonce, Using<VectorFormatter<CustomUintFormatter<CBlockHeaderAndShortTxIDs::SHORTTXIDS_LENGTH>>>(obj.shorttxids), obj.prefilledtxn); }
};
BOOST_AUTO_TEST_CASE(NonCoinbasePreforwardRTTest)
diff --git a/src/test/dbwrapper_tests.cpp b/src/test/dbwrapper_tests.cpp
index c378546e8b..3d802cbeb3 100644
--- a/src/test/dbwrapper_tests.cpp
+++ b/src/test/dbwrapper_tests.cpp
@@ -331,24 +331,26 @@ struct StringContentsSerializer {
}
StringContentsSerializer& operator+=(const StringContentsSerializer& s) { return *this += s.str; }
- ADD_SERIALIZE_METHODS;
-
- template <typename Stream, typename Operation>
- inline void SerializationOp(Stream& s, Operation ser_action) {
- if (ser_action.ForRead()) {
- str.clear();
- char c = 0;
- while (true) {
- try {
- READWRITE(c);
- str.push_back(c);
- } catch (const std::ios_base::failure&) {
- break;
- }
+ template<typename Stream>
+ void Serialize(Stream& s) const
+ {
+ for (size_t i = 0; i < str.size(); i++) {
+ s << str[i];
+ }
+ }
+
+ template<typename Stream>
+ void Unserialize(Stream& s)
+ {
+ str.clear();
+ char c = 0;
+ while (true) {
+ try {
+ s >> c;
+ str.push_back(c);
+ } catch (const std::ios_base::failure&) {
+ break;
}
- } else {
- for (size_t i = 0; i < str.size(); i++)
- READWRITE(str[i]);
}
}
};
diff --git a/src/test/serialize_tests.cpp b/src/test/serialize_tests.cpp
index 9a6c721ab8..c2328f931c 100644
--- a/src/test/serialize_tests.cpp
+++ b/src/test/serialize_tests.cpp
@@ -29,15 +29,13 @@ public:
memcpy(charstrval, charstrvalin, sizeof(charstrval));
}
- ADD_SERIALIZE_METHODS;
-
- template <typename Stream, typename Operation>
- inline void SerializationOp(Stream& s, Operation ser_action) {
- READWRITE(intval);
- READWRITE(boolval);
- READWRITE(stringval);
- READWRITE(charstrval);
- READWRITE(txval);
+ SERIALIZE_METHODS(CSerializeMethodsTestSingle, obj)
+ {
+ READWRITE(obj.intval);
+ READWRITE(obj.boolval);
+ READWRITE(obj.stringval);
+ READWRITE(obj.charstrval);
+ READWRITE(obj.txval);
}
bool operator==(const CSerializeMethodsTestSingle& rhs)
@@ -54,11 +52,10 @@ class CSerializeMethodsTestMany : public CSerializeMethodsTestSingle
{
public:
using CSerializeMethodsTestSingle::CSerializeMethodsTestSingle;
- ADD_SERIALIZE_METHODS;
- template <typename Stream, typename Operation>
- inline void SerializationOp(Stream& s, Operation ser_action) {
- READWRITE(intval, boolval, stringval, charstrval, txval);
+ SERIALIZE_METHODS(CSerializeMethodsTestMany, obj)
+ {
+ READWRITE(obj.intval, obj.boolval, obj.stringval, obj.charstrval, obj.txval);
}
};
diff --git a/src/txdb.cpp b/src/txdb.cpp
index 071aa1336b..129697f0e7 100644
--- a/src/txdb.cpp
+++ b/src/txdb.cpp
@@ -36,19 +36,7 @@ struct CoinEntry {
char key;
explicit CoinEntry(const COutPoint* ptr) : outpoint(const_cast<COutPoint*>(ptr)), key(DB_COIN) {}
- template<typename Stream>
- 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);
- }
+ SERIALIZE_METHODS(CoinEntry, obj) { READWRITE(obj.key, obj.outpoint->hash, VARINT(obj.outpoint->n)); }
};
}