10
10
create_block ,
11
11
add_witness_commitment ,
12
12
MAX_BLOCK_SIGOPS_WEIGHT ,
13
- NORMAL_GBT_REQUEST_PARAMS ,
14
13
WITNESS_SCALE_FACTOR ,
15
14
)
16
15
from test_framework .messages import (
96
95
from test_framework .key import generate_privkey , compute_xonly_pubkey , sign_schnorr , tweak_add_privkey , ECKey
97
96
from test_framework .address import (
98
97
hash160 ,
99
- program_to_witness
98
+ program_to_witness ,
100
99
)
101
100
from collections import OrderedDict , namedtuple
102
- from enum import Enum
103
101
from io import BytesIO
104
102
import json
105
103
import hashlib
@@ -458,7 +456,7 @@ def to_script(elem):
458
456
# Each spender is a tuple of:
459
457
# - A scriptPubKey which is to be spent from (CScript)
460
458
# - A comment describing the test (string)
461
- # - Whether the spending (on itself) is expected to be standard (Enum.Standard )
459
+ # - Whether the spending (on itself) is expected to be standard (bool )
462
460
# - A tx-signing lambda returning (scriptsig, witness_stack), taking as inputs:
463
461
# - A transaction to sign (CTransaction)
464
462
# - An input position (int)
@@ -470,14 +468,9 @@ def to_script(elem):
470
468
# - Whether this test demands being placed in a txin with no corresponding txout (for testing SIGHASH_SINGLE behavior)
471
469
472
470
Spender = namedtuple ("Spender" , "script,comment,is_standard,sat_function,err_msg,sigops_weight,no_fail,need_vin_vout_mismatch" )
473
- # The full node versions that treat the tx standard.
474
- # ALL means any version
475
- # V23 means the major version 23.0 and any later version
476
- # NONE means no version
477
- Standard = Enum ('Standard' , 'ALL V23 NONE' )
478
471
479
472
480
- def make_spender (comment , * , tap = None , witv0 = False , script = None , pkh = None , p2sh = False , spk_mutate_pre_p2sh = None , failure = None , standard = Standard . ALL , err_msg = None , sigops_weight = 0 , need_vin_vout_mismatch = False , ** kwargs ):
473
+ def make_spender (comment , * , tap = None , witv0 = False , script = None , pkh = None , p2sh = False , spk_mutate_pre_p2sh = None , failure = None , standard = True , err_msg = None , sigops_weight = 0 , need_vin_vout_mismatch = False , ** kwargs ):
481
474
"""Helper for constructing Spender objects using the context signing framework.
482
475
483
476
* tap: a TaprootInfo object (see taproot_construct), for Taproot spends (cannot be combined with pkh, witv0, or script)
@@ -487,18 +480,13 @@ def make_spender(comment, *, tap=None, witv0=False, script=None, pkh=None, p2sh=
487
480
* p2sh: whether the output is P2SH wrapper (this is supported even for Taproot, where it makes the output unencumbered)
488
481
* spk_mutate_pre_psh: a callable to be applied to the script (before potentially P2SH-wrapping it)
489
482
* failure: a dict of entries to override in the context when intentionally failing to spend (if None, no_fail will be set)
490
- * standard: whether the (valid version of) spending is expected to be standard (True is mapped to Standard.ALL, False is mapped to Standard.NONE)
483
+ * standard: whether the (valid version of) spending is expected to be standard
491
484
* err_msg: a string with an expected error message for failure (or None, if not cared about)
492
485
* sigops_weight: the pre-taproot sigops weight consumed by a successful spend
493
486
* need_vin_vout_mismatch: whether this test requires being tested in a transaction input that has no corresponding
494
487
transaction output.
495
488
"""
496
489
497
- if standard == True :
498
- standard = Standard .ALL
499
- elif standard == False :
500
- standard = Standard .NONE
501
-
502
490
conf = dict ()
503
491
504
492
# Compute scriptPubKey and set useful defaults based on the inputs.
@@ -1168,24 +1156,20 @@ def predict_sigops_ratio(n, dummy_size):
1168
1156
1169
1157
return spenders
1170
1158
1171
- def spenders_taproot_inactive ():
1172
- """Spenders for testing that pre-activation Taproot rules don't apply."""
1159
+
1160
+ def spenders_taproot_nonstandard ():
1161
+ """Spenders for testing that post-activation Taproot rules may be nonstandard."""
1173
1162
1174
1163
spenders = []
1175
1164
1176
1165
sec = generate_privkey ()
1177
1166
pub , _ = compute_xonly_pubkey (sec )
1178
1167
scripts = [
1179
- ("pk" , CScript ([pub , OP_CHECKSIG ])),
1180
1168
("future_leaf" , CScript ([pub , OP_CHECKSIG ]), 0xc2 ),
1181
1169
("op_success" , CScript ([pub , OP_CHECKSIG , OP_0 , OP_IF , CScriptOp (0x50 ), OP_ENDIF ])),
1182
1170
]
1183
1171
tap = taproot_construct (pub , scripts )
1184
1172
1185
- # Test that valid spending is standard.
1186
- add_spender (spenders , "inactive/keypath_valid" , key = sec , tap = tap , standard = Standard .V23 )
1187
- add_spender (spenders , "inactive/scriptpath_valid" , key = sec , tap = tap , leaf = "pk" , standard = Standard .V23 , inputs = [getter ("sign" )])
1188
-
1189
1173
# Test that features like annex, leaf versions, or OP_SUCCESS are valid but non-standard
1190
1174
add_spender (spenders , "inactive/scriptpath_valid_unkleaf" , key = sec , tap = tap , leaf = "future_leaf" , standard = False , inputs = [getter ("sign" )])
1191
1175
add_spender (spenders , "inactive/scriptpath_invalid_unkleaf" , key = sec , tap = tap , leaf = "future_leaf" , standard = False , inputs = [getter ("sign" )], sighash = bitflipper (default_sighash ))
@@ -1214,7 +1198,7 @@ def dump_json_test(tx, input_utxos, idx, success, failure):
1214
1198
1215
1199
# The "final" field indicates that a spend should be always valid, even with more validation flags enabled
1216
1200
# than the listed ones. Use standardness as a proxy for this (which gives a conservative underestimate).
1217
- if spender .is_standard == Standard . ALL :
1201
+ if spender .is_standard :
1218
1202
fields .append (("final" , True ))
1219
1203
1220
1204
def dump_witness (wit ):
@@ -1241,31 +1225,14 @@ class TaprootTest(BitcoinTestFramework):
1241
1225
def add_options (self , parser ):
1242
1226
parser .add_argument ("--dumptests" , dest = "dump_tests" , default = False , action = "store_true" ,
1243
1227
help = "Dump generated test cases to directory set by TEST_DUMP_DIR environment variable" )
1244
- parser .add_argument ("--previous_release" , dest = "previous_release" , default = False , action = "store_true" ,
1245
- help = "Use a previous release as taproot-inactive node" )
1246
1228
1247
1229
def skip_test_if_missing_module (self ):
1248
1230
self .skip_if_no_wallet ()
1249
- if self .options .previous_release :
1250
- self .skip_if_no_previous_releases ()
1251
1231
1252
1232
def set_test_params (self ):
1253
- self .num_nodes = 2
1233
+ self .num_nodes = 1
1254
1234
self .setup_clean_chain = True
1255
- # Node 0 has Taproot inactive, Node 1 active.
1256
- self .extra_args = [["-par=1" ], ["-par=1" ]]
1257
- if self .options .previous_release :
1258
- self .wallet_names = [None , self .default_wallet_name ]
1259
- else :
1260
- self .extra_args [0 ].append ("-vbparams=taproot:1:1" )
1261
-
1262
- def setup_nodes (self ):
1263
- self .add_nodes (self .num_nodes , self .extra_args , versions = [
1264
- 200100 if self .options .previous_release else None ,
1265
- None ,
1266
- ])
1267
- self .start_nodes ()
1268
- self .import_deterministic_coinbase_privkeys ()
1235
+ self .extra_args = [["-par=1" ]]
1269
1236
1270
1237
def block_submit (self , node , txs , msg , err_msg , cb_pubkey = None , fees = 0 , sigops_weight = 0 , witness = False , accept = False ):
1271
1238
@@ -1479,11 +1446,10 @@ def test_spenders(self, node, spenders, input_counts):
1479
1446
for i in range (len (input_utxos )):
1480
1447
tx .vin [i ].scriptSig = input_data [i ][i != fail_input ][0 ]
1481
1448
tx .wit .vtxinwit [i ].scriptWitness .stack = input_data [i ][i != fail_input ][1 ]
1482
- taproot_spend_policy = Standard .V23 if node .version is None else Standard .ALL
1483
1449
# Submit to mempool to check standardness
1484
1450
is_standard_tx = (
1485
1451
fail_input is None # Must be valid to be standard
1486
- and (all (utxo .spender .is_standard == Standard . ALL or utxo . spender . is_standard == taproot_spend_policy for utxo in input_utxos )) # All inputs must be standard
1452
+ and (all (utxo .spender .is_standard for utxo in input_utxos )) # All inputs must be standard
1487
1453
and tx .nVersion >= 1 # The tx version must be standard
1488
1454
and tx .nVersion <= 2 )
1489
1455
tx .rehash ()
@@ -1510,7 +1476,7 @@ def gen_test_vectors(self):
1510
1476
self .log .info ("Unit test scenario..." )
1511
1477
1512
1478
# Deterministically mine coins to OP_TRUE in block 1
1513
- assert self .nodes [1 ].getblockcount () == 0
1479
+ assert_equal ( self .nodes [0 ].getblockcount (), 0 )
1514
1480
coinbase = CTransaction ()
1515
1481
coinbase .nVersion = 1
1516
1482
coinbase .vin = [CTxIn (COutPoint (0 , 0xffffffff ), CScript ([OP_1 , OP_1 ]), SEQUENCE_FINAL )]
@@ -1519,12 +1485,12 @@ def gen_test_vectors(self):
1519
1485
coinbase .rehash ()
1520
1486
assert coinbase .hash == "f60c73405d499a956d3162e3483c395526ef78286458a4cb17b125aa92e49b20"
1521
1487
# Mine it
1522
- block = create_block (hashprev = int (self .nodes [1 ].getbestblockhash (), 16 ), coinbase = coinbase )
1488
+ block = create_block (hashprev = int (self .nodes [0 ].getbestblockhash (), 16 ), coinbase = coinbase )
1523
1489
block .rehash ()
1524
1490
block .solve ()
1525
- self .nodes [1 ].submitblock (block .serialize ().hex ())
1526
- assert self .nodes [1 ].getblockcount () == 1
1527
- self .generate (self .nodes [1 ], COINBASE_MATURITY )
1491
+ self .nodes [0 ].submitblock (block .serialize ().hex ())
1492
+ assert_equal ( self .nodes [0 ].getblockcount (), 1 )
1493
+ self .generate (self .nodes [0 ], COINBASE_MATURITY )
1528
1494
1529
1495
SEED = 317
1530
1496
VALID_LEAF_VERS = list (range (0xc0 , 0x100 , 2 )) + [0x66 , 0x7e , 0x80 , 0x84 , 0x96 , 0x98 , 0xba , 0xbc , 0xbe ]
@@ -1613,8 +1579,8 @@ def gen_test_vectors(self):
1613
1579
spend_info [spk ]['prevout' ] = COutPoint (tx .sha256 , i & 1 )
1614
1580
spend_info [spk ]['utxo' ] = CTxOut (val , spk )
1615
1581
# Mine those transactions
1616
- self .init_blockinfo (self .nodes [1 ])
1617
- self .block_submit (self .nodes [1 ], txn , "Crediting txn" , None , sigops_weight = 10 , accept = True )
1582
+ self .init_blockinfo (self .nodes [0 ])
1583
+ self .block_submit (self .nodes [0 ], txn , "Crediting txn" , None , sigops_weight = 10 , accept = True )
1618
1584
1619
1585
# scriptPubKey computation
1620
1586
tests = {"version" : 1 }
@@ -1726,53 +1692,21 @@ def pr(node):
1726
1692
keypath_tests .append (tx_test )
1727
1693
assert_equal (hashlib .sha256 (tx .serialize ()).hexdigest (), "24bab662cb55a7f3bae29b559f651674c62bcc1cd442d44715c0133939107b38" )
1728
1694
# Mine the spending transaction
1729
- self .block_submit (self .nodes [1 ], [tx ], "Spending txn" , None , sigops_weight = 10000 , accept = True , witness = True )
1695
+ self .block_submit (self .nodes [0 ], [tx ], "Spending txn" , None , sigops_weight = 10000 , accept = True , witness = True )
1730
1696
1731
1697
if GEN_TEST_VECTORS :
1732
1698
print (json .dumps (tests , indent = 4 , sort_keys = False ))
1733
1699
1734
-
1735
1700
def run_test (self ):
1736
1701
self .gen_test_vectors ()
1737
1702
1738
- # Post-taproot activation tests go first (pre-taproot tests' blocks are invalid post-taproot).
1739
1703
self .log .info ("Post-activation tests..." )
1740
- self .test_spenders (self .nodes [1 ], spenders_taproot_active (), input_counts = [1 , 2 , 2 , 2 , 2 , 3 ])
1741
-
1742
- # Re-connect nodes in case they have been disconnected
1743
- self .disconnect_nodes (0 , 1 )
1744
- self .connect_nodes (0 , 1 )
1745
-
1746
- # Transfer value of the largest 500 coins to pre-taproot node.
1747
- addr = self .nodes [0 ].getnewaddress ()
1748
-
1749
- unsp = self .nodes [1 ].listunspent ()
1750
- unsp = sorted (unsp , key = lambda i : i ['amount' ], reverse = True )
1751
- unsp = unsp [:500 ]
1752
-
1753
- rawtx = self .nodes [1 ].createrawtransaction (
1754
- inputs = [{
1755
- 'txid' : i ['txid' ],
1756
- 'vout' : i ['vout' ]
1757
- } for i in unsp ],
1758
- outputs = {addr : sum (i ['amount' ] for i in unsp )}
1759
- )
1760
- rawtx = self .nodes [1 ].signrawtransactionwithwallet (rawtx )['hex' ]
1761
-
1762
- # Mine a block with the transaction
1763
- block = create_block (tmpl = self .nodes [1 ].getblocktemplate (NORMAL_GBT_REQUEST_PARAMS ), txlist = [rawtx ])
1764
- add_witness_commitment (block )
1765
- block .solve ()
1766
- assert_equal (None , self .nodes [1 ].submitblock (block .serialize ().hex ()))
1767
- self .sync_blocks ()
1768
-
1769
- # Pre-taproot activation tests.
1770
- self .log .info ("Pre-activation tests..." )
1704
+ self .test_spenders (self .nodes [0 ], spenders_taproot_active (), input_counts = [1 , 2 , 2 , 2 , 2 , 3 ])
1771
1705
# Run each test twice; once in isolation, and once combined with others. Testing in isolation
1772
1706
# means that the standardness is verified in every test (as combined transactions are only standard
1773
1707
# when all their inputs are standard).
1774
- self .test_spenders (self .nodes [0 ], spenders_taproot_inactive (), input_counts = [1 ])
1775
- self .test_spenders (self .nodes [0 ], spenders_taproot_inactive (), input_counts = [2 , 3 ])
1708
+ self .test_spenders (self .nodes [0 ], spenders_taproot_nonstandard (), input_counts = [1 ])
1709
+ self .test_spenders (self .nodes [0 ], spenders_taproot_nonstandard (), input_counts = [2 , 3 ])
1776
1710
1777
1711
1778
1712
if __name__ == '__main__' :
0 commit comments