diff --git a/src/addrdb.h b/src/addrdb.h index c42494f88f16..b467645d098a 100644 --- a/src/addrdb.h +++ b/src/addrdb.h @@ -43,15 +43,7 @@ class CBanEntry nCreateTime = nCreateTimeIn; } - ADD_SERIALIZE_METHODS; - - template - inline void SerializationOp(Stream& s, Operation ser_action) { - READWRITE(this->nVersion); - READWRITE(nCreateTime); - READWRITE(nBanUntil); - READWRITE(banReason); - } + SERIALIZE_METHODS(CBanEntry, obj) { READWRITE(obj.nVersion, obj.nCreateTime, obj.nBanUntil, obj.banReason); } void SetNull() { diff --git a/src/addrman.h b/src/addrman.h index 48ee327e6994..7a4cd4ee647d 100644 --- a/src/addrman.h +++ b/src/addrman.h @@ -55,14 +55,10 @@ class CAddrInfo : public CAddress public: - ADD_SERIALIZE_METHODS; - - template - inline void SerializationOp(Stream& s, Operation ser_action) { - READWRITEAS(CAddress, *this); - READWRITE(source); - READWRITE(nLastSuccess); - READWRITE(nAttempts); + SERIALIZE_METHODS(CAddrInfo, obj) + { + READWRITEAS(CAddress, obj); + READWRITE(obj.source, obj.nLastSuccess, obj.nAttempts); } void Init() @@ -315,7 +311,7 @@ class CAddrMan * This format is more complex, but significantly smaller (at most 1.5 MiB), and supports * changes to the ADDRMAN_ parameters without breaking the on-disk structure. * - * We don't use ADD_SERIALIZE_METHODS since the serialization and deserialization code has + * We don't use SERIALIZE_METHODS since the serialization and deserialization code has * very little in common. */ template diff --git a/src/blockencodings.h b/src/blockencodings.h index 61134c94b0e6..84d722adc1a2 100644 --- a/src/blockencodings.h +++ b/src/blockencodings.h @@ -11,18 +11,29 @@ class CTxMemPool; -// Dumb helper to handle CTransaction compression at serialize-time -struct TransactionCompressor { -private: - CTransactionRef& tx; -public: - explicit TransactionCompressor(CTransactionRef& txIn) : tx(txIn) {} +// Transaction compression schemes for compact block relay can be introduced by writing +// an actual formatter here. +using TransactionCompression = DefaultFormatter; - ADD_SERIALIZE_METHODS; +class DifferenceFormatter +{ + uint64_t m_shift = 0; - template - inline void SerializationOp(Stream& s, Operation ser_action) { - READWRITE(tx); //TODO: Compress tx encoding +public: + template + void Ser(Stream& s, I v) + { + if (v < m_shift || v >= std::numeric_limits::max()) throw std::ios_base::failure("differential value overflow"); + WriteCompactSize(s, v - m_shift); + m_shift = uint64_t(v) + 1; + } + template + void Unser(Stream& s, I& v) + { + uint64_t n = ReadCompactSize(s); + m_shift += n; + if (m_shift < n || m_shift >= std::numeric_limits::max() || m_shift < std::numeric_limits::min() || m_shift > std::numeric_limits::max()) throw std::ios_base::failure("differential value overflow"); + v = I(m_shift++); } }; @@ -32,39 +43,9 @@ class BlockTransactionsRequest { uint256 blockhash; std::vector indexes; - ADD_SERIALIZE_METHODS; - - template - inline void SerializationOp(Stream& s, Operation ser_action) { - READWRITE(blockhash); - uint64_t indexes_size = (uint64_t)indexes.size(); - READWRITE(COMPACTSIZE(indexes_size)); - if (ser_action.ForRead()) { - size_t i = 0; - while (indexes.size() < indexes_size) { - indexes.resize(std::min((uint64_t)(1000 + indexes.size()), indexes_size)); - for (; i < indexes.size(); i++) { - uint64_t index = 0; - READWRITE(COMPACTSIZE(index)); - if (index > std::numeric_limits::max()) - throw std::ios_base::failure("index overflowed 16 bits"); - indexes[i] = index; - } - } - - int32_t offset = 0; - for (size_t j = 0; j < indexes.size(); j++) { - if (int32_t(indexes[j]) + offset > std::numeric_limits::max()) - throw std::ios_base::failure("indexes overflowed 16 bits"); - indexes[j] = indexes[j] + offset; - offset = int32_t(indexes[j]) + 1; - } - } else { - for (size_t i = 0; i < indexes.size(); i++) { - uint64_t index = indexes[i] - (i == 0 ? 0 : (indexes[i - 1] + 1)); - READWRITE(COMPACTSIZE(index)); - } - } + SERIALIZE_METHODS(BlockTransactionsRequest, obj) + { + READWRITE(obj.blockhash, Using>(obj.indexes)); } }; @@ -78,24 +59,9 @@ class BlockTransactions { explicit BlockTransactions(const BlockTransactionsRequest& req) : blockhash(req.blockhash), txn(req.indexes.size()) {} - ADD_SERIALIZE_METHODS; - - template - inline void SerializationOp(Stream& s, Operation ser_action) { - READWRITE(blockhash); - uint64_t txn_size = (uint64_t)txn.size(); - READWRITE(COMPACTSIZE(txn_size)); - if (ser_action.ForRead()) { - size_t i = 0; - while (txn.size() < txn_size) { - txn.resize(std::min((uint64_t)(1000 + txn.size()), txn_size)); - for (; i < txn.size(); i++) - READWRITE(TransactionCompressor(txn[i])); - } - } else { - for (size_t i = 0; i < txn.size(); i++) - READWRITE(TransactionCompressor(txn[i])); - } + SERIALIZE_METHODS(BlockTransactions, obj) + { + READWRITE(obj.blockhash, Using>(obj.txn)); } }; @@ -106,17 +72,7 @@ struct PrefilledTransaction { uint16_t index; CTransactionRef tx; - ADD_SERIALIZE_METHODS; - - template - inline void SerializationOp(Stream& s, Operation ser_action) { - uint64_t idx = index; - READWRITE(COMPACTSIZE(idx)); - if (idx > std::numeric_limits::max()) - throw std::ios_base::failure("index overflowed 16-bits"); - index = idx; - READWRITE(TransactionCompressor(tx)); - } + SERIALIZE_METHODS(PrefilledTransaction, obj) { READWRITE(COMPACTSIZE(obj.index), Using(obj.tx)); } }; typedef enum ReadStatus_t @@ -154,43 +110,15 @@ class CBlockHeaderAndShortTxIDs { size_t BlockTxCount() const { return shorttxids.size() + prefilledtxn.size(); } - ADD_SERIALIZE_METHODS; - - template - inline void SerializationOp(Stream& s, Operation ser_action) { - READWRITE(header); - READWRITE(nonce); - - uint64_t shorttxids_size = (uint64_t)shorttxids.size(); - READWRITE(COMPACTSIZE(shorttxids_size)); + SERIALIZE_METHODS(CBlockHeaderAndShortTxIDs, obj) + { + READWRITE(obj.header, obj.nonce, Using>>(obj.shorttxids), obj.prefilledtxn); if (ser_action.ForRead()) { - size_t i = 0; - while (shorttxids.size() < shorttxids_size) { - shorttxids.resize(std::min((uint64_t)(1000 + shorttxids.size()), shorttxids_size)); - for (; i < shorttxids.size(); i++) { - uint32_t lsb = 0; uint16_t msb = 0; - READWRITE(lsb); - READWRITE(msb); - shorttxids[i] = (uint64_t(msb) << 32) | uint64_t(lsb); - static_assert(SHORTTXIDS_LENGTH == 6, "shorttxids serialization assumes 6-byte shorttxids"); - } - } - } else { - 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); + if (obj.BlockTxCount() > std::numeric_limits::max()) { + throw std::ios_base::failure("indexes overflowed 16 bits"); } + obj.FillShortTxIDSelector(); } - - READWRITE(prefilledtxn); - - if (BlockTxCount() > std::numeric_limits::max()) - throw std::ios_base::failure("indexes overflowed 16 bits"); - - if (ser_action.ForRead()) - FillShortTxIDSelector(); } }; diff --git a/src/chain.h b/src/chain.h index 89123185ab62..bb2763a1b1f5 100644 --- a/src/chain.h +++ b/src/chain.h @@ -39,17 +39,15 @@ class CBlockFileInfo uint64_t nTimeFirst; //!< earliest time of block in file uint64_t nTimeLast; //!< latest time of block in file - ADD_SERIALIZE_METHODS; - - template - inline void SerializationOp(Stream& s, Operation ser_action) { - READWRITE(VARINT(nBlocks)); - READWRITE(VARINT(nSize)); - READWRITE(VARINT(nUndoSize)); - READWRITE(VARINT(nHeightFirst)); - READWRITE(VARINT(nHeightLast)); - READWRITE(VARINT(nTimeFirst)); - READWRITE(VARINT(nTimeLast)); + SERIALIZE_METHODS(CBlockFileInfo, obj) + { + READWRITE(VARINT(obj.nBlocks)); + READWRITE(VARINT(obj.nSize)); + READWRITE(VARINT(obj.nUndoSize)); + READWRITE(VARINT(obj.nHeightFirst)); + READWRITE(VARINT(obj.nHeightLast)); + READWRITE(VARINT(obj.nTimeFirst)); + READWRITE(VARINT(obj.nTimeLast)); } void SetNull() { @@ -383,33 +381,27 @@ class CDiskBlockIndex : public CBlockIndex hashPrev = (pprev ? pprev->GetBlockHash() : uint256()); } - ADD_SERIALIZE_METHODS; - - template - inline void SerializationOp(Stream& s, Operation ser_action) { + SERIALIZE_METHODS(CDiskBlockIndex, obj) + { int _nVersion = s.GetVersion(); - if (!(s.GetType() & SER_GETHASH)) - READWRITE(VARINT(_nVersion, VarIntMode::NONNEGATIVE_SIGNED)); - - READWRITE(VARINT(nHeight, VarIntMode::NONNEGATIVE_SIGNED)); - READWRITE(VARINT(nStatus)); - READWRITE(VARINT(nTx)); - if (nStatus & (BLOCK_HAVE_DATA | BLOCK_HAVE_UNDO)) - READWRITE(VARINT(nFile, VarIntMode::NONNEGATIVE_SIGNED)); - if (nStatus & BLOCK_HAVE_DATA) - READWRITE(VARINT(nDataPos)); - if (nStatus & BLOCK_HAVE_UNDO) - READWRITE(VARINT(nUndoPos)); + if (!(s.GetType() & SER_GETHASH)) READWRITE(VARINT(_nVersion, VarIntMode::NONNEGATIVE_SIGNED)); + + READWRITE(VARINT(obj.nHeight, VarIntMode::NONNEGATIVE_SIGNED)); + READWRITE(VARINT(obj.nStatus)); + READWRITE(VARINT(obj.nTx)); + if (obj.nStatus & (BLOCK_HAVE_DATA | BLOCK_HAVE_UNDO)) READWRITE(VARINT(obj.nFile, VarIntMode::NONNEGATIVE_SIGNED)); + if (obj.nStatus & BLOCK_HAVE_DATA) READWRITE(VARINT(obj.nDataPos)); + if (obj.nStatus & BLOCK_HAVE_UNDO) READWRITE(VARINT(obj.nUndoPos)); // block hash - READWRITE(hash); + READWRITE(obj.hash); // block header - READWRITE(this->nVersion); - READWRITE(hashPrev); - READWRITE(hashMerkleRoot); - READWRITE(nTime); - READWRITE(nBits); - READWRITE(nNonce); + READWRITE(obj.nVersion); + READWRITE(obj.hashPrev); + READWRITE(obj.hashMerkleRoot); + READWRITE(obj.nTime); + READWRITE(obj.nBits); + READWRITE(obj.nNonce); } uint256 GetBlockHash() const diff --git a/src/coins.h b/src/coins.h index bd472dacf787..2034477c7721 100644 --- a/src/coins.h +++ b/src/coins.h @@ -60,7 +60,7 @@ class Coin assert(!IsSpent()); uint32_t code = nHeight * 2 + fCoinBase; ::Serialize(s, VARINT(code)); - ::Serialize(s, CTxOutCompressor(REF(out))); + ::Serialize(s, Using(out)); } template @@ -69,7 +69,7 @@ class Coin ::Unserialize(s, VARINT(code)); nHeight = code >> 1; fCoinBase = code & 1; - ::Unserialize(s, CTxOutCompressor(out)); + ::Unserialize(s, Using(out)); } bool IsSpent() const { diff --git a/src/compressor.cpp b/src/compressor.cpp index a729e28f079f..b003a86ce7a4 100644 --- a/src/compressor.cpp +++ b/src/compressor.cpp @@ -9,7 +9,15 @@ #include #include