Skip to content

Commit a285fff

Browse files
51e1170 merge bitcoin#24324: refactor: remove unneeded bytes<->hex conversions in `byte_to_base58` (Kittywhiskers Van Gogh) 473ee8e merge bitcoin#24195: Fix failfast option for functional test runner (Kittywhiskers Van Gogh) 64dd467 merge bitcoin#23799: Let test_runner.py start multiple jobs per timeslot (Kittywhiskers Van Gogh) 1b241a2 merge bitcoin#23392: move check_node_connections to util (Kittywhiskers Van Gogh) f6fa0c0 merge bitcoin#23501: various feature_nulldummy.py improvements (Kittywhiskers Van Gogh) 851dae7 merge bitcoin#23210: Replace satoshi_round with int() or Decimal() (Kittywhiskers Van Gogh) 739394d merge bitcoin#23209: Avoid RPC roundtrip in MiniWallet get_descriptor() (Kittywhiskers Van Gogh) c96b9aa merge bitcoin#23102: Add missing re.escape() to feature_addrman test (Kittywhiskers Van Gogh) 4db9108 merge bitcoin#23047: Use MiniWallet in mempool_persist (Kittywhiskers Van Gogh) 234f22a merge bitcoin#23037: fix confusing off-by-one nValue in feature_coinstatsindex.py (Kittywhiskers Van Gogh) Pull request description: ## Breaking Changes None expected. ## Checklist - [x] I have performed a self-review of my own code - [x] I have commented my code, particularly in hard-to-understand areas **(note: N/A)** - [x] I have added or updated relevant unit/integration/functional/e2e tests - [x] I have made corresponding changes to the documentation **(note: N/A)** - [x] I have assigned this pull request to a milestone _(for repository code-owners and collaborators only)_ ACKs for top commit: knst: utACK 51e1170 UdjinM6: utACK 51e1170 Tree-SHA512: 54ffbb2a44ad411d8602a7a752a05527faa65199da6cfa585f953892017c4d9e906c86c0b5b5e5d151d76eb0649aa76a7d17104ab0b3797a111d364ca52d716b
2 parents e493d59 + 51e1170 commit a285fff

File tree

12 files changed

+124
-114
lines changed

12 files changed

+124
-114
lines changed

test/functional/feature_addrman.py

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -5,6 +5,7 @@
55
"""Test addrman functionality"""
66

77
import os
8+
import re
89
import struct
910

1011
from test_framework.messages import ser_uint256, hash256
@@ -56,7 +57,7 @@ def run_test(self):
5657
init_error = lambda reason: (
5758
f"Error: Invalid or corrupt peers.dat \\({reason}\\). If you believe this "
5859
f"is a bug, please report it to {self.config['environment']['PACKAGE_BUGREPORT']}. "
59-
f'As a workaround, you can move the file \\("{peers_dat}"\\) out of the way \\(rename, '
60+
f'As a workaround, you can move the file \\("{re.escape(peers_dat)}"\\) out of the way \\(rename, '
6061
"move, or delete\\) to have a new one created on the next start."
6162
)
6263

test/functional/feature_anchors.py

Lines changed: 1 addition & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -8,18 +8,12 @@
88

99
from test_framework.p2p import P2PInterface
1010
from test_framework.test_framework import BitcoinTestFramework
11-
from test_framework.util import assert_equal
11+
from test_framework.util import check_node_connections
1212

1313
INBOUND_CONNECTIONS = 5
1414
BLOCK_RELAY_CONNECTIONS = 2
1515

1616

17-
def check_node_connections(*, node, num_in, num_out):
18-
info = node.getnetworkinfo()
19-
assert_equal(info["connections_in"], num_in)
20-
assert_equal(info["connections_out"], num_out)
21-
22-
2317
class AnchorsTest(BitcoinTestFramework):
2418
def set_test_params(self):
2519
self.num_nodes = 1

test/functional/feature_bip68_sequence.py

Lines changed: 1 addition & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -21,7 +21,6 @@
2121
assert_equal,
2222
assert_greater_than,
2323
assert_raises_rpc_error,
24-
satoshi_round,
2524
softfork_active,
2625
)
2726
from test_framework.script_util import DUMMY_P2SH_SCRIPT
@@ -91,7 +90,7 @@ def test_disable_flag(self):
9190
utxo = utxos[0]
9291

9392
tx1 = CTransaction()
94-
value = int(satoshi_round(utxo["amount"] - self.relayfee)*COIN)
93+
value = int((utxo["amount"] - self.relayfee) * COIN)
9594

9695
# Check that the disable flag disables relative locktime.
9796
# If sequence locks were used, this would require 1 block for the

test/functional/feature_coinstatsindex.py

Lines changed: 6 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -178,7 +178,7 @@ def _test_coin_stats_index(self):
178178
# Generate and send another tx with an OP_RETURN output (which is unspendable)
179179
tx2 = CTransaction()
180180
tx2.vin.append(CTxIn(COutPoint(int(tx1_txid, 16), n), b''))
181-
tx2.vout.append(CTxOut(int(20.99 * COIN), CScript([OP_RETURN] + [OP_FALSE]*30)))
181+
tx2.vout.append(CTxOut(int(Decimal('20.99') * COIN), CScript([OP_RETURN] + [OP_FALSE]*30)))
182182
tx2_hex = self.nodes[0].signrawtransactionwithwallet(tx2.serialize().hex())['hex']
183183
self.nodes[0].sendrawtransaction(tx2_hex)
184184

@@ -189,16 +189,16 @@ def _test_coin_stats_index(self):
189189
for hash_option in index_hash_options:
190190
# Check all amounts were registered correctly
191191
res6 = index_node.gettxoutsetinfo(hash_option, 108)
192-
assert_equal(res6['total_unspendable_amount'], Decimal('70.98999999'))
192+
assert_equal(res6['total_unspendable_amount'], Decimal('70.99000000'))
193193
assert_equal(res6['block_info'], {
194-
'unspendable': Decimal('20.98999999'),
194+
'unspendable': Decimal('20.99000000'),
195195
'prevout_spent': 511,
196196
'new_outputs_ex_coinbase': Decimal('489.99999741'),
197-
'coinbase': Decimal('500.01000260'),
197+
'coinbase': Decimal('500.01000259'),
198198
'unspendables': {
199199
'genesis_block': 0,
200200
'bip30': 0,
201-
'scripts': Decimal('20.98999999'),
201+
'scripts': Decimal('20.99000000'),
202202
'unclaimed_rewards': 0
203203
}
204204
})
@@ -220,7 +220,7 @@ def _test_coin_stats_index(self):
220220

221221
for hash_option in index_hash_options:
222222
res7 = index_node.gettxoutsetinfo(hash_option, 109)
223-
assert_equal(res7['total_unspendable_amount'], Decimal('530.98999999'))
223+
assert_equal(res7['total_unspendable_amount'], Decimal('530.99000000'))
224224
assert_equal(res7['block_info'], {
225225
'unspendable': 460,
226226
'prevout_spent': 0,

test/functional/feature_nulldummy.py

Lines changed: 13 additions & 19 deletions
Original file line numberDiff line numberDiff line change
@@ -20,7 +20,10 @@
2020
create_transaction,
2121
)
2222
from test_framework.messages import CTransaction
23-
from test_framework.script import CScript
23+
from test_framework.script import (
24+
OP_0,
25+
OP_TRUE,
26+
)
2427
from test_framework.test_framework import BitcoinTestFramework
2528
from test_framework.util import (
2629
assert_equal,
@@ -29,16 +32,12 @@
2932

3033
NULLDUMMY_ERROR = "non-mandatory-script-verify-flag (Dummy CHECKMULTISIG argument must be zero)"
3134

32-
def trueDummy(tx):
33-
scriptSig = CScript(tx.vin[0].scriptSig)
34-
newscript = []
35-
for i in scriptSig:
36-
if len(newscript) == 0:
37-
assert len(i) == 0
38-
newscript.append(b'\x51')
39-
else:
40-
newscript.append(i)
41-
tx.vin[0].scriptSig = CScript(newscript)
35+
36+
def invalidate_nulldummy_tx(tx):
37+
"""Transform a NULLDUMMY compliant tx (i.e. scriptSig starts with OP_0)
38+
to be non-NULLDUMMY compliant by replacing the dummy with OP_TRUE"""
39+
assert_equal(tx.vin[0].scriptSig[0], OP_0)
40+
tx.vin[0].scriptSig = bytes([OP_TRUE]) + tx.vin[0].scriptSig[1:]
4241
tx.rehash()
4342

4443
class NULLDUMMYTest(BitcoinTestFramework):
@@ -86,7 +85,7 @@ def run_test(self):
8685

8786
self.log.info("Test 2: Non-NULLDUMMY base multisig transaction should not be accepted to mempool before activation")
8887
test2tx = create_transaction(self.nodes[0], txid2, self.ms_address, amount=47)
89-
trueDummy(test2tx)
88+
invalidate_nulldummy_tx(test2tx)
9089
assert_raises_rpc_error(-26, NULLDUMMY_ERROR, self.nodes[0].sendrawtransaction, test2tx.serialize().hex(), 0)
9190

9291
self.log.info(f"Test 3: Non-NULLDUMMY base transactions should be accepted in a block before activation [{COINBASE_MATURITY + 4}]")
@@ -95,7 +94,7 @@ def run_test(self):
9594
self.log.info("Test 4: Non-NULLDUMMY base multisig transaction is invalid after activation")
9695
test4tx = create_transaction(self.nodes[0], test2tx.hash, self.address, amount=46)
9796
test6txs=[CTransaction(test4tx)]
98-
trueDummy(test4tx)
97+
invalidate_nulldummy_tx(test4tx)
9998
assert_raises_rpc_error(-26, NULLDUMMY_ERROR, self.nodes[0].sendrawtransaction, test4tx.serialize().hex(), 0)
10099
self.block_submit(self.nodes[0], [test4tx], accept=False)
101100

@@ -110,12 +109,7 @@ def block_submit(self, node, txs, *, accept=False):
110109
tmpl = node.getblocktemplate(NORMAL_GBT_REQUEST_PARAMS)
111110
assert_equal(tmpl['previousblockhash'], self.lastblockhash)
112111
assert_equal(tmpl['height'], self.lastblockheight + 1)
113-
block = create_block(tmpl=tmpl, ntime=self.lastblocktime + 1, dip4_activated=dip4_activated)
114-
for tx in txs:
115-
tx.rehash()
116-
block.vtx.append(tx)
117-
block.hashMerkleRoot = block.calc_merkle_root()
118-
block.rehash()
112+
block = create_block(tmpl=tmpl, ntime=self.lastblocktime + 1, txlist=txs, dip4_activated=dip4_activated)
119113
block.solve()
120114
assert_equal(None if accept else NULLDUMMY_ERROR, node.submitblock(block.serialize().hex()))
121115
if accept:

test/functional/mempool_packages.py

Lines changed: 4 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -14,7 +14,6 @@
1414
assert_equal,
1515
assert_raises_rpc_error,
1616
chain_transaction,
17-
satoshi_round,
1817
)
1918

2019
# default limits
@@ -190,10 +189,10 @@ def run_test(self):
190189
entry = self.nodes[0].getmempoolentry(x)
191190
descendant_fees += entry['fee']
192191
if (x == chain[-1]):
193-
assert_equal(entry['modifiedfee'], entry['fee']+satoshi_round(0.00002))
194-
assert_equal(entry['fees']['modified'], entry['fee']+satoshi_round(0.00002))
192+
assert_equal(entry['modifiedfee'], entry['fee'] + Decimal("0.00002"))
193+
assert_equal(entry['fees']['modified'], entry['fee'] + Decimal("0.00002"))
195194
assert_equal(entry['descendantfees'], descendant_fees * COIN + 2000)
196-
assert_equal(entry['fees']['descendant'], descendant_fees+satoshi_round(0.00002))
195+
assert_equal(entry['fees']['descendant'], descendant_fees + Decimal("0.00002"))
197196

198197
# Check that node1's mempool is as expected (-> custom ancestor limit)
199198
mempool0 = self.nodes[0].getrawmempool(False)
@@ -289,7 +288,7 @@ def run_test(self):
289288
value = utxo[0]['amount']
290289
vout = utxo[0]['vout']
291290

292-
send_value = satoshi_round((value - fee)/2)
291+
send_value = (value - fee) / 2
293292
inputs = [ {'txid' : txid, 'vout' : vout} ]
294293
outputs = {}
295294
for _ in range(2):

test/functional/mempool_persist.py

Lines changed: 37 additions & 23 deletions
Original file line numberDiff line numberDiff line change
@@ -44,22 +44,34 @@
4444
assert_equal,
4545
assert_greater_than_or_equal, assert_raises_rpc_error,
4646
)
47+
from test_framework.wallet import MiniWallet
4748

4849

4950
class MempoolPersistTest(BitcoinTestFramework):
5051
def set_test_params(self):
5152
self.num_nodes = 3
5253
self.extra_args = [[], ["-persistmempool=0"], []]
5354

54-
def skip_test_if_missing_module(self):
55-
self.skip_if_no_wallet()
56-
5755
def run_test(self):
56+
self.mini_wallet = MiniWallet(self.nodes[2])
57+
self.mini_wallet.rescan_utxos()
58+
if self.is_sqlite_compiled():
59+
self.nodes[2].createwallet(
60+
wallet_name="watch",
61+
descriptors=True,
62+
disable_private_keys=True,
63+
load_on_startup=False,
64+
)
65+
wallet_watch = self.nodes[2].get_wallet_rpc("watch")
66+
assert_equal([{'success': True}], wallet_watch.importdescriptors([{'desc': self.mini_wallet.get_descriptor(), 'timestamp': 0}]))
67+
5868
self.log.debug("Send 5 transactions from node2 (to its own address)")
5969
tx_creation_time_lower = self.mocktime
6070
for _ in range(5):
61-
last_txid = self.nodes[2].sendtoaddress(self.nodes[2].getnewaddress(), Decimal("10"))
62-
node2_balance = self.nodes[2].getbalance()
71+
last_txid = self.mini_wallet.send_self_transfer(from_node=self.nodes[2])["txid"]
72+
if self.is_sqlite_compiled():
73+
self.nodes[2].syncwithvalidationinterfacequeue() # Flush mempool to wallet
74+
node2_balance = wallet_watch.getbalance()
6375
self.sync_all()
6476
tx_creation_time_higher = self.mocktime
6577

@@ -80,16 +92,16 @@ def run_test(self):
8092
assert_equal(total_fee_old, self.nodes[0].getmempoolinfo()['total_fee'])
8193
assert_equal(total_fee_old, sum(v['fees']['base'] for k, v in self.nodes[0].getrawmempool(verbose=True).items()))
8294

83-
tx_creation_time = self.nodes[0].getmempoolentry(txid=last_txid)['time']
95+
last_entry = self.nodes[0].getmempoolentry(txid=last_txid)
96+
tx_creation_time = last_entry['time']
8497
assert_greater_than_or_equal(tx_creation_time, tx_creation_time_lower)
8598
assert_greater_than_or_equal(tx_creation_time_higher, tx_creation_time)
8699

87100
# disconnect nodes & make a txn that remains in the unbroadcast set.
88101
self.disconnect_nodes(0, 1)
89-
assert(len(self.nodes[0].getpeerinfo()) == 0)
90-
assert(len(self.nodes[0].p2ps) == 0)
91-
self.nodes[0].sendtoaddress(self.nodes[2].getnewaddress(), Decimal("12"))
92-
self.connect_nodes(0, 2)
102+
assert_equal(len(self.nodes[0].getpeerinfo()), 0)
103+
assert_equal(len(self.nodes[0].p2ps), 0)
104+
self.mini_wallet.send_self_transfer(from_node=self.nodes[0])
93105

94106
self.log.debug("Stop-start the nodes. Verify that node0 has the transactions in its mempool and node1 does not. Verify that node2 calculates its balance correctly after loading wallet transactions.")
95107
self.stop_nodes()
@@ -109,17 +121,19 @@ def run_test(self):
109121
fees = self.nodes[0].getmempoolentry(txid=last_txid)['fees']
110122
assert_equal(fees['base'] + Decimal('0.00001000'), fees['modified'])
111123

112-
self.log.debug('Verify time is loaded correctly')
113-
assert_equal(tx_creation_time, self.nodes[0].getmempoolentry(txid=last_txid)['time'])
124+
self.log.debug('Verify all fields are loaded correctly')
125+
assert_equal(last_entry, self.nodes[0].getmempoolentry(txid=last_txid))
114126

115127
# Verify accounting of mempool transactions after restart is correct
116-
self.nodes[2].syncwithvalidationinterfacequeue() # Flush mempool to wallet
117-
assert_equal(node2_balance, self.nodes[2].getbalance())
128+
if self.is_sqlite_compiled():
129+
self.nodes[2].loadwallet("watch")
130+
wallet_watch = self.nodes[2].get_wallet_rpc("watch")
131+
self.nodes[2].syncwithvalidationinterfacequeue() # Flush mempool to wallet
132+
assert_equal(node2_balance, wallet_watch.getbalance())
118133

119-
# start node0 with wallet disabled so wallet transactions don't get resubmitted
120134
self.log.debug("Stop-start node0 with -persistmempool=0. Verify that it doesn't load its mempool.dat file.")
121135
self.stop_nodes()
122-
self.start_node(0, extra_args=["-persistmempool=0", "-disablewallet"])
136+
self.start_node(0, extra_args=["-persistmempool=0"])
123137
assert self.nodes[0].getmempoolinfo()["loaded"]
124138
assert_equal(len(self.nodes[0].getrawmempool()), 0)
125139

@@ -163,18 +177,18 @@ def test_persist_unbroadcast(self):
163177

164178
# ensure node0 doesn't have any connections
165179
# make a transaction that will remain in the unbroadcast set
166-
assert(len(node0.getpeerinfo()) == 0)
167-
assert(len(node0.p2ps) == 0)
168-
node0.sendtoaddress(self.nodes[1].getnewaddress(), Decimal("12"))
180+
assert_equal(len(node0.getpeerinfo()), 0)
181+
assert_equal(len(node0.p2ps), 0)
182+
self.mini_wallet.send_self_transfer(from_node=node0)
169183

170184
# shutdown, then startup with wallet disabled
171-
self.stop_nodes()
172-
self.start_node(0, extra_args=["-disablewallet"])
185+
self.restart_node(0, extra_args=["-disablewallet"])
173186

174187
# check that txn gets broadcast due to unbroadcast logic
175188
# conn = node0.add_p2p_connection(P2PTxInvStore())
176-
# node0.mockscheduler(16*60) # 15 min + 1 for buffer
189+
# node0.mockscheduler(16 * 60) # 15 min + 1 for buffer
177190
# self.wait_until(lambda: len(conn.get_invs()) == 1)
178191

179-
if __name__ == '__main__':
192+
193+
if __name__ == "__main__":
180194
MempoolPersistTest().main()

test/functional/p2p_add_connections.py

Lines changed: 1 addition & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -6,13 +6,7 @@
66

77
from test_framework.p2p import P2PInterface
88
from test_framework.test_framework import BitcoinTestFramework
9-
from test_framework.util import assert_equal
10-
11-
12-
def check_node_connections(*, node, num_in, num_out):
13-
info = node.getnetworkinfo()
14-
assert_equal(info["connections_in"], num_in)
15-
assert_equal(info["connections_out"], num_out)
9+
from test_framework.util import check_node_connections
1610

1711

1812
class P2PAddConnections(BitcoinTestFramework):

test/functional/test_framework/address.py

Lines changed: 5 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -25,17 +25,15 @@
2525

2626
def byte_to_base58(b, version):
2727
result = ''
28-
str = b.hex()
29-
str = chr(version).encode('latin-1').hex() + str
30-
checksum = hash256(bytes.fromhex(str)).hex()
31-
str += checksum[:8]
32-
value = int('0x' + str, 0)
28+
b = bytes([version]) + b # prepend version
29+
b += hash256(b)[:4] # append checksum
30+
value = int.from_bytes(b, 'big')
3331
while value > 0:
3432
result = chars[value % 58] + result
3533
value //= 58
36-
while (str[:2] == '00'):
34+
while b[0] == 0:
3735
result = chars[0] + result
38-
str = str[2:]
36+
b = b[1:]
3937
return result
4038

4139

test/functional/test_framework/util.py

Lines changed: 6 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -264,6 +264,7 @@ def wait_until_helper(predicate, *, attempts=float('inf'), timeout=float('inf'),
264264
else:
265265
return False
266266

267+
267268
def sha256sum_file(filename):
268269
h = hashlib.sha256()
269270
with open(filename, 'rb') as f:
@@ -479,6 +480,11 @@ def set_node_times(nodes, t):
479480
node.mocktime = t
480481
node.setmocktime(t)
481482

483+
def check_node_connections(*, node, num_in, num_out):
484+
info = node.getnetworkinfo()
485+
assert_equal(info["connections_in"], num_in)
486+
assert_equal(info["connections_out"], num_out)
487+
482488

483489
def force_finish_mnsync(node):
484490
"""

0 commit comments

Comments
 (0)