diff options
author | MarcoFalke <falke.marco@gmail.com> | 2021-11-01 17:03:09 +0100 |
---|---|---|
committer | MarcoFalke <falke.marco@gmail.com> | 2021-12-17 10:47:31 +0100 |
commit | fa996c58e8a31ebe610d186cef408b6dd3b385a8 (patch) | |
tree | db5a678ba2b97fa080446d10247a92c9cc426895 | |
parent | fac01888d17423d6c23a9ce15d98fc88fb34e3cc (diff) | |
download | bitcoin-fa996c58e8a31ebe610d186cef408b6dd3b385a8.tar.xz |
refactor: Avoid integer overflow in ApplyStats when activating snapshot
-rw-r--r-- | src/index/coinstatsindex.cpp | 2 | ||||
-rw-r--r-- | src/node/coinstats.cpp | 5 | ||||
-rw-r--r-- | src/node/coinstats.h | 3 | ||||
-rw-r--r-- | src/rpc/blockchain.cpp | 3 |
4 files changed, 9 insertions, 4 deletions
diff --git a/src/index/coinstatsindex.cpp b/src/index/coinstatsindex.cpp index 9ab9209ca4..e4ee0e674b 100644 --- a/src/index/coinstatsindex.cpp +++ b/src/index/coinstatsindex.cpp @@ -321,7 +321,7 @@ bool CoinStatsIndex::LookUpStats(const CBlockIndex* block_index, CCoinsStats& co coins_stats.hashSerialized = entry.muhash; coins_stats.nTransactionOutputs = entry.transaction_output_count; coins_stats.nBogoSize = entry.bogo_size; - coins_stats.nTotalAmount = entry.total_amount; + coins_stats.total_amount = entry.total_amount; coins_stats.total_subsidy = entry.total_subsidy; coins_stats.total_unspendable_amount = entry.total_unspendable_amount; coins_stats.total_prevout_spent_amount = entry.total_prevout_spent_amount; diff --git a/src/node/coinstats.cpp b/src/node/coinstats.cpp index 639a579172..eb21bbdba8 100644 --- a/src/node/coinstats.cpp +++ b/src/node/coinstats.cpp @@ -11,6 +11,7 @@ #include <index/coinstatsindex.h> #include <serialize.h> #include <uint256.h> +#include <util/overflow.h> #include <util/system.h> #include <validation.h> @@ -82,7 +83,9 @@ static void ApplyStats(CCoinsStats& stats, const uint256& hash, const std::map<u stats.nTransactions++; for (auto it = outputs.begin(); it != outputs.end(); ++it) { stats.nTransactionOutputs++; - stats.nTotalAmount += it->second.out.nValue; + if (stats.total_amount.has_value()) { + stats.total_amount = CheckedAdd(*stats.total_amount, it->second.out.nValue); + } stats.nBogoSize += GetBogoSize(it->second.out.scriptPubKey); } } diff --git a/src/node/coinstats.h b/src/node/coinstats.h index 1d95417d4f..2a8fbf5bc6 100644 --- a/src/node/coinstats.h +++ b/src/node/coinstats.h @@ -35,7 +35,8 @@ struct CCoinsStats { uint64_t nBogoSize{0}; uint256 hashSerialized{}; uint64_t nDiskSize{0}; - CAmount nTotalAmount{0}; + //! The total amount, or nullopt if an overflow occurred calculating it + std::optional<CAmount> total_amount{0}; //! The number of coins contained. uint64_t coins_count{0}; diff --git a/src/rpc/blockchain.cpp b/src/rpc/blockchain.cpp index 689c8751f3..f6112e78e0 100644 --- a/src/rpc/blockchain.cpp +++ b/src/rpc/blockchain.cpp @@ -1244,7 +1244,8 @@ static RPCHelpMan gettxoutsetinfo() if (hash_type == CoinStatsHashType::MUHASH) { ret.pushKV("muhash", stats.hashSerialized.GetHex()); } - ret.pushKV("total_amount", ValueFromAmount(stats.nTotalAmount)); + CHECK_NONFATAL(stats.total_amount.has_value()); + ret.pushKV("total_amount", ValueFromAmount(stats.total_amount.value())); if (!stats.index_used) { ret.pushKV("transactions", static_cast<int64_t>(stats.nTransactions)); ret.pushKV("disk_size", stats.nDiskSize); |