aboutsummaryrefslogtreecommitdiff
path: root/src
diff options
context:
space:
mode:
authorGavin Andresen <gavinandresen@gmail.com>2012-06-24 17:04:50 -0400
committerGavin Andresen <gavinandresen@gmail.com>2012-07-05 12:42:25 -0400
commit9a6ab7f1420691267e78e302ff224076945e9133 (patch)
tree932408e289103a55f057eb34751cae5fcca2b2a5 /src
parentfe70b09c428585166f1040e9023251c9c250e894 (diff)
Rework gettransaction / getblock RPC calls
This PULL reworks new (post-0.6.*) features of the gettransaction/getblock RPC calls as follows: It removes the 'decompositions' object argument from getblock, replacing it just a list of transaction hashes; equivalent (I believe) of passing the {"tx":"hash"} decomposition. It replaces the 'decompositions' object argument of gettransaction with a boolean flag; if true, returns the same stuff that the {"script":"obj"} decomposition would return (txins/txouts as hex, disassembled, and bitcoin addresses). It adds a "rawtx" field to the output of gettransaction, that is the entire transaction serialized and hex-encoded. It removes the "size" field from gettransaction, since the size is trivial to compute from the "rawtx" field (either take the length after hex-decoding, or just compute it as hex-length/2).
Diffstat (limited to 'src')
-rw-r--r--src/bitcoinrpc.cpp292
1 files changed, 28 insertions, 264 deletions
diff --git a/src/bitcoinrpc.cpp b/src/bitcoinrpc.cpp
index 109cb92f32..19815ef0fe 100644
--- a/src/bitcoinrpc.cpp
+++ b/src/bitcoinrpc.cpp
@@ -137,33 +137,6 @@ EnsureWalletIsUnlocked()
throw JSONRPCError(-13, "Error: Please enter the wallet passphrase with walletpassphrase first.");
}
-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)
{
int confirms = wtx.GetDepthInMainChain();
@@ -179,141 +152,6 @@ void WalletTxToJSON(const CWalletTx& wtx, Object& entry)
entry.push_back(Pair(item.first, item.second));
}
-void
-ScriptSigToJSON(const CTxIn& txin, Object& out)
-{
- out.push_back(Pair("asm", txin.scriptSig.ToString()));
- out.push_back(Pair("hex", HexStr(txin.scriptSig.begin(), txin.scriptSig.end())));
-
- CTransaction txprev;
- uint256 hashTxprevBlock;
- if (!GetTransaction(txin.prevout.hash, txprev, hashTxprevBlock))
- return;
-
- txnouttype type;
- vector<CTxDestination> addresses;
- int nRequired;
-
- if (!ExtractDestinations(txprev.vout[txin.prevout.n].scriptPubKey, type,
- addresses, nRequired))
- {
- out.push_back(Pair("type", GetTxnOutputType(TX_NONSTANDARD)));
- return;
- }
-
- out.push_back(Pair("type", GetTxnOutputType(type)));
- if (type == TX_MULTISIG)
- {
- // TODO: Need to handle this specially since not all input addresses are required...
- return;
- }
-
- Array a;
- BOOST_FOREACH(const CTxDestination& addr, addresses)
- a.push_back(CBitcoinAddress(addr).ToString());
- out.push_back(Pair("addresses", a));
-}
-
-void
-ScriptPubKeyToJSON(const CScript& scriptPubKey, Object& out)
-{
- txnouttype type;
- vector<CTxDestination> addresses;
- int nRequired;
-
- out.push_back(Pair("asm", scriptPubKey.ToString()));
- out.push_back(Pair("hex", HexStr(scriptPubKey.begin(), scriptPubKey.end())));
-
- if (!ExtractDestinations(scriptPubKey, type, addresses, nRequired))
- {
- out.push_back(Pair("type", GetTxnOutputType(TX_NONSTANDARD)));
- return;
- }
-
- out.push_back(Pair("reqSigs", nRequired));
- out.push_back(Pair("type", GetTxnOutputType(type)));
-
- Array a;
- BOOST_FOREACH(const CTxDestination& addr, addresses)
- a.push_back(CBitcoinAddress(addr).ToString());
- out.push_back(Pair("addresses", a));
-}
-
-void TxToJSON(const CTransaction &tx, Object& entry, const Object& decompositions)
-{
- entry.push_back(Pair("version", tx.nVersion));
- entry.push_back(Pair("locktime", (boost::int64_t)tx.nLockTime));
- entry.push_back(Pair("size", (boost::int64_t)::GetSerializeSize(tx, SER_NETWORK, PROTOCOL_VERSION)));
-
- enum DecomposeMode decomposeScript = FindDecompose(decompositions, "script", "asm");
-
- Array vin;
- BOOST_FOREACH(const CTxIn& txin, tx.vin)
- {
- Object in;
- if (tx.IsCoinBase())
- in.push_back(Pair("coinbase", HexStr(txin.scriptSig.begin(), txin.scriptSig.end())));
- else
- {
- Object prevout;
- prevout.push_back(Pair("hash", txin.prevout.hash.GetHex()));
- prevout.push_back(Pair("n", (boost::int64_t)txin.prevout.n));
- 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()));
- break;
- case DM_OBJ:
- {
- Object o;
- ScriptSigToJSON(txin, o);
- in.push_back(Pair("scriptSig", o));
- break;
- }
- default:
- throw JSONRPCError(-18, "Invalid script decomposition");
- }
- }
- in.push_back(Pair("sequence", (boost::int64_t)txin.nSequence));
- vin.push_back(in);
- }
- entry.push_back(Pair("vin", vin));
- Array vout;
- BOOST_FOREACH(const CTxOut& txout, tx.vout)
- {
- Object out;
- 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()));
- break;
- case DM_OBJ:
- {
- Object o;
- ScriptPubKeyToJSON(txout.scriptPubKey, o);
- out.push_back(Pair("scriptPubKey", o));
- break;
- }
- default:
- throw JSONRPCError(-18, "Invalid script decomposition");
- }
- vout.push_back(out);
- }
- 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 strAccount = value.get_str();
@@ -322,7 +160,7 @@ string AccountFromValue(const Value& value)
return strAccount;
}
-Object blockToJSON(const CBlock& block, const CBlockIndex* blockindex, const Object& decompositions)
+Object blockToJSON(const CBlock& block, const CBlockIndex* blockindex)
{
Object result;
result.push_back(Pair("hash", block.GetHash().GetHex()));
@@ -333,43 +171,15 @@ Object blockToJSON(const CBlock& block, const CBlockIndex* blockindex, const Obj
result.push_back(Pair("height", blockindex->nHeight));
result.push_back(Pair("version", block.nVersion));
result.push_back(Pair("merkleroot", block.hashMerkleRoot.GetHex()));
+ Array txs;
+ BOOST_FOREACH(const CTransaction&tx, block.vtx)
+ txs.push_back(tx.GetHash().GetHex());
+ result.push_back(Pair("tx", txs));
result.push_back(Pair("time", (boost::int64_t)block.GetBlockTime()));
result.push_back(Pair("nonce", (boost::uint64_t)block.nNonce));
result.push_back(Pair("bits", HexBits(block.nBits)));
result.push_back(Pair("difficulty", GetDifficulty(blockindex)));
- enum DecomposeMode decomposeTxn = FindDecompose(decompositions, "tx", "hash");
- if (decomposeTxn)
- {
- Array txs;
- switch (decomposeTxn) {
- case DM_OBJ:
- BOOST_FOREACH (const CTransaction&tx, block.vtx)
- {
- 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)
result.push_back(Pair("previousblockhash", blockindex->pprev->GetBlockHash().GetHex()));
if (blockindex->pnext)
@@ -1651,78 +1461,35 @@ Value listsinceblock(const Array& params, bool fHelp)
return ret;
}
-void
-AnyTxToJSON(const uint256 hash, const CTransaction* ptx, Object& entry, const Object& decompositions)
-{
- if (pwalletMain->mapWallet.count(hash))
- {
- const CWalletTx& wtx = pwalletMain->mapWallet[hash];
-
- TxToJSON(wtx, entry, decompositions);
-
- int64 nCredit = wtx.GetCredit();
- int64 nDebit = wtx.GetDebit();
- int64 nNet = nCredit - nDebit;
- int64 nFee = (wtx.IsFromMe() ? wtx.GetValueOut() - nDebit : 0);
-
- entry.push_back(Pair("amount", ValueFromAmount(nNet - nFee)));
- if (wtx.IsFromMe())
- entry.push_back(Pair("fee", ValueFromAmount(nFee)));
-
- WalletTxToJSON(wtx, entry);
-
- Array details;
- ListTransactions(pwalletMain->mapWallet[hash], "*", 0, false, details);
- entry.push_back(Pair("details", details));
- }
- else
- {
- CTransaction tx;
- uint256 hashBlock = 0;
- if ((!ptx) && GetTransaction(hash, tx, hashBlock))
- ptx = &tx;
- if (ptx)
- {
- entry.push_back(Pair("txid", hash.GetHex()));
- TxToJSON(*ptx, entry, decompositions);
- if (hashBlock == 0)
- entry.push_back(Pair("confirmations", 0));
- else
- {
- entry.push_back(Pair("blockhash", hashBlock.GetHex()));
- map<uint256, CBlockIndex*>::iterator mi = mapBlockIndex.find(hashBlock);
- if (mi != mapBlockIndex.end() && (*mi).second)
- {
- CBlockIndex* pindex = (*mi).second;
- if (pindex->IsInMainChain())
- {
- entry.push_back(Pair("confirmations", 1 + nBestHeight - pindex->nHeight));
- entry.push_back(Pair("time", (boost::int64_t)pindex->nTime));
- }
- else
- entry.push_back(Pair("confirmations", 0));
- }
- }
- }
- else
- throw JSONRPCError(-5, "No information available about transaction");
- }
-}
-
Value gettransaction(const Array& params, bool fHelp)
{
- if (fHelp || params.size() < 1 || params.size() > 2)
+ if (fHelp || params.size() != 1)
throw runtime_error(
- "gettransaction <txid> [decompositions]\n"
- "Get detailed information about <txid>");
+ "gettransaction <txid>\n"
+ "Get detailed information about in-wallet transaction <txid>");
uint256 hash;
hash.SetHex(params[0].get_str());
Object entry;
+ if (!pwalletMain->mapWallet.count(hash))
+ throw JSONRPCError(-5, "Invalid or non-wallet transaction id");
+ const CWalletTx& wtx = pwalletMain->mapWallet[hash];
+
+ int64 nCredit = wtx.GetCredit();
+ int64 nDebit = wtx.GetDebit();
+ int64 nNet = nCredit - nDebit;
+ int64 nFee = (wtx.IsFromMe() ? wtx.GetValueOut() - nDebit : 0);
+
+ entry.push_back(Pair("amount", ValueFromAmount(nNet - nFee)));
+ if (wtx.IsFromMe())
+ entry.push_back(Pair("fee", ValueFromAmount(nFee)));
- AnyTxToJSON(hash, NULL, entry,
- (params.size() > 1) ? params[1].get_obj() : emptyobj);
+ WalletTxToJSON(wtx, entry);
+
+ Array details;
+ ListTransactions(wtx, "*", 0, false, details);
+ entry.push_back(Pair("details", details));
return entry;
}
@@ -2226,9 +1993,9 @@ Value getblockhash(const Array& params, bool fHelp)
Value getblock(const Array& params, bool fHelp)
{
- if (fHelp || params.size() < 1 || params.size() > 2)
+ if (fHelp || params.size() != 1)
throw runtime_error(
- "getblock <hash> [decompositions]\n"
+ "getblock <hash>\n"
"Returns details of a block with given block-hash.");
std::string strHash = params[0].get_str();
@@ -2241,8 +2008,7 @@ Value getblock(const Array& params, bool fHelp)
CBlockIndex* pblockindex = mapBlockIndex[hash];
block.ReadFromDisk(pblockindex, true);
- return blockToJSON(block, pblockindex,
- (params.size() > 1) ? params[1].get_obj() : emptyobj);
+ return blockToJSON(block, pblockindex);
}
Value sendrawtx(const Array& params, bool fHelp)
@@ -3204,9 +2970,7 @@ 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 > 1) ConvertTo<bool>(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 == "gettransaction" && n > 1) ConvertTo<Object>(params[1]);
if (strMethod == "move" && n > 2) ConvertTo<double>(params[2]);
if (strMethod == "move" && n > 3) ConvertTo<boost::int64_t>(params[3]);
if (strMethod == "sendfrom" && n > 2) ConvertTo<double>(params[2]);