Skip to content

Commit

Permalink
fix parsing of peculiar multisig scripts, add tests on unknown scripts
Browse files Browse the repository at this point in the history
  • Loading branch information
SimoneBronzini committed Feb 9, 2018
1 parent 9b97290 commit 82d3a06
Show file tree
Hide file tree
Showing 3 changed files with 42 additions and 4 deletions.
20 changes: 16 additions & 4 deletions btcpy/structs/script.py
Original file line number Diff line number Diff line change
Expand Up @@ -699,14 +699,29 @@ class MultisigScript(ScriptPubKey):

template = '<>+ OP_CHECKMULTISIG'

@classmethod
def verify(cls, bytes_):
from .crypto import PublicKey
parser = ScriptParser(bytes_)
if not bytes_:
raise WrongScriptTypeException('Empty script')
try:
m, *pubkeys, n = [data for data in parser.match(cls.template)]
except UnexpectedOperationFound as exc:
raise WrongScriptTypeException(str(exc))

if len(pubkeys) == 0 or len(pubkeys) != int(n):
raise WrongScriptTypeException('Non-matching N and number of pubkeys')

return [int(m), *[PublicKey(pubkey.data) for pubkey in pubkeys], int(n)]

def __init__(self, *args):
"""
:param args: if one arg is provided that is interpreted as a precompiled script which needs
verification to see if it belongs to this type. Once verification is done, `m`, a list of pubkeys
and `n` are extracted and saved.
If more than one arg is provided, we assume that the parameters are `m, pubkey1, ..., pubkeyn, n`.
"""
from .crypto import PublicKey

if len(args) == 0:
raise TypeError('Wrong number of params for MultisigScript __init__: {}'.format(len(args)))
Expand All @@ -715,9 +730,6 @@ def __init__(self, *args):
script = args[0]
super().__init__(script.body)
m, *pubkeys, n = self.verify(script.body)
m = int(m)
pubkeys = [PublicKey(pk.data) for pk in pubkeys]
n = int(n)
else:
m, *pubkeys, n = args

Expand Down
17 changes: 17 additions & 0 deletions tests/data/unknownscripts.json
Original file line number Diff line number Diff line change
@@ -0,0 +1,17 @@
["5152ae",
"6a",
"6a4b",
"6368",
"4bb175",
"4bb275",
"4bac",
"004b",
"a94b87",
"76a94b88ac",
"6a",
"ac",
"00",
"b175",
"b275",
"a987",
"76a988ac"]
9 changes: 9 additions & 0 deletions tests/unit.py
Original file line number Diff line number Diff line change
Expand Up @@ -36,6 +36,7 @@ def get_data(filename):

transactions = get_data('rawtxs')
scripts = get_data('scripts')
unknownscripts = get_data('unknownscripts')
keys = get_data('xkeys')
segwit_valid_addresses = get_data('segwit_addr_valid')
segwit_invalid_addresses = get_data('segwit_addr_invalid')
Expand All @@ -51,6 +52,14 @@ def get_data(filename):
priv_pub_hash_addr_p2pkh_segwit = get_data('priv_pub_hash_addr_p2pkh_segwit')


class TestUnknownScript(unittest.TestCase):

def test(self):
for script in unknownscripts:
result = ScriptBuilder.identify(unhexlify(script))
self.assertTrue(isinstance(result, UnknownScript))


class TestPrivPubHashAddrP2pkhSegwit(unittest.TestCase):

def test(self):
Expand Down

0 comments on commit 82d3a06

Please sign in to comment.