Skip to content

Commit f9cac63

Browse files
committed
test: cover testmempoolaccept debug-message in RBF test
1 parent f9650e1 commit f9cac63

File tree

1 file changed

+48
-12
lines changed

1 file changed

+48
-12
lines changed

test/functional/feature_rbf.py

Lines changed: 48 additions & 12 deletions
Original file line numberDiff line numberDiff line change
@@ -103,14 +103,22 @@ def test_simple_doublespend(self):
103103
"""Simple doublespend"""
104104
# we use MiniWallet to create a transaction template with inputs correctly set,
105105
# and modify the output (amount, scriptPubKey) according to our needs
106-
tx = self.wallet.create_self_transfer()["tx"]
106+
tx = self.wallet.create_self_transfer(fee_rate=Decimal("0.003"))["tx"]
107107
tx1a_txid = self.nodes[0].sendrawtransaction(tx.serialize().hex())
108108

109109
# Should fail because we haven't changed the fee
110110
tx.vout[0].scriptPubKey[-1] ^= 1
111+
tx.rehash()
112+
tx_hex = tx.serialize().hex()
111113

112114
# This will raise an exception due to insufficient fee
113-
assert_raises_rpc_error(-26, "insufficient fee", self.nodes[0].sendrawtransaction, tx.serialize().hex(), 0)
115+
reject_reason = "insufficient fee"
116+
reject_details = f"{reject_reason}, rejecting replacement {tx.hash}; new feerate 0.00300000 BTC/kvB <= old feerate 0.00300000 BTC/kvB"
117+
res = self.nodes[0].testmempoolaccept(rawtxs=[tx_hex])[0]
118+
assert_equal(res["reject-reason"], reject_reason)
119+
assert_equal(res["reject-details"], reject_details)
120+
assert_raises_rpc_error(-26, f"{reject_details}", self.nodes[0].sendrawtransaction, tx_hex, 0)
121+
114122

115123
# Extra 0.1 BTC fee
116124
tx.vout[0].nValue -= int(0.1 * COIN)
@@ -154,7 +162,14 @@ def test_doublespend_chain(self):
154162
dbl_tx_hex = dbl_tx.serialize().hex()
155163

156164
# This will raise an exception due to insufficient fee
157-
assert_raises_rpc_error(-26, "insufficient fee", self.nodes[0].sendrawtransaction, dbl_tx_hex, 0)
165+
reject_reason = "insufficient fee"
166+
reject_details = f"{reject_reason}, rejecting replacement {dbl_tx.hash}, less fees than conflicting txs; 3.00 < 4.00"
167+
res = self.nodes[0].testmempoolaccept(rawtxs=[dbl_tx_hex])[0]
168+
assert_equal(res["reject-reason"], reject_reason)
169+
assert_equal(res["reject-details"], reject_details)
170+
assert_raises_rpc_error(-26, f"{reject_details}", self.nodes[0].sendrawtransaction, dbl_tx_hex, 0)
171+
172+
158173

159174
# Accepted with sufficient fee
160175
dbl_tx.vout[0].nValue = int(0.1 * COIN)
@@ -273,22 +288,30 @@ def test_spends_of_conflicting_outputs(self):
273288
utxo1 = self.make_utxo(self.nodes[0], int(1.2 * COIN))
274289
utxo2 = self.make_utxo(self.nodes[0], 3 * COIN)
275290

276-
tx1a_utxo = self.wallet.send_self_transfer(
291+
tx1a = self.wallet.send_self_transfer(
277292
from_node=self.nodes[0],
278293
utxo_to_spend=utxo1,
279294
sequence=0,
280295
fee=Decimal("0.1"),
281-
)["new_utxo"]
296+
)
297+
tx1a_utxo = tx1a["new_utxo"]
282298

283299
# Direct spend an output of the transaction we're replacing.
284-
tx2_hex = self.wallet.create_self_transfer_multi(
300+
tx2 = self.wallet.create_self_transfer_multi(
285301
utxos_to_spend=[utxo1, utxo2, tx1a_utxo],
286302
sequence=0,
287303
amount_per_output=int(COIN * tx1a_utxo["value"]),
288-
)["hex"]
304+
)["tx"]
305+
tx2_hex = tx2.serialize().hex()
289306

290307
# This will raise an exception
291-
assert_raises_rpc_error(-26, "bad-txns-spends-conflicting-tx", self.nodes[0].sendrawtransaction, tx2_hex, 0)
308+
reject_reason = "bad-txns-spends-conflicting-tx"
309+
reject_details = f"{reject_reason}, {tx2.hash} spends conflicting transaction {tx1a['tx'].hash}"
310+
res = self.nodes[0].testmempoolaccept(rawtxs=[tx2_hex])[0]
311+
assert_equal(res["reject-reason"], reject_reason)
312+
assert_equal(res["reject-details"], reject_details)
313+
assert_raises_rpc_error(-26, f"{reject_details}", self.nodes[0].sendrawtransaction, tx2_hex, 0)
314+
292315

293316
# Spend tx1a's output to test the indirect case.
294317
tx1b_utxo = self.wallet.send_self_transfer(
@@ -319,14 +342,21 @@ def test_new_unconfirmed_inputs(self):
319342
fee=Decimal("0.1"),
320343
)
321344

322-
tx2_hex = self.wallet.create_self_transfer_multi(
345+
tx2 = self.wallet.create_self_transfer_multi(
323346
utxos_to_spend=[confirmed_utxo, unconfirmed_utxo],
324347
sequence=0,
325348
amount_per_output=1 * COIN,
326-
)["hex"]
349+
)["tx"]
350+
tx2_hex = tx2.serialize().hex()
327351

328352
# This will raise an exception
329-
assert_raises_rpc_error(-26, "replacement-adds-unconfirmed", self.nodes[0].sendrawtransaction, tx2_hex, 0)
353+
reject_reason = "replacement-adds-unconfirmed"
354+
reject_details = f"{reject_reason}, replacement {tx2.hash} adds unconfirmed input, idx 1"
355+
res = self.nodes[0].testmempoolaccept(rawtxs=[tx2_hex])[0]
356+
assert_equal(res["reject-reason"], reject_reason)
357+
assert_equal(res["reject-details"], reject_details)
358+
assert_raises_rpc_error(-26, f"{reject_details}", self.nodes[0].sendrawtransaction, tx2_hex, 0)
359+
330360

331361
def test_too_many_replacements(self):
332362
"""Replacements that evict too many transactions are rejected"""
@@ -368,7 +398,13 @@ def test_too_many_replacements(self):
368398
double_tx_hex = double_tx.serialize().hex()
369399

370400
# This will raise an exception
371-
assert_raises_rpc_error(-26, "too many potential replacements", self.nodes[0].sendrawtransaction, double_tx_hex, 0)
401+
reject_reason = "too many potential replacements"
402+
reject_details = f"{reject_reason}, rejecting replacement {double_tx.hash}; too many potential replacements ({MAX_REPLACEMENT_LIMIT + 1} > {MAX_REPLACEMENT_LIMIT})"
403+
res = self.nodes[0].testmempoolaccept(rawtxs=[double_tx_hex])[0]
404+
assert_equal(res["reject-reason"], reject_reason)
405+
assert_equal(res["reject-details"], reject_details)
406+
assert_raises_rpc_error(-26, f"{reject_details}", self.nodes[0].sendrawtransaction, double_tx_hex, 0)
407+
372408

373409
# If we remove an input, it should pass
374410
double_tx.vin.pop()

0 commit comments

Comments
 (0)