generic m of n multisig
This commit is contained in:
@@ -368,32 +368,29 @@ def parse_scriptSig(d, bytes):
|
||||
d['address'] = address
|
||||
return
|
||||
|
||||
# p2sh transaction, 2 of n
|
||||
# p2sh transaction, m of n
|
||||
match = [ opcodes.OP_0 ] + [ opcodes.OP_PUSHDATA4 ] * (len(decoded) - 1)
|
||||
|
||||
if not match_decoded(decoded, match):
|
||||
print_error("cannot find address in input script", bytes.encode('hex'))
|
||||
return
|
||||
|
||||
x_sig = [x[1].encode('hex') for x in decoded[1:-1]]
|
||||
d['signatures'] = parse_sig(x_sig)
|
||||
d['num_sig'] = 2
|
||||
|
||||
dec2 = [ x for x in script_GetOp(decoded[-1][1]) ]
|
||||
match_2of2 = [ opcodes.OP_2, opcodes.OP_PUSHDATA4, opcodes.OP_PUSHDATA4, opcodes.OP_2, opcodes.OP_CHECKMULTISIG ]
|
||||
match_2of3 = [ opcodes.OP_2, opcodes.OP_PUSHDATA4, opcodes.OP_PUSHDATA4, opcodes.OP_PUSHDATA4, opcodes.OP_3, opcodes.OP_CHECKMULTISIG ]
|
||||
if match_decoded(dec2, match_2of2):
|
||||
x_pubkeys = [ dec2[1][1].encode('hex'), dec2[2][1].encode('hex') ]
|
||||
elif match_decoded(dec2, match_2of3):
|
||||
x_pubkeys = [ dec2[1][1].encode('hex'), dec2[2][1].encode('hex'), dec2[3][1].encode('hex') ]
|
||||
else:
|
||||
m = dec2[0][0] - opcodes.OP_1 + 1
|
||||
n = dec2[-2][0] - opcodes.OP_1 + 1
|
||||
op_m = opcodes.OP_1 + m - 1
|
||||
op_n = opcodes.OP_1 + n - 1
|
||||
match_multisig = [ op_m ] + [opcodes.OP_PUSHDATA4]*n + [ op_n, opcodes.OP_CHECKMULTISIG ]
|
||||
if not match_decoded(dec2, match_multisig):
|
||||
print_error("cannot find address in input script", bytes.encode('hex'))
|
||||
return
|
||||
|
||||
d['x_pubkeys'] = x_pubkeys
|
||||
x_pubkeys = map(lambda x: x[1].encode('hex'), dec2[1:-2])
|
||||
pubkeys = [parse_xpub(x)[0] for x in x_pubkeys] # xpub, addr = parse_xpub()
|
||||
redeemScript = Transaction.multisig_script(pubkeys, m)
|
||||
# write result in d
|
||||
d['num_sig'] = m
|
||||
d['signatures'] = parse_sig(x_sig)
|
||||
d['x_pubkeys'] = x_pubkeys
|
||||
d['pubkeys'] = pubkeys
|
||||
redeemScript = Transaction.multisig_script(pubkeys,2)
|
||||
d['redeemScript'] = redeemScript
|
||||
d['address'] = hash_160_to_bc_address(hash_160(redeemScript.decode('hex')), 5)
|
||||
|
||||
@@ -535,31 +532,14 @@ class Transaction:
|
||||
return self
|
||||
|
||||
@classmethod
|
||||
def multisig_script(klass, public_keys, num=None):
|
||||
def multisig_script(klass, public_keys, m):
|
||||
n = len(public_keys)
|
||||
if num is None: num = n
|
||||
|
||||
assert num <= n and n in [2,3] , 'Only "2 of 2", and "2 of 3" transactions are supported'
|
||||
|
||||
if num==2:
|
||||
s = '52'
|
||||
elif num == 3:
|
||||
s = '53'
|
||||
else:
|
||||
raise
|
||||
|
||||
for k in public_keys:
|
||||
s += op_push(len(k)/2) + k
|
||||
if n==2:
|
||||
s += '52'
|
||||
elif n==3:
|
||||
s += '53'
|
||||
else:
|
||||
raise
|
||||
s += 'ae'
|
||||
|
||||
return s
|
||||
|
||||
assert n <= 15
|
||||
assert m <= n
|
||||
op_m = format(opcodes.OP_1 + m - 1, 'x')
|
||||
op_n = format(opcodes.OP_1 + n - 1, 'x')
|
||||
keylist = [op_push(len(k)/2) + k for k in public_keys]
|
||||
return op_m + ''.join(keylist) + op_n + 'ae'
|
||||
|
||||
@classmethod
|
||||
def pay_script(self, output_type, addr):
|
||||
@@ -617,7 +597,7 @@ class Transaction:
|
||||
script += push_script(x_pubkey)
|
||||
else:
|
||||
script = '00' + script # put op_0 in front of script
|
||||
redeem_script = self.multisig_script(pubkeys,2)
|
||||
redeem_script = self.multisig_script(pubkeys, num_sig)
|
||||
script += push_script(redeem_script)
|
||||
|
||||
elif for_sig==i:
|
||||
|
||||
Reference in New Issue
Block a user