diff --git a/src/node/coinstats.cpp b/src/node/coinstats.cpp index 0aa569047..a010e66ad 100644 --- a/src/node/coinstats.cpp +++ b/src/node/coinstats.cpp @@ -1,80 +1,105 @@ // Copyright (c) 2010 Satoshi Nakamoto // Copyright (c) 2009-2019 The Bitcoin Core developers // Distributed under the MIT software license, see the accompanying // file COPYING or http://www.opensource.org/licenses/mit-license.php. #include #include #include #include #include #include #include static uint64_t GetBogoSize(const CScript &scriptPubKey) { return 32 /* txid */ + 4 /* vout index */ + 4 /* height + coinbase */ + 8 /* amount */ + 2 /* scriptPubKey len */ + scriptPubKey.size() /* scriptPubKey */; } static void ApplyStats(CCoinsStats &stats, CHashWriter &ss, const uint256 &hash, const std::map &outputs) { assert(!outputs.empty()); ss << hash; ss << VARINT(outputs.begin()->second.GetHeight() * 2 + outputs.begin()->second.IsCoinBase()); stats.nTransactions++; for (const auto &output : outputs) { ss << VARINT(output.first + 1); ss << output.second.GetTxOut().scriptPubKey; ss << VARINT_MODE(output.second.GetTxOut().nValue / SATOSHI, VarIntMode::NONNEGATIVE_SIGNED); stats.nTransactionOutputs++; stats.nTotalAmount += output.second.GetTxOut().nValue; stats.nBogoSize += GetBogoSize(output.second.GetTxOut().scriptPubKey); } ss << VARINT(0u); } //! Calculate statistics about the unspent transaction output set -bool GetUTXOStats(CCoinsView *view, CCoinsStats &stats, - const std::function &interruption_point) { +template +static bool GetUTXOStats(CCoinsView *view, CCoinsStats &stats, T hash_obj, + const std::function &interruption_point) { stats = CCoinsStats(); std::unique_ptr pcursor(view->Cursor()); assert(pcursor); - CHashWriter ss(SER_GETHASH, PROTOCOL_VERSION); stats.hashBlock = pcursor->GetBestBlock(); { LOCK(cs_main); stats.nHeight = LookupBlockIndex(stats.hashBlock)->nHeight; } - ss << stats.hashBlock; + + PrepareHash(hash_obj, stats); + uint256 prevkey; std::map outputs; while (pcursor->Valid()) { interruption_point(); COutPoint key; Coin coin; if (pcursor->GetKey(key) && pcursor->GetValue(coin)) { if (!outputs.empty() && key.GetTxId() != prevkey) { - ApplyStats(stats, ss, prevkey, outputs); + ApplyStats(stats, hash_obj, prevkey, outputs); outputs.clear(); } prevkey = key.GetTxId(); outputs[key.GetN()] = std::move(coin); stats.coins_count++; } else { return error("%s: unable to read value", __func__); } pcursor->Next(); } if (!outputs.empty()) { - ApplyStats(stats, ss, prevkey, outputs); + ApplyStats(stats, hash_obj, prevkey, outputs); } - stats.hashSerialized = ss.GetHash(); + + FinalizeHash(hash_obj, stats); + stats.nDiskSize = view->EstimateSize(); return true; } + +bool GetUTXOStats(CCoinsView *view, CCoinsStats &stats, + CoinStatsHashType hash_type, + const std::function &interruption_point) { + switch (hash_type) { + case (CoinStatsHashType::HASH_SERIALIZED): { + CHashWriter ss(SER_GETHASH, PROTOCOL_VERSION); + return GetUTXOStats(view, stats, ss, interruption_point); + } + } // no default case, so the compiler can warn about missing cases + assert(false); +} + +// The legacy hash serializes the hashBlock +static void PrepareHash(CHashWriter &ss, CCoinsStats &stats) { + ss << stats.hashBlock; +} + +static void FinalizeHash(CHashWriter &ss, CCoinsStats &stats) { + stats.hashSerialized = ss.GetHash(); +} diff --git a/src/node/coinstats.h b/src/node/coinstats.h index 90503e8ea..d4a90c1d3 100644 --- a/src/node/coinstats.h +++ b/src/node/coinstats.h @@ -1,36 +1,41 @@ // Copyright (c) 2010 Satoshi Nakamoto // Copyright (c) 2009-2019 The Bitcoin Core developers // Distributed under the MIT software license, see the accompanying // file COPYING or http://www.opensource.org/licenses/mit-license.php. #ifndef BITCOIN_NODE_COINSTATS_H #define BITCOIN_NODE_COINSTATS_H #include #include #include #include #include class CCoinsView; +enum class CoinStatsHashType { + HASH_SERIALIZED, +}; + struct CCoinsStats { int nHeight{0}; BlockHash hashBlock{}; uint64_t nTransactions{0}; uint64_t nTransactionOutputs{0}; uint64_t nBogoSize{0}; uint256 hashSerialized{}; uint64_t nDiskSize{0}; Amount nTotalAmount{Amount::zero()}; //! The number of coins contained. uint64_t coins_count{0}; }; //! Calculate statistics about the unspent transaction output set bool GetUTXOStats(CCoinsView *view, CCoinsStats &stats, + const CoinStatsHashType hash_type, const std::function &interruption_point = {}); #endif // BITCOIN_NODE_COINSTATS_H diff --git a/src/rpc/blockchain.cpp b/src/rpc/blockchain.cpp index 29492fea3..929e5f57f 100644 --- a/src/rpc/blockchain.cpp +++ b/src/rpc/blockchain.cpp @@ -1,2979 +1,2991 @@ // Copyright (c) 2010 Satoshi Nakamoto // Copyright (c) 2009-2019 The Bitcoin Core developers // Distributed under the MIT software license, see the accompanying // file COPYING or http://www.opensource.org/licenses/mit-license.php. #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include