Skip to content
This repository

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
Owner

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 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.

Gavin Andresen gavinandresen closed this
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Showing 1 unique commit by 1 author.

Jul 26, 2011
Forrest Voight Added a new RPC command, getrawtransaction. Given a transaction hash,…
… getrawtransaction returns that transaction and some metadata.
dac314a
This page is out of date. Refresh to see the latest.

Showing 2 changed files with 112 additions and 0 deletions. Show diff stats Hide diff stats

  1. 2  src/main.h
  2. 110  src/rpc.cpp
2  src/main.h
@@ -1568,5 +1568,7 @@ class CAlert : public CUnsignedAlert
1568 1568
 
1569 1569
 
1570 1570
 extern std::map<uint256, CTransaction> mapTransactions;
  1571
+extern CCriticalSection cs_mapTransactions;
  1572
+extern std::map<COutPoint, CInPoint> mapNextTx;
1571 1573
 
1572 1574
 #endif
110  src/rpc.cpp
@@ -1667,6 +1667,114 @@ Value getwork(const Array& params, bool fHelp)
1667 1667
 }
1668 1668
 
1669 1669
 
  1670
+Value getrawtransaction(const Array& params, bool fHelp)
  1671
+{
  1672
+    if (fHelp || params.size() != 1)
  1673
+        throw runtime_error(
  1674
+            "getrawtransaction <txid>\n"
  1675
+            "Get transaction <txid>'s data and associated metadata");
  1676
+
  1677
+    uint256 hash;
  1678
+    hash.SetHex(params[0].get_str());
  1679
+
  1680
+    CTxDB txdb("r");
  1681
+    CTxIndex txindex;
  1682
+    CTransaction this_tx;
  1683
+    bool fFound = txdb.ReadTxIndex(hash, txindex);
  1684
+    if (fFound)
  1685
+    {
  1686
+        if (!this_tx.ReadFromDisk(txindex.pos))
  1687
+            throw JSONRPCError(-7, "this_tx.ReadFromDisk failed");
  1688
+    }
  1689
+    else
  1690
+        CRITICAL_BLOCK(cs_mapTransactions)
  1691
+        {
  1692
+            if (!mapTransactions.count(hash))
  1693
+                throw JSONRPCError(-5, "Transaction not found");
  1694
+            this_tx = mapTransactions[hash];
  1695
+        }
  1696
+
  1697
+
  1698
+    Array txins;
  1699
+    for (int i = 0; i < this_tx.vin.size(); i++)
  1700
+    {
  1701
+        Object previous_output;
  1702
+        previous_output.push_back(Pair("hash", this_tx.vin[i].prevout.hash.ToString()));
  1703
+        previous_output.push_back(Pair("index", (uint64_t)this_tx.vin[i].prevout.n));
  1704
+
  1705
+        Object txin;
  1706
+        txin.push_back(Pair("previous_output", previous_output));
  1707
+        txin.push_back(Pair("script", HexStr(this_tx.vin[i].scriptSig)));
  1708
+        txin.push_back(Pair("sequence", (uint64_t)this_tx.vin[i].nSequence));
  1709
+
  1710
+        txins.push_back(txin);
  1711
+    }
  1712
+
  1713
+    Array txouts;
  1714
+    for (int i = 0; i < this_tx.vout.size(); i++)
  1715
+    {
  1716
+        Object txout;
  1717
+        txout.push_back(Pair("value", (uint64_t)this_tx.vout[i].nValue));
  1718
+        txout.push_back(Pair("script2", HexStr(this_tx.vout[i].scriptPubKey)));
  1719
+
  1720
+        txouts.push_back(txout);
  1721
+    }
  1722
+
  1723
+    Object tx;
  1724
+    tx.push_back(Pair("version", this_tx.nVersion));
  1725
+    tx.push_back(Pair("txins", txins));
  1726
+    tx.push_back(Pair("txouts", txouts));
  1727
+    tx.push_back(Pair("lock_time", (uint64_t)this_tx.nLockTime));
  1728
+
  1729
+    Array parent_blocks;
  1730
+    if (fFound)
  1731
+    {
  1732
+        // There can be more than one block that include this transaction
  1733
+        // Only one can be found efficiently, though...
  1734
+        CBlock block;
  1735
+        if (!block.ReadFromDisk(txindex.pos.nFile, txindex.pos.nBlockPos, false))
  1736
+            throw JSONRPCError(-7, "block.ReadFromDisk failed");
  1737
+        parent_blocks.push_back(block.GetHash().ToString());
  1738
+    }
  1739
+
  1740
+    Array txout_claims;
  1741
+    for (int i = 0; i < this_tx.vout.size(); i++)
  1742
+        txout_claims.push_back(Array());
  1743
+    if (fFound)
  1744
+    {
  1745
+        for (int i = 0; i < txindex.vSpent.size(); i++)
  1746
+        {
  1747
+            if (txindex.vSpent[i].IsNull())
  1748
+                continue;
  1749
+            CTransaction next_tx;
  1750
+            if (!next_tx.ReadFromDisk(txindex.vSpent[i]))
  1751
+                throw JSONRPCError(-7, "next_tx.ReadFromDisk failed");
  1752
+            txout_claims[i].get_array().push_back(next_tx.GetHash().ToString());
  1753
+        }
  1754
+    }
  1755
+    CRITICAL_BLOCK(cs_mapTransactions)
  1756
+    {
  1757
+        for (int i = 0; i < this_tx.vout.size(); i++)
  1758
+        {
  1759
+            COutPoint outpoint(hash, i);
  1760
+            if (!mapNextTx.count(outpoint))
  1761
+                continue;
  1762
+            txout_claims[i].get_array().push_back(mapNextTx[outpoint].ptx->GetHash().ToString());
  1763
+        }
  1764
+    }
  1765
+
  1766
+    Object result;
  1767
+    result.push_back(Pair("tx", tx));
  1768
+    result.push_back(Pair("parent_blocks", parent_blocks));
  1769
+    result.push_back(Pair("txout_claims", txout_claims));
  1770
+    if (pindexBest != NULL)
  1771
+        result.push_back(Pair("as_of", pindexBest->GetBlockHash().ToString()));
  1772
+    else
  1773
+        result.push_back(Pair("as_of", Value::null));
  1774
+    return result;
  1775
+}
  1776
+
  1777
+
1670 1778
 
1671 1779
 
1672 1780
 
@@ -1725,6 +1833,7 @@ pair<string, rpcfn_type> pCallTable[] =
1725 1833
     make_pair("getwork",                &getwork),
1726 1834
     make_pair("listaccounts",           &listaccounts),
1727 1835
     make_pair("settxfee",               &settxfee),
  1836
+    make_pair("getrawtransaction",      &getrawtransaction),
1728 1837
 };
1729 1838
 map<string, rpcfn_type> mapCallTable(pCallTable, pCallTable + sizeof(pCallTable)/sizeof(pCallTable[0]));
1730 1839
 
@@ -1753,6 +1862,7 @@ string pAllowInSafeMode[] =
1753 1862
     "walletlock",
1754 1863
     "validateaddress",
1755 1864
     "getwork",
  1865
+    "getrawtransaction",
1756 1866
 };
1757 1867
 set<string> setAllowInSafeMode(pAllowInSafeMode, pAllowInSafeMode + sizeof(pAllowInSafeMode)/sizeof(pAllowInSafeMode[0]));
1758 1868
 
Commit_comment_tip

Tip: You can add notes to lines in a file. Hover to the left of a line to make a note

Something went wrong with that request. Please try again.