Skip to content

Commit a47319d

Browse files
author
MarcoFalke
committed
Merge #15159: [RPC] Remove lookup to UTXO set from GetTransaction
04da9f4 [RPC] Update getrawtransaction interface (Amiti Uttarwar) Pull request description: - stop checking unspent UTXOs for a transaction when txindex is not enabled, as per conversation here: bitcoin/bitcoin#3220 (comment) - code contributed by sipa Tree-SHA512: aa07353bccc14b81b7803992a25d076d6bc06d15ec7c1b85828dc10aea7e0498d9b49f71783e352ab8a14b0bb2010cfb7835de3dfd1bc6f2323f460449348e66
2 parents bd8bda1 + 04da9f4 commit a47319d

12 files changed

+35
-28
lines changed

doc/release-notes.md

Lines changed: 6 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -254,6 +254,12 @@ in the Low-level Changes section below.
254254

255255
- See the [Mining](#mining) section for changes to `getblocktemplate`.
256256

257+
- The `getrawtransaction` RPC no longer checks the unspent UTXO set for
258+
a transaction. The remaining behaviors are as follows: 1. If a
259+
blockhash is provided, check the corresponding block. 2. If no
260+
blockhash is provided, check the mempool. 3. If no blockhash is
261+
provided but txindex is enabled, also check txindex.
262+
257263
Graphical User Interface (GUI)
258264
------------------------------
259265

src/rest.cpp

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -352,7 +352,7 @@ static bool rest_tx(HTTPRequest* req, const std::string& strURIPart)
352352

353353
CTransactionRef tx;
354354
uint256 hashBlock = uint256();
355-
if (!GetTransaction(hash, tx, Params().GetConsensus(), hashBlock, true))
355+
if (!GetTransaction(hash, tx, Params().GetConsensus(), hashBlock))
356356
return RESTERR(req, HTTP_NOT_FOUND, hashStr + " not found");
357357

358358
switch (rf) {

src/rpc/blockchain.cpp

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1960,7 +1960,7 @@ static UniValue getblockstats(const JSONRPCRequest& request)
19601960
for (const CTxIn& in : tx->vin) {
19611961
CTransactionRef tx_in;
19621962
uint256 hashBlock;
1963-
if (!GetTransaction(in.prevout.hash, tx_in, Params().GetConsensus(), hashBlock, false)) {
1963+
if (!GetTransaction(in.prevout.hash, tx_in, Params().GetConsensus(), hashBlock)) {
19641964
throw JSONRPCError(RPC_INTERNAL_ERROR, std::string("Unexpected internal error (tx index seems corrupt)"));
19651965
}
19661966

src/rpc/rawtransaction.cpp

Lines changed: 7 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -67,12 +67,11 @@ static UniValue getrawtransaction(const JSONRPCRequest& request)
6767
if (request.fHelp || request.params.size() < 1 || request.params.size() > 3)
6868
throw std::runtime_error(
6969
RPCHelpMan{"getrawtransaction",
70-
"\nNOTE: By default this function only works for mempool transactions. If the -txindex option is\n"
71-
"enabled, it also works for blockchain transactions. If the block which contains the transaction\n"
72-
"is known, its hash can be provided even for nodes without -txindex. Note that if a blockhash is\n"
73-
"provided, only that block will be searched and if the transaction is in the mempool or other\n"
74-
"blocks, or if this node does not have the given block available, the transaction will not be found.\n"
75-
"DEPRECATED: for now, it also works for transactions with unspent outputs.\n"
70+
"\nBy default this function only works for mempool transactions. When called with a blockhash\n"
71+
"argument, getrawtransaction will return the transaction if the specified block is available and\n"
72+
"the transaction is found in that block. When called without a blockhash argument, getrawtransaction\n"
73+
"will return the transaction if it is in the mempool, or if -txindex is enabled and the transaction\n"
74+
"is in a block in the blockchain.\n"
7675

7776
"\nReturn the raw transaction data.\n"
7877
"\nIf verbose is 'true', returns an Object with information about 'txid'.\n"
@@ -177,7 +176,7 @@ static UniValue getrawtransaction(const JSONRPCRequest& request)
177176

178177
CTransactionRef tx;
179178
uint256 hash_block;
180-
if (!GetTransaction(hash, tx, Params().GetConsensus(), hash_block, true, blockindex)) {
179+
if (!GetTransaction(hash, tx, Params().GetConsensus(), hash_block, blockindex)) {
181180
std::string errmsg;
182181
if (blockindex) {
183182
if (!(blockindex->nStatus & BLOCK_HAVE_DATA)) {
@@ -274,7 +273,7 @@ static UniValue gettxoutproof(const JSONRPCRequest& request)
274273
if (pblockindex == nullptr)
275274
{
276275
CTransactionRef tx;
277-
if (!GetTransaction(oneTxid, tx, Params().GetConsensus(), hashBlock, false) || hashBlock.IsNull())
276+
if (!GetTransaction(oneTxid, tx, Params().GetConsensus(), hashBlock) || hashBlock.IsNull())
278277
throw JSONRPCError(RPC_INVALID_ADDRESS_OR_KEY, "Transaction not yet in block");
279278
pblockindex = LookupBlockIndex(hashBlock);
280279
if (!pblockindex) {

src/validation.cpp

Lines changed: 5 additions & 14 deletions
Original file line numberDiff line numberDiff line change
@@ -1002,13 +1002,11 @@ bool AcceptToMemoryPool(CTxMemPool& pool, CValidationState &state, const CTransa
10021002
* Return transaction in txOut, and if it was found inside a block, its hash is placed in hashBlock.
10031003
* If blockIndex is provided, the transaction is fetched from the corresponding block.
10041004
*/
1005-
bool GetTransaction(const uint256& hash, CTransactionRef& txOut, const Consensus::Params& consensusParams, uint256& hashBlock, bool fAllowSlow, CBlockIndex* blockIndex)
1005+
bool GetTransaction(const uint256& hash, CTransactionRef& txOut, const Consensus::Params& consensusParams, uint256& hashBlock, const CBlockIndex* const block_index)
10061006
{
1007-
CBlockIndex* pindexSlow = blockIndex;
1008-
10091007
LOCK(cs_main);
10101008

1011-
if (!blockIndex) {
1009+
if (!block_index) {
10121010
CTransactionRef ptx = mempool.get(hash);
10131011
if (ptx) {
10141012
txOut = ptx;
@@ -1018,20 +1016,13 @@ bool GetTransaction(const uint256& hash, CTransactionRef& txOut, const Consensus
10181016
if (g_txindex) {
10191017
return g_txindex->FindTx(hash, hashBlock, txOut);
10201018
}
1021-
1022-
if (fAllowSlow) { // use coin database to locate block that contains transaction, and scan it
1023-
const Coin& coin = AccessByTxid(*pcoinsTip, hash);
1024-
if (!coin.IsSpent()) pindexSlow = chainActive[coin.nHeight];
1025-
}
1026-
}
1027-
1028-
if (pindexSlow) {
1019+
} else {
10291020
CBlock block;
1030-
if (ReadBlockFromDisk(block, pindexSlow, consensusParams)) {
1021+
if (ReadBlockFromDisk(block, block_index, consensusParams)) {
10311022
for (const auto& tx : block.vtx) {
10321023
if (tx->GetHash() == hash) {
10331024
txOut = tx;
1034-
hashBlock = pindexSlow->GetBlockHash();
1025+
hashBlock = block_index->GetBlockHash();
10351026
return true;
10361027
}
10371028
}

src/validation.h

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -269,7 +269,7 @@ void ThreadScriptCheck();
269269
/** Check whether we are doing an initial block download (synchronizing from disk or network) */
270270
bool IsInitialBlockDownload();
271271
/** Retrieve a transaction (from memory pool, or from disk, if possible) */
272-
bool GetTransaction(const uint256& hash, CTransactionRef& tx, const Consensus::Params& params, uint256& hashBlock, bool fAllowSlow = false, CBlockIndex* blockIndex = nullptr);
272+
bool GetTransaction(const uint256& hash, CTransactionRef& tx, const Consensus::Params& params, uint256& hashBlock, const CBlockIndex* const blockIndex = nullptr);
273273
/**
274274
* Find the best known block, and make it the tip of the block chain
275275
*

test/functional/feature_segwit.py

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -43,22 +43,26 @@ def set_test_params(self):
4343
self.setup_clean_chain = True
4444
self.num_nodes = 3
4545
# This test tests SegWit both pre and post-activation, so use the normal BIP9 activation.
46+
# TODO: remove -txindex. Currently required for getrawtransaction call.
4647
self.extra_args = [
4748
[
4849
"-rpcserialversion=0",
4950
"-vbparams=segwit:0:999999999999",
5051
"-addresstype=legacy",
52+
"-txindex"
5153
],
5254
[
5355
"-blockversion=4",
5456
"-rpcserialversion=1",
5557
"-vbparams=segwit:0:999999999999",
5658
"-addresstype=legacy",
59+
"-txindex"
5760
],
5861
[
5962
"-blockversion=536870915",
6063
"-vbparams=segwit:0:999999999999",
6164
"-addresstype=legacy",
65+
"-txindex"
6266
],
6367
]
6468

test/functional/interface_rest.py

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -41,7 +41,8 @@ class RESTTest (BitcoinTestFramework):
4141
def set_test_params(self):
4242
self.setup_clean_chain = True
4343
self.num_nodes = 2
44-
self.extra_args = [["-rest"], []]
44+
# TODO: remove -txindex. Currently required for getrawtransaction call.
45+
self.extra_args = [["-rest", "-txindex"], []]
4546

4647
def skip_test_if_missing_module(self):
4748
self.skip_if_no_wallet()

test/functional/rpc_psbt.py

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -19,6 +19,8 @@ class PSBTTest(BitcoinTestFramework):
1919
def set_test_params(self):
2020
self.setup_clean_chain = False
2121
self.num_nodes = 3
22+
# TODO: remove -txindex. Currently required for getrawtransaction call.
23+
self.extra_args = [[], ["-txindex"], ["-txindex"]]
2224

2325
def skip_test_if_missing_module(self):
2426
self.skip_if_no_wallet()

test/functional/rpc_rawtransaction.py

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -42,7 +42,8 @@ class RawTransactionsTest(BitcoinTestFramework):
4242
def set_test_params(self):
4343
self.setup_clean_chain = True
4444
self.num_nodes = 3
45-
self.extra_args = [["-addresstype=legacy"], ["-addresstype=legacy"], ["-addresstype=legacy"]]
45+
# TODO: remove -txindex. Currently required for getrawtransaction call.
46+
self.extra_args = [["-addresstype=legacy", "-txindex"], ["-addresstype=legacy", "-txindex"], ["-addresstype=legacy", "-txindex"]]
4647

4748
def skip_test_if_missing_module(self):
4849
self.skip_if_no_wallet()

0 commit comments

Comments
 (0)