@@ -27,29 +27,29 @@ def decodescript_script_sig(self):
27
27
28
28
# below are test cases for all of the standard transaction types
29
29
30
- # 1) P2PK scriptSig
30
+ self . log . info ( "- P2PK" )
31
31
# the scriptSig of a public key scriptPubKey simply pushes a signature onto the stack
32
32
rpc_result = self .nodes [0 ].decodescript (push_signature )
33
33
assert_equal (signature , rpc_result ['asm' ])
34
34
35
- # 2) P2PKH scriptSig
35
+ self . log . info ( "- P2PKH" )
36
36
rpc_result = self .nodes [0 ].decodescript (push_signature + push_public_key )
37
37
assert_equal (signature + ' ' + public_key , rpc_result ['asm' ])
38
38
39
- # 3) multisig scriptSig
39
+ self . log . info ( "- multisig" )
40
40
# this also tests the leading portion of a P2SH multisig scriptSig
41
41
# OP_0 <A sig> <B sig>
42
42
rpc_result = self .nodes [0 ].decodescript ('00' + push_signature + push_signature )
43
43
assert_equal ('0 ' + signature + ' ' + signature , rpc_result ['asm' ])
44
44
45
- # 4) P2SH scriptSig
45
+ self . log . info ( "- P2SH" )
46
46
# an empty P2SH redeemScript is valid and makes for a very simple test case.
47
47
# thus, such a spending scriptSig would just need to pass the outer redeemScript
48
48
# hash test and leave true on the top of the stack.
49
49
rpc_result = self .nodes [0 ].decodescript ('5100' )
50
50
assert_equal ('1 0' , rpc_result ['asm' ])
51
51
52
- # 5) null data scriptSig - no such thing because null data scripts can not be spent.
52
+ # null data scriptSig - no such thing because null data scripts can not be spent.
53
53
# thus, no test case for that standard transaction type is here.
54
54
55
55
def decodescript_script_pub_key (self ):
@@ -63,50 +63,58 @@ def decodescript_script_pub_key(self):
63
63
64
64
# below are test cases for all of the standard transaction types
65
65
66
- # 1) P2PK scriptPubKey
66
+ self . log . info ( "- P2PK" )
67
67
# <pubkey> OP_CHECKSIG
68
68
rpc_result = self .nodes [0 ].decodescript (push_public_key + 'ac' )
69
69
assert_equal (public_key + ' OP_CHECKSIG' , rpc_result ['asm' ])
70
+ assert_equal ('pubkey' , rpc_result ['type' ])
70
71
# P2PK is translated to P2WPKH
71
72
assert_equal ('0 ' + public_key_hash , rpc_result ['segwit' ]['asm' ])
72
73
73
- # 2) P2PKH scriptPubKey
74
+ self . log . info ( "- P2PKH" )
74
75
# OP_DUP OP_HASH160 <PubKeyHash> OP_EQUALVERIFY OP_CHECKSIG
75
76
rpc_result = self .nodes [0 ].decodescript ('76a9' + push_public_key_hash + '88ac' )
77
+ assert_equal ('pubkeyhash' , rpc_result ['type' ])
76
78
assert_equal ('OP_DUP OP_HASH160 ' + public_key_hash + ' OP_EQUALVERIFY OP_CHECKSIG' , rpc_result ['asm' ])
77
79
# P2PKH is translated to P2WPKH
80
+ assert_equal ('witness_v0_keyhash' , rpc_result ['segwit' ]['type' ])
78
81
assert_equal ('0 ' + public_key_hash , rpc_result ['segwit' ]['asm' ])
79
82
80
- # 3) multisig scriptPubKey
83
+ self . log . info ( "- multisig" )
81
84
# <m> <A pubkey> <B pubkey> <C pubkey> <n> OP_CHECKMULTISIG
82
85
# just imagine that the pub keys used below are different.
83
86
# for our purposes here it does not matter that they are the same even though it is unrealistic.
84
87
multisig_script = '52' + push_public_key + push_public_key + push_public_key + '53ae'
85
88
rpc_result = self .nodes [0 ].decodescript (multisig_script )
89
+ assert_equal ('multisig' , rpc_result ['type' ])
86
90
assert_equal ('2 ' + public_key + ' ' + public_key + ' ' + public_key + ' 3 OP_CHECKMULTISIG' , rpc_result ['asm' ])
87
91
# multisig in P2WSH
88
92
multisig_script_hash = sha256 (bytes .fromhex (multisig_script )).hex ()
93
+ assert_equal ('witness_v0_scripthash' , rpc_result ['segwit' ]['type' ])
89
94
assert_equal ('0 ' + multisig_script_hash , rpc_result ['segwit' ]['asm' ])
90
95
91
- # 4) P2SH scriptPubKey
96
+ self . log . info ( "- P2SH" )
92
97
# OP_HASH160 <Hash160(redeemScript)> OP_EQUAL.
93
98
# push_public_key_hash here should actually be the hash of a redeem script.
94
99
# but this works the same for purposes of this test.
95
100
rpc_result = self .nodes [0 ].decodescript ('a9' + push_public_key_hash + '87' )
101
+ assert_equal ('scripthash' , rpc_result ['type' ])
96
102
assert_equal ('OP_HASH160 ' + public_key_hash + ' OP_EQUAL' , rpc_result ['asm' ])
97
103
# P2SH does not work in segwit secripts. decodescript should not return a result for it.
98
104
assert 'segwit' not in rpc_result
99
105
100
- # 5) null data scriptPubKey
106
+ self . log . info ( "- null data" )
101
107
# use a signature look-alike here to make sure that we do not decode random data as a signature.
102
108
# this matters if/when signature sighash decoding comes along.
103
109
# would want to make sure that no such decoding takes place in this case.
104
110
signature_imposter = '48304502207fa7a6d1e0ee81132a269ad84e68d695483745cde8b541e3bf630749894e342a022100c1f7ab20e13e22fb95281a870f3dcf38d782e53023ee313d741ad0cfbc0c509001'
105
111
# OP_RETURN <data>
106
112
rpc_result = self .nodes [0 ].decodescript ('6a' + signature_imposter )
113
+ assert_equal ('nulldata' , rpc_result ['type' ])
107
114
assert_equal ('OP_RETURN ' + signature_imposter [2 :], rpc_result ['asm' ])
108
115
109
- # 6) a CLTV redeem script. redeem scripts are in-effect scriptPubKey scripts, so adding a test here.
116
+ self .log .info ("- CLTV redeem script" )
117
+ # redeem scripts are in-effect scriptPubKey scripts, so adding a test here.
110
118
# OP_NOP2 is also known as OP_CHECKLOCKTIMEVERIFY.
111
119
# just imagine that the pub keys used below are different.
112
120
# for our purposes here it does not matter that they are the same even though it is unrealistic.
@@ -121,55 +129,69 @@ def decodescript_script_pub_key(self):
121
129
# lock until block 500,000
122
130
cltv_script = '63' + push_public_key + 'ad670320a107b17568' + push_public_key + 'ac'
123
131
rpc_result = self .nodes [0 ].decodescript (cltv_script )
132
+ assert_equal ('nonstandard' , rpc_result ['type' ])
124
133
assert_equal ('OP_IF ' + public_key + ' OP_CHECKSIGVERIFY OP_ELSE 500000 OP_CHECKLOCKTIMEVERIFY OP_DROP OP_ENDIF ' + public_key + ' OP_CHECKSIG' , rpc_result ['asm' ])
125
134
# CLTV script in P2WSH
126
135
cltv_script_hash = sha256 (bytes .fromhex (cltv_script )).hex ()
127
136
assert_equal ('0 ' + cltv_script_hash , rpc_result ['segwit' ]['asm' ])
128
137
129
- # 7) P2PK scriptPubKey
138
+ self . log . info ( "- P2PK with uncompressed pubkey" )
130
139
# <pubkey> OP_CHECKSIG
131
140
rpc_result = self .nodes [0 ].decodescript (push_uncompressed_public_key + 'ac' )
141
+ assert_equal ('pubkey' , rpc_result ['type' ])
132
142
assert_equal (uncompressed_public_key + ' OP_CHECKSIG' , rpc_result ['asm' ])
133
143
# uncompressed pubkeys are invalid for checksigs in segwit scripts.
134
144
# decodescript should not return a P2WPKH equivalent.
135
145
assert 'segwit' not in rpc_result
136
146
137
- # 8) multisig scriptPubKey with an uncompressed pubkey
147
+ self . log . info ( "- multisig with uncompressed pubkey" )
138
148
# <m> <A pubkey> <B pubkey> <n> OP_CHECKMULTISIG
139
149
# just imagine that the pub keys used below are different.
140
150
# the purpose of this test is to check that a segwit script is not returned for bare multisig scripts
141
151
# with an uncompressed pubkey in them.
142
152
rpc_result = self .nodes [0 ].decodescript ('52' + push_public_key + push_uncompressed_public_key + '52ae' )
153
+ assert_equal ('multisig' , rpc_result ['type' ])
143
154
assert_equal ('2 ' + public_key + ' ' + uncompressed_public_key + ' 2 OP_CHECKMULTISIG' , rpc_result ['asm' ])
144
155
# uncompressed pubkeys are invalid for checksigs in segwit scripts.
145
156
# decodescript should not return a P2WPKH equivalent.
146
157
assert 'segwit' not in rpc_result
147
158
148
- # 9) P2WPKH scriptpubkey
159
+ self . log . info ( "- P2WPKH" )
149
160
# 0 <PubKeyHash>
150
161
rpc_result = self .nodes [0 ].decodescript ('00' + push_public_key_hash )
162
+ assert_equal ('witness_v0_keyhash' , rpc_result ['type' ])
151
163
assert_equal ('0 ' + public_key_hash , rpc_result ['asm' ])
152
164
# segwit scripts do not work nested into each other.
153
165
# a nested segwit script should not be returned in the results.
154
166
assert 'segwit' not in rpc_result
155
167
156
- # 10) P2WSH scriptpubkey
168
+ self . log . info ( "- P2WSH" )
157
169
# 0 <ScriptHash>
158
170
# even though this hash is of a P2PK script which is better used as bare P2WPKH, it should not matter
159
171
# for the purpose of this test.
160
172
rpc_result = self .nodes [0 ].decodescript ('0020' + p2wsh_p2pk_script_hash )
173
+ assert_equal ('witness_v0_scripthash' , rpc_result ['type' ])
161
174
assert_equal ('0 ' + p2wsh_p2pk_script_hash , rpc_result ['asm' ])
162
175
# segwit scripts do not work nested into each other.
163
176
# a nested segwit script should not be returned in the results.
164
177
assert 'segwit' not in rpc_result
165
178
179
+ self .log .info ("- P2TR" )
180
+ # 1 <x-only pubkey>
181
+ xonly_public_key = '01' * 32 # first ever P2TR output on mainnet
182
+ rpc_result = self .nodes [0 ].decodescript ('5120' + xonly_public_key )
183
+ assert_equal ('witness_v1_taproot' , rpc_result ['type' ])
184
+ assert_equal ('1 ' + xonly_public_key , rpc_result ['asm' ])
185
+ assert 'segwit' not in rpc_result
186
+
166
187
def decoderawtransaction_asm_sighashtype (self ):
167
188
"""Test decoding scripts via RPC command "decoderawtransaction".
168
189
169
190
This test is in with the "decodescript" tests because they are testing the same "asm" script decodes.
170
191
"""
171
192
172
- # this test case uses a random plain vanilla mainnet transaction with a single P2PKH input and output
193
+ self .log .info ("- various mainnet txs" )
194
+ # this test case uses a mainnet transaction that has a P2SH input and both P2PKH and P2SH outputs.
173
195
tx = '0100000001696a20784a2c70143f634e95227dbdfdf0ecd51647052e70854512235f5986ca010000008a47304402207174775824bec6c2700023309a168231ec80b82c6069282f5133e6f11cbb04460220570edc55c7c5da2ca687ebd0372d3546ebc3f810516a002350cac72dfe192dfb014104d3f898e6487787910a690410b7a917ef198905c27fb9d3b0a42da12aceae0544fc7088d239d9a48f2828a15a09e84043001f27cc80d162cb95404e1210161536ffffffff0100e1f505000000001976a914eb6c6e0cdb2d256a32d97b8df1fc75d1920d9bca88ac00000000'
174
196
rpc_result = self .nodes [0 ].decoderawtransaction (tx )
175
197
assert_equal ('304402207174775824bec6c2700023309a168231ec80b82c6069282f5133e6f11cbb04460220570edc55c7c5da2ca687ebd0372d3546ebc3f810516a002350cac72dfe192dfb[ALL] 04d3f898e6487787910a690410b7a917ef198905c27fb9d3b0a42da12aceae0544fc7088d239d9a48f2828a15a09e84043001f27cc80d162cb95404e1210161536' , rpc_result ['vin' ][0 ]['scriptSig' ]['asm' ])
@@ -185,11 +207,13 @@ def decoderawtransaction_asm_sighashtype(self):
185
207
assert_equal ('OP_HASH160 2a5edea39971049a540474c6a99edf0aa4074c58 OP_EQUAL' , rpc_result ['vout' ][1 ]['scriptPubKey' ]['asm' ])
186
208
txSave = tx_from_hex (tx )
187
209
210
+ self .log .info ("- tx not passing DER signature checks" )
188
211
# make sure that a specifically crafted op_return value will not pass all the IsDERSignature checks and then get decoded as a sighash type
189
212
tx = '01000000015ded05872fdbda629c7d3d02b194763ce3b9b1535ea884e3c8e765d42e316724020000006b48304502204c10d4064885c42638cbff3585915b322de33762598321145ba033fc796971e2022100bb153ad3baa8b757e30a2175bd32852d2e1cb9080f84d7e32fcdfd667934ef1b012103163c0ff73511ea1743fb5b98384a2ff09dd06949488028fd819f4d83f56264efffffffff0200000000000000000b6a0930060201000201000180380100000000001976a9141cabd296e753837c086da7a45a6c2fe0d49d7b7b88ac00000000'
190
213
rpc_result = self .nodes [0 ].decoderawtransaction (tx )
191
214
assert_equal ('OP_RETURN 300602010002010001' , rpc_result ['vout' ][0 ]['scriptPubKey' ]['asm' ])
192
215
216
+ self .log .info ("- tx passing DER signature checks" )
193
217
# verify that we have not altered scriptPubKey processing even of a specially crafted P2PKH pubkeyhash and P2SH redeem script hash that is made to pass the der signature checks
194
218
tx = '01000000018d1f5635abd06e2c7e2ddf58dc85b3de111e4ad6e0ab51bb0dcf5e84126d927300000000fdfe0000483045022100ae3b4e589dfc9d48cb82d41008dc5fa6a86f94d5c54f9935531924602730ab8002202f88cf464414c4ed9fa11b773c5ee944f66e9b05cc1e51d97abc22ce098937ea01483045022100b44883be035600e9328a01b66c7d8439b74db64187e76b99a68f7893b701d5380220225bf286493e4c4adcf928c40f785422572eb232f84a0b83b0dea823c3a19c75014c695221020743d44be989540d27b1b4bbbcfd17721c337cb6bc9af20eb8a32520b393532f2102c0120a1dda9e51a938d39ddd9fe0ebc45ea97e1d27a7cbd671d5431416d3dd87210213820eb3d5f509d7438c9eeecb4157b2f595105e7cd564b3cdbb9ead3da41eed53aeffffffff02611e0000000000001976a914301102070101010101010102060101010101010188acee2a02000000000017a91430110207010101010101010206010101010101018700000000'
195
219
rpc_result = self .nodes [0 ].decoderawtransaction (tx )
@@ -207,7 +231,7 @@ def decoderawtransaction_asm_sighashtype(self):
207
231
push_signature_2 = '48' + signature_2
208
232
signature_2_sighash_decoded = der_signature + '[NONE|ANYONECANPAY]'
209
233
210
- # 1) P2PK scriptSig
234
+ self . log . info ( "- P2PK scriptSig" )
211
235
txSave .vin [0 ].scriptSig = bytes .fromhex (push_signature )
212
236
rpc_result = self .nodes [0 ].decoderawtransaction (txSave .serialize ().hex ())
213
237
assert_equal (signature_sighash_decoded , rpc_result ['vin' ][0 ]['scriptSig' ]['asm' ])
@@ -217,20 +241,23 @@ def decoderawtransaction_asm_sighashtype(self):
217
241
rpc_result = self .nodes [0 ].decoderawtransaction (txSave .serialize ().hex ())
218
242
assert_equal (signature_2_sighash_decoded , rpc_result ['vin' ][0 ]['scriptSig' ]['asm' ])
219
243
220
- # 2) multisig scriptSig
244
+ self . log . info ( "- multisig scriptSig" )
221
245
txSave .vin [0 ].scriptSig = bytes .fromhex ('00' + push_signature + push_signature_2 )
222
246
rpc_result = self .nodes [0 ].decoderawtransaction (txSave .serialize ().hex ())
223
247
assert_equal ('0 ' + signature_sighash_decoded + ' ' + signature_2_sighash_decoded , rpc_result ['vin' ][0 ]['scriptSig' ]['asm' ])
224
248
225
- # 3) test a scriptSig that contains more than push operations.
249
+ self . log . info ( "- scriptSig that contains more than push operations" )
226
250
# in fact, it contains an OP_RETURN with data specially crafted to cause improper decode if the code does not catch it.
227
251
txSave .vin [0 ].scriptSig = bytes .fromhex ('6a143011020701010101010101020601010101010101' )
228
252
rpc_result = self .nodes [0 ].decoderawtransaction (txSave .serialize ().hex ())
229
253
assert_equal ('OP_RETURN 3011020701010101010101020601010101010101' , rpc_result ['vin' ][0 ]['scriptSig' ]['asm' ])
230
254
231
255
def run_test (self ):
256
+ self .log .info ("Test decoding of standard input scripts [scriptSig]" )
232
257
self .decodescript_script_sig ()
258
+ self .log .info ("Test decoding of standard output scripts [scriptPubKey]" )
233
259
self .decodescript_script_pub_key ()
260
+ self .log .info ("Test 'asm' script decoding of transactions" )
234
261
self .decoderawtransaction_asm_sighashtype ()
235
262
236
263
if __name__ == '__main__' :
0 commit comments