Skip to content

Commit

Permalink
Distinct redeemscript from rest of script
Browse files Browse the repository at this point in the history
  • Loading branch information
Cryp Toon committed May 28, 2024
1 parent 18083ad commit 4fffc73
Show file tree
Hide file tree
Showing 2 changed files with 24 additions and 10 deletions.
21 changes: 18 additions & 3 deletions bitcoinlib/scripts.py
Original file line number Diff line number Diff line change
Expand Up @@ -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)

Expand Down Expand Up @@ -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 \
Expand Down Expand Up @@ -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
Expand Down Expand Up @@ -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)
Expand Down Expand Up @@ -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:
Expand Down Expand Up @@ -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:
Expand Down
13 changes: 6 additions & 7 deletions tests/test_script.py
Original file line number Diff line number Diff line change
Expand Up @@ -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))
Expand Down Expand Up @@ -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))
Expand Down Expand Up @@ -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,
Expand Down

0 comments on commit 4fffc73

Please sign in to comment.