mirror of
https://github.com/bitcoin/bitcoin.git
synced 2025-01-19 05:45:05 +01:00
test: MiniWallet: add P2TR support and use it per default
This commit is contained in:
parent
4a2edf2bf7
commit
041abfebe4
@ -47,8 +47,8 @@ class ReplaceByFeeTest(BitcoinTestFramework):
|
||||
def run_test(self):
|
||||
self.wallet = MiniWallet(self.nodes[0])
|
||||
# the pre-mined test framework chain contains coinbase outputs to the
|
||||
# MiniWallet's default address ADDRESS_BCRT1_P2WSH_OP_TRUE in blocks
|
||||
# 76-100 (see method BitcoinTestFramework._initialize_chain())
|
||||
# MiniWallet's default address in blocks 76-100 (see method
|
||||
# BitcoinTestFramework._initialize_chain())
|
||||
self.wallet.rescan_utxos()
|
||||
|
||||
self.log.info("Running test simple doublespend...")
|
||||
|
@ -69,8 +69,8 @@ class UTXOSetHashTest(BitcoinTestFramework):
|
||||
assert_equal(finalized[::-1].hex(), node_muhash)
|
||||
|
||||
self.log.info("Test deterministic UTXO set hash results")
|
||||
assert_equal(node.gettxoutsetinfo()['hash_serialized_2'], "5b1b44097406226c0eb8e1362cd17a1f346522cf9390a8175a57a5262cb1963f")
|
||||
assert_equal(node.gettxoutsetinfo("muhash")['muhash'], "4b8803075d7151d06fad3e88b68ba726886794873fbfa841d12aefb2cc2b881b")
|
||||
assert_equal(node.gettxoutsetinfo()['hash_serialized_2'], "221f245cf4c9010eeb7f5183d342c002ae6c1c27e98aa357dccb788c21d98049")
|
||||
assert_equal(node.gettxoutsetinfo("muhash")['muhash'], "7c0890c68501f7630d36aeb3999dc924e63af084ae1bbfba11dd462144637635")
|
||||
|
||||
def run_test(self):
|
||||
self.test_muhash_implementation()
|
||||
|
@ -7,14 +7,17 @@
|
||||
NOTE: The test is designed to prevent cases when compatibility is broken accidentally.
|
||||
In case we need to break mempool compatibility we can continue to use the test by just bumping the version number.
|
||||
|
||||
The previous release v0.15.2 is required by this test, see test/README.md.
|
||||
The previous release v0.19.1 is required by this test, see test/README.md.
|
||||
"""
|
||||
|
||||
import os
|
||||
|
||||
from test_framework.blocktools import COINBASE_MATURITY
|
||||
from test_framework.test_framework import BitcoinTestFramework
|
||||
from test_framework.wallet import MiniWallet
|
||||
from test_framework.wallet import (
|
||||
MiniWallet,
|
||||
MiniWalletMode,
|
||||
)
|
||||
|
||||
|
||||
class MempoolCompatibilityTest(BitcoinTestFramework):
|
||||
@ -37,7 +40,7 @@ class MempoolCompatibilityTest(BitcoinTestFramework):
|
||||
self.log.info("Test that mempool.dat is compatible between versions")
|
||||
|
||||
old_node, new_node = self.nodes
|
||||
new_wallet = MiniWallet(new_node)
|
||||
new_wallet = MiniWallet(new_node, mode=MiniWalletMode.RAW_P2PK)
|
||||
self.generate(new_wallet, 1, sync_fun=self.no_op)
|
||||
self.generate(new_node, COINBASE_MATURITY, sync_fun=self.no_op)
|
||||
# Sync the nodes to ensure old_node has the block that contains the coinbase that new_wallet will spend.
|
||||
|
@ -5,12 +5,21 @@
|
||||
"""Encode and decode Bitcoin addresses.
|
||||
|
||||
- base58 P2PKH and P2SH addresses.
|
||||
- bech32 segwit v0 P2WPKH and P2WSH addresses."""
|
||||
- bech32 segwit v0 P2WPKH and P2WSH addresses.
|
||||
- bech32m segwit v1 P2TR addresses."""
|
||||
|
||||
import enum
|
||||
import unittest
|
||||
|
||||
from .script import hash256, hash160, sha256, CScript, OP_0
|
||||
from .script import (
|
||||
CScript,
|
||||
OP_0,
|
||||
OP_TRUE,
|
||||
hash160,
|
||||
hash256,
|
||||
sha256,
|
||||
taproot_construct,
|
||||
)
|
||||
from .segwit_addr import encode_segwit_address
|
||||
from .util import assert_equal
|
||||
|
||||
@ -29,6 +38,21 @@ class AddressType(enum.Enum):
|
||||
chars = '123456789ABCDEFGHJKLMNPQRSTUVWXYZabcdefghijkmnopqrstuvwxyz'
|
||||
|
||||
|
||||
def create_deterministic_address_bcrt1_p2tr_op_true():
|
||||
"""
|
||||
Generates a deterministic bech32m address (segwit v1 output) that
|
||||
can be spent with a witness stack of OP_TRUE and the control block
|
||||
with internal public key (script-path spending).
|
||||
|
||||
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:])
|
||||
assert_equal(address, 'bcrt1p9yfmy5h72durp7zrhlw9lf7jpwjgvwdg0jr0lqmmjtgg83266lqsekaqka')
|
||||
return (address, internal_key)
|
||||
|
||||
|
||||
def byte_to_base58(b, version):
|
||||
result = ''
|
||||
str = b.hex()
|
||||
|
@ -19,7 +19,7 @@ import tempfile
|
||||
import time
|
||||
|
||||
from typing import List
|
||||
from .address import ADDRESS_BCRT1_P2WSH_OP_TRUE
|
||||
from .address import create_deterministic_address_bcrt1_p2tr_op_true
|
||||
from .authproxy import JSONRPCException
|
||||
from . import coverage
|
||||
from .p2p import NetworkThread
|
||||
@ -777,7 +777,7 @@ class BitcoinTestFramework(metaclass=BitcoinTestMetaClass):
|
||||
# block in the cache does not age too much (have an old tip age).
|
||||
# This is needed so that we are out of IBD when the test starts,
|
||||
# see the tip age check in IsInitialBlockDownload().
|
||||
gen_addresses = [k.address for k in TestNode.PRIV_KEYS][:3] + [ADDRESS_BCRT1_P2WSH_OP_TRUE]
|
||||
gen_addresses = [k.address for k in TestNode.PRIV_KEYS][:3] + [create_deterministic_address_bcrt1_p2tr_op_true()[0]]
|
||||
assert_equal(len(gen_addresses), 4)
|
||||
for i in range(8):
|
||||
self.generatetoaddress(
|
||||
|
@ -9,7 +9,7 @@ from decimal import Decimal
|
||||
from enum import Enum
|
||||
from random import choice
|
||||
from typing import Optional
|
||||
from test_framework.address import ADDRESS_BCRT1_P2WSH_OP_TRUE
|
||||
from test_framework.address import create_deterministic_address_bcrt1_p2tr_op_true
|
||||
from test_framework.descriptors import descsum_create
|
||||
from test_framework.key import ECKey
|
||||
from test_framework.messages import (
|
||||
@ -24,8 +24,9 @@ from test_framework.messages import (
|
||||
from test_framework.script import (
|
||||
CScript,
|
||||
LegacySignatureHash,
|
||||
OP_TRUE,
|
||||
LEAF_VERSION_TAPSCRIPT,
|
||||
OP_NOP,
|
||||
OP_TRUE,
|
||||
SIGHASH_ALL,
|
||||
)
|
||||
from test_framework.script_util import (
|
||||
@ -43,7 +44,7 @@ class MiniWalletMode(Enum):
|
||||
"""Determines the transaction type the MiniWallet is creating and spending.
|
||||
|
||||
For most purposes, the default mode ADDRESS_OP_TRUE should be sufficient;
|
||||
it simply uses a fixed bech32 P2WSH address whose coins are spent with a
|
||||
it simply uses a fixed bech32m P2TR address whose coins are spent with a
|
||||
witness stack of OP_TRUE, i.e. following an anyone-can-spend policy.
|
||||
However, if the transactions need to be modified by the user (e.g. prepending
|
||||
scriptSig for testing opcodes that are activated by a soft-fork), or the txs
|
||||
@ -53,7 +54,7 @@ class MiniWalletMode(Enum):
|
||||
| output | | tx is | can modify | needs
|
||||
mode | description | address | standard | scriptSig | signing
|
||||
----------------+-------------------+-----------+----------+------------+----------
|
||||
ADDRESS_OP_TRUE | anyone-can-spend | bech32 | yes | no | no
|
||||
ADDRESS_OP_TRUE | anyone-can-spend | bech32m | yes | no | no
|
||||
RAW_OP_TRUE | anyone-can-spend | - (raw) | no | yes | no
|
||||
RAW_P2PK | pay-to-public-key | - (raw) | yes | yes | yes
|
||||
"""
|
||||
@ -79,7 +80,7 @@ class MiniWallet:
|
||||
pub_key = self._priv_key.get_pubkey()
|
||||
self._scriptPubKey = key_to_p2pk_script(pub_key.get_bytes())
|
||||
elif mode == MiniWalletMode.ADDRESS_OP_TRUE:
|
||||
self._address = ADDRESS_BCRT1_P2WSH_OP_TRUE
|
||||
self._address, self._internal_key = create_deterministic_address_bcrt1_p2tr_op_true()
|
||||
self._scriptPubKey = bytes.fromhex(self._test_node.validateaddress(self._address)['scriptPubKey'])
|
||||
|
||||
def rescan_utxos(self):
|
||||
@ -174,7 +175,7 @@ class MiniWallet:
|
||||
self._utxos = sorted(self._utxos, key=lambda k: (k['value'], -k['height']))
|
||||
utxo_to_spend = utxo_to_spend or self._utxos.pop() # Pick the largest utxo (if none provided) and hope it covers the fee
|
||||
if self._priv_key is None:
|
||||
vsize = Decimal(96) # anyone-can-spend
|
||||
vsize = Decimal(104) # anyone-can-spend
|
||||
else:
|
||||
vsize = Decimal(168) # P2PK (73 bytes scriptSig + 35 bytes scriptPubKey + 60 bytes other)
|
||||
send_value = int(COIN * (utxo_to_spend['value'] - fee_rate * (vsize / 1000)))
|
||||
@ -191,10 +192,10 @@ class MiniWallet:
|
||||
self.sign_tx(tx)
|
||||
else:
|
||||
# anyone-can-spend
|
||||
tx.vin[0].scriptSig = CScript([OP_NOP] * 35) # pad to identical size
|
||||
tx.vin[0].scriptSig = CScript([OP_NOP] * 43) # pad to identical size
|
||||
else:
|
||||
tx.wit.vtxinwit = [CTxInWitness()]
|
||||
tx.wit.vtxinwit[0].scriptWitness.stack = [CScript([OP_TRUE])]
|
||||
tx.wit.vtxinwit[0].scriptWitness.stack = [CScript([OP_TRUE]), bytes([LEAF_VERSION_TAPSCRIPT]) + self._internal_key]
|
||||
tx_hex = tx.serialize().hex()
|
||||
|
||||
tx_info = from_node.testmempoolaccept([tx_hex])[0]
|
||||
|
Loading…
Reference in New Issue
Block a user