1
0
mirror of https://github.com/trezor/trezor-firmware.git synced 2024-11-26 09:28:13 +00:00

feat(core): Support multisig_xpub_magic in GetPublicKey.

This commit is contained in:
Andrew Kozlik 2024-11-03 10:59:30 +01:00
parent 4287d2b377
commit 6568c36a83
4 changed files with 44 additions and 47 deletions

View File

@ -0,0 +1 @@
Add multisig_xpub_magic option to GetPublicKey.

View File

@ -271,3 +271,30 @@ def descriptor_checksum(desc: str) -> str:
for j in range(0, 8):
ret[j] = CHECKSUM_CHARSET[(c >> (5 * (7 - j))) & 31]
return "".join(ret)
def get_xpub_magic(
coin: CoinInfo,
script_type: InputScriptType,
ignore_xpub_magic: bool | None,
is_multisig: bool | None,
) -> int:
from trezor.enums import InputScriptType
xpub_magic = None
if not ignore_xpub_magic:
# Handle SegWit v0 script types.
# When coin.segwit is true, cointool.py guarantees that the corresponding xpub_magic_* attributes not None.
if not is_multisig:
if script_type == InputScriptType.SPENDP2SHWITNESS:
xpub_magic = coin.xpub_magic_segwit_p2sh
elif script_type == InputScriptType.SPENDWITNESS:
xpub_magic = coin.xpub_magic_segwit_native
else:
if script_type == InputScriptType.SPENDWITNESS:
xpub_magic = coin.xpub_magic_multisig_segwit_native
elif script_type == InputScriptType.SPENDP2SHWITNESS:
xpub_magic = coin.xpub_magic_multisig_segwit_p2sh
# SPENDADDRESS, SPENDMULTISIG, SPENDTAPROOT, ignore_xpub_magic or fallback.
return xpub_magic or coin.xpub_magic

View File

@ -39,6 +39,7 @@ async def get_address(msg: GetAddress, keychain: Keychain, coin: CoinInfo) -> Ad
from apps.common.paths import address_n_to_str, validate_path
from . import addresses
from .common import get_xpub_magic
from .keychain import (
address_n_to_name_or_unknown,
validate_path_against_script_type,
@ -72,20 +73,7 @@ async def get_address(msg: GetAddress, keychain: Keychain, coin: CoinInfo) -> Ad
address_case_sensitive = False # cashaddr address
mac: bytes | None = None
multisig_xpub_magic = coin.xpub_magic
if multisig:
if coin.segwit and not msg.ignore_xpub_magic:
if (
script_type == InputScriptType.SPENDWITNESS
and coin.xpub_magic_multisig_segwit_native is not None
):
multisig_xpub_magic = coin.xpub_magic_multisig_segwit_native
elif (
script_type == InputScriptType.SPENDP2SHWITNESS
and coin.xpub_magic_multisig_segwit_p2sh is not None
):
multisig_xpub_magic = coin.xpub_magic_multisig_segwit_p2sh
else:
if not multisig:
# Attach a MAC for single-sig addresses, but only if the path is standard
# or if the user explicitly confirms a non-standard path.
if msg.show_display or (
@ -97,6 +85,10 @@ async def get_address(msg: GetAddress, keychain: Keychain, coin: CoinInfo) -> Ad
if msg.show_display:
path = address_n_to_str(address_n)
if multisig:
multisig_xpub_magic = get_xpub_magic(
coin, script_type, msg.ignore_xpub_magic, is_multisig=True
)
if multisig.nodes:
pubnodes = multisig.nodes
else:

View File

@ -10,20 +10,20 @@ if TYPE_CHECKING:
async def get_public_key(
msg: GetPublicKey, auth_msg: MessageType | None = None
) -> PublicKey:
from trezor import TR, wire
from trezor import TR
from trezor.enums import InputScriptType
from trezor.messages import HDNodeType, PublicKey, UnlockPath
from apps.common import coininfo, paths
from apps.common.keychain import FORBIDDEN_KEY_PATH, get_keychain
from .common import get_xpub_magic, sanitize_input_script_type
coin_name = msg.coin_name or "Bitcoin"
script_type = msg.script_type or InputScriptType.SPENDADDRESS
coin = coininfo.by_name(coin_name)
curve_name = msg.ecdsa_curve_name or coin.curve_name
address_n = msg.address_n # local_cache_attribute
ignore_xpub_magic = msg.ignore_xpub_magic # local_cache_attribute
xpub_magic = coin.xpub_magic # local_cache_attribute
if address_n and address_n[0] == paths.SLIP25_PURPOSE:
# UnlockPath is required to access SLIP25 paths.
@ -38,36 +38,13 @@ async def get_public_key(
node = keychain.derive(address_n)
if (
script_type
in (
InputScriptType.SPENDADDRESS,
InputScriptType.SPENDMULTISIG,
InputScriptType.SPENDTAPROOT,
sanitize_input_script_type(coin, script_type)
node_xpub = node.serialize_public(
get_xpub_magic(
coin, script_type, msg.ignore_xpub_magic, msg.multisig_xpub_magic
)
and xpub_magic is not None
):
node_xpub = node.serialize_public(xpub_magic)
elif (
coin.segwit
and script_type == InputScriptType.SPENDP2SHWITNESS
and (ignore_xpub_magic or coin.xpub_magic_segwit_p2sh is not None)
):
assert coin.xpub_magic_segwit_p2sh is not None
node_xpub = node.serialize_public(
xpub_magic if ignore_xpub_magic else coin.xpub_magic_segwit_p2sh
)
elif (
coin.segwit
and script_type == InputScriptType.SPENDWITNESS
and (ignore_xpub_magic or coin.xpub_magic_segwit_native is not None)
):
assert coin.xpub_magic_segwit_native is not None
node_xpub = node.serialize_public(
xpub_magic if ignore_xpub_magic else coin.xpub_magic_segwit_native
)
else:
raise wire.DataError("Invalid combination of coin and script_type")
)
pubkey = node.public_key()
# For curve25519 and ed25519, the public key has the prefix 0x00, as specified by SLIP-10. However, since this prefix is non-standard, it may be removed in the future.
@ -79,7 +56,7 @@ async def get_public_key(
public_key=pubkey,
)
descriptor = _xpub_descriptor(
node, xpub_magic, address_n, script_type, keychain.root_fingerprint()
node, coin.xpub_magic, address_n, script_type, keychain.root_fingerprint()
)
if msg.show_display: