Dash Core  0.12.2.1
P2P Digital Currency
decodescript.py
Go to the documentation of this file.
1 #!/usr/bin/env python2
2 # Copyright (c) 2015 The Bitcoin Core developers
3 # Distributed under the MIT software license, see the accompanying
4 # file COPYING or http://www.opensource.org/licenses/mit-license.php.
5 
6 from test_framework.test_framework import BitcoinTestFramework
7 from test_framework.util import *
8 from test_framework.mininode import *
9 from io import BytesIO
10 
12  """Tests decoding scripts via RPC command "decodescript"."""
13 
14  def setup_chain(self):
15  print('Initializing test directory ' + self.options.tmpdir)
16  initialize_chain_clean(self.options.tmpdir, 1)
17 
18  def setup_network(self, split=False):
19  self.nodes = start_nodes(1, self.options.tmpdir)
20  self.is_network_split = False
21 
23  signature = '304502207fa7a6d1e0ee81132a269ad84e68d695483745cde8b541e3bf630749894e342a022100c1f7ab20e13e22fb95281a870f3dcf38d782e53023ee313d741ad0cfbc0c509001'
24  push_signature = '48' + signature
25  public_key = '03b0da749730dc9b4b1f4a14d6902877a92541f5368778853d9c4a0cb7802dcfb2'
26  push_public_key = '21' + public_key
27 
28  # below are test cases for all of the standard transaction types
29 
30  # 1) P2PK scriptSig
31  # the scriptSig of a public key scriptPubKey simply pushes a signature onto the stack
32  rpc_result = self.nodes[0].decodescript(push_signature)
33  assert_equal(signature, rpc_result['asm'])
34 
35  # 2) P2PKH scriptSig
36  rpc_result = self.nodes[0].decodescript(push_signature + push_public_key)
37  assert_equal(signature + ' ' + public_key, rpc_result['asm'])
38 
39  # 3) multisig scriptSig
40  # this also tests the leading portion of a P2SH multisig scriptSig
41  # OP_0 <A sig> <B sig>
42  rpc_result = self.nodes[0].decodescript('00' + push_signature + push_signature)
43  assert_equal('0 ' + signature + ' ' + signature, rpc_result['asm'])
44 
45  # 4) P2SH scriptSig
46  # an empty P2SH redeemScript is valid and makes for a very simple test case.
47  # thus, such a spending scriptSig would just need to pass the outer redeemScript
48  # hash test and leave true on the top of the stack.
49  rpc_result = self.nodes[0].decodescript('5100')
50  assert_equal('1 0', rpc_result['asm'])
51 
52  # 5) null data scriptSig - no such thing because null data scripts can not be spent.
53  # thus, no test case for that standard transaction type is here.
54 
56  public_key = '03b0da749730dc9b4b1f4a14d6902877a92541f5368778853d9c4a0cb7802dcfb2'
57  push_public_key = '21' + public_key
58  public_key_hash = '11695b6cd891484c2d49ec5aa738ec2b2f897777'
59  push_public_key_hash = '14' + public_key_hash
60 
61  # below are test cases for all of the standard transaction types
62 
63  # 1) P2PK scriptPubKey
64  # <pubkey> OP_CHECKSIG
65  rpc_result = self.nodes[0].decodescript(push_public_key + 'ac')
66  assert_equal(public_key + ' OP_CHECKSIG', rpc_result['asm'])
67 
68  # 2) P2PKH scriptPubKey
69  # OP_DUP OP_HASH160 <PubKeyHash> OP_EQUALVERIFY OP_CHECKSIG
70  rpc_result = self.nodes[0].decodescript('76a9' + push_public_key_hash + '88ac')
71  assert_equal('OP_DUP OP_HASH160 ' + public_key_hash + ' OP_EQUALVERIFY OP_CHECKSIG', rpc_result['asm'])
72 
73  # 3) multisig scriptPubKey
74  # <m> <A pubkey> <B pubkey> <C pubkey> <n> OP_CHECKMULTISIG
75  # just imagine that the pub keys used below are different.
76  # for our purposes here it does not matter that they are the same even though it is unrealistic.
77  rpc_result = self.nodes[0].decodescript('52' + push_public_key + push_public_key + push_public_key + '53ae')
78  assert_equal('2 ' + public_key + ' ' + public_key + ' ' + public_key + ' 3 OP_CHECKMULTISIG', rpc_result['asm'])
79 
80  # 4) P2SH scriptPubKey
81  # OP_HASH160 <Hash160(redeemScript)> OP_EQUAL.
82  # push_public_key_hash here should actually be the hash of a redeem script.
83  # but this works the same for purposes of this test.
84  rpc_result = self.nodes[0].decodescript('a9' + push_public_key_hash + '87')
85  assert_equal('OP_HASH160 ' + public_key_hash + ' OP_EQUAL', rpc_result['asm'])
86 
87  # 5) null data scriptPubKey
88  # use a signature look-alike here to make sure that we do not decode random data as a signature.
89  # this matters if/when signature sighash decoding comes along.
90  # would want to make sure that no such decoding takes place in this case.
91  signature_imposter = '48304502207fa7a6d1e0ee81132a269ad84e68d695483745cde8b541e3bf630749894e342a022100c1f7ab20e13e22fb95281a870f3dcf38d782e53023ee313d741ad0cfbc0c509001'
92  # OP_RETURN <data>
93  rpc_result = self.nodes[0].decodescript('6a' + signature_imposter)
94  assert_equal('OP_RETURN ' + signature_imposter[2:], rpc_result['asm'])
95 
96  # 6) a CLTV redeem script. redeem scripts are in-effect scriptPubKey scripts, so adding a test here.
97  # OP_NOP2 is also known as OP_CHECKLOCKTIMEVERIFY.
98  # just imagine that the pub keys used below are different.
99  # for our purposes here it does not matter that they are the same even though it is unrealistic.
100  #
101  # OP_IF
102  # <receiver-pubkey> OP_CHECKSIGVERIFY
103  # OP_ELSE
104  # <lock-until> OP_CHECKLOCKTIMEVERIFY OP_DROP
105  # OP_ENDIF
106  # <sender-pubkey> OP_CHECKSIG
107  #
108  # lock until block 500,000
109  rpc_result = self.nodes[0].decodescript('63' + push_public_key + 'ad670320a107b17568' + push_public_key + 'ac')
110  assert_equal('OP_IF ' + public_key + ' OP_CHECKSIGVERIFY OP_ELSE 500000 OP_CHECKLOCKTIMEVERIFY OP_DROP OP_ENDIF ' + public_key + ' OP_CHECKSIG', rpc_result['asm'])
111 
113  """Tests decoding scripts via RPC command "decoderawtransaction".
114 
115  This test is in with the "decodescript" tests because they are testing the same "asm" script decodes.
116  """
117 
118  # this test case uses a random plain vanilla mainnet transaction with a single P2PKH input and output
119  tx = '0100000001696a20784a2c70143f634e95227dbdfdf0ecd51647052e70854512235f5986ca010000008a47304402207174775824bec6c2700023309a168231ec80b82c6069282f5133e6f11cbb04460220570edc55c7c5da2ca687ebd0372d3546ebc3f810516a002350cac72dfe192dfb014104d3f898e6487787910a690410b7a917ef198905c27fb9d3b0a42da12aceae0544fc7088d239d9a48f2828a15a09e84043001f27cc80d162cb95404e1210161536ffffffff0100e1f505000000001976a914eb6c6e0cdb2d256a32d97b8df1fc75d1920d9bca88ac00000000'
120  rpc_result = self.nodes[0].decoderawtransaction(tx)
121  assert_equal('304402207174775824bec6c2700023309a168231ec80b82c6069282f5133e6f11cbb04460220570edc55c7c5da2ca687ebd0372d3546ebc3f810516a002350cac72dfe192dfb[ALL] 04d3f898e6487787910a690410b7a917ef198905c27fb9d3b0a42da12aceae0544fc7088d239d9a48f2828a15a09e84043001f27cc80d162cb95404e1210161536', rpc_result['vin'][0]['scriptSig']['asm'])
122 
123  # this test case uses a mainnet transaction that has a P2SH input and both P2PKH and P2SH outputs.
124  # it's from James D'Angelo's awesome introductory videos about multisig: https://www.youtube.com/watch?v=zIbUSaZBJgU and https://www.youtube.com/watch?v=OSA1pwlaypc
125  # verify that we have not altered scriptPubKey decoding.
126  tx = '01000000018d1f5635abd06e2c7e2ddf58dc85b3de111e4ad6e0ab51bb0dcf5e84126d927300000000fdfe0000483045022100ae3b4e589dfc9d48cb82d41008dc5fa6a86f94d5c54f9935531924602730ab8002202f88cf464414c4ed9fa11b773c5ee944f66e9b05cc1e51d97abc22ce098937ea01483045022100b44883be035600e9328a01b66c7d8439b74db64187e76b99a68f7893b701d5380220225bf286493e4c4adcf928c40f785422572eb232f84a0b83b0dea823c3a19c75014c695221020743d44be989540d27b1b4bbbcfd17721c337cb6bc9af20eb8a32520b393532f2102c0120a1dda9e51a938d39ddd9fe0ebc45ea97e1d27a7cbd671d5431416d3dd87210213820eb3d5f509d7438c9eeecb4157b2f595105e7cd564b3cdbb9ead3da41eed53aeffffffff02611e0000000000001976a914dc863734a218bfe83ef770ee9d41a27f824a6e5688acee2a02000000000017a9142a5edea39971049a540474c6a99edf0aa4074c588700000000'
127  rpc_result = self.nodes[0].decoderawtransaction(tx)
128  assert_equal('8e3730608c3b0bb5df54f09076e196bc292a8e39a78e73b44b6ba08c78f5cbb0', rpc_result['txid'])
129  assert_equal('0 3045022100ae3b4e589dfc9d48cb82d41008dc5fa6a86f94d5c54f9935531924602730ab8002202f88cf464414c4ed9fa11b773c5ee944f66e9b05cc1e51d97abc22ce098937ea[ALL] 3045022100b44883be035600e9328a01b66c7d8439b74db64187e76b99a68f7893b701d5380220225bf286493e4c4adcf928c40f785422572eb232f84a0b83b0dea823c3a19c75[ALL] 5221020743d44be989540d27b1b4bbbcfd17721c337cb6bc9af20eb8a32520b393532f2102c0120a1dda9e51a938d39ddd9fe0ebc45ea97e1d27a7cbd671d5431416d3dd87210213820eb3d5f509d7438c9eeecb4157b2f595105e7cd564b3cdbb9ead3da41eed53ae', rpc_result['vin'][0]['scriptSig']['asm'])
130  assert_equal('OP_DUP OP_HASH160 dc863734a218bfe83ef770ee9d41a27f824a6e56 OP_EQUALVERIFY OP_CHECKSIG', rpc_result['vout'][0]['scriptPubKey']['asm'])
131  assert_equal('OP_HASH160 2a5edea39971049a540474c6a99edf0aa4074c58 OP_EQUAL', rpc_result['vout'][1]['scriptPubKey']['asm'])
132  txSave = CTransaction()
133  txSave.deserialize(BytesIO(hex_str_to_bytes(tx)))
134 
135  # make sure that a specifically crafted op_return value will not pass all the IsDERSignature checks and then get decoded as a sighash type
136  tx = '01000000015ded05872fdbda629c7d3d02b194763ce3b9b1535ea884e3c8e765d42e316724020000006b48304502204c10d4064885c42638cbff3585915b322de33762598321145ba033fc796971e2022100bb153ad3baa8b757e30a2175bd32852d2e1cb9080f84d7e32fcdfd667934ef1b012103163c0ff73511ea1743fb5b98384a2ff09dd06949488028fd819f4d83f56264efffffffff0200000000000000000b6a0930060201000201000180380100000000001976a9141cabd296e753837c086da7a45a6c2fe0d49d7b7b88ac00000000'
137  rpc_result = self.nodes[0].decoderawtransaction(tx)
138  assert_equal('OP_RETURN 300602010002010001', rpc_result['vout'][0]['scriptPubKey']['asm'])
139 
140  # 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
141  tx = '01000000018d1f5635abd06e2c7e2ddf58dc85b3de111e4ad6e0ab51bb0dcf5e84126d927300000000fdfe0000483045022100ae3b4e589dfc9d48cb82d41008dc5fa6a86f94d5c54f9935531924602730ab8002202f88cf464414c4ed9fa11b773c5ee944f66e9b05cc1e51d97abc22ce098937ea01483045022100b44883be035600e9328a01b66c7d8439b74db64187e76b99a68f7893b701d5380220225bf286493e4c4adcf928c40f785422572eb232f84a0b83b0dea823c3a19c75014c695221020743d44be989540d27b1b4bbbcfd17721c337cb6bc9af20eb8a32520b393532f2102c0120a1dda9e51a938d39ddd9fe0ebc45ea97e1d27a7cbd671d5431416d3dd87210213820eb3d5f509d7438c9eeecb4157b2f595105e7cd564b3cdbb9ead3da41eed53aeffffffff02611e0000000000001976a914301102070101010101010102060101010101010188acee2a02000000000017a91430110207010101010101010206010101010101018700000000'
142  rpc_result = self.nodes[0].decoderawtransaction(tx)
143  assert_equal('OP_DUP OP_HASH160 3011020701010101010101020601010101010101 OP_EQUALVERIFY OP_CHECKSIG', rpc_result['vout'][0]['scriptPubKey']['asm'])
144  assert_equal('OP_HASH160 3011020701010101010101020601010101010101 OP_EQUAL', rpc_result['vout'][1]['scriptPubKey']['asm'])
145 
146  # some more full transaction tests of varying specific scriptSigs. used instead of
147  # tests in decodescript_script_sig because the decodescript RPC is specifically
148  # for working on scriptPubKeys (argh!).
149  push_signature = bytes_to_hex_str(txSave.vin[0].scriptSig)[2:(0x48*2+4)]
150  signature = push_signature[2:]
151  der_signature = signature[:-2]
152  signature_sighash_decoded = der_signature + '[ALL]'
153  signature_2 = der_signature + '82'
154  push_signature_2 = '48' + signature_2
155  signature_2_sighash_decoded = der_signature + '[NONE|ANYONECANPAY]'
156 
157  # 1) P2PK scriptSig
158  txSave.vin[0].scriptSig = hex_str_to_bytes(push_signature)
159  rpc_result = self.nodes[0].decoderawtransaction(bytes_to_hex_str(txSave.serialize()))
160  assert_equal(signature_sighash_decoded, rpc_result['vin'][0]['scriptSig']['asm'])
161 
162  # make sure that the sighash decodes come out correctly for a more complex / lesser used case.
163  txSave.vin[0].scriptSig = hex_str_to_bytes(push_signature_2)
164  rpc_result = self.nodes[0].decoderawtransaction(bytes_to_hex_str(txSave.serialize()))
165  assert_equal(signature_2_sighash_decoded, rpc_result['vin'][0]['scriptSig']['asm'])
166 
167  # 2) multisig scriptSig
168  txSave.vin[0].scriptSig = hex_str_to_bytes('00' + push_signature + push_signature_2)
169  rpc_result = self.nodes[0].decoderawtransaction(bytes_to_hex_str(txSave.serialize()))
170  assert_equal('0 ' + signature_sighash_decoded + ' ' + signature_2_sighash_decoded, rpc_result['vin'][0]['scriptSig']['asm'])
171 
172  # 3) test a scriptSig that contains more than push operations.
173  # in fact, it contains an OP_RETURN with data specially crafted to cause improper decode if the code does not catch it.
174  txSave.vin[0].scriptSig = hex_str_to_bytes('6a143011020701010101010101020601010101010101')
175  rpc_result = self.nodes[0].decoderawtransaction(bytes_to_hex_str(txSave.serialize()))
176  assert_equal('OP_RETURN 3011020701010101010101020601010101010101', rpc_result['vin'][0]['scriptSig']['asm'])
177 
178  def run_test(self):
182 
183 if __name__ == '__main__':
def hex_str_to_bytes(hex_str)
Definition: util.py:111
def start_nodes(num_nodes, dirname, extra_args=None, rpchost=None, binary=None)
Definition: util.py:305
def setup_network(self, split=False)
Definition: decodescript.py:18
def initialize_chain_clean(test_dir, num_nodes)
Definition: util.py:252
UniValue decoderawtransaction(const UniValue &params, bool fHelp)
def decoderawtransaction_asm_sighashtype(self)
def assert_equal(thing1, thing2)
Definition: util.py:461
def bytes_to_hex_str(byte_str)
Definition: util.py:108