Second parameter to JSON-RPC getblock/gettransaction: decompositions
This is an Object specifying how to decompose specific elements. Currently supported: - "tx": "no", "hash", "hex", "obj" - "script": "no", "hex", "asm"
This commit is contained in:
parent
d4e09300f3
commit
74335bd32a
1 changed files with 122 additions and 25 deletions
|
@ -44,6 +44,8 @@ static CCriticalSection cs_nWalletUnlockTime;
|
||||||
extern Value dumpprivkey(const Array& params, bool fHelp);
|
extern Value dumpprivkey(const Array& params, bool fHelp);
|
||||||
extern Value importprivkey(const Array& params, bool fHelp);
|
extern Value importprivkey(const Array& params, bool fHelp);
|
||||||
|
|
||||||
|
const Object emptyobj;
|
||||||
|
|
||||||
Object JSONRPCError(int code, const string& message)
|
Object JSONRPCError(int code, const string& message)
|
||||||
{
|
{
|
||||||
Object error;
|
Object error;
|
||||||
|
@ -111,6 +113,33 @@ HexBits(unsigned int nBits)
|
||||||
return HexStr(BEGIN(uBits.cBits), END(uBits.cBits));
|
return HexStr(BEGIN(uBits.cBits), END(uBits.cBits));
|
||||||
}
|
}
|
||||||
|
|
||||||
|
enum DecomposeMode {
|
||||||
|
DM_NONE = 0,
|
||||||
|
DM_HASH,
|
||||||
|
DM_HEX,
|
||||||
|
DM_ASM,
|
||||||
|
DM_OBJ,
|
||||||
|
};
|
||||||
|
|
||||||
|
enum DecomposeMode
|
||||||
|
FindDecompose(const Object& decompositions, const char* pcType, const char* pcDefault)
|
||||||
|
{
|
||||||
|
Value val = find_value(decompositions, pcType);
|
||||||
|
std::string strDecompose = (val.type() == null_type) ? pcDefault : val.get_str();
|
||||||
|
|
||||||
|
if (strDecompose == "no")
|
||||||
|
return DM_NONE;
|
||||||
|
if (strDecompose == "hash")
|
||||||
|
return DM_HASH;
|
||||||
|
if (strDecompose == "hex")
|
||||||
|
return DM_HEX;
|
||||||
|
if (strDecompose == "asm")
|
||||||
|
return DM_ASM;
|
||||||
|
if (strDecompose == "obj")
|
||||||
|
return DM_OBJ;
|
||||||
|
throw JSONRPCError(-18, "Invalid decomposition");
|
||||||
|
}
|
||||||
|
|
||||||
void WalletTxToJSON(const CWalletTx& wtx, Object& entry)
|
void WalletTxToJSON(const CWalletTx& wtx, Object& entry)
|
||||||
{
|
{
|
||||||
int confirms = wtx.GetDepthInMainChain();
|
int confirms = wtx.GetDepthInMainChain();
|
||||||
|
@ -126,11 +155,14 @@ void WalletTxToJSON(const CWalletTx& wtx, Object& entry)
|
||||||
entry.push_back(Pair(item.first, item.second));
|
entry.push_back(Pair(item.first, item.second));
|
||||||
}
|
}
|
||||||
|
|
||||||
void TxToJSON(const CTransaction &tx, Object& entry)
|
void TxToJSON(const CTransaction &tx, Object& entry, const Object& decompositions)
|
||||||
{
|
{
|
||||||
entry.push_back(Pair("version", tx.nVersion));
|
entry.push_back(Pair("version", tx.nVersion));
|
||||||
entry.push_back(Pair("locktime", (boost::int64_t)tx.nLockTime));
|
entry.push_back(Pair("locktime", (boost::int64_t)tx.nLockTime));
|
||||||
entry.push_back(Pair("size", (boost::int64_t)::GetSerializeSize(tx, SER_NETWORK, PROTOCOL_VERSION)));
|
entry.push_back(Pair("size", (boost::int64_t)::GetSerializeSize(tx, SER_NETWORK, PROTOCOL_VERSION)));
|
||||||
|
|
||||||
|
enum DecomposeMode decomposeScript = FindDecompose(decompositions, "script", "asm");
|
||||||
|
|
||||||
Array vin;
|
Array vin;
|
||||||
BOOST_FOREACH(const CTxIn& txin, tx.vin)
|
BOOST_FOREACH(const CTxIn& txin, tx.vin)
|
||||||
{
|
{
|
||||||
|
@ -143,7 +175,18 @@ void TxToJSON(const CTransaction &tx, Object& entry)
|
||||||
prevout.push_back(Pair("hash", txin.prevout.hash.GetHex()));
|
prevout.push_back(Pair("hash", txin.prevout.hash.GetHex()));
|
||||||
prevout.push_back(Pair("n", (boost::int64_t)txin.prevout.n));
|
prevout.push_back(Pair("n", (boost::int64_t)txin.prevout.n));
|
||||||
in.push_back(Pair("prevout", prevout));
|
in.push_back(Pair("prevout", prevout));
|
||||||
|
switch (decomposeScript) {
|
||||||
|
case DM_NONE:
|
||||||
|
break;
|
||||||
|
case DM_HEX:
|
||||||
|
in.push_back(Pair("scriptSig", HexStr(txin.scriptSig.begin(), txin.scriptSig.end())));
|
||||||
|
break;
|
||||||
|
case DM_ASM:
|
||||||
in.push_back(Pair("scriptSig", txin.scriptSig.ToString()));
|
in.push_back(Pair("scriptSig", txin.scriptSig.ToString()));
|
||||||
|
break;
|
||||||
|
default:
|
||||||
|
throw JSONRPCError(-18, "Invalid script decomposition");
|
||||||
|
}
|
||||||
}
|
}
|
||||||
in.push_back(Pair("sequence", (boost::int64_t)txin.nSequence));
|
in.push_back(Pair("sequence", (boost::int64_t)txin.nSequence));
|
||||||
vin.push_back(in);
|
vin.push_back(in);
|
||||||
|
@ -154,12 +197,25 @@ void TxToJSON(const CTransaction &tx, Object& entry)
|
||||||
{
|
{
|
||||||
Object out;
|
Object out;
|
||||||
out.push_back(Pair("value", ValueFromAmount(txout.nValue)));
|
out.push_back(Pair("value", ValueFromAmount(txout.nValue)));
|
||||||
|
switch (decomposeScript) {
|
||||||
|
case DM_NONE:
|
||||||
|
break;
|
||||||
|
case DM_HEX:
|
||||||
|
out.push_back(Pair("scriptPubKey", HexStr(txout.scriptPubKey.begin(), txout.scriptPubKey.end())));
|
||||||
|
break;
|
||||||
|
case DM_ASM:
|
||||||
out.push_back(Pair("scriptPubKey", txout.scriptPubKey.ToString()));
|
out.push_back(Pair("scriptPubKey", txout.scriptPubKey.ToString()));
|
||||||
|
break;
|
||||||
|
default:
|
||||||
|
throw JSONRPCError(-18, "Invalid script decomposition");
|
||||||
|
}
|
||||||
vout.push_back(out);
|
vout.push_back(out);
|
||||||
}
|
}
|
||||||
entry.push_back(Pair("vout", vout));
|
entry.push_back(Pair("vout", vout));
|
||||||
}
|
}
|
||||||
|
|
||||||
|
void AnyTxToJSON(const uint256 hash, const CTransaction* ptx, Object& entry, const Object& decompositions);
|
||||||
|
|
||||||
string AccountFromValue(const Value& value)
|
string AccountFromValue(const Value& value)
|
||||||
{
|
{
|
||||||
string strAccount = value.get_str();
|
string strAccount = value.get_str();
|
||||||
|
@ -168,7 +224,7 @@ string AccountFromValue(const Value& value)
|
||||||
return strAccount;
|
return strAccount;
|
||||||
}
|
}
|
||||||
|
|
||||||
Object blockToJSON(const CBlock& block, const CBlockIndex* blockindex)
|
Object blockToJSON(const CBlock& block, const CBlockIndex* blockindex, const Object& decompositions)
|
||||||
{
|
{
|
||||||
Object result;
|
Object result;
|
||||||
result.push_back(Pair("hash", block.GetHash().GetHex()));
|
result.push_back(Pair("hash", block.GetHash().GetHex()));
|
||||||
|
@ -183,10 +239,38 @@ Object blockToJSON(const CBlock& block, const CBlockIndex* blockindex)
|
||||||
result.push_back(Pair("nonce", (boost::uint64_t)block.nNonce));
|
result.push_back(Pair("nonce", (boost::uint64_t)block.nNonce));
|
||||||
result.push_back(Pair("bits", HexBits(block.nBits)));
|
result.push_back(Pair("bits", HexBits(block.nBits)));
|
||||||
result.push_back(Pair("difficulty", GetDifficulty(blockindex)));
|
result.push_back(Pair("difficulty", GetDifficulty(blockindex)));
|
||||||
Array txhashes;
|
|
||||||
|
enum DecomposeMode decomposeTxn = FindDecompose(decompositions, "tx", "hash");
|
||||||
|
if (decomposeTxn)
|
||||||
|
{
|
||||||
|
Array txs;
|
||||||
|
switch (decomposeTxn) {
|
||||||
|
case DM_OBJ:
|
||||||
BOOST_FOREACH (const CTransaction&tx, block.vtx)
|
BOOST_FOREACH (const CTransaction&tx, block.vtx)
|
||||||
txhashes.push_back(tx.GetHash().GetHex());
|
{
|
||||||
result.push_back(Pair("tx", txhashes));
|
Object entry;
|
||||||
|
AnyTxToJSON(tx.GetHash(), &tx, entry, decompositions);
|
||||||
|
txs.push_back(entry);
|
||||||
|
}
|
||||||
|
break;
|
||||||
|
case DM_HEX:
|
||||||
|
BOOST_FOREACH (const CTransaction&tx, block.vtx)
|
||||||
|
{
|
||||||
|
CDataStream ssTx(SER_NETWORK, PROTOCOL_VERSION);
|
||||||
|
ssTx << tx;
|
||||||
|
|
||||||
|
txs.push_back(HexStr(ssTx.begin(), ssTx.end()));
|
||||||
|
}
|
||||||
|
break;
|
||||||
|
case DM_HASH:
|
||||||
|
BOOST_FOREACH (const CTransaction&tx, block.vtx)
|
||||||
|
txs.push_back(tx.GetHash().GetHex());
|
||||||
|
break;
|
||||||
|
default:
|
||||||
|
throw JSONRPCError(-18, "Invalid transaction decomposition");
|
||||||
|
}
|
||||||
|
result.push_back(Pair("tx", txs));
|
||||||
|
}
|
||||||
|
|
||||||
if (blockindex->pprev)
|
if (blockindex->pprev)
|
||||||
result.push_back(Pair("previousblockhash", blockindex->pprev->GetBlockHash().GetHex()));
|
result.push_back(Pair("previousblockhash", blockindex->pprev->GetBlockHash().GetHex()));
|
||||||
|
@ -197,6 +281,7 @@ Object blockToJSON(const CBlock& block, const CBlockIndex* blockindex)
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
///
|
///
|
||||||
/// Note: This interface may still be subject to change.
|
/// Note: This interface may still be subject to change.
|
||||||
///
|
///
|
||||||
|
@ -1501,23 +1586,14 @@ Value listsinceblock(const Array& params, bool fHelp)
|
||||||
return ret;
|
return ret;
|
||||||
}
|
}
|
||||||
|
|
||||||
Value gettransaction(const Array& params, bool fHelp)
|
void
|
||||||
|
AnyTxToJSON(const uint256 hash, const CTransaction* ptx, Object& entry, const Object& decompositions)
|
||||||
{
|
{
|
||||||
if (fHelp || params.size() != 1)
|
|
||||||
throw runtime_error(
|
|
||||||
"gettransaction <txid>\n"
|
|
||||||
"Get detailed information about <txid>");
|
|
||||||
|
|
||||||
uint256 hash;
|
|
||||||
hash.SetHex(params[0].get_str());
|
|
||||||
|
|
||||||
Object entry;
|
|
||||||
|
|
||||||
if (pwalletMain->mapWallet.count(hash))
|
if (pwalletMain->mapWallet.count(hash))
|
||||||
{
|
{
|
||||||
const CWalletTx& wtx = pwalletMain->mapWallet[hash];
|
const CWalletTx& wtx = pwalletMain->mapWallet[hash];
|
||||||
|
|
||||||
TxToJSON(wtx, entry);
|
TxToJSON(wtx, entry, decompositions);
|
||||||
|
|
||||||
int64 nCredit = wtx.GetCredit();
|
int64 nCredit = wtx.GetCredit();
|
||||||
int64 nDebit = wtx.GetDebit();
|
int64 nDebit = wtx.GetDebit();
|
||||||
|
@ -1538,10 +1614,12 @@ Value gettransaction(const Array& params, bool fHelp)
|
||||||
{
|
{
|
||||||
CTransaction tx;
|
CTransaction tx;
|
||||||
uint256 hashBlock = 0;
|
uint256 hashBlock = 0;
|
||||||
if (GetTransaction(hash, tx, hashBlock))
|
if ((!ptx) && GetTransaction(hash, tx, hashBlock))
|
||||||
|
ptx = &tx;
|
||||||
|
if (ptx)
|
||||||
{
|
{
|
||||||
entry.push_back(Pair("txid", hash.GetHex()));
|
entry.push_back(Pair("txid", hash.GetHex()));
|
||||||
TxToJSON(tx, entry);
|
TxToJSON(*ptx, entry, decompositions);
|
||||||
if (hashBlock == 0)
|
if (hashBlock == 0)
|
||||||
entry.push_back(Pair("confirmations", 0));
|
entry.push_back(Pair("confirmations", 0));
|
||||||
else
|
else
|
||||||
|
@ -1564,6 +1642,22 @@ Value gettransaction(const Array& params, bool fHelp)
|
||||||
else
|
else
|
||||||
throw JSONRPCError(-5, "No information available about transaction");
|
throw JSONRPCError(-5, "No information available about transaction");
|
||||||
}
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
Value gettransaction(const Array& params, bool fHelp)
|
||||||
|
{
|
||||||
|
if (fHelp || params.size() < 1 || params.size() > 2)
|
||||||
|
throw runtime_error(
|
||||||
|
"gettransaction <txid> [decompositions]\n"
|
||||||
|
"Get detailed information about <txid>");
|
||||||
|
|
||||||
|
uint256 hash;
|
||||||
|
hash.SetHex(params[0].get_str());
|
||||||
|
|
||||||
|
Object entry;
|
||||||
|
|
||||||
|
AnyTxToJSON(hash, NULL, entry,
|
||||||
|
(params.size() > 1) ? params[1].get_obj() : emptyobj);
|
||||||
|
|
||||||
return entry;
|
return entry;
|
||||||
}
|
}
|
||||||
|
@ -2045,9 +2139,9 @@ Value getblockhash(const Array& params, bool fHelp)
|
||||||
|
|
||||||
Value getblock(const Array& params, bool fHelp)
|
Value getblock(const Array& params, bool fHelp)
|
||||||
{
|
{
|
||||||
if (fHelp || params.size() != 1)
|
if (fHelp || params.size() < 1 || params.size() > 2)
|
||||||
throw runtime_error(
|
throw runtime_error(
|
||||||
"getblock <hash>\n"
|
"getblock <hash> [decompositions]\n"
|
||||||
"Returns details of a block with given block-hash.");
|
"Returns details of a block with given block-hash.");
|
||||||
|
|
||||||
std::string strHash = params[0].get_str();
|
std::string strHash = params[0].get_str();
|
||||||
|
@ -2060,7 +2154,8 @@ Value getblock(const Array& params, bool fHelp)
|
||||||
CBlockIndex* pblockindex = mapBlockIndex[hash];
|
CBlockIndex* pblockindex = mapBlockIndex[hash];
|
||||||
block.ReadFromDisk(pblockindex, true);
|
block.ReadFromDisk(pblockindex, true);
|
||||||
|
|
||||||
return blockToJSON(block, pblockindex);
|
return blockToJSON(block, pblockindex,
|
||||||
|
(params.size() > 1) ? params[1].get_obj() : emptyobj);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
@ -2718,7 +2813,9 @@ Array RPCConvertValues(const std::string &strMethod, const std::vector<std::stri
|
||||||
if (strMethod == "listreceivedbyaccount" && n > 0) ConvertTo<boost::int64_t>(params[0]);
|
if (strMethod == "listreceivedbyaccount" && n > 0) ConvertTo<boost::int64_t>(params[0]);
|
||||||
if (strMethod == "listreceivedbyaccount" && n > 1) ConvertTo<bool>(params[1]);
|
if (strMethod == "listreceivedbyaccount" && n > 1) ConvertTo<bool>(params[1]);
|
||||||
if (strMethod == "getbalance" && n > 1) ConvertTo<boost::int64_t>(params[1]);
|
if (strMethod == "getbalance" && n > 1) ConvertTo<boost::int64_t>(params[1]);
|
||||||
|
if (strMethod == "getblock" && n > 1) ConvertTo<Object>(params[1]);
|
||||||
if (strMethod == "getblockhash" && n > 0) ConvertTo<boost::int64_t>(params[0]);
|
if (strMethod == "getblockhash" && n > 0) ConvertTo<boost::int64_t>(params[0]);
|
||||||
|
if (strMethod == "gettransaction" && n > 1) ConvertTo<Object>(params[1]);
|
||||||
if (strMethod == "move" && n > 2) ConvertTo<double>(params[2]);
|
if (strMethod == "move" && n > 2) ConvertTo<double>(params[2]);
|
||||||
if (strMethod == "move" && n > 3) ConvertTo<boost::int64_t>(params[3]);
|
if (strMethod == "move" && n > 3) ConvertTo<boost::int64_t>(params[3]);
|
||||||
if (strMethod == "sendfrom" && n > 2) ConvertTo<double>(params[2]);
|
if (strMethod == "sendfrom" && n > 2) ConvertTo<double>(params[2]);
|
||||||
|
|
Loading…
Reference in a new issue