I’ve reworked this test to use the MiniWallet.
If you want you can take the diff and squash. It requires a rebase on current master, though.
However, for some reason one line in the test fails and I fail to see why. I can take another look there, unless someone beats me to it.
Also, there are some whitespace fixes. You can check them with git diff --ignore-all-space
.
0diff --git a/src/rpc/mempool.cpp b/src/rpc/mempool.cpp
1index fe25dc9edc..2d07b8bd2e 100644
2--- a/src/rpc/mempool.cpp
3+++ b/src/rpc/mempool.cpp
4@@ -590,83 +590,83 @@ static RPCHelpMan getmempoolentry()
5 static RPCHelpMan getmempooltxspendingprevout()
6 {
7 return RPCHelpMan{"getmempooltxspendingprevout",
8- "Scans the mempool to find transactions spending any of the given outputs",
9+ "Scans the mempool to find transactions spending any of the given outputs",
10+ {
11+ {"outputs", RPCArg::Type::ARR, RPCArg::Optional::NO, "The transaction outputs that we want to check, and within each, the txid (string) vout (numeric).",
12 {
13- {"outputs", RPCArg::Type::ARR, RPCArg::Optional::NO, "The transaction outputs that we want to check, and within each, the txid (string) vout (numeric).",
14+ {"", RPCArg::Type::OBJ, RPCArg::Optional::OMITTED, "",
15 {
16- {"", RPCArg::Type::OBJ, RPCArg::Optional::OMITTED, "",
17- {
18- {"txid", RPCArg::Type::STR_HEX, RPCArg::Optional::NO, "The transaction id"},
19- {"vout", RPCArg::Type::NUM, RPCArg::Optional::NO, "The output number"},
20- },
21- },
22+ {"txid", RPCArg::Type::STR_HEX, RPCArg::Optional::NO, "The transaction id"},
23+ {"vout", RPCArg::Type::NUM, RPCArg::Optional::NO, "The output number"},
24 },
25 },
26 },
27- RPCResult{
28- RPCResult::Type::ARR, "", "",
29- {
30- {RPCResult::Type::OBJ, "", "",
31- {
32- {RPCResult::Type::STR_HEX, "txid", "the transaction id of the spent output"},
33- {RPCResult::Type::NUM, "vout", "the vout value of the spent output"},
34- {RPCResult::Type::STR_HEX, "spendingtxid", /*optional=*/true, "the transaction id of the mempool transaction spending this output (omitted if unspent)"},
35- }},
36- }
37- },
38- RPCExamples{
39- HelpExampleCli("getmempooltxspendingprevout", "\"[{\\\"txid\\\":\\\"a08e6907dbbd3d809776dbfc5d82e371b764ed838b5655e72f463568df1aadf0\\\",\\\"vout\\\":3}]\"")
40- + HelpExampleRpc("getmempooltxspendingprevout", "\"[{\\\"txid\\\":\\\"a08e6907dbbd3d809776dbfc5d82e371b764ed838b5655e72f463568df1aadf0\\\",\\\"vout\\\":3}]\"")
41- },
42+ },
43+ },
44+ RPCResult{
45+ RPCResult::Type::ARR, "", "",
46+ {
47+ {RPCResult::Type::OBJ, "", "",
48+ {
49+ {RPCResult::Type::STR_HEX, "txid", "the transaction id of the spent output"},
50+ {RPCResult::Type::NUM, "vout", "the vout value of the spent output"},
51+ {RPCResult::Type::STR_HEX, "spendingtxid", /*optional=*/true, "the transaction id of the mempool transaction spending this output (omitted if unspent)"},
52+ }},
53+ }
54+ },
55+ RPCExamples{
56+ HelpExampleCli("getmempooltxspendingprevout", "\"[{\\\"txid\\\":\\\"a08e6907dbbd3d809776dbfc5d82e371b764ed838b5655e72f463568df1aadf0\\\",\\\"vout\\\":3}]\"")
57+ + HelpExampleRpc("getmempooltxspendingprevout", "\"[{\\\"txid\\\":\\\"a08e6907dbbd3d809776dbfc5d82e371b764ed838b5655e72f463568df1aadf0\\\",\\\"vout\\\":3}]\"")
58+ },
59 [&](const RPCHelpMan& self, const JSONRPCRequest& request) -> UniValue
60-{
61- RPCTypeCheckArgument(request.params[0], UniValue::VARR);
62- const UniValue& output_params = request.params[0];
63- if (output_params.empty()) {
64- throw JSONRPCError(RPC_INVALID_PARAMETER, "Invalid parameter, outputs are missing");
65- }
66+ {
67+ RPCTypeCheckArgument(request.params[0], UniValue::VARR);
68+ const UniValue& output_params = request.params[0];
69+ if (output_params.empty()) {
70+ throw JSONRPCError(RPC_INVALID_PARAMETER, "Invalid parameter, outputs are missing");
71+ }
72
73- std::vector<COutPoint> outputs;
74- outputs.reserve(output_params.size());
75+ std::vector<COutPoint> outputs;
76+ outputs.reserve(output_params.size());
77
78- for (unsigned int idx = 0; idx < output_params.size(); idx++) {
79- const UniValue& o = output_params[idx].get_obj();
80+ for (unsigned int idx = 0; idx < output_params.size(); idx++) {
81+ const UniValue& o = output_params[idx].get_obj();
82
83- RPCTypeCheckObj(o,
84- {
85- {"txid", UniValueType(UniValue::VSTR)},
86- {"vout", UniValueType(UniValue::VNUM)},
87- });
88+ RPCTypeCheckObj(o,
89+ {
90+ {"txid", UniValueType(UniValue::VSTR)},
91+ {"vout", UniValueType(UniValue::VNUM)},
92+ });
93+
94+ const uint256 txid(ParseHashO(o, "txid"));
95+ const int nOutput = find_value(o, "vout").get_int();
96+ if (nOutput < 0) {
97+ throw JSONRPCError(RPC_INVALID_PARAMETER, "Invalid parameter, vout cannot be negative");
98+ }
99
100- const uint256 txid(ParseHashO(o, "txid"));
101- const int nOutput = find_value(o, "vout").get_int();
102- if (nOutput < 0) {
103- throw JSONRPCError(RPC_INVALID_PARAMETER, "Invalid parameter, vout cannot be negative");
104- }
105+ outputs.emplace_back(txid, nOutput);
106+ }
107
108- outputs.emplace_back(txid, nOutput);
109- }
110+ const CTxMemPool& mempool = EnsureAnyMemPool(request.context);
111+ LOCK(mempool.cs);
112
113- const CTxMemPool& mempool = EnsureAnyMemPool(request.context);
114- LOCK(mempool.cs);
115-
116- UniValue result{UniValue::VARR};
117+ UniValue result{UniValue::VARR};
118
119- for (const COutPoint& output : outputs) {
120- UniValue o(UniValue::VOBJ);
121- o.pushKV("txid", output.hash.ToString());
122- o.pushKV("vout", (uint64_t)output.n);
123+ for (const COutPoint& output : outputs) {
124+ UniValue o(UniValue::VOBJ);
125+ o.pushKV("txid", output.hash.ToString());
126+ o.pushKV("vout", (uint64_t)output.n);
127
128- const CTransaction* spendingTx = mempool.GetConflictTx(output);
129- if (spendingTx != nullptr) {
130- o.pushKV("spendingtxid", spendingTx->GetHash().ToString());
131- }
132+ const CTransaction* spendingTx = mempool.GetConflictTx(output);
133+ if (spendingTx != nullptr) {
134+ o.pushKV("spendingtxid", spendingTx->GetHash().ToString());
135+ }
136
137- result.push_back(o);
138- }
139+ result.push_back(o);
140+ }
141
142- return result;
143-},
144+ return result;
145+ },
146 };
147 }
148
149diff --git a/test/functional/rpc_mempool_info.py b/test/functional/rpc_mempool_info.py
150index ef5b9535d4..da4314444d 100755
151--- a/test/functional/rpc_mempool_info.py
152+++ b/test/functional/rpc_mempool_info.py
153@@ -13,19 +13,17 @@ from test_framework.util import (
154 assert_raises_rpc_error,
155 chain_transaction,
156 )
157+from test_framework.wallet import MiniWallet
158+
159
160 class RPCMempoolInfoTest(BitcoinTestFramework):
161 def set_test_params(self):
162 self.num_nodes = 1
163- self.setup_clean_chain = True
164-
165- def skip_test_if_missing_module(self):
166- self.skip_if_no_wallet()
167
168 def run_test(self):
169- # Mine some blocks and have them mature.
170- self.generate(self.nodes[0], COINBASE_MATURITY + 1)
171- confirmed_utxo = self.nodes[0].listunspent(1)[0]
172+ self.wallet = MiniWallet(self.nodes[0])
173+ self.wallet.rescan_utxos()
174+ confirmed_utxo = self.wallet.get_utxo()
175
176 # Create a tree of unconfirmed transactions in the mempool:
177 # txA
178@@ -41,15 +39,21 @@ class RPCMempoolInfoTest(BitcoinTestFramework):
179 # \ /
180 # \ /
181 # txH
182- fee = Decimal("0.0001")
183- (txidA, txA_amount) = chain_transaction(self.nodes[0], [confirmed_utxo['txid']], [0], confirmed_utxo['amount'], fee, 2)
184- (txidB, txB_amount) = chain_transaction(self.nodes[0], [txidA], [0], txA_amount, fee, 2)
185- (txidC, txC_amount) = chain_transaction(self.nodes[0], [txidA], [1], txA_amount, fee, 2)
186- txidD, _ = chain_transaction(self.nodes[0], [txidB], [0], txB_amount, fee, 1)
187- (txidE, txE_amount) = chain_transaction(self.nodes[0], [txidB], [1], txB_amount, fee, 3)
188- (txidF, txF_amount) = chain_transaction(self.nodes[0], [txidC], [0], txC_amount, fee, 2)
189- txidG, _ = chain_transaction(self.nodes[0], [txidC], [1], txC_amount, fee, 1)
190- txidH, _ = chain_transaction(self.nodes[0], [txidE, txidF], [0, 1], txE_amount + txF_amount, fee, 1)
191+
192+ def create_tx(**kwargs):
193+ return self.wallet.send_self_transfer_multi(
194+ from_node=self.nodes[0],
195+ **kwargs,
196+ )
197+
198+ txA = create_tx(utxos_to_spend=[confirmed_utxo], num_outputs=2)
199+ txB, txC = [create_tx(utxos_to_spend=[u], num_outputs=2) for u in txA["new_utxos"]]
200+ txD, txE = [create_tx(utxos_to_spend=[u]) for u in txB["new_utxos"]]
201+ txF, txG = [create_tx(utxos_to_spend=[u]) for u in txC["new_utxos"]]
202+ txH = create_tx(utxos_to_spend=txE["new_utxos"] + txF["new_utxos"])
203+ txidA, txidB, txidC, txidD, txidE, txidF, txidG, txidH = [
204+ tx["txid"] for tx in [txA, txB, txC, txD, txE, txF, txG, txH]
205+ ]
206
207 mempool = self.nodes[0].getrawmempool()
208 assert_equal(len(mempool), 8)