Skip to content

Commit c557170

Browse files
authored
Merge pull request #121
Feature: Test mini wallet add P2TR support and use it per default
2 parents 02ed5dd + 9ed0a4a commit c557170

7 files changed

+56
-31
lines changed

test/functional/feature_coinstatsindex.py

+7-7
Original file line numberDiff line numberDiff line change
@@ -129,17 +129,17 @@ def _test_coin_stats_index(self):
129129

130130
# Test an older block height that included a normal tx
131131
res5 = index_node.gettxoutsetinfo(hash_option, 102)
132-
assert_equal(Decimal(res5['total_unspendable_amount']), Decimal('200.0002592'))
132+
assert_equal(Decimal(res5['total_unspendable_amount']), Decimal('200.00028080'))
133133
assert_equal(res5['block_info'], {
134-
'unspendable': Decimal('0.00025920'),
134+
'unspendable': Decimal('0.00028080'),
135135
'prevout_spent': 200,
136-
'new_outputs_ex_coinbase': Decimal('199.99971200'),
137-
'coinbase': Decimal('200.00002880'),
136+
'new_outputs_ex_coinbase': Decimal('199.99968800'),
137+
'coinbase': Decimal('200.00003120'),
138138
'unspendables': {
139139
'genesis_block': 0,
140140
'bip30': 0,
141141
'scripts': 0,
142-
'unclaimed_rewards': Decimal('0.00025920'),
142+
'unclaimed_rewards': Decimal('0.00028080'),
143143
}
144144
})
145145
self.block_sanity_check(res5['block_info'])
@@ -166,7 +166,7 @@ def _test_coin_stats_index(self):
166166
for hash_option in index_hash_options:
167167
# Check all amounts were registered correctly
168168
res6 = index_node.gettxoutsetinfo(hash_option, 108)
169-
assert_equal(res6['total_unspendable_amount'], Decimal('220.99976820'))
169+
assert_equal(res6['total_unspendable_amount'], Decimal('220.99978980'))
170170
assert_equal(res6['block_info'], {
171171
'unspendable': Decimal('20.99950900'),
172172
'prevout_spent': Decimal('221.00000000'),
@@ -197,7 +197,7 @@ def _test_coin_stats_index(self):
197197

198198
for hash_option in index_hash_options:
199199
res7 = index_node.gettxoutsetinfo(hash_option, 109)
200-
assert_equal(res7['total_unspendable_amount'], Decimal('380.99976820'))
200+
assert_equal(res7['total_unspendable_amount'], Decimal('380.99978980'))
201201
assert_equal(res7['block_info'], {
202202
'unspendable': Decimal('160.00000000'),
203203
'prevout_spent': 0,

test/functional/feature_maxuploadtarget.py

+1-1
Original file line numberDiff line numberDiff line change
@@ -106,7 +106,7 @@ def run_test(self):
106106
assert_equal(len(self.nodes[0].getpeerinfo()), 3)
107107
# At most a couple more tries should succeed (depending on how long
108108
# the test has been running so far).
109-
for _ in range(10):
109+
for _ in range(100):
110110
p2p_conns[0].send_message(getdata_request)
111111
p2p_conns[0].wait_for_disconnect()
112112
assert_equal(len(self.nodes[0].getpeerinfo()), 2)

test/functional/feature_utxo_set_hash.py

+2-2
Original file line numberDiff line numberDiff line change
@@ -69,8 +69,8 @@ def test_muhash_implementation(self):
6969
assert_equal(finalized[::-1].hex(), node_muhash)
7070

7171
self.log.info("Test deterministic UTXO set hash results")
72-
assert_equal(node.gettxoutsetinfo()['hash_serialized_2'], "f4edcc42a569bfef13f56306cf32821774ce36b0868cabbf698859d453b3ee0a")
73-
assert_equal(node.gettxoutsetinfo("muhash")['muhash'], "6aebab920c5c6102e2ae8fe94122c0cf6546e48eb167a9278693c00f7b348436")
72+
assert_equal(node.gettxoutsetinfo()['hash_serialized_2'], "4b7ea0bd09947f5d0d9f983dfce3f590a5a2e1a83aa2ab252561b849d3f23d73")
73+
assert_equal(node.gettxoutsetinfo("muhash")['muhash'], "88f5d8f48b36504974ce92cfd1f91a7000a5bb28288126b81d4788b7250b5b00")
7474

7575
def run_test(self):
7676
self.test_muhash_implementation()

test/functional/mempool_compatibility.py

+6-6
Original file line numberDiff line numberDiff line change
@@ -7,17 +7,17 @@
77
NOTE: The test is designed to prevent cases when compatibility is broken accidentally.
88
In case we need to break mempool compatibility we can continue to use the test by just bumping the version number.
99
10-
Download node binaries:
11-
test/get_previous_releases.py -b v0.19.1 v0.18.1 v0.17.2 v0.16.3 v0.15.2
12-
13-
Only v0.15.2 is required by this test. The rest is used in other backwards compatibility tests.
10+
The previous release v0.19.1 is required by this test, see test/README.md.
1411
"""
1512

1613
import os
1714

1815
from test_framework.blocktools import COINBASE_MATURITY
1916
from test_framework.test_framework import BGLTestFramework
20-
from test_framework.wallet import MiniWallet
17+
from test_framework.wallet import (
18+
MiniWallet,
19+
MiniWalletMode,
20+
)
2121

2222

2323
class MempoolCompatibilityTest(BGLTestFramework):
@@ -40,7 +40,7 @@ def run_test(self):
4040
self.log.info("Test that mempool.dat is compatible between versions")
4141

4242
old_node, new_node = self.nodes
43-
new_wallet = MiniWallet(new_node)
43+
new_wallet = MiniWallet(new_node, mode=MiniWalletMode.RAW_P2PK)
4444
self.generate(new_wallet, 1, sync_fun=self.no_op)
4545
self.generate(new_node, COINBASE_MATURITY, sync_fun=self.no_op)
4646
# Sync the nodes to ensure old_node has the block that contains the coinbase that new_wallet will spend.

test/functional/test_framework/address.py

+26-2
Original file line numberDiff line numberDiff line change
@@ -5,12 +5,21 @@
55
"""Encode and decode Bitcoin addresses.
66
77
- base58 P2PKH and P2SH addresses.
8-
- bech32 segwit v0 P2WPKH and P2WSH addresses."""
8+
- bech32 segwit v0 P2WPKH and P2WSH addresses.
9+
- bech32m segwit v1 P2TR addresses."""
910

1011
import enum
1112
import unittest
1213
import sha3
13-
from .script import hash256, hash160, sha256, CScript, OP_0
14+
from .script import (
15+
CScript,
16+
OP_0,
17+
OP_TRUE,
18+
hash160,
19+
hash256,
20+
sha256,
21+
taproot_construct,
22+
)
1423
from .segwit_addr import encode_segwit_address
1524
from .util import assert_equal
1625

@@ -29,6 +38,21 @@ class AddressType(enum.Enum):
2938
chars = '123456789ABCDEFGHJKLMNPQRSTUVWXYZabcdefghijkmnopqrstuvwxyz'
3039

3140

41+
def create_deterministic_address_bcrt1_p2tr_op_true():
42+
"""
43+
Generates a deterministic bech32m address (segwit v1 output) that
44+
can be spent with a witness stack of OP_TRUE and the control block
45+
with internal public key (script-path spending).
46+
47+
Returns a tuple with the generated address and the internal key.
48+
"""
49+
internal_key = (1).to_bytes(32, 'big')
50+
scriptPubKey = taproot_construct(internal_key, [(None, CScript([OP_TRUE]))]).scriptPubKey
51+
address = encode_segwit_address("rbgl", 1, scriptPubKey[2:])
52+
assert_equal(address, 'rbgl1p9yfmy5h72durp7zrhlw9lf7jpwjgvwdg0jr0lqmmjtgg83266lqsylg5sy')
53+
return (address, internal_key)
54+
55+
3256
def byte_to_base58(b, version):
3357
result = ''
3458
str = b.hex()

test/functional/test_framework/test_framework.py

+3-2
Original file line numberDiff line numberDiff line change
@@ -19,7 +19,7 @@
1919
import time
2020

2121
from typing import List
22-
from .address import ADDRESS_BCRT1_P2WSH_OP_TRUE
22+
from .address import create_deterministic_address_bcrt1_p2tr_op_true
2323
from .authproxy import JSONRPCException
2424
from . import coverage
2525
from .p2p import NetworkThread
@@ -777,7 +777,8 @@ def _initialize_chain(self):
777777
# block in the cache does not age too much (have an old tip age).
778778
# This is needed so that we are out of IBD when the test starts,
779779
# see the tip age check in IsInitialBlockDownload().
780-
gen_addresses = [k.address for k in TestNode.PRIV_KEYS][:3] + [ADDRESS_BCRT1_P2WSH_OP_TRUE]
780+
gen_addresses = [k.address for k in TestNode.PRIV_KEYS][:3] + [create_deterministic_address_bcrt1_p2tr_op_true()[0]]
781+
assert_equal(len(gen_addresses), 4)
781782
for i in range(8):
782783
self.generatetoaddress(
783784
cache_node,

test/functional/test_framework/wallet.py

+11-11
Original file line numberDiff line numberDiff line change
@@ -7,21 +7,21 @@
77
from copy import deepcopy
88
from decimal import Decimal
99
from enum import Enum
10-
from random import choice
1110
from typing import (
1211
Any,
1312
List,
1413
Optional,
1514
)
1615
from test_framework.address import (
1716
base58_to_byte,
18-
ADDRESS_BCRT1_P2WSH_OP_TRUE,
17+
create_deterministic_address_bcrt1_p2tr_op_true,
1918
key_to_p2pkh,
2019
key_to_p2sh_p2wpkh,
2120
key_to_p2wpkh,
2221
output_key_to_p2tr,
2322
)
24-
23+
from random import choice
24+
from typing import Optional
2525
from test_framework.descriptors import descsum_create
2626
from test_framework.key import (
2727
ECKey,
@@ -39,8 +39,9 @@
3939
from test_framework.script import (
4040
CScript,
4141
LegacySignatureHash,
42-
OP_TRUE,
42+
LEAF_VERSION_TAPSCRIPT,
4343
OP_NOP,
44+
OP_TRUE,
4445
SIGHASH_ALL,
4546
taproot_construct,
4647
)
@@ -56,15 +57,14 @@
5657
assert_equal,
5758
assert_greater_than_or_equal,
5859
)
59-
from enum import Enum
6060

6161
DEFAULT_FEE = Decimal("0.0001")
6262

6363
class MiniWalletMode(Enum):
6464
"""Determines the transaction type the MiniWallet is creating and spending.
6565
6666
For most purposes, the default mode ADDRESS_OP_TRUE should be sufficient;
67-
it simply uses a fixed bech32 P2WSH address whose coins are spent with a
67+
it simply uses a fixed bech32m P2TR address whose coins are spent with a
6868
witness stack of OP_TRUE, i.e. following an anyone-can-spend policy.
6969
However, if the transactions need to be modified by the user (e.g. prepending
7070
scriptSig for testing opcodes that are activated by a soft-fork), or the txs
@@ -74,7 +74,7 @@ class MiniWalletMode(Enum):
7474
| output | | tx is | can modify | needs
7575
mode | description | address | standard | scriptSig | signing
7676
----------------+-------------------+-----------+----------+------------+----------
77-
ADDRESS_OP_TRUE | anyone-can-spend | bech32 | yes | no | no
77+
ADDRESS_OP_TRUE | anyone-can-spend | bech32m | yes | no | no
7878
RAW_OP_TRUE | anyone-can-spend | - (raw) | no | yes | no
7979
RAW_P2PK | pay-to-public-key | - (raw) | yes | yes | yes
8080
"""
@@ -100,7 +100,7 @@ def __init__(self, test_node, *, mode=MiniWalletMode.ADDRESS_OP_TRUE):
100100
pub_key = self._priv_key.get_pubkey()
101101
self._scriptPubKey = key_to_p2pk_script(pub_key.get_bytes())
102102
elif mode == MiniWalletMode.ADDRESS_OP_TRUE:
103-
self._address = ADDRESS_BCRT1_P2WSH_OP_TRUE
103+
self._address, self._internal_key = create_deterministic_address_bcrt1_p2tr_op_true()
104104
self._scriptPubKey = bytes.fromhex(self._test_node.validateaddress(self._address)['scriptPubKey'])
105105

106106
def _create_utxo(self, *, txid, vout, value, height):
@@ -283,7 +283,7 @@ def create_self_transfer(self, *, fee_rate=Decimal("0.003"), fee=Decimal("0"), u
283283
"""Create and return a tx with the specified fee. If fee is 0, use fee_rate, where the resulting fee may be exact or at most one satoshi higher than needed."""
284284
utxo_to_spend = utxo_to_spend or self.get_utxo()
285285
if self._priv_key is None:
286-
vsize = Decimal(96) # anyone-can-spend
286+
vsize = Decimal(104) # anyone-can-spend
287287
else:
288288
vsize = Decimal(168) # P2PK (73 bytes scriptSig + 35 bytes scriptPubKey + 60 bytes other)
289289
send_value = utxo_to_spend["value"] - (fee or (fee_rate * vsize / 1000))
@@ -300,10 +300,10 @@ def create_self_transfer(self, *, fee_rate=Decimal("0.003"), fee=Decimal("0"), u
300300
self.sign_tx(tx)
301301
else:
302302
# anyone-can-spend
303-
tx.vin[0].scriptSig = CScript([OP_NOP] * 35) # pad to identical size
303+
tx.vin[0].scriptSig = CScript([OP_NOP] * 43) # pad to identical size
304304
else:
305305
tx.wit.vtxinwit = [CTxInWitness()]
306-
tx.wit.vtxinwit[0].scriptWitness.stack = [CScript([OP_TRUE])]
306+
tx.wit.vtxinwit[0].scriptWitness.stack = [CScript([OP_TRUE]), bytes([LEAF_VERSION_TAPSCRIPT]) + self._internal_key]
307307
tx_hex = tx.serialize().hex()
308308

309309
assert_equal(tx.get_vsize(), vsize)

0 commit comments

Comments
 (0)