signing/multisig: get_address for change outputs, address_n check

pull/25/head
Tomas Susanka 7 years ago committed by Jan Pochyla
parent 8715e20b79
commit 6a73a7922b

@ -19,7 +19,7 @@ class AddressError(Exception):
pass
def get_address(script_type: InputScriptType, coin: CoinType, node) -> str:
def get_address(script_type: InputScriptType, coin: CoinType, node, multisig=None) -> str:
if script_type == InputScriptType.SPENDADDRESS: # p2pkh
return node.address(coin.address_type)
@ -36,6 +36,21 @@ def get_address(script_type: InputScriptType, coin: CoinType, node) -> str:
'Segwit not enabled on this coin')
return address_p2wpkh_in_p2sh(node.public_key(), coin.address_type_p2sh)
elif script_type == InputScriptType.SPENDMULTISIG: # multisig
if multisig is None:
raise AddressError(FailureType.ProcessError,
'Multisig details required')
pubkey = node.public_key()
index = multisig_pubkey_index(multisig, pubkey)
if index is None:
raise AddressError(FailureType.ProcessError,
'Public key not found')
if coin.address_type_p2sh is None:
raise AddressError(FailureType.ProcessError,
'Multisig not enabled on this coin')
return address_multisig_p2sh(multisig_get_pubkeys(multisig), multisig.m, coin.address_type_p2sh)
else:
raise AddressError(FailureType.ProcessError,
'Invalid script type')

@ -29,3 +29,10 @@ def multisig_get_pubkey(hd: HDNodePathType) -> bytes:
def multisig_get_pubkeys(multisig: MultisigRedeemScriptType):
return [multisig_get_pubkey(hd) for hd in multisig.pubkeys]
def check_address_n_against_pubkeys(multisig: MultisigRedeemScriptType, address_n) -> bool:
for p in multisig.pubkeys:
if p.address_n == address_n:
return True
return False

@ -122,14 +122,14 @@ def input_script_multisig(current_signature, other_signatures, pubkeys, m: int):
# returns a ripedm(sha256()) hash of a multisig script used in P2SH
def output_script_multisig_p2sh(pubkeys, m) -> HashWriter:
def output_script_multisig_p2sh(pubkeys, m) -> bytes:
script = script_multisig(pubkeys, m)
h = sha256(script).digest()
return ripemd160(h).digest()
# returns a sha256() hash of a multisig script used in native P2WSH
def output_script_multisig_p2wsh(pubkeys, m) -> HashWriter:
def output_script_multisig_p2wsh(pubkeys, m) -> bytes:
for pubkey in pubkeys:
if len(pubkey) != 33:
raise Exception # only compressed public keys are allowed for P2WSH
@ -137,7 +137,7 @@ def output_script_multisig_p2wsh(pubkeys, m) -> HashWriter:
return sha256(script).digest()
def script_multisig(pubkeys, m) -> bytes:
def script_multisig(pubkeys, m) -> bytearray:
n = len(pubkeys)
if n < 1 or n > 15:
raise Exception

@ -438,6 +438,10 @@ def output_derive_script(o: TxOutputType, coin: CoinType, root) -> bytes:
if o.address_n: # change output
if o.address:
raise SigningError(FailureType.DataError, 'Address in change output')
if o.multisig:
if not check_address_n_against_pubkeys(o.multisig, o.address_n):
raise AddressError(FailureType.ProcessError,
'address_n must match one of the address_n in the MultisigRedeemScriptType pubkeys')
o.address = get_address_for_change(o, coin, root)
else:
if not o.address:
@ -471,7 +475,7 @@ def get_address_for_change(o: TxOutputType, coin: CoinType, root):
input_script_type = InputScriptType.SPENDP2SHWITNESS
else:
raise SigningError(FailureType.DataError, 'Invalid script type')
return get_address(input_script_type, coin, node_derive(root, o.address_n))
return get_address(input_script_type, coin, node_derive(root, o.address_n), o.multisig)
def output_is_change(o: TxOutputType, wallet_path: list, segwit_in: int) -> bool:

Loading…
Cancel
Save