Add gettxout and gettxoutsetinfo RPCs
This commit is contained in:
parent
e1bfbab802
commit
beeb57610c
7 changed files with 120 additions and 2 deletions
|
@ -256,6 +256,8 @@ static const CRPCCommand vRPCCommands[] =
|
|||
{ "decoderawtransaction", &decoderawtransaction, false, false },
|
||||
{ "signrawtransaction", &signrawtransaction, false, false },
|
||||
{ "sendrawtransaction", &sendrawtransaction, false, false },
|
||||
{ "gettxoutsetinfo", &gettxoutsetinfo, true, false },
|
||||
{ "gettxout", &gettxout, true, false },
|
||||
};
|
||||
|
||||
CRPCTable::CRPCTable()
|
||||
|
@ -1166,6 +1168,8 @@ Array RPCConvertValues(const std::string &strMethod, const std::vector<std::stri
|
|||
if (strMethod == "createrawtransaction" && n > 1) ConvertTo<Object>(params[1]);
|
||||
if (strMethod == "signrawtransaction" && n > 1) ConvertTo<Array>(params[1], true);
|
||||
if (strMethod == "signrawtransaction" && n > 2) ConvertTo<Array>(params[2], true);
|
||||
if (strMethod == "gettxout" && n > 1) ConvertTo<boost::int64_t>(params[1]);
|
||||
if (strMethod == "gettxout" && n > 2) ConvertTo<bool>(params[2]);
|
||||
|
||||
return params;
|
||||
}
|
||||
|
|
|
@ -187,5 +187,7 @@ extern json_spirit::Value settxfee(const json_spirit::Array& params, bool fHelp)
|
|||
extern json_spirit::Value getrawmempool(const json_spirit::Array& params, bool fHelp);
|
||||
extern json_spirit::Value getblockhash(const json_spirit::Array& params, bool fHelp);
|
||||
extern json_spirit::Value getblock(const json_spirit::Array& params, bool fHelp);
|
||||
extern json_spirit::Value gettxoutsetinfo(const json_spirit::Array& params, bool fHelp);
|
||||
extern json_spirit::Value gettxout(const json_spirit::Array& params, bool fHelp);
|
||||
|
||||
#endif
|
||||
|
|
|
@ -171,6 +171,7 @@ bool CCoinsView::HaveCoins(uint256 txid) { return false; }
|
|||
CBlockIndex *CCoinsView::GetBestBlock() { return NULL; }
|
||||
bool CCoinsView::SetBestBlock(CBlockIndex *pindex) { return false; }
|
||||
bool CCoinsView::BatchWrite(const std::map<uint256, CCoins> &mapCoins, CBlockIndex *pindex) { return false; }
|
||||
bool CCoinsView::GetStats(CCoinsStats &stats) { return false; }
|
||||
|
||||
|
||||
CCoinsViewBacked::CCoinsViewBacked(CCoinsView &viewIn) : base(&viewIn) { }
|
||||
|
@ -181,6 +182,7 @@ CBlockIndex *CCoinsViewBacked::GetBestBlock() { return base->GetBestBlock(); }
|
|||
bool CCoinsViewBacked::SetBestBlock(CBlockIndex *pindex) { return base->SetBestBlock(pindex); }
|
||||
void CCoinsViewBacked::SetBackend(CCoinsView &viewIn) { base = &viewIn; }
|
||||
bool CCoinsViewBacked::BatchWrite(const std::map<uint256, CCoins> &mapCoins, CBlockIndex *pindex) { return base->BatchWrite(mapCoins, pindex); }
|
||||
bool CCoinsViewBacked::GetStats(CCoinsStats &stats) { return base->GetStats(stats); }
|
||||
|
||||
CCoinsViewCache::CCoinsViewCache(CCoinsView &baseIn, bool fDummy) : CCoinsViewBacked(baseIn), pindexTip(NULL) { }
|
||||
|
||||
|
|
12
src/main.h
12
src/main.h
|
@ -1791,6 +1791,16 @@ public:
|
|||
|
||||
extern CTxMemPool mempool;
|
||||
|
||||
struct CCoinsStats
|
||||
{
|
||||
int nHeight;
|
||||
uint64 nTransactions;
|
||||
uint64 nTransactionOutputs;
|
||||
uint64 nSerializedSize;
|
||||
|
||||
CCoinsStats() : nHeight(0), nTransactions(0), nTransactionOutputs(0), nSerializedSize(0) {}
|
||||
};
|
||||
|
||||
/** Abstract view on the open txout dataset. */
|
||||
class CCoinsView
|
||||
{
|
||||
|
@ -1811,6 +1821,7 @@ public:
|
|||
// Modify the currently active block index
|
||||
virtual bool SetBestBlock(CBlockIndex *pindex);
|
||||
virtual bool BatchWrite(const std::map<uint256, CCoins> &mapCoins, CBlockIndex *pindex);
|
||||
virtual bool GetStats(CCoinsStats &stats);
|
||||
};
|
||||
|
||||
/** CCoinsView backed by another CCoinsView */
|
||||
|
@ -1828,6 +1839,7 @@ public:
|
|||
bool SetBestBlock(CBlockIndex *pindex);
|
||||
void SetBackend(CCoinsView &viewIn);
|
||||
bool BatchWrite(const std::map<uint256, CCoins> &mapCoins, CBlockIndex *pindex);
|
||||
bool GetStats(CCoinsStats &stats);
|
||||
};
|
||||
|
||||
/** CCoinsView that adds a memory cache for transactions to another CCoinsView */
|
||||
|
|
|
@ -159,7 +159,69 @@ Value getblock(const Array& params, bool fHelp)
|
|||
return blockToJSON(block, pblockindex);
|
||||
}
|
||||
|
||||
|
||||
|
||||
Value gettxoutsetinfo(const Array& params, bool fHelp)
|
||||
{
|
||||
if (fHelp || params.size() != 0)
|
||||
throw runtime_error(
|
||||
"gettxoutsetinfo\n"
|
||||
"Returns statistics about the unspent transaction output set.");
|
||||
|
||||
Object ret;
|
||||
|
||||
CCoinsStats stats;
|
||||
if (pcoinsTip->GetStats(stats)) {
|
||||
ret.push_back(Pair("bestblock", pcoinsTip->GetBestBlock()->GetBlockHash().GetHex()));
|
||||
ret.push_back(Pair("transactions", (boost::int64_t)stats.nTransactions));
|
||||
ret.push_back(Pair("txouts", (boost::int64_t)stats.nTransactionOutputs));
|
||||
ret.push_back(Pair("bytes_serialized", (boost::int64_t)stats.nSerializedSize));
|
||||
}
|
||||
return ret;
|
||||
}
|
||||
|
||||
Value gettxout(const Array& params, bool fHelp)
|
||||
{
|
||||
if (fHelp || params.size() < 2 || params.size() > 3)
|
||||
throw runtime_error(
|
||||
"gettxout <txid> <n> [includemempool=true]\n"
|
||||
"Returns details about an unspent transaction output.");
|
||||
|
||||
Object ret;
|
||||
|
||||
std::string strHash = params[0].get_str();
|
||||
uint256 hash(strHash);
|
||||
int n = params[1].get_int();
|
||||
bool fMempool = true;
|
||||
if (params.size() > 2)
|
||||
fMempool = params[2].get_bool();
|
||||
|
||||
CCoins coins;
|
||||
if (fMempool) {
|
||||
LOCK(mempool.cs);
|
||||
CCoinsViewMemPool view(*pcoinsTip, mempool);
|
||||
if (!view.GetCoins(hash, coins))
|
||||
return Value::null;
|
||||
mempool.pruneSpent(hash, coins); // TODO: this should be done by the CCoinsViewMemPool
|
||||
} else {
|
||||
if (!pcoinsTip->GetCoins(hash, coins))
|
||||
return Value::null;
|
||||
}
|
||||
if (n<0 || (unsigned int)n>=coins.vout.size() || coins.vout[n].IsNull())
|
||||
return Value::null;
|
||||
|
||||
ret.push_back(Pair("bestblock", pcoinsTip->GetBestBlock()->GetBlockHash().GetHex()));
|
||||
if ((unsigned int)coins.nHeight == MEMPOOL_HEIGHT)
|
||||
ret.push_back(Pair("confirmations", 0));
|
||||
else
|
||||
ret.push_back(Pair("confirmations", pcoinsTip->GetBestBlock()->nHeight - coins.nHeight + 1));
|
||||
ret.push_back(Pair("amount", (boost::int64_t)coins.vout[n].nValue));
|
||||
Object o;
|
||||
o.push_back(Pair("asm", coins.vout[n].scriptPubKey.ToString()));
|
||||
o.push_back(Pair("hex", HexStr(coins.vout[n].scriptPubKey.begin(), coins.vout[n].scriptPubKey.end())));
|
||||
ret.push_back(Pair("scriptPubKey", o));
|
||||
ret.push_back(Pair("version", coins.nVersion));
|
||||
ret.push_back(Pair("coinbase", coins.fCoinBase));
|
||||
|
||||
return ret;
|
||||
}
|
||||
|
||||
|
||||
|
|
|
@ -97,6 +97,41 @@ bool CBlockTreeDB::ReadLastBlockFile(int &nFile) {
|
|||
return Read('l', nFile);
|
||||
}
|
||||
|
||||
bool CCoinsViewDB::GetStats(CCoinsStats &stats) {
|
||||
leveldb::Iterator *pcursor = db.NewIterator();
|
||||
pcursor->SeekToFirst();
|
||||
|
||||
while (pcursor->Valid()) {
|
||||
try {
|
||||
leveldb::Slice slKey = pcursor->key();
|
||||
CDataStream ssKey(slKey.data(), slKey.data()+slKey.size(), SER_DISK, CLIENT_VERSION);
|
||||
char chType;
|
||||
ssKey >> chType;
|
||||
if (chType == 'c' && !fRequestShutdown) {
|
||||
leveldb::Slice slValue = pcursor->value();
|
||||
CDataStream ssValue(slValue.data(), slValue.data()+slValue.size(), SER_DISK, CLIENT_VERSION);
|
||||
CCoins coins;
|
||||
ssValue >> coins;
|
||||
uint256 txhash;
|
||||
ssKey >> txhash;
|
||||
|
||||
stats.nTransactions++;
|
||||
BOOST_FOREACH(const CTxOut &out, coins.vout) {
|
||||
if (!out.IsNull())
|
||||
stats.nTransactionOutputs++;
|
||||
}
|
||||
stats.nSerializedSize += 32 + slValue.size();
|
||||
}
|
||||
pcursor->Next();
|
||||
} catch (std::exception &e) {
|
||||
return error("%s() : deserialize error", __PRETTY_FUNCTION__);
|
||||
}
|
||||
}
|
||||
delete pcursor;
|
||||
stats.nHeight = GetBestBlock()->nHeight;
|
||||
return true;
|
||||
}
|
||||
|
||||
bool CBlockTreeDB::LoadBlockIndexGuts()
|
||||
{
|
||||
leveldb::Iterator *pcursor = NewIterator();
|
||||
|
|
|
@ -22,6 +22,7 @@ public:
|
|||
CBlockIndex *GetBestBlock();
|
||||
bool SetBestBlock(CBlockIndex *pindex);
|
||||
bool BatchWrite(const std::map<uint256, CCoins> &mapCoins, CBlockIndex *pindex);
|
||||
bool GetStats(CCoinsStats &stats);
|
||||
};
|
||||
|
||||
/** Access to the block database (blktree/) */
|
||||
|
|
Loading…
Reference in a new issue