diff options
author | Wladimir J. van der Laan <laanwj@gmail.com> | 2016-04-15 16:36:39 +0200 |
---|---|---|
committer | Wladimir J. van der Laan <laanwj@gmail.com> | 2016-04-15 16:43:21 +0200 |
commit | 9e47fcec1798e1db9a32ae243605e8245ffdb273 (patch) | |
tree | 233e8ae0b6d19e5e42b791b26bbc43c514f430c7 /src/rpc | |
parent | be14ca5e8c0f0e8cd8ef511ccb9c41f245d62fbf (diff) | |
parent | 509cb006d514cece5ab7680094f033c8dc8a2318 (diff) |
Merge #7756: Add cursor to iterate over utxo set, use this in `gettxoutsetinfo`
509cb00 txdb: Add Cursor() method to CCoinsView to iterate over UTXO set (Wladimir J. van der Laan)
Diffstat (limited to 'src/rpc')
-rw-r--r-- | src/rpc/blockchain.cpp | 58 |
1 files changed, 57 insertions, 1 deletions
diff --git a/src/rpc/blockchain.cpp b/src/rpc/blockchain.cpp index 7a01a10b7d..b85b2f6b57 100644 --- a/src/rpc/blockchain.cpp +++ b/src/rpc/blockchain.cpp @@ -18,11 +18,14 @@ #include "txmempool.h" #include "util.h" #include "utilstrencodings.h" +#include "hash.h" #include <stdint.h> #include <univalue.h> +#include <boost/thread/thread.hpp> // boost::thread::interrupt + using namespace std; extern void TxToJSON(const CTransaction& tx, const uint256 hashBlock, UniValue& entry); @@ -432,6 +435,59 @@ UniValue getblock(const UniValue& params, bool fHelp) return blockToJSON(block, pblockindex); } +struct CCoinsStats +{ + int nHeight; + uint256 hashBlock; + uint64_t nTransactions; + uint64_t nTransactionOutputs; + uint64_t nSerializedSize; + uint256 hashSerialized; + CAmount nTotalAmount; + + CCoinsStats() : nHeight(0), nTransactions(0), nTransactionOutputs(0), nSerializedSize(0), nTotalAmount(0) {} +}; + +//! Calculate statistics about the unspent transaction output set +static bool GetUTXOStats(CCoinsView *view, CCoinsStats &stats) +{ + boost::scoped_ptr<CCoinsViewCursor> pcursor(view->Cursor()); + + CHashWriter ss(SER_GETHASH, PROTOCOL_VERSION); + stats.hashBlock = pcursor->GetBestBlock(); + { + LOCK(cs_main); + stats.nHeight = mapBlockIndex.find(stats.hashBlock)->second->nHeight; + } + ss << stats.hashBlock; + CAmount nTotalAmount = 0; + while (pcursor->Valid()) { + boost::this_thread::interruption_point(); + uint256 key; + CCoins coins; + if (pcursor->GetKey(key) && pcursor->GetValue(coins)) { + stats.nTransactions++; + for (unsigned int i=0; i<coins.vout.size(); i++) { + const CTxOut &out = coins.vout[i]; + if (!out.IsNull()) { + stats.nTransactionOutputs++; + ss << VARINT(i+1); + ss << out; + nTotalAmount += out.nValue; + } + } + stats.nSerializedSize += 32 + pcursor->GetValueSize(); + ss << VARINT(0); + } else { + return error("%s: unable to read value", __func__); + } + pcursor->Next(); + } + stats.hashSerialized = ss.GetHash(); + stats.nTotalAmount = nTotalAmount; + return true; +} + UniValue gettxoutsetinfo(const UniValue& params, bool fHelp) { if (fHelp || params.size() != 0) @@ -458,7 +514,7 @@ UniValue gettxoutsetinfo(const UniValue& params, bool fHelp) CCoinsStats stats; FlushStateToDisk(); - if (pcoinsTip->GetStats(stats)) { + if (GetUTXOStats(pcoinsTip, stats)) { ret.push_back(Pair("height", (int64_t)stats.nHeight)); ret.push_back(Pair("bestblock", stats.hashBlock.GetHex())); ret.push_back(Pair("transactions", (int64_t)stats.nTransactions)); |