mirror of
https://github.com/trezor/trezor-firmware.git
synced 2025-02-08 13:42:41 +00:00
signing/multisig: get_address for change outputs, address_n check
This commit is contained in:
parent
8715e20b79
commit
6a73a7922b
@ -19,7 +19,7 @@ class AddressError(Exception):
|
|||||||
pass
|
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
|
if script_type == InputScriptType.SPENDADDRESS: # p2pkh
|
||||||
return node.address(coin.address_type)
|
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')
|
'Segwit not enabled on this coin')
|
||||||
return address_p2wpkh_in_p2sh(node.public_key(), coin.address_type_p2sh)
|
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:
|
else:
|
||||||
raise AddressError(FailureType.ProcessError,
|
raise AddressError(FailureType.ProcessError,
|
||||||
'Invalid script type')
|
'Invalid script type')
|
||||||
|
@ -29,3 +29,10 @@ def multisig_get_pubkey(hd: HDNodePathType) -> bytes:
|
|||||||
|
|
||||||
def multisig_get_pubkeys(multisig: MultisigRedeemScriptType):
|
def multisig_get_pubkeys(multisig: MultisigRedeemScriptType):
|
||||||
return [multisig_get_pubkey(hd) for hd in multisig.pubkeys]
|
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
|
# 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)
|
script = script_multisig(pubkeys, m)
|
||||||
h = sha256(script).digest()
|
h = sha256(script).digest()
|
||||||
return ripemd160(h).digest()
|
return ripemd160(h).digest()
|
||||||
|
|
||||||
|
|
||||||
# returns a sha256() hash of a multisig script used in native P2WSH
|
# 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:
|
for pubkey in pubkeys:
|
||||||
if len(pubkey) != 33:
|
if len(pubkey) != 33:
|
||||||
raise Exception # only compressed public keys are allowed for P2WSH
|
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()
|
return sha256(script).digest()
|
||||||
|
|
||||||
|
|
||||||
def script_multisig(pubkeys, m) -> bytes:
|
def script_multisig(pubkeys, m) -> bytearray:
|
||||||
n = len(pubkeys)
|
n = len(pubkeys)
|
||||||
if n < 1 or n > 15:
|
if n < 1 or n > 15:
|
||||||
raise Exception
|
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_n: # change output
|
||||||
if o.address:
|
if o.address:
|
||||||
raise SigningError(FailureType.DataError, 'Address in change output')
|
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)
|
o.address = get_address_for_change(o, coin, root)
|
||||||
else:
|
else:
|
||||||
if not o.address:
|
if not o.address:
|
||||||
@ -471,7 +475,7 @@ def get_address_for_change(o: TxOutputType, coin: CoinType, root):
|
|||||||
input_script_type = InputScriptType.SPENDP2SHWITNESS
|
input_script_type = InputScriptType.SPENDP2SHWITNESS
|
||||||
else:
|
else:
|
||||||
raise SigningError(FailureType.DataError, 'Invalid script type')
|
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:
|
def output_is_change(o: TxOutputType, wallet_path: list, segwit_in: int) -> bool:
|
||||||
|
Loading…
Reference in New Issue
Block a user