txdb: Add Cursor() method to CCoinsView to iterate over UTXO set
Add a method Cursor() to CCoinsView that returns a cursor which can be used to iterate over the whole UTXO set. - rpc: Change gettxoutsetinfo to use new Cursor method - txdb: Remove GetStats method - Now that GetStats is implemented in terms of Cursor, remove it.
This commit is contained in:
@@ -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));
|
||||
|
||||
Reference in New Issue
Block a user