Merge bitcoin/bitcoin#25289: test: implement 'bech32m' mode for getnewdestination() helper

dcf36fe8e3 test: implement 'bech32m' mode for `getnewdestination()` helper (Sebastian Falbesoner)
1999dcfa40 test: add helpers for creating P2TR scripts/addresses from output key (Sebastian Falbesoner)

Pull request description:

  This PR adds the missing 'bech32m' mode for the `getnewdestination()` helper and sets it as default, i.e. the function returns a tuple (output x-only-pubkey, scriptPubKey, taproot address) now if not specified otherwise. In a preparation commit, the helpers `output_key_to_p2tr{_script}` are introduced. Note that in contrast to all other common script output types, there are usually _two_ keys involved in creating a taproot output (internal key and output key), hence the prefix `output_` is used to clarify that the  output key is expected and the helpers don't do any key tweaking.

  Thanks to michaelfolkson (for pointing out this TODO that I forgot about) and sipa (for patiently explaining basic things about BIP341).

ACKs for top commit:
  michaelfolkson:
    ACK dcf36fe8e3
  w0xlt:
    reACK dcf36fe8e3

Tree-SHA512: 5bb8d5fd96c63092ede10c3f022ffb2e13c14e333c4aa73348d95deb70cbf0a74745218dc4a7c419eb846793dd69e8217a7b4332a13ae2b2758e100b51fb1a9f
This commit is contained in:
laanwj
2022-06-17 22:44:32 +02:00
5 changed files with 27 additions and 16 deletions

View File

@ -47,8 +47,7 @@ def create_deterministic_address_bcrt1_p2tr_op_true():
Returns a tuple with the generated address and the internal key.
"""
internal_key = (1).to_bytes(32, 'big')
scriptPubKey = taproot_construct(internal_key, [(None, CScript([OP_TRUE]))]).scriptPubKey
address = encode_segwit_address("bcrt", 1, scriptPubKey[2:])
address = output_key_to_p2tr(taproot_construct(internal_key, [(None, CScript([OP_TRUE]))]).output_pubkey)
assert_equal(address, 'bcrt1p9yfmy5h72durp7zrhlw9lf7jpwjgvwdg0jr0lqmmjtgg83266lqsekaqka')
return (address, internal_key)
@ -141,6 +140,10 @@ def script_to_p2sh_p2wsh(script, main=False):
p2shscript = CScript([OP_0, sha256(script)])
return script_to_p2sh(p2shscript, main)
def output_key_to_p2tr(key, main=False):
assert len(key) == 32
return program_to_witness(1, key, main)
def check_key(key):
if (type(key) is str):
key = bytes.fromhex(key) # Assuming this is hex string

View File

@ -105,6 +105,11 @@ def script_to_p2sh_p2wsh_script(script):
return script_to_p2sh_script(p2shscript)
def output_key_to_p2tr_script(key):
assert len(key) == 32
return program_to_witness_script(1, key)
def check_key(key):
if isinstance(key, str):
key = bytes.fromhex(key) # Assuming this is hex string

View File

@ -19,9 +19,13 @@ from test_framework.address import (
key_to_p2pkh,
key_to_p2sh_p2wpkh,
key_to_p2wpkh,
output_key_to_p2tr,
)
from test_framework.descriptors import descsum_create
from test_framework.key import ECKey
from test_framework.key import (
ECKey,
compute_xonly_pubkey,
)
from test_framework.messages import (
COIN,
COutPoint,
@ -38,6 +42,7 @@ from test_framework.script import (
OP_NOP,
OP_TRUE,
SIGHASH_ALL,
taproot_construct,
)
from test_framework.script_util import (
key_to_p2pk_script,
@ -286,10 +291,10 @@ class MiniWallet:
return txid
def getnewdestination(address_type='bech32'):
def getnewdestination(address_type='bech32m'):
"""Generate a random destination of the specified type and return the
corresponding public key, scriptPubKey and address. Supported types are
'legacy', 'p2sh-segwit' and 'bech32'. Can be used when a random
'legacy', 'p2sh-segwit', 'bech32' and 'bech32m'. Can be used when a random
destination is needed, but no compiled wallet is available (e.g. as
replacement to the getnewaddress/getaddressinfo RPCs)."""
key = ECKey()
@ -304,7 +309,11 @@ def getnewdestination(address_type='bech32'):
elif address_type == 'bech32':
scriptpubkey = key_to_p2wpkh_script(pubkey)
address = key_to_p2wpkh(pubkey)
# TODO: also support bech32m (need to generate x-only-pubkey)
elif address_type == 'bech32m':
tap = taproot_construct(compute_xonly_pubkey(key.get_bytes())[0])
pubkey = tap.output_pubkey
scriptpubkey = tap.scriptPubKey
address = output_key_to_p2tr(pubkey)
else:
assert False
return pubkey, scriptpubkey, address