From fa364af89bd914ea7cd0d4a5470e0a502e0a2075 Mon Sep 17 00:00:00 2001 From: MarcoFalke <*~=`'#}+{/-|&$^_@721217.xyz> Date: Tue, 28 Oct 2025 15:57:33 +0100 Subject: [PATCH 1/6] test: Remove outdated comment The serialize related methods were removed in commit 30007fda76aa7ba4e4090f7a16298874a7722926. If someone wants to see the tested methods, they can just read the test itself, instead of relying on the wrong comment. --- src/test/arith_uint256_tests.cpp | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/test/arith_uint256_tests.cpp b/src/test/arith_uint256_tests.cpp index 37a39adb9cc..1dca87cfdc8 100644 --- a/src/test/arith_uint256_tests.cpp +++ b/src/test/arith_uint256_tests.cpp @@ -368,7 +368,7 @@ static bool almostEqual(double d1, double d2) return fabs(d1-d2) <= 4*fabs(d1)*std::numeric_limits::epsilon(); } -BOOST_AUTO_TEST_CASE(methods) // GetHex operator= size() GetLow64 GetSerializeSize, Serialize, Unserialize +BOOST_AUTO_TEST_CASE(methods) { BOOST_CHECK(R1L.GetHex() == R1L.ToString()); BOOST_CHECK(R2L.GetHex() == R2L.ToString()); From fa2bbc9e4cfe017436a5167ab5c443f4412efa3c Mon Sep 17 00:00:00 2001 From: MarcoFalke <*~=`'#}+{/-|&$^_@721217.xyz> Date: Tue, 28 Oct 2025 15:20:38 +0100 Subject: [PATCH 2/6] refactor: [rpc] Remove cast when reporting serialized size The values are small enough to fit in an int, so the cast is at best redundant. However, UniValue can handle any integer type, so having to think about the cast here is also confusing. --- src/rpc/blockchain.cpp | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/src/rpc/blockchain.cpp b/src/rpc/blockchain.cpp index 2ff5f52977a..831bf5fe498 100644 --- a/src/rpc/blockchain.cpp +++ b/src/rpc/blockchain.cpp @@ -185,9 +185,9 @@ UniValue blockToJSON(BlockManager& blockman, const CBlock& block, const CBlockIn { UniValue result = blockheaderToJSON(tip, blockindex, pow_limit); - result.pushKV("strippedsize", (int)::GetSerializeSize(TX_NO_WITNESS(block))); - result.pushKV("size", (int)::GetSerializeSize(TX_WITH_WITNESS(block))); - result.pushKV("weight", (int)::GetBlockWeight(block)); + result.pushKV("strippedsize", ::GetSerializeSize(TX_NO_WITNESS(block))); + result.pushKV("size", ::GetSerializeSize(TX_WITH_WITNESS(block))); + result.pushKV("weight", ::GetBlockWeight(block)); UniValue txs(UniValue::VARR); txs.reserve(block.vtx.size()); From fa01f38e53cfda4155d0ea09ca8b1291b7001fe8 Mon Sep 17 00:00:00 2001 From: MarcoFalke <*~=`'#}+{/-|&$^_@721217.xyz> Date: Tue, 28 Oct 2025 12:14:16 +0100 Subject: [PATCH 3/6] move-only: Move CBlockFileInfo to kernel namespace Also, move it to the blockstorage module, because it is only used inside that module. Can be reviewed with the git option --color-moved=dimmed-zebra --- src/chain.cpp | 6 ----- src/chain.h | 41 -------------------------------- src/node/blockstorage.cpp | 6 +++++ src/node/blockstorage.h | 42 +++++++++++++++++++++++++++++++++ src/test/blockmanager_tests.cpp | 1 + src/test/fuzz/block_index.cpp | 2 ++ src/test/fuzz/deserialize.cpp | 2 ++ 7 files changed, 53 insertions(+), 47 deletions(-) diff --git a/src/chain.cpp b/src/chain.cpp index 3dd22634110..94be71805f7 100644 --- a/src/chain.cpp +++ b/src/chain.cpp @@ -6,12 +6,6 @@ #include #include #include -#include - -std::string CBlockFileInfo::ToString() const -{ - return strprintf("CBlockFileInfo(blocks=%u, size=%u, heights=%u...%u, time=%s...%s)", nBlocks, nSize, nHeightFirst, nHeightLast, FormatISO8601Date(nTimeFirst), FormatISO8601Date(nTimeLast)); -} std::string CBlockIndex::ToString() const { diff --git a/src/chain.h b/src/chain.h index 2c86526520b..64c86357032 100644 --- a/src/chain.h +++ b/src/chain.h @@ -47,47 +47,6 @@ static constexpr int32_t SEQ_ID_INIT_FROM_DISK = 1; */ static constexpr int64_t MAX_BLOCK_TIME_GAP = 90 * 60; -class CBlockFileInfo -{ -public: - unsigned int nBlocks{}; //!< number of blocks stored in file - unsigned int nSize{}; //!< number of used bytes of block file - unsigned int nUndoSize{}; //!< number of used bytes in the undo file - unsigned int nHeightFirst{}; //!< lowest height of block in file - unsigned int nHeightLast{}; //!< highest height of block in file - uint64_t nTimeFirst{}; //!< earliest time of block in file - uint64_t nTimeLast{}; //!< latest time of block in file - - 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)); - } - - CBlockFileInfo() = default; - - std::string ToString() const; - - /** update statistics (does not update nSize) */ - void AddBlock(unsigned int nHeightIn, uint64_t nTimeIn) - { - if (nBlocks == 0 || nHeightFirst > nHeightIn) - nHeightFirst = nHeightIn; - if (nBlocks == 0 || nTimeFirst > nTimeIn) - nTimeFirst = nTimeIn; - nBlocks++; - if (nHeightIn > nHeightLast) - nHeightLast = nHeightIn; - if (nTimeIn > nTimeLast) - nTimeLast = nTimeIn; - } -}; - enum BlockStatus : uint32_t { //! Unused. BLOCK_VALID_UNKNOWN = 0, diff --git a/src/node/blockstorage.cpp b/src/node/blockstorage.cpp index e1b54175dc2..20ace6668f5 100644 --- a/src/node/blockstorage.cpp +++ b/src/node/blockstorage.cpp @@ -35,6 +35,7 @@ #include #include #include +#include #include #include @@ -151,6 +152,11 @@ bool BlockTreeDB::LoadBlockIndexGuts(const Consensus::Params& consensusParams, s return true; } + +std::string CBlockFileInfo::ToString() const +{ + return strprintf("CBlockFileInfo(blocks=%u, size=%u, heights=%u...%u, time=%s...%s)", nBlocks, nSize, nHeightFirst, nHeightLast, FormatISO8601Date(nTimeFirst), FormatISO8601Date(nTimeLast)); +} } // namespace kernel namespace node { diff --git a/src/node/blockstorage.h b/src/node/blockstorage.h index cee0eb61ed6..e4d208c1c13 100644 --- a/src/node/blockstorage.h +++ b/src/node/blockstorage.h @@ -47,6 +47,47 @@ class SignalInterrupt; } // namespace util namespace kernel { +class CBlockFileInfo +{ +public: + unsigned int nBlocks{}; //!< number of blocks stored in file + unsigned int nSize{}; //!< number of used bytes of block file + unsigned int nUndoSize{}; //!< number of used bytes in the undo file + unsigned int nHeightFirst{}; //!< lowest height of block in file + unsigned int nHeightLast{}; //!< highest height of block in file + uint64_t nTimeFirst{}; //!< earliest time of block in file + uint64_t nTimeLast{}; //!< latest time of block in file + + 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)); + } + + CBlockFileInfo() = default; + + std::string ToString() const; + + /** update statistics (does not update nSize) */ + void AddBlock(unsigned int nHeightIn, uint64_t nTimeIn) + { + if (nBlocks == 0 || nHeightFirst > nHeightIn) + nHeightFirst = nHeightIn; + if (nBlocks == 0 || nTimeFirst > nTimeIn) + nTimeFirst = nTimeIn; + nBlocks++; + if (nHeightIn > nHeightLast) + nHeightLast = nHeightIn; + if (nTimeIn > nTimeLast) + nTimeLast = nTimeIn; + } +}; + /** Access to the block database (blocks/index/) */ class BlockTreeDB : public CDBWrapper { @@ -65,6 +106,7 @@ public: } // namespace kernel namespace node { +using kernel::CBlockFileInfo; using kernel::BlockTreeDB; /** The pre-allocation chunk size for blk?????.dat files (since 0.8) */ diff --git a/src/test/blockmanager_tests.cpp b/src/test/blockmanager_tests.cpp index f06665d3055..679ba815645 100644 --- a/src/test/blockmanager_tests.cpp +++ b/src/test/blockmanager_tests.cpp @@ -17,6 +17,7 @@ #include #include +using kernel::CBlockFileInfo; using node::STORAGE_HEADER_BYTES; using node::BlockManager; using node::KernelNotifications; diff --git a/src/test/fuzz/block_index.cpp b/src/test/fuzz/block_index.cpp index eef8c2efc80..5e7f789ca89 100644 --- a/src/test/fuzz/block_index.cpp +++ b/src/test/fuzz/block_index.cpp @@ -12,6 +12,8 @@ #include #include +using kernel::CBlockFileInfo; + namespace { const BasicTestingSetup* g_setup; diff --git a/src/test/fuzz/deserialize.cpp b/src/test/fuzz/deserialize.cpp index 05ca62b6fd0..97985ef0edb 100644 --- a/src/test/fuzz/deserialize.cpp +++ b/src/test/fuzz/deserialize.cpp @@ -17,6 +17,7 @@ #include #include #include +#include #include #include #include @@ -34,6 +35,7 @@ #include #include +using kernel::CBlockFileInfo; using node::SnapshotMetadata; namespace { From fa4f388fc99c9ec7c3cf2bac3863c7b3004bb2ae Mon Sep 17 00:00:00 2001 From: MarcoFalke <*~=`'#}+{/-|&$^_@721217.xyz> Date: Tue, 28 Oct 2025 15:33:10 +0100 Subject: [PATCH 4/6] refactor: Use fixed size ints over (un)signed ints for serialized values Bitcoin Core already assumes that 'unsigned int' means uint32_t and 'signed int' means int32_t. See src/compat/assumptions.h. Also, any serialized integral value must be of a fixed size. So make the fixed size explicit in this documenting refactor, which does not change the behavior on any platform. --- src/flatfile.h | 10 +++++----- src/index/disktxpos.h | 4 ++-- src/node/blockstorage.h | 14 +++++++------- 3 files changed, 14 insertions(+), 14 deletions(-) diff --git a/src/flatfile.h b/src/flatfile.h index 3edb0b85da4..3ec4eaf346a 100644 --- a/src/flatfile.h +++ b/src/flatfile.h @@ -13,16 +13,16 @@ struct FlatFilePos { - int nFile{-1}; - unsigned int nPos{0}; + int32_t nFile{-1}; + uint32_t nPos{0}; SERIALIZE_METHODS(FlatFilePos, obj) { READWRITE(VARINT_MODE(obj.nFile, VarIntMode::NONNEGATIVE_SIGNED), VARINT(obj.nPos)); } FlatFilePos() = default; - FlatFilePos(int nFileIn, unsigned int nPosIn) : - nFile(nFileIn), - nPos(nPosIn) + FlatFilePos(int32_t nFileIn, uint32_t nPosIn) + : nFile{nFileIn}, + nPos{nPosIn} {} friend bool operator==(const FlatFilePos &a, const FlatFilePos &b) { diff --git a/src/index/disktxpos.h b/src/index/disktxpos.h index a03638469e8..5e4352db98d 100644 --- a/src/index/disktxpos.h +++ b/src/index/disktxpos.h @@ -10,14 +10,14 @@ struct CDiskTxPos : public FlatFilePos { - unsigned int nTxOffset{0}; // after header + uint32_t nTxOffset{0}; // after header SERIALIZE_METHODS(CDiskTxPos, obj) { READWRITE(AsBase(obj), VARINT(obj.nTxOffset)); } - CDiskTxPos(const FlatFilePos &blockIn, unsigned int nTxOffsetIn) : FlatFilePos(blockIn.nFile, blockIn.nPos), nTxOffset(nTxOffsetIn) { + CDiskTxPos(const FlatFilePos& blockIn, uint32_t nTxOffsetIn) : FlatFilePos{blockIn.nFile, blockIn.nPos}, nTxOffset{nTxOffsetIn} { } CDiskTxPos() = default; diff --git a/src/node/blockstorage.h b/src/node/blockstorage.h index e4d208c1c13..b397fc268ef 100644 --- a/src/node/blockstorage.h +++ b/src/node/blockstorage.h @@ -50,13 +50,13 @@ namespace kernel { class CBlockFileInfo { public: - unsigned int nBlocks{}; //!< number of blocks stored in file - unsigned int nSize{}; //!< number of used bytes of block file - unsigned int nUndoSize{}; //!< number of used bytes in the undo file - unsigned int nHeightFirst{}; //!< lowest height of block in file - unsigned int nHeightLast{}; //!< highest height of block in file - uint64_t nTimeFirst{}; //!< earliest time of block in file - uint64_t nTimeLast{}; //!< latest time of block in file + uint32_t nBlocks{}; //!< number of blocks stored in file + uint32_t nSize{}; //!< number of used bytes of block file + uint32_t nUndoSize{}; //!< number of used bytes in the undo file + uint32_t nHeightFirst{}; //!< lowest height of block in file + uint32_t nHeightLast{}; //!< highest height of block in file + uint64_t nTimeFirst{}; //!< earliest time of block in file + uint64_t nTimeLast{}; //!< latest time of block in file SERIALIZE_METHODS(CBlockFileInfo, obj) { From fad0c8680ea7ef433c2d6e7c0d5799f81fd861b9 Mon Sep 17 00:00:00 2001 From: MarcoFalke <*~=`'#}+{/-|&$^_@721217.xyz> Date: Tue, 28 Oct 2025 13:51:48 +0100 Subject: [PATCH 5/6] refactor: Use uint64_t over size_t for serialized-size values The values are small enough to fit in size_t, but to avoid having to think about it, just use uint64_t consistently for all architectures. On 64-bit systems, this refactor is a no-op. On 32-bit systems, it could avoid bugs in the theoretical and unexpected case where a 32-bit size_t is too small and overflows. --- src/coins.cpp | 4 ++-- src/index/blockfilterindex.cpp | 4 ++-- src/policy/policy.cpp | 2 +- src/rpc/blockchain.cpp | 4 ++-- src/test/flatfile_tests.cpp | 4 ++-- src/test/fuzz/miniscript.cpp | 2 +- src/test/miner_tests.cpp | 2 +- src/test/miniscript_tests.cpp | 2 +- src/wallet/spend.cpp | 2 +- 9 files changed, 13 insertions(+), 13 deletions(-) diff --git a/src/coins.cpp b/src/coins.cpp index 090d36dd041..554a3ebe962 100644 --- a/src/coins.cpp +++ b/src/coins.cpp @@ -349,8 +349,8 @@ void CCoinsViewCache::SanityCheck() const assert(recomputed_usage == cachedCoinsUsage); } -static const size_t MIN_TRANSACTION_OUTPUT_WEIGHT = WITNESS_SCALE_FACTOR * ::GetSerializeSize(CTxOut()); -static const size_t MAX_OUTPUTS_PER_BLOCK = MAX_BLOCK_WEIGHT / MIN_TRANSACTION_OUTPUT_WEIGHT; +static const uint64_t MIN_TRANSACTION_OUTPUT_WEIGHT{WITNESS_SCALE_FACTOR * ::GetSerializeSize(CTxOut())}; +static const uint64_t MAX_OUTPUTS_PER_BLOCK{MAX_BLOCK_WEIGHT / MIN_TRANSACTION_OUTPUT_WEIGHT}; const Coin& AccessByTxid(const CCoinsViewCache& view, const Txid& txid) { diff --git a/src/index/blockfilterindex.cpp b/src/index/blockfilterindex.cpp index 2ccae3a221b..a6c63e5bec8 100644 --- a/src/index/blockfilterindex.cpp +++ b/src/index/blockfilterindex.cpp @@ -202,9 +202,9 @@ size_t BlockFilterIndex::WriteFilterToDisk(FlatFilePos& pos, const BlockFilter& { assert(filter.GetFilterType() == GetFilterType()); - size_t data_size = + uint64_t data_size{ GetSerializeSize(filter.GetBlockHash()) + - GetSerializeSize(filter.GetEncodedFilter()); + GetSerializeSize(filter.GetEncodedFilter())}; // If writing the filter would overflow the file, flush and move to the next one. if (pos.nPos + data_size > MAX_FLTR_FILE_SIZE) { diff --git a/src/policy/policy.cpp b/src/policy/policy.cpp index 3da6cb7489b..e749b14f50f 100644 --- a/src/policy/policy.cpp +++ b/src/policy/policy.cpp @@ -42,7 +42,7 @@ CAmount GetDustThreshold(const CTxOut& txout, const CFeeRate& dustRelayFeeIn) if (txout.scriptPubKey.IsUnspendable()) return 0; - size_t nSize = GetSerializeSize(txout); + uint64_t nSize{GetSerializeSize(txout)}; int witnessversion = 0; std::vector witnessprogram; diff --git a/src/rpc/blockchain.cpp b/src/rpc/blockchain.cpp index 831bf5fe498..4ef7bc96a4f 100644 --- a/src/rpc/blockchain.cpp +++ b/src/rpc/blockchain.cpp @@ -2033,7 +2033,7 @@ static RPCHelpMan getblockstats() for (const CTxOut& out : tx->vout) { tx_total_out += out.nValue; - size_t out_size = GetSerializeSize(out) + PER_UTXO_OVERHEAD; + uint64_t out_size{GetSerializeSize(out) + PER_UTXO_OVERHEAD}; utxo_size_inc += out_size; // The Genesis block and the repeated BIP30 block coinbases don't change the UTXO @@ -2085,7 +2085,7 @@ static RPCHelpMan getblockstats() const CTxOut& prevoutput = coin.out; tx_total_in += prevoutput.nValue; - size_t prevout_size = GetSerializeSize(prevoutput) + PER_UTXO_OVERHEAD; + uint64_t prevout_size{GetSerializeSize(prevoutput) + PER_UTXO_OVERHEAD}; utxo_size_inc -= prevout_size; utxo_size_inc_actual -= prevout_size; } diff --git a/src/test/flatfile_tests.cpp b/src/test/flatfile_tests.cpp index d94cab640b8..5ef603cabaf 100644 --- a/src/test/flatfile_tests.cpp +++ b/src/test/flatfile_tests.cpp @@ -39,8 +39,8 @@ BOOST_AUTO_TEST_CASE(flatfile_open) std::string line2("Digital signatures provide part of the solution, but the main benefits are " "lost if a trusted third party is still required to prevent double-spending."); - size_t pos1 = 0; - size_t pos2 = pos1 + GetSerializeSize(line1); + uint64_t pos1{0}; + uint64_t pos2{pos1 + GetSerializeSize(line1)}; // Write first line to file. { diff --git a/src/test/fuzz/miniscript.cpp b/src/test/fuzz/miniscript.cpp index aea31c6fb16..42195313029 100644 --- a/src/test/fuzz/miniscript.cpp +++ b/src/test/fuzz/miniscript.cpp @@ -1120,7 +1120,7 @@ void TestNode(const MsCtx script_ctx, const NodeRef& node, FuzzedDataProvider& p assert(mal_success); assert(stack_nonmal == stack_mal); // Compute witness size (excluding script push, control block, and witness count encoding). - const size_t wit_size = GetSerializeSize(stack_nonmal) - GetSizeOfCompactSize(stack_nonmal.size()); + const uint64_t wit_size{GetSerializeSize(stack_nonmal) - GetSizeOfCompactSize(stack_nonmal.size())}; assert(wit_size <= *node->GetWitnessSize()); // Test non-malleable satisfaction. diff --git a/src/test/miner_tests.cpp b/src/test/miner_tests.cpp index 94ade598439..a3c576dd2a3 100644 --- a/src/test/miner_tests.cpp +++ b/src/test/miner_tests.cpp @@ -188,7 +188,7 @@ void MinerTestingSetup::TestPackageSelection(const CScript& scriptPubKey, const tx.vout[0].nValue = 5000000000LL - 1000 - 50000; // 0 fee Txid hashFreeTx = tx.GetHash(); AddToMempool(tx_mempool, entry.Fee(0).FromTx(tx)); - size_t freeTxSize = ::GetSerializeSize(TX_WITH_WITNESS(tx)); + uint64_t freeTxSize{::GetSerializeSize(TX_WITH_WITNESS(tx))}; // Calculate a fee on child transaction that will put the package just // below the block min tx fee (assuming 1 child tx of the same size). diff --git a/src/test/miniscript_tests.cpp b/src/test/miniscript_tests.cpp index 0a32727f37e..4d31968c787 100644 --- a/src/test/miniscript_tests.cpp +++ b/src/test/miniscript_tests.cpp @@ -372,7 +372,7 @@ void TestSatisfy(const KeyConverter& converter, const std::string& testcase, con CScriptWitness witness_nonmal; const bool nonmal_success = node->Satisfy(satisfier, witness_nonmal.stack, true) == miniscript::Availability::YES; // Compute witness size (excluding script push, control block, and witness count encoding). - const size_t wit_size = GetSerializeSize(witness_nonmal.stack) - GetSizeOfCompactSize(witness_nonmal.stack.size()); + const uint64_t wit_size{GetSerializeSize(witness_nonmal.stack) - GetSizeOfCompactSize(witness_nonmal.stack.size())}; SatisfactionToWitness(converter.MsContext(), witness_nonmal, script, builder); if (nonmal_success) { diff --git a/src/wallet/spend.cpp b/src/wallet/spend.cpp index 146fb49ea78..bd7bb01f98e 100644 --- a/src/wallet/spend.cpp +++ b/src/wallet/spend.cpp @@ -1034,7 +1034,7 @@ void DiscourageFeeSniping(CMutableTransaction& tx, FastRandomContext& rng_fast, } } -size_t GetSerializeSizeForRecipient(const CRecipient& recipient) +uint64_t GetSerializeSizeForRecipient(const CRecipient& recipient) { return ::GetSerializeSize(CTxOut(recipient.nAmount, GetScriptForDestination(recipient.dest))); } From fa6c0bedd33ac7ad27454adaf9522fd27bef6ea3 Mon Sep 17 00:00:00 2001 From: MarcoFalke <*~=`'#}+{/-|&$^_@721217.xyz> Date: Tue, 28 Oct 2025 16:05:50 +0100 Subject: [PATCH 6/6] refactor: Return uint64_t from GetSerializeSize Normally, the values are small enough to fit in size_t, but the risk that it may not fit sometimes is a reason to use uint64_t consistently for all architectures. On 64-bit systems, this refactor is a no-op. On 32-bit systems, it could avoid bugs in the theoretical and unexpected case where a 32-bit size_t is too small and overflows. For example, 32-bit Bitcoin Core versions with CVE-2025-46597 unfixed may overflow while checking for the bad-blk-length violation when receiving a malformed and bloated compact block. --- src/serialize.h | 21 +++++++++++---------- 1 file changed, 11 insertions(+), 10 deletions(-) diff --git a/src/serialize.h b/src/serialize.h index e88a25fa114..4da48a0bb31 100644 --- a/src/serialize.h +++ b/src/serialize.h @@ -1051,31 +1051,32 @@ struct ActionUnserialize { class SizeComputer { protected: - size_t nSize{0}; + uint64_t m_size{0}; public: SizeComputer() = default; void write(std::span src) { - this->nSize += src.size(); + m_size += src.size(); } - /** Pretend _nSize bytes are written, without specifying them. */ - void seek(size_t _nSize) + /** Pretend this many bytes are written, without specifying them. */ + void seek(uint64_t num) { - this->nSize += _nSize; + m_size += num; } - template + template SizeComputer& operator<<(const T& obj) { ::Serialize(*this, obj); - return (*this); + return *this; } - size_t size() const { - return nSize; + uint64_t size() const + { + return m_size; } }; @@ -1091,7 +1092,7 @@ inline void WriteCompactSize(SizeComputer &s, uint64_t nSize) } template -size_t GetSerializeSize(const T& t) +uint64_t GetSerializeSize(const T& t) { return (SizeComputer() << t).size(); }