Skip to content

Commit b81cd4c

Browse files
MarcoFalkeFabcien
MarcoFalke
authored andcommitted
test: Run mempool_packages.py with MiniWallet
Summary: ``` This allows to run the test even when no wallet is compiled in. Also, it is a lot nicer to read now. ``` Backport of [core#26625](bitcoin/bitcoin#26625). Depends on D16431. Test Plan: ./test/functional/test_runner.py mempool_packages Reviewers: #bitcoin_abc, roqqit Reviewed By: roqqit Differential Revision: https://reviews.bitcoinabc.org/D16432
1 parent 05ef30b commit b81cd4c

File tree

4 files changed

+42
-69
lines changed

4 files changed

+42
-69
lines changed

test/functional/abc_mempool_chainedtx.py

+6-3
Original file line numberDiff line numberDiff line change
@@ -22,9 +22,12 @@ def run_test(self):
2222
wallet = MiniWallet(node)
2323

2424
self.generate(wallet, COINBASE_MATURITY + 2)
25-
chain_hex = wallet.create_self_transfer_chain(
26-
chain_length=LEGACY_MAX_CHAINED_TX * 2
27-
)["chain_hex"]
25+
chain_hex = [
26+
t["hex"]
27+
for t in wallet.create_self_transfer_chain(
28+
chain_length=LEGACY_MAX_CHAINED_TX * 2
29+
)
30+
]
2831

2932
for i, tx_hex in enumerate(chain_hex):
3033
txid = wallet.sendrawtransaction(from_node=node, tx_hex=tx_hex)

test/functional/mempool_packages.py

+10-38
Original file line numberDiff line numberDiff line change
@@ -3,12 +3,10 @@
33
# file COPYING or http://www.opensource.org/licenses/mit-license.php.
44
"""Test descendant package tracking code."""
55

6-
from decimal import Decimal
7-
8-
from test_framework.blocktools import COINBASE_MATURITY
96
from test_framework.p2p import P2PTxInvStore
107
from test_framework.test_framework import BitcoinTestFramework
118
from test_framework.util import assert_equal, satoshi_round
9+
from test_framework.wallet import MiniWallet
1210

1311
MAX_ANCESTORS = 50
1412

@@ -18,49 +16,22 @@ def set_test_params(self):
1816
self.num_nodes = 2
1917
self.extra_args = [["-maxorphantx=1000"]] * self.num_nodes
2018

21-
def skip_test_if_missing_module(self):
22-
self.skip_if_no_wallet()
23-
24-
# Build a transaction that spends parent_txid:vout
25-
# Return amount sent
26-
def chain_transaction(self, node, parent_txid, vout, value, fee, num_outputs):
27-
send_value = satoshi_round((value - fee) / num_outputs)
28-
inputs = [{"txid": parent_txid, "vout": vout}]
29-
outputs = {}
30-
for _ in range(num_outputs):
31-
outputs[node.getnewaddress()] = send_value
32-
rawtx = node.createrawtransaction(inputs, outputs)
33-
signedtx = node.signrawtransactionwithwallet(rawtx)
34-
txid = node.sendrawtransaction(signedtx["hex"])
35-
fulltx = node.getrawtransaction(txid, 1)
36-
# make sure we didn't generate a change output
37-
assert len(fulltx["vout"]) == num_outputs
38-
return (txid, send_value)
39-
4019
def run_test(self):
41-
# Mine some blocks and have them mature.
42-
# keep track of invs
20+
self.wallet = MiniWallet(self.nodes[0])
21+
self.wallet.rescan_utxos()
22+
4323
peer_inv_store = self.nodes[0].add_p2p_connection(P2PTxInvStore())
44-
self.generate(self.nodes[0], COINBASE_MATURITY + 1)
45-
utxo = self.nodes[0].listunspent(10)
46-
txid = utxo[0]["txid"]
47-
value = utxo[0]["amount"]
4824

49-
fee = Decimal("100")
5025
# MAX_ANCESTORS transactions off a confirmed tx should be fine
51-
chain = []
52-
for i in range(MAX_ANCESTORS):
53-
(txid, sent_value) = self.chain_transaction(
54-
self.nodes[0], txid, 0, value, fee, 1
55-
)
56-
value = sent_value
57-
chain.append(txid)
26+
chain = self.wallet.send_self_transfer_chain(
27+
from_node=self.nodes[0], chain_length=MAX_ANCESTORS
28+
)
5829

5930
# Wait until mempool transactions have passed initial broadcast
6031
# (sent inv and received getdata)
6132
# Otherwise, getrawmempool may be inconsistent with getmempoolentry if
6233
# unbroadcast changes in between
63-
peer_inv_store.wait_for_broadcast(chain)
34+
peer_inv_store.wait_for_broadcast([t["txid"] for t in chain])
6435

6536
# Check mempool has MAX_ANCESTORS transactions in it
6637
mempool = self.nodes[0].getrawmempool(True)
@@ -74,7 +45,8 @@ def run_test(self):
7445
ancestor_fees = sum([mempool[tx]["fees"]["base"] for tx in mempool])
7546

7647
descendants = []
77-
ancestors = list(chain)
48+
ancestors = [t["txid"] for t in chain]
49+
chain = [t["txid"] for t in chain]
7850
for x in reversed(chain):
7951
# Check that getmempoolentry is consistent with getrawmempool
8052
entry = self.nodes[0].getmempoolentry(x)

test/functional/rpc_packages.py

+5-3
Original file line numberDiff line numberDiff line change
@@ -178,8 +178,8 @@ def test_chain(self):
178178
node = self.nodes[0]
179179

180180
chain = self.wallet.create_self_transfer_chain(chain_length=25)
181-
chain_hex = chain["chain_hex"]
182-
chain_txns = chain["chain_txns"]
181+
chain_hex = [t["hex"] for t in chain]
182+
chain_txns = [t["tx"] for t in chain]
183183

184184
self.log.info(
185185
"Check that testmempoolaccept requires packages to be sorted by dependency"
@@ -471,7 +471,9 @@ def test_submitpackage(self):
471471

472472
self.log.info("Submitpackage only allows packages of 1 child with its parents")
473473
# Chain of 3 transactions has too many generations
474-
chain_hex = self.wallet.create_self_transfer_chain(chain_length=25)["chain_hex"]
474+
chain_hex = [
475+
t["hex"] for t in self.wallet.create_self_transfer_chain(chain_length=25)
476+
]
475477
assert_raises_rpc_error(
476478
-25, "not-child-with-parents", node.submitpackage, chain_hex
477479
)

test/functional/test_framework/wallet.py

+21-25
Original file line numberDiff line numberDiff line change
@@ -254,6 +254,9 @@ def create_self_transfer_multi(
254254
inputs_value_total = sum([int(XEC * utxo["value"]) for utxo in utxos_to_spend])
255255
outputs_value_total = inputs_value_total - fee_per_output * num_outputs
256256
amount_per_output = amount_per_output or (outputs_value_total // num_outputs)
257+
assert amount_per_output > 0
258+
outputs_value_total = amount_per_output * num_outputs
259+
fee = Decimal(inputs_value_total - outputs_value_total) / XEC
257260

258261
# create tx
259262
tx = CTransaction()
@@ -302,6 +305,7 @@ def create_self_transfer_multi(
302305
)
303306
for i in range(len(tx.vout))
304307
],
308+
"fee": fee,
305309
"txid": txid,
306310
"hex": tx.serialize().hex(),
307311
"tx": tx,
@@ -334,7 +338,6 @@ def create_self_transfer(
334338
send_value = satoshi_round(
335339
utxo_to_spend["value"] - (fee or (fee_rate * (Decimal(size) / 1000)))
336340
)
337-
assert send_value > 0
338341

339342
# create tx
340343
tx = self.create_self_transfer_multi(
@@ -347,49 +350,42 @@ def create_self_transfer(
347350
if not target_size:
348351
assert_equal(len(tx["tx"].serialize()), size)
349352

350-
return {
351-
"txid": tx["txid"],
352-
"hex": tx["hex"],
353-
"tx": tx["tx"],
354-
"new_utxo": tx["new_utxos"][0],
355-
}
353+
tx["new_utxo"] = tx.pop("new_utxos")[0]
354+
355+
return tx
356356

357357
def sendrawtransaction(self, *, from_node, tx_hex):
358358
txid = from_node.sendrawtransaction(tx_hex)
359359
self.scan_tx(from_node.decoderawtransaction(tx_hex))
360360
return txid
361361

362-
def create_self_transfer_chain(self, *, chain_length):
362+
def create_self_transfer_chain(self, *, chain_length, utxo_to_spend=None):
363363
"""
364364
Create a "chain" of chain_length transactions. The nth transaction in
365365
the chain is a child of the n-1th transaction and parent of the n+1th transaction.
366-
Returns a dic {"chain_hex": chain_hex, "chain_txns" : chain_txns}
367-
"chain_hex" is a list representing the chain's transactions in hexadecimal.
368-
"chain_txns" is a list representing the chain's transactions in the CTransaction object.
369366
"""
370-
chaintip_utxo = self.get_utxo()
371-
chain_hex = []
372-
chain_txns = []
367+
chaintip_utxo = utxo_to_spend or self.get_utxo()
368+
chain = []
373369

374370
for _ in range(chain_length):
375371
tx = self.create_self_transfer(utxo_to_spend=chaintip_utxo)
376372
chaintip_utxo = tx["new_utxo"]
377-
chain_hex.append(tx["hex"])
378-
chain_txns.append(tx["tx"])
373+
chain.append(tx)
379374

380-
return {"chain_hex": chain_hex, "chain_txns": chain_txns}
375+
return chain
381376

382-
def send_self_transfer_chain(self, *, from_node, chain_length, utxo_to_spend=None):
377+
def send_self_transfer_chain(self, *, from_node, **kwargs):
383378
"""Create and send a "chain" of chain_length transactions. The nth
384379
transaction in the chain is a child of the n-1th transaction and parent
385-
of the n+1th transaction. Returns the chaintip (nth) utxo.
380+
of the n+1th transaction.
381+
382+
Returns a list of objects for each tx (see create_self_transfer_multi).
386383
"""
387-
chaintip_utxo = utxo_to_spend or self.get_utxo()
388-
for _ in range(chain_length):
389-
chaintip_utxo = self.send_self_transfer(
390-
utxo_to_spend=chaintip_utxo, from_node=from_node
391-
)["new_utxo"]
392-
return chaintip_utxo
384+
chain = self.create_self_transfer_chain(**kwargs)
385+
for t in chain:
386+
self.sendrawtransaction(from_node=from_node, tx_hex=t["hex"])
387+
388+
return chain
393389

394390

395391
def getnewdestination():

0 commit comments

Comments
 (0)