Skip to content

HTTPS clone URL

Subversion checkout URL

You can clone with HTTPS or Subversion.

Download ZIP

Loading…

New RPC command - getrawtransaction #324

Closed
wants to merge 1 commit into from

3 participants

Forrest Voight Gavin Andresen Matt Corallo
Forrest Voight

Given a transaction hash, getrawtransaction returns that transaction and some metadata.

Example: (this is on the testnet)

$ ./bitcoind getrawtransaction ba73f8c8701550e50f667c6c02d671afd3f95069ce02938453048e79b0812bba
{
"tx" : {
"version" : 1,
"txins" : [
{
"previous_output" : {
"hash" : "daea922234887459ba985977112454895466a36c167921651111596cc439add4",
"index" : 0
},
"script" : "47304402206fdeaabac261ef0e0183892555a7cdc94d23e4a01c1c55509d352215ee1628c302204dae58fa97ecf77cede4d340573f62abe13f1b7d9bc487a8e9230d4e9557fdd50141043338498afdbe933339072d3fe6ed36196b2e868f888df55e1b32ad27e418f3621628941482a816acde7b53d651fc13b3208885c07e6f1c54b4c04a5c5d009d86",
"sequence" : 4294967295
}
],
"txouts" : [
{
"value" : 29462000000,
"script2" : "76a9142a5ce61dff67eb864979905d2ca05d000a0586fd88ac"
},
{
"value" : 500000000,
"script2" : "76a9142400224224860152f4211a2b9daa6c45c79d04f388ac"
}
],
"lock_time" : 0
},
"parent_blocks" : [
"00000000004610ac94e40725653c5ff54588a41e24d284244fcd4efd36f12ee9"
],
"txout_claims" : [
[
"9f8aa7191c75c96d1cdf8a9fe78a5b4fa1d772cbe7345c1cabdb3f7c91c71cf7"
],
[
]
]
}

Gavin Andresen

What is this for? I'm about to start working on the 'headers only' branch that will break this (because not every node will store every transaction).

Forrest Voight

This is for providing a way for RPC clients to check the status of transactions. It's mostly useful for mining pool servers - to check whether a tx has been put into a block, and so whether to include it and txs depending on it in the block being mined.

Forrest Voight

Usage example: My p2pool software - http://forum.bitcoin.org/index.php?topic=18313.0 :P

Matt Corallo

Im not a big fan of this, RPC is getting really huge and we keep adding more and more features to it. I wouldnt mind it being so big if all the UIs were using something more standard, ie a libbitcoin-style thing, and I prefer to get something like that up before we keep merging more and more rpc calls.

Forrest Voight forrestv Added a new RPC command, getrawtransaction. Given a transaction hash,…
… getrawtransaction returns that transaction and some metadata.
dac314a
Gavin Andresen

Closing this; please propose/discuss new RPC commands on the bitcoin mailing list or the forums.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Commits on Jul 26, 2011
  1. Forrest Voight

    Added a new RPC command, getrawtransaction. Given a transaction hash,…

    forrestv authored
    … getrawtransaction returns that transaction and some metadata.
This page is out of date. Refresh to see the latest.
Showing with 112 additions and 0 deletions.
  1. +2 −0  src/main.h
  2. +110 −0 src/rpc.cpp
2  src/main.h
View
@@ -1568,5 +1568,7 @@ class CAlert : public CUnsignedAlert
extern std::map<uint256, CTransaction> mapTransactions;
+extern CCriticalSection cs_mapTransactions;
+extern std::map<COutPoint, CInPoint> mapNextTx;
#endif
110 src/rpc.cpp
View
@@ -1667,6 +1667,114 @@ Value getwork(const Array& params, bool fHelp)
}
+Value getrawtransaction(const Array& params, bool fHelp)
+{
+ if (fHelp || params.size() != 1)
+ throw runtime_error(
+ "getrawtransaction <txid>\n"
+ "Get transaction <txid>'s data and associated metadata");
+
+ uint256 hash;
+ hash.SetHex(params[0].get_str());
+
+ CTxDB txdb("r");
+ CTxIndex txindex;
+ CTransaction this_tx;
+ bool fFound = txdb.ReadTxIndex(hash, txindex);
+ if (fFound)
+ {
+ if (!this_tx.ReadFromDisk(txindex.pos))
+ throw JSONRPCError(-7, "this_tx.ReadFromDisk failed");
+ }
+ else
+ CRITICAL_BLOCK(cs_mapTransactions)
+ {
+ if (!mapTransactions.count(hash))
+ throw JSONRPCError(-5, "Transaction not found");
+ this_tx = mapTransactions[hash];
+ }
+
+
+ Array txins;
+ for (int i = 0; i < this_tx.vin.size(); i++)
+ {
+ Object previous_output;
+ previous_output.push_back(Pair("hash", this_tx.vin[i].prevout.hash.ToString()));
+ previous_output.push_back(Pair("index", (uint64_t)this_tx.vin[i].prevout.n));
+
+ Object txin;
+ txin.push_back(Pair("previous_output", previous_output));
+ txin.push_back(Pair("script", HexStr(this_tx.vin[i].scriptSig)));
+ txin.push_back(Pair("sequence", (uint64_t)this_tx.vin[i].nSequence));
+
+ txins.push_back(txin);
+ }
+
+ Array txouts;
+ for (int i = 0; i < this_tx.vout.size(); i++)
+ {
+ Object txout;
+ txout.push_back(Pair("value", (uint64_t)this_tx.vout[i].nValue));
+ txout.push_back(Pair("script2", HexStr(this_tx.vout[i].scriptPubKey)));
+
+ txouts.push_back(txout);
+ }
+
+ Object tx;
+ tx.push_back(Pair("version", this_tx.nVersion));
+ tx.push_back(Pair("txins", txins));
+ tx.push_back(Pair("txouts", txouts));
+ tx.push_back(Pair("lock_time", (uint64_t)this_tx.nLockTime));
+
+ Array parent_blocks;
+ if (fFound)
+ {
+ // There can be more than one block that include this transaction
+ // Only one can be found efficiently, though...
+ CBlock block;
+ if (!block.ReadFromDisk(txindex.pos.nFile, txindex.pos.nBlockPos, false))
+ throw JSONRPCError(-7, "block.ReadFromDisk failed");
+ parent_blocks.push_back(block.GetHash().ToString());
+ }
+
+ Array txout_claims;
+ for (int i = 0; i < this_tx.vout.size(); i++)
+ txout_claims.push_back(Array());
+ if (fFound)
+ {
+ for (int i = 0; i < txindex.vSpent.size(); i++)
+ {
+ if (txindex.vSpent[i].IsNull())
+ continue;
+ CTransaction next_tx;
+ if (!next_tx.ReadFromDisk(txindex.vSpent[i]))
+ throw JSONRPCError(-7, "next_tx.ReadFromDisk failed");
+ txout_claims[i].get_array().push_back(next_tx.GetHash().ToString());
+ }
+ }
+ CRITICAL_BLOCK(cs_mapTransactions)
+ {
+ for (int i = 0; i < this_tx.vout.size(); i++)
+ {
+ COutPoint outpoint(hash, i);
+ if (!mapNextTx.count(outpoint))
+ continue;
+ txout_claims[i].get_array().push_back(mapNextTx[outpoint].ptx->GetHash().ToString());
+ }
+ }
+
+ Object result;
+ result.push_back(Pair("tx", tx));
+ result.push_back(Pair("parent_blocks", parent_blocks));
+ result.push_back(Pair("txout_claims", txout_claims));
+ if (pindexBest != NULL)
+ result.push_back(Pair("as_of", pindexBest->GetBlockHash().ToString()));
+ else
+ result.push_back(Pair("as_of", Value::null));
+ return result;
+}
+
+
@@ -1725,6 +1833,7 @@ pair<string, rpcfn_type> pCallTable[] =
make_pair("getwork", &getwork),
make_pair("listaccounts", &listaccounts),
make_pair("settxfee", &settxfee),
+ make_pair("getrawtransaction", &getrawtransaction),
};
map<string, rpcfn_type> mapCallTable(pCallTable, pCallTable + sizeof(pCallTable)/sizeof(pCallTable[0]));
@@ -1753,6 +1862,7 @@ string pAllowInSafeMode[] =
"walletlock",
"validateaddress",
"getwork",
+ "getrawtransaction",
};
set<string> setAllowInSafeMode(pAllowInSafeMode, pAllowInSafeMode + sizeof(pAllowInSafeMode)/sizeof(pAllowInSafeMode[0]));
Something went wrong with that request. Please try again.