|
|
|
@ -18,11 +18,14 @@
@@ -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)
@@ -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)
@@ -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)); |
|
|
|
|