Changeset View
Changeset View
Standalone View
Standalone View
src/rpc/blockchain.cpp
Show First 20 Lines • Show All 861 Lines • ▼ Show 20 Lines | struct CCoinsStats { | ||||
uint64_t nDiskSize; | uint64_t nDiskSize; | ||||
CAmount nTotalAmount; | CAmount nTotalAmount; | ||||
CCoinsStats() | CCoinsStats() | ||||
: nHeight(0), nTransactions(0), nTransactionOutputs(0), nBogoSize(0), | : nHeight(0), nTransactions(0), nTransactionOutputs(0), nBogoSize(0), | ||||
nDiskSize(0), nTotalAmount(0) {} | nDiskSize(0), nTotalAmount(0) {} | ||||
}; | }; | ||||
static void ApplyStats(CCoinsStats &stats, CHashWriter &ss, const uint256 &hash, | |||||
const std::map<uint32_t, Coin> &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 << *(const CScriptBase *)(&output.second.GetTxOut().scriptPubKey); | |||||
ss << VARINT(output.second.GetTxOut().nValue); | |||||
stats.nTransactionOutputs++; | |||||
stats.nTotalAmount += output.second.GetTxOut().nValue; | |||||
stats.nBogoSize += | |||||
32 /* txid */ + 4 /* vout index */ + 4 /* height + coinbase */ + | |||||
8 /* amount */ + 2 /* scriptPubKey len */ + | |||||
output.second.GetTxOut().scriptPubKey.size() /* scriptPubKey */; | |||||
} | |||||
ss << VARINT(0); | |||||
} | |||||
//! Calculate statistics about the unspent transaction output set | //! Calculate statistics about the unspent transaction output set | ||||
static bool GetUTXOStats(CCoinsView *view, CCoinsStats &stats) { | static bool GetUTXOStats(CCoinsView *view, CCoinsStats &stats) { | ||||
std::unique_ptr<CCoinsViewCursor> pcursor(view->Cursor()); | std::unique_ptr<CCoinsViewCursor> pcursor(view->Cursor()); | ||||
CHashWriter ss(SER_GETHASH, PROTOCOL_VERSION); | CHashWriter ss(SER_GETHASH, PROTOCOL_VERSION); | ||||
stats.hashBlock = pcursor->GetBestBlock(); | stats.hashBlock = pcursor->GetBestBlock(); | ||||
{ | { | ||||
LOCK(cs_main); | LOCK(cs_main); | ||||
stats.nHeight = mapBlockIndex.find(stats.hashBlock)->second->nHeight; | stats.nHeight = mapBlockIndex.find(stats.hashBlock)->second->nHeight; | ||||
} | } | ||||
ss << stats.hashBlock; | ss << stats.hashBlock; | ||||
CAmount nTotalAmount = 0; | uint256 prevkey; | ||||
std::map<uint32_t, Coin> outputs; | |||||
while (pcursor->Valid()) { | while (pcursor->Valid()) { | ||||
boost::this_thread::interruption_point(); | boost::this_thread::interruption_point(); | ||||
uint256 key; | COutPoint key; | ||||
CCoins coins; | Coin coin; | ||||
if (pcursor->GetKey(key) && pcursor->GetValue(coins)) { | if (pcursor->GetKey(key) && pcursor->GetValue(coin)) { | ||||
stats.nTransactions++; | if (!outputs.empty() && key.hash != prevkey) { | ||||
ss << key; | ApplyStats(stats, ss, prevkey, outputs); | ||||
ss << VARINT(coins.nHeight * 2 + coins.fCoinBase); | outputs.clear(); | ||||
for (size_t 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.nBogoSize += | |||||
32 /* txid */ + 4 /* vout index */ + | |||||
4 /* height + coinbase */ + 8 /* amount */ + | |||||
2 /* scriptPubKey len */ + | |||||
out.scriptPubKey.size() /* scriptPubKey */; | |||||
} | |||||
} | } | ||||
ss << VARINT(0); | prevkey = key.hash; | ||||
outputs[key.n] = std::move(coin); | |||||
} else { | } else { | ||||
return error("%s: unable to read value", __func__); | return error("%s: unable to read value", __func__); | ||||
} | } | ||||
pcursor->Next(); | pcursor->Next(); | ||||
} | } | ||||
if (!outputs.empty()) { | |||||
ApplyStats(stats, ss, prevkey, outputs); | |||||
} | |||||
stats.hashSerialized = ss.GetHash(); | stats.hashSerialized = ss.GetHash(); | ||||
stats.nTotalAmount = nTotalAmount; | |||||
stats.nDiskSize = view->EstimateSize(); | stats.nDiskSize = view->EstimateSize(); | ||||
return true; | return true; | ||||
} | } | ||||
UniValue pruneblockchain(const Config &config, const JSONRPCRequest &request) { | UniValue pruneblockchain(const Config &config, const JSONRPCRequest &request) { | ||||
if (request.fHelp || request.params.size() != 1) { | if (request.fHelp || request.params.size() != 1) { | ||||
throw std::runtime_error( | throw std::runtime_error( | ||||
"pruneblockchain\n" | "pruneblockchain\n" | ||||
▲ Show 20 Lines • Show All 128 Lines • ▼ Show 20 Lines | if (request.fHelp || request.params.size() < 2 || | ||||
"signatures\n" | "signatures\n" | ||||
" \"type\" : \"pubkeyhash\", (string) The type, eg pubkeyhash\n" | " \"type\" : \"pubkeyhash\", (string) The type, eg pubkeyhash\n" | ||||
" \"addresses\" : [ (array of string) array of " | " \"addresses\" : [ (array of string) array of " | ||||
"bitcoin addresses\n" | "bitcoin addresses\n" | ||||
" \"address\" (string) bitcoin address\n" | " \"address\" (string) bitcoin address\n" | ||||
" ,...\n" | " ,...\n" | ||||
" ]\n" | " ]\n" | ||||
" },\n" | " },\n" | ||||
" \"version\" : n, (numeric) The version\n" | |||||
" \"coinbase\" : true|false (boolean) Coinbase or not\n" | " \"coinbase\" : true|false (boolean) Coinbase or not\n" | ||||
"}\n" | "}\n" | ||||
"\nExamples:\n" | "\nExamples:\n" | ||||
"\nGet unspent transactions\n" + | "\nGet unspent transactions\n" + | ||||
HelpExampleCli("listunspent", "") + "\nView the details\n" + | HelpExampleCli("listunspent", "") + "\nView the details\n" + | ||||
HelpExampleCli("gettxout", "\"txid\" 1") + | HelpExampleCli("gettxout", "\"txid\" 1") + | ||||
"\nAs a json rpc call\n" + | "\nAs a json rpc call\n" + | ||||
▲ Show 20 Lines • Show All 589 Lines • Show Last 20 Lines |