Skip to content

Commit aa8a65e

Browse files
committed
test: use MiniWallet for mempool_accept.py
This test can now be run even with the Bitcoin Core wallet disabled.
1 parent b24f6c6 commit aa8a65e

File tree

2 files changed

+38
-46
lines changed

2 files changed

+38
-46
lines changed

test/functional/mempool_accept.py

Lines changed: 36 additions & 44 deletions
Original file line numberDiff line numberDiff line change
@@ -4,6 +4,7 @@
44
# file COPYING or http://www.opensource.org/licenses/mit-license.php.
55
"""Test mempool acceptance of raw transactions."""
66

7+
from copy import deepcopy
78
from decimal import Decimal
89
import math
910

@@ -34,6 +35,7 @@
3435
assert_equal,
3536
assert_raises_rpc_error,
3637
)
38+
from test_framework.wallet import MiniWallet
3739

3840

3941
class MempoolAcceptanceTest(BitcoinTestFramework):
@@ -44,9 +46,6 @@ def set_test_params(self):
4446
]] * self.num_nodes
4547
self.supports_cli = False
4648

47-
def skip_test_if_missing_module(self):
48-
self.skip_if_no_wallet()
49-
5049
def check_mempool_result(self, result_expected, *args, **kwargs):
5150
"""Wrapper to check result of testmempoolaccept on node_0's mempool"""
5251
result_test = self.nodes[0].testmempoolaccept(*args, **kwargs)
@@ -57,12 +56,13 @@ def check_mempool_result(self, result_expected, *args, **kwargs):
5756

5857
def run_test(self):
5958
node = self.nodes[0]
59+
self.wallet = MiniWallet(node)
60+
self.wallet.rescan_utxos()
6061

6162
self.log.info('Start with empty mempool, and 200 blocks')
6263
self.mempool_size = 0
6364
assert_equal(node.getblockcount(), 200)
6465
assert_equal(node.getmempoolinfo()['size'], self.mempool_size)
65-
coins = node.listunspent()
6666

6767
self.log.info('Should not accept garbage to testmempoolaccept')
6868
assert_raises_rpc_error(-3, 'Expected type array, got string', lambda: node.testmempoolaccept(rawtxs='ff00baar'))
@@ -71,12 +71,12 @@ def run_test(self):
7171
assert_raises_rpc_error(-22, 'TX decode failed', lambda: node.testmempoolaccept(rawtxs=['ff00baar']))
7272

7373
self.log.info('A transaction already in the blockchain')
74-
coin = coins.pop() # Pick a random coin(base) to spend
75-
raw_tx_in_block = node.signrawtransactionwithwallet(node.createrawtransaction(
76-
inputs=[{'txid': coin['txid'], 'vout': coin['vout']}],
77-
outputs=[{node.getnewaddress(): 0.3}, {node.getnewaddress(): 49}],
78-
))['hex']
79-
txid_in_block = node.sendrawtransaction(hexstring=raw_tx_in_block, maxfeerate=0)
74+
tx = self.wallet.create_self_transfer()['tx'] # Pick a random coin(base) to spend
75+
tx.vout.append(deepcopy(tx.vout[0]))
76+
tx.vout[0].nValue = int(0.3 * COIN)
77+
tx.vout[1].nValue = int(49 * COIN)
78+
raw_tx_in_block = tx.serialize().hex()
79+
txid_in_block = self.wallet.sendrawtransaction(from_node=node, tx_hex=raw_tx_in_block, maxfeerate=0)
8080
self.generate(node, 1)
8181
self.mempool_size = 0
8282
self.check_mempool_result(
@@ -86,27 +86,26 @@ def run_test(self):
8686

8787
self.log.info('A transaction not in the mempool')
8888
fee = Decimal('0.000007')
89-
raw_tx_0 = node.signrawtransactionwithwallet(node.createrawtransaction(
90-
inputs=[{"txid": txid_in_block, "vout": 0, "sequence": BIP125_SEQUENCE_NUMBER}], # RBF is used later
91-
outputs=[{node.getnewaddress(): Decimal('0.3') - fee}],
92-
))['hex']
93-
tx = tx_from_hex(raw_tx_0)
89+
utxo_to_spend = self.wallet.get_utxo(txid=txid_in_block) # use 0.3 BTC UTXO
90+
tx = self.wallet.create_self_transfer(utxo_to_spend=utxo_to_spend, sequence=BIP125_SEQUENCE_NUMBER)['tx']
91+
tx.vout[0].nValue = int((Decimal('0.3') - fee) * COIN)
92+
raw_tx_0 = tx.serialize().hex()
9493
txid_0 = tx.rehash()
9594
self.check_mempool_result(
9695
result_expected=[{'txid': txid_0, 'allowed': True, 'vsize': tx.get_vsize(), 'fees': {'base': fee}}],
9796
rawtxs=[raw_tx_0],
9897
)
9998

10099
self.log.info('A final transaction not in the mempool')
101-
coin = coins.pop() # Pick a random coin(base) to spend
102100
output_amount = Decimal('0.025')
103-
raw_tx_final = node.signrawtransactionwithwallet(node.createrawtransaction(
104-
inputs=[{'txid': coin['txid'], 'vout': coin['vout'], "sequence": SEQUENCE_FINAL}],
105-
outputs=[{node.getnewaddress(): output_amount}],
101+
tx = self.wallet.create_self_transfer(
102+
sequence=SEQUENCE_FINAL,
106103
locktime=node.getblockcount() + 2000, # Can be anything
107-
))['hex']
104+
)['tx']
105+
tx.vout[0].nValue = int(output_amount * COIN)
106+
raw_tx_final = tx.serialize().hex()
108107
tx = tx_from_hex(raw_tx_final)
109-
fee_expected = coin['amount'] - output_amount
108+
fee_expected = Decimal('50.0') - output_amount
110109
self.check_mempool_result(
111110
result_expected=[{'txid': tx.rehash(), 'allowed': True, 'vsize': tx.get_vsize(), 'fees': {'base': fee_expected}}],
112111
rawtxs=[tx.serialize().hex()],
@@ -127,8 +126,7 @@ def run_test(self):
127126
tx = tx_from_hex(raw_tx_0)
128127
tx.vout[0].nValue -= int(fee * COIN) # Double the fee
129128
tx.vin[0].nSequence = BIP125_SEQUENCE_NUMBER + 1 # Now, opt out of RBF
130-
raw_tx_0 = node.signrawtransactionwithwallet(tx.serialize().hex())['hex']
131-
tx = tx_from_hex(raw_tx_0)
129+
raw_tx_0 = tx.serialize().hex()
132130
txid_0 = tx.rehash()
133131
self.check_mempool_result(
134132
result_expected=[{'txid': txid_0, 'allowed': True, 'vsize': tx.get_vsize(), 'fees': {'base': (2 * fee)}}],
@@ -141,7 +139,6 @@ def run_test(self):
141139
# take original raw_tx_0
142140
tx = tx_from_hex(raw_tx_0)
143141
tx.vout[0].nValue -= int(4 * fee * COIN) # Set more fee
144-
# skip re-signing the tx
145142
self.check_mempool_result(
146143
result_expected=[{'txid': tx.rehash(), 'allowed': False, 'reject-reason': 'txn-mempool-conflict'}],
147144
rawtxs=[tx.serialize().hex()],
@@ -151,7 +148,6 @@ def run_test(self):
151148
self.log.info('A transaction with missing inputs, that never existed')
152149
tx = tx_from_hex(raw_tx_0)
153150
tx.vin[0].prevout = COutPoint(hash=int('ff' * 32, 16), n=14)
154-
# skip re-signing the tx
155151
self.check_mempool_result(
156152
result_expected=[{'txid': tx.rehash(), 'allowed': False, 'reject-reason': 'missing-inputs'}],
157153
rawtxs=[tx.serialize().hex()],
@@ -160,17 +156,17 @@ def run_test(self):
160156
self.log.info('A transaction with missing inputs, that existed once in the past')
161157
tx = tx_from_hex(raw_tx_0)
162158
tx.vin[0].prevout.n = 1 # Set vout to 1, to spend the other outpoint (49 coins) of the in-chain-tx we want to double spend
163-
raw_tx_1 = node.signrawtransactionwithwallet(tx.serialize().hex())['hex']
159+
raw_tx_1 = tx.serialize().hex()
164160
txid_1 = node.sendrawtransaction(hexstring=raw_tx_1, maxfeerate=0)
165161
# Now spend both to "clearly hide" the outputs, ie. remove the coins from the utxo set by spending them
166-
raw_tx_spend_both = node.signrawtransactionwithwallet(node.createrawtransaction(
167-
inputs=[
168-
{'txid': txid_0, 'vout': 0},
169-
{'txid': txid_1, 'vout': 0},
170-
],
171-
outputs=[{node.getnewaddress(): 0.1}]
172-
))['hex']
173-
txid_spend_both = node.sendrawtransaction(hexstring=raw_tx_spend_both, maxfeerate=0)
162+
tx = self.wallet.create_self_transfer()['tx']
163+
tx.vin.append(deepcopy(tx.vin[0]))
164+
tx.wit.vtxinwit.append(deepcopy(tx.wit.vtxinwit[0]))
165+
tx.vin[0].prevout = COutPoint(hash=int(txid_0, 16), n=0)
166+
tx.vin[1].prevout = COutPoint(hash=int(txid_1, 16), n=0)
167+
tx.vout[0].nValue = int(0.1 * COIN)
168+
raw_tx_spend_both = tx.serialize().hex()
169+
txid_spend_both = self.wallet.sendrawtransaction(from_node=node, tx_hex=raw_tx_spend_both, maxfeerate=0)
174170
self.generate(node, 1)
175171
self.mempool_size = 0
176172
# Now see if we can add the coins back to the utxo set by sending the exact txs again
@@ -183,12 +179,11 @@ def run_test(self):
183179
rawtxs=[raw_tx_1],
184180
)
185181

186-
self.log.info('Create a signed "reference" tx for later use')
187-
raw_tx_reference = node.signrawtransactionwithwallet(node.createrawtransaction(
188-
inputs=[{'txid': txid_spend_both, 'vout': 0}],
189-
outputs=[{node.getnewaddress(): 0.05}],
190-
))['hex']
191-
tx = tx_from_hex(raw_tx_reference)
182+
self.log.info('Create a "reference" tx for later use')
183+
utxo_to_spend = self.wallet.get_utxo(txid=txid_spend_both)
184+
tx = self.wallet.create_self_transfer(utxo_to_spend=utxo_to_spend, sequence=SEQUENCE_FINAL)['tx']
185+
tx.vout[0].nValue = int(0.05 * COIN)
186+
raw_tx_reference = tx.serialize().hex()
192187
# Reference tx should be valid on itself
193188
self.check_mempool_result(
194189
result_expected=[{'txid': tx.rehash(), 'allowed': True, 'vsize': tx.get_vsize(), 'fees': { 'base': Decimal('0.1') - Decimal('0.05')}}],
@@ -199,8 +194,6 @@ def run_test(self):
199194
self.log.info('A transaction with no outputs')
200195
tx = tx_from_hex(raw_tx_reference)
201196
tx.vout = []
202-
# Skip re-signing the transaction for context independent checks from now on
203-
# tx = tx_from_hex(node.signrawtransactionwithwallet(tx.serialize().hex())['hex'])
204197
self.check_mempool_result(
205198
result_expected=[{'txid': tx.rehash(), 'allowed': False, 'reject-reason': 'bad-txns-vout-empty'}],
206199
rawtxs=[tx.serialize().hex()],
@@ -257,7 +250,7 @@ def run_test(self):
257250
)
258251

259252
self.log.info('A coinbase transaction')
260-
# Pick the input of the first tx we signed, so it has to be a coinbase tx
253+
# Pick the input of the first tx we created, so it has to be a coinbase tx
261254
raw_tx_coinbase_spent = node.getrawtransaction(txid=node.decoderawtransaction(hexstring=raw_tx_in_block)['vin'][0]['txid'])
262255
tx = tx_from_hex(raw_tx_coinbase_spent)
263256
self.check_mempool_result(
@@ -334,7 +327,6 @@ def run_test(self):
334327
self.log.info('A transaction that is locked by BIP68 sequence logic')
335328
tx = tx_from_hex(raw_tx_reference)
336329
tx.vin[0].nSequence = 2 # We could include it in the second block mined from now, but not the very next one
337-
# Can skip re-signing the tx because of early rejection
338330
self.check_mempool_result(
339331
result_expected=[{'txid': tx.rehash(), 'allowed': False, 'reject-reason': 'non-BIP68-final'}],
340332
rawtxs=[tx.serialize().hex()],

test/functional/test_framework/wallet.py

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -214,8 +214,8 @@ def create_self_transfer(self, *, fee_rate=Decimal("0.003"), from_node=None, utx
214214
assert_equal(tx_info['fees']['base'], utxo_to_spend['value'] - Decimal(send_value) / COIN)
215215
return {'txid': tx_info['txid'], 'wtxid': tx_info['wtxid'], 'hex': tx_hex, 'tx': tx}
216216

217-
def sendrawtransaction(self, *, from_node, tx_hex):
218-
txid = from_node.sendrawtransaction(tx_hex)
217+
def sendrawtransaction(self, *, from_node, tx_hex, **kwargs):
218+
txid = from_node.sendrawtransaction(hexstring=tx_hex, **kwargs)
219219
self.scan_tx(from_node.decoderawtransaction(tx_hex))
220220
return txid
221221

0 commit comments

Comments
 (0)