diff --git a/bitcoinlib/scripts.py b/bitcoinlib/scripts.py index 0a9318aa..4d6415b7 100644 --- a/bitcoinlib/scripts.py +++ b/bitcoinlib/scripts.py @@ -53,6 +53,8 @@ def _get_script_types(blueprint, is_locking=None): bp[-1] = 'key' elif item == 'signature' and len(bp) and bp[-1] == 'signature': bp[-1] = 'signature' + elif isinstance(item, list): + bp.append('redeemscript') else: bp.append(item) @@ -130,6 +132,8 @@ def get_data_type(data): return 'key_object' elif isinstance(data, Signature): return 'signature_object' + elif isinstance(data, list): + return 'redeemscript' elif data.startswith(b'\x30') and 69 <= len(data) <= 74: return 'signature' elif ((data.startswith(b'\x02') or data.startswith(b'\x03')) and len(data) == 33) or \ @@ -365,8 +369,8 @@ def parse_bytesio(cls, script, message=None, env_data=None, data_length=0, is_lo else: s2 = Script.parse_bytes(data, _level=_level+1, strict=strict) commands.pop() - commands += s2.commands - blueprint += s2.blueprint + commands += [s2.commands] + blueprint += [s2.blueprint] keys += s2.keys signatures += s2.signatures redeemscript = s2.redeemscript @@ -399,6 +403,10 @@ def parse_bytesio(cls, script, message=None, env_data=None, data_length=0, is_lo chb = script.read(1) ch = int.from_bytes(chb, 'big') + if len(commands) == 1 and isinstance(commands[0], list): + commands = commands[0] + if len(blueprint) == 1 and isinstance(blueprint[0], list): + blueprint = blueprint[0] s = cls(commands, message, keys=keys, signatures=signatures, blueprint=blueprint, env_data=env_data, hash_type=hash_type) script.seek(0) @@ -639,6 +647,8 @@ def view(self, blueprint=False, as_list=False, op_code_numbers=False, show_1_byt s_items.append(command) else: s_items.append(opcodenames.get(command, 'unknown-op-%s' % command)) + elif isinstance(command, list): + s_items.append('redeemscript') else: if blueprint: if self.blueprint and len(self.blueprint) >= i: @@ -687,7 +697,12 @@ def evaluate(self, message=None, env_data=None, trace=False): self.env_data = self.env_data if env_data is None else env_data self.stack = Stack() - commands = self.commands[:] + commands = [] + for c in self.commands: + if isinstance(c, list): + commands += c + else: + commands.append(c) while len(commands): command = commands.pop(0) if trace: diff --git a/tests/test_script.py b/tests/test_script.py index cd857722..7a24e49e 100644 --- a/tests/test_script.py +++ b/tests/test_script.py @@ -624,10 +624,10 @@ def test_script_verify_transaction_input_p2sh_multisig(self): script = unlock_script + lock_script s = Script.parse_bytes(script) - self.assertEqual(s.blueprint, [0, 'signature', 'signature', 82, 'key', 'key', 'key', 83, 174, 169, + self.assertEqual(s.blueprint, [0, 'signature', 'signature', [82, 'key', 'key', 'key', 83, 174], 169, 'data-20', 135]) self.assertEqual(s.script_types, ['p2sh_multisig', 'p2sh']) - self.assertEqual(str(s), "OP_0 signature signature OP_2 key key key OP_3 OP_CHECKMULTISIG OP_HASH160 " + self.assertEqual(str(s), "OP_0 signature signature redeemscript OP_HASH160 " "data-20 OP_EQUAL") transaction_hash = bytes.fromhex('5a805853bf82bcdd865deb09c73ccdd61d2331ac19d8c2911f17c7d954aec059') self.assertTrue(s.evaluate(message=transaction_hash)) @@ -673,13 +673,12 @@ def test_script_verify_transaction_input_p2sh_multisig_huge(self): script = unlock_script + lock_script s = Script.parse_bytes(script) self.assertEqual(s.blueprint, [0, 'signature', 'signature', 'signature', 'signature', 'signature', - 'signature', 'signature', 'signature', 88, 'key', 'key', 'key', 'key', + 'signature', 'signature', 'signature', [88, 'key', 'key', 'key', 'key', 'key', 'key', 'key', 'key', 'key', 'key', 'key', 'key', 'key', 'key', 'key', - 95, 174, 169, 'data-20', 135]) + 95, 174], 169, 'data-20', 135]) self.assertEqual(s.script_types, ['p2sh_multisig', 'p2sh']) self.assertEqual(str(s), "OP_0 signature signature signature signature signature signature signature " - "signature OP_8 key key key key key key key key key key key key key key key OP_15 " - "OP_CHECKMULTISIG OP_HASH160 data-20 OP_EQUAL") + "signature redeemscript OP_HASH160 data-20 OP_EQUAL") transaction_hash = bytes.fromhex('8d190df3d02369999cad3eb222ac18b3315ff2bdc449b8fb30eb14db45730fe3') self.assertEqual(s.redeemscript, redeemscript) self.assertTrue(s.evaluate(message=transaction_hash)) @@ -884,7 +883,7 @@ def test_script_large_redeemscript_packing(self): redeemscript_size = '4dff01' + redeemscript s = Script.parse_hex(redeemscript_size) - self.assertEqual((str(s)), redeemscript_str) + self.assertEqual((str(s)), "redeemscript OP_15 OP_CHECKMULTISIG") redeemscript_error = '4d0101' + redeemscript self.assertRaisesRegex(ScriptError, "Malformed script, not enough data found", Script.parse_hex,