66
77from decimal import Decimal
88from test_framework .address import ADDRESS_BCRT1_P2WSH_OP_TRUE
9+ from test_framework .key import ECKey
910from test_framework .messages import (
1011 COIN ,
1112 COutPoint ,
1617)
1718from test_framework .script import (
1819 CScript ,
20+ LegacySignatureHash ,
21+ OP_CHECKSIG ,
1922 OP_TRUE ,
2023 OP_NOP ,
24+ SIGHASH_ALL ,
2125)
2226from test_framework .util import (
2327 assert_equal ,
2731
2832
2933class MiniWallet :
30- def __init__ (self , test_node , * , raw_script = False ):
34+ def __init__ (self , test_node , * , raw_script = False , use_p2pk = False ):
3135 self ._test_node = test_node
3236 self ._utxos = []
37+ self ._priv_key = None
38+ self ._address = None
39+
3340 if raw_script :
34- self ._address = None
3541 self ._scriptPubKey = bytes (CScript ([OP_TRUE ]))
42+ elif use_p2pk :
43+ # use simple deterministic private key (k=1)
44+ self ._priv_key = ECKey ()
45+ self ._priv_key .set ((1 ).to_bytes (32 , 'big' ), True )
46+ pub_key = self ._priv_key .get_pubkey ()
47+ self ._scriptPubKey = bytes (CScript ([pub_key .get_bytes (), OP_CHECKSIG ]))
3648 else :
3749 self ._address = ADDRESS_BCRT1_P2WSH_OP_TRUE
3850 self ._scriptPubKey = hex_str_to_bytes (self ._test_node .validateaddress (self ._address )['scriptPubKey' ])
@@ -50,6 +62,13 @@ def scan_tx(self, tx):
5062 if out ['scriptPubKey' ]['hex' ] == self ._scriptPubKey .hex ():
5163 self ._utxos .append ({'txid' : tx ['txid' ], 'vout' : out ['n' ], 'value' : out ['value' ]})
5264
65+ def sign_tx (self , tx ):
66+ """Sign tx that has been created by MiniWallet in P2PK mode"""
67+ assert self ._priv_key is not None
68+ (sighash , err ) = LegacySignatureHash (CScript (self ._scriptPubKey ), tx , 0 , SIGHASH_ALL )
69+ assert err is None
70+ tx .vin [0 ].scriptSig = CScript ([self ._priv_key .sign_ecdsa (sighash ) + bytes (bytearray ([SIGHASH_ALL ]))])
71+
5372 def generate (self , num_blocks ):
5473 """Generate blocks with coinbase outputs to the internal address, and append the outputs to the internal list"""
5574 blocks = self ._test_node .generatetodescriptor (num_blocks , f'raw({ self ._scriptPubKey .hex ()} )' )
@@ -99,7 +118,12 @@ def create_self_transfer(self, *, fee_rate=Decimal("0.003"), from_node, utxo_to_
99118 tx .vout = [CTxOut (int (send_value * COIN ), self ._scriptPubKey )]
100119 if not self ._address :
101120 # raw script
102- tx .vin [0 ].scriptSig = CScript ([OP_NOP ] * 35 ) # pad to identical size
121+ if self ._priv_key is not None :
122+ # P2PK, need to sign
123+ self .sign_tx (tx )
124+ else :
125+ # anyone-can-spend
126+ tx .vin [0 ].scriptSig = CScript ([OP_NOP ] * 35 ) # pad to identical size
103127 else :
104128 tx .wit .vtxinwit = [CTxInWitness ()]
105129 tx .wit .vtxinwit [0 ].scriptWitness .stack = [CScript ([OP_TRUE ])]
@@ -108,7 +132,10 @@ def create_self_transfer(self, *, fee_rate=Decimal("0.003"), from_node, utxo_to_
108132 tx_info = from_node .testmempoolaccept ([tx_hex ])[0 ]
109133 assert_equal (mempool_valid , tx_info ['allowed' ])
110134 if mempool_valid :
111- assert_equal (tx_info ['vsize' ], vsize )
135+ # TODO: for P2PK, vsize is not constant due to varying scriptSig length,
136+ # so only check this for anyone-can-spend outputs right now
137+ if self ._priv_key is None :
138+ assert_equal (tx_info ['vsize' ], vsize )
112139 assert_equal (tx_info ['fees' ]['base' ], fee )
113140 return {'txid' : tx_info ['txid' ], 'wtxid' : tx_info ['wtxid' ], 'hex' : tx_hex , 'tx' : tx }
114141
0 commit comments