Skip to content

Commit

Permalink
Extract redeemscript from p2sh script
Browse files Browse the repository at this point in the history
  • Loading branch information
Cryp Toon committed Jul 3, 2024
1 parent 48e9984 commit 6b4a9d0
Show file tree
Hide file tree
Showing 2 changed files with 30 additions and 4 deletions.
15 changes: 12 additions & 3 deletions bitcoinlib/scripts.py
Original file line number Diff line number Diff line change
Expand Up @@ -192,7 +192,7 @@ def __init__(self, commands=None, message=None, script_types='', is_locking=True
:param sigs_required: Nubmer of signatures required to create multisig script
:type sigs_required: int
:param redeemscript: Provide redeemscript to create a new (multisig) script
:type redeemscript: bytes
:type redeemscript: bytes, Script
:param hash_type: Specific script hash type, default is SIGHASH_ALL
:type hash_type: int
"""
Expand All @@ -207,7 +207,12 @@ def __init__(self, commands=None, message=None, script_types='', is_locking=True
self._blueprint = blueprint if blueprint else []
self.env_data = {} if not env_data else env_data
self.sigs_required = sigs_required if sigs_required else len(self.keys) if len(self.keys) else 1
self.redeemscript = redeemscript
self.redeemscript_obj = None
if isinstance(redeemscript, Script):
self.redeemscript_obj = redeemscript
self.redeemscript = redeemscript.as_bytes()
else:
self.redeemscript = redeemscript
self.public_hash = public_hash
self.hash_type = hash_type

Expand Down Expand Up @@ -312,6 +317,7 @@ def parse_bytesio(cls, script, message=None, env_data=None, data_length=0, is_lo
keys = []
blueprint = []
redeemscript = b''
redeemscript_obj = None
sigs_required = None
# hash_type = SIGHASH_ALL # todo: check
hash_type = None
Expand Down Expand Up @@ -373,7 +379,8 @@ def parse_bytesio(cls, script, message=None, env_data=None, data_length=0, is_lo
blueprint += [s2.blueprint]
keys += s2.keys
signatures += s2.signatures
redeemscript = s2.redeemscript
redeemscript_obj = s2
redeemscript = s2.as_bytes()
sigs_required = s2.sigs_required
except (ScriptError, IndexError):
blueprint.append('data-%d' % len(data))
Expand Down Expand Up @@ -419,6 +426,7 @@ def parse_bytesio(cls, script, message=None, env_data=None, data_length=0, is_lo
# Extract extra information from script data
for st in s.script_types[:1]:
if st == 'multisig':
redeemscript_obj = s
s.redeemscript = s.as_bytes()
s.sigs_required = s.commands[0] - 80
if s.sigs_required > len(keys):
Expand All @@ -434,6 +442,7 @@ def parse_bytesio(cls, script, message=None, env_data=None, data_length=0, is_lo
elif st == 'p2pkh' and len(s.commands) > 2:
s.public_hash = s.commands[2]
s.redeemscript = redeemscript if redeemscript else s.redeemscript
s.redeemscript_obj = redeemscript_obj
if s.redeemscript and 'redeemscript' not in s.env_data:
s.env_data['redeemscript'] = s.redeemscript

Expand Down
19 changes: 18 additions & 1 deletion tests/test_script.py
Original file line number Diff line number Diff line change
Expand Up @@ -815,7 +815,9 @@ def test_deserialize_script_with_sizebyte(self):
s1 = Script.parse(script_size_byte)
s2 = Script.parse(script)
s1._raw = s2.as_bytes()
self.assertDictEqualExt(s1.__dict__, s2.__dict__)
s1.redeemscript = b''
s1.redeemscript_obj = None
self.assertDictEqualExt(s1.__dict__, s2.__dict__, )

def test_script_parse_redeemscript(self):
redeemscript = '524104a882d414e478039cd5b52a92ffb13dd5e6bd4515497439dffd691a0f12af9575fa349b5694ed3155b136f09' \
Expand All @@ -826,6 +828,21 @@ def test_script_parse_redeemscript(self):
s = Script.parse_hex(redeemscript)
self.assertEqual(s.serialize().hex(), redeemscript)

def test_script_parse_p2sh_redeemscript(self):
script = ('00473044022076521fc60292a564fcac9ecb05e78846ff0d0e1d9f9de87d23d71cc130504e5c02202b1e0b5aea07d530eab'
'146d1db54542cb2ca2bf6dcf69e77b7ee21671e97f51c0148304502210099eef1bca6087f8f20e0f183a19d057230851ef2'
'fa4f356f192a9745fe1711510220336610d9dc4617a9bb02bdffec0e231df6ad998c6909a7b136dcb30f4bc60953014c725'
'2210352d50656796dd79e3e3385c29636d849b8705c9c6d9b86a1717adc38e4a567c72102f39d0b69c3b8e06030ef9dc295'
'cf8c848f51e398fe85414e33509afdc7f01fb321027072ba2319ead2b0b387d69d36508f57b397da8d4ac76ea64676ee8a1'
'356dae053af048e254ac175740087')
s = Script.parse_hex(script)
self.assertEqual(s.redeemscript,
b'R!\x03R\xd5\x06Vym\xd7\x9e>3\x85\xc2\x966\xd8I\xb8p\\\x9cm\x9b\x86\xa1q'
b'z\xdc8\xe4\xa5g\xc7!\x02\xf3\x9d\x0bi\xc3\xb8\xe0`0\xef\x9d\xc2\x95\xcf\x8c'
b'\x84\x8fQ\xe3\x98\xfe\x85AN3P\x9a\xfd\xc7\xf0\x1f\xb3!\x02pr\xba#\x19'
b'\xea\xd2\xb0\xb3\x87\xd6\x9d6P\x8fW\xb3\x97\xda\x8dJ\xc7n\xa6Fv\xee\x8a\x13'
b'V\xda\xe0S\xaf\x04\x8e%J\xc1ut\x00\x87')

def test_script_create_redeemscript(self):
key1 = '5JruagvxNLXTnkksyLMfgFgf3CagJ3Ekxu5oGxpTm5mPfTAPez3'
key2 = '5JX3qAwDEEaapvLXRfbXRMSiyRgRSW9WjgxeyJQWwBugbudCwsk'
Expand Down

0 comments on commit 6b4a9d0

Please sign in to comment.