feat(cardano): add support for 1854 and 1855 path roots

pull/1846/head
gabrielkerekes 3 years ago committed by matejcik
parent 2687fd4ade
commit 54909681a8

@ -57,6 +57,78 @@
"public_key": "be81ace1f63f4f0cae74dd274a72d7818f238bc764ab3e0dc0beb1945b756dca",
"chain_code": "29034f036a162ac4f9f9f397b2d1f289754bb6633915f26b199e156f81d05c88"
}
},
{
"parameters": {
"path": "m/1854'/1815'/0'"
},
"result": {
"public_key": "99694f772a1cffa68ad4a8d911e649cfe990aee720d26893211a8818c4566a42",
"chain_code": "9c3372fcecd832bfe2418319e473b981cdd641e0e12bd878b5e94d93fa0b1552"
}
},
{
"parameters": {
"path": "m/1854'/1815'/1'"
},
"result": {
"public_key": "1b66eb903dc15131c0f39c1ac41ca659115ab790c3e2aef129e3095e406abffe",
"chain_code": "0fcb6522d3aa8ad78370c48e62c97eb1315f4234ded8d8fdd9b941c4e5fda0c0"
}
},
{
"parameters": {
"path": "m/1854'/1815'/2'"
},
"result": {
"public_key": "29f3535b40978eda8038de3fe85cf08efecff5e565a3dc745660a43a172aaa0a",
"chain_code": "b82dbc91a252a93ec6d3f9e418a4e779c848162777367f729468ec23f409304e"
}
},
{
"parameters": {
"path": "m/1854'/1815'/3'"
},
"result": {
"public_key": "bdc40afecb357a08538cd98878b11d0afa7a0a36a8c5f71be1b591ae09088149",
"chain_code": "c4e0b579c132de4204d19f12260ac6bede8ae67f0fe15b9098d4f32a42314924"
}
},
{
"parameters": {
"path": "m/1855'/1815'/0'"
},
"result": {
"public_key": "b75258e4f61eb7b313d8554c2fe10673cf214ca2d762bfd53ec3b7846e2ee872",
"chain_code": "9ad37dc23fe1cda7b0ac5574c6f16171cdb2bb723496954770a2bf0e08334e8f"
}
},
{
"parameters": {
"path": "m/1855'/1815'/1'"
},
"result": {
"public_key": "a54627d6d16724032172541d4261e7aa87c06395724f1d18975a21d56650bda9",
"chain_code": "bccfd881a3bb7eefbfb885a80909c30892a9a2151f7530c10c68ec6e7a89b28a"
}
},
{
"parameters": {
"path": "m/1855'/1815'/2'"
},
"result": {
"public_key": "5307953b17d4195e0b87d61731339dba2c7d543f621d87c1bd73466328372345",
"chain_code": "0e3314c9499b6efec4fa48cd5068dd549ed5ee524c300e754ebc0a63c3bc06ff"
}
},
{
"parameters": {
"path": "m/1855'/1815'/3'"
},
"result": {
"public_key": "b404bb5bf674a38ebd6141416df8e1aea9ed04c2ebea659c29145d24db7e67db",
"chain_code": "2dc07d8eda29c2a806295ee42dc1f3bf63814d0c9ee978a24827575dcb5a53bb"
}
}
]
}

@ -7,7 +7,7 @@ from trezor.ui.layouts import show_pubkey
from apps.common import paths
from . import seed
from .helpers.paths import SCHEMA_PUBKEY
from .helpers.paths import SCHEMA_MINT, SCHEMA_PUBKEY
from .helpers.utils import derive_public_key
if False:
@ -23,7 +23,7 @@ async def get_public_key(
keychain,
msg.address_n,
# path must match the PUBKEY schema
SCHEMA_PUBKEY.match(msg.address_n),
SCHEMA_PUBKEY.match(msg.address_n) or SCHEMA_MINT.match(msg.address_n),
)
try:

@ -6,13 +6,17 @@ SLIP44_ID = 1815
BYRON_ROOT = [44 | HARDENED, SLIP44_ID | HARDENED]
SHELLEY_ROOT = [1852 | HARDENED, SLIP44_ID | HARDENED]
MULTISIG_ROOT = [1854 | HARDENED, SLIP44_ID | HARDENED]
MINTING_ROOT = [1855 | HARDENED, SLIP44_ID | HARDENED]
# fmt: off
SCHEMA_PUBKEY = PathSchema.parse("m/[44,1852]'/coin_type'/account'/*", SLIP44_ID)
SCHEMA_PUBKEY = PathSchema.parse("m/[44,1852,1854]'/coin_type'/account'/*", SLIP44_ID)
# minting has a specific schema for key derivation - see CIP-1855
SCHEMA_MINT = PathSchema.parse("m/1855'/coin_type'/[0-%s]'" % (HARDENED - 1), SLIP44_ID)
SCHEMA_PAYMENT = PathSchema.parse("m/[44,1852]'/coin_type'/account'/[0,1]/address_index", SLIP44_ID)
# staking is only allowed on Shelley paths with suffix /2/0
SCHEMA_STAKING = PathSchema.parse("m/1852'/coin_type'/account'/2/0", SLIP44_ID)
SCHEMA_STAKING_ANY_ACCOUNT = PathSchema.parse("m/1852'/coin_type'/[0-%s]'/2/0" % (HARDENED - 1), SLIP44_ID)
SCHEMA_STAKING = PathSchema.parse("m/[1852]'/coin_type'/account'/2/0", SLIP44_ID)
SCHEMA_STAKING_ANY_ACCOUNT = PathSchema.parse("m/[1852]'/coin_type'/[0-%s]'/2/0" % (HARDENED - 1), SLIP44_ID)
# fmt: on
ACCOUNT_PATH_LENGTH = const(3)

@ -18,15 +18,20 @@ if False:
class Keychain:
"""Cardano keychain hard-coded to Byron and Shelley seed namespaces."""
"""
Cardano keychain hard-coded to 44 (Byron), 1852 (Shelley), 1854 (multi-sig) and 1855 (token minting)
seed namespaces.
"""
def __init__(self, root: bip32.HDNode) -> None:
self.byron_root = derive_path_cardano(root, paths.BYRON_ROOT)
self.shelley_root = derive_path_cardano(root, paths.SHELLEY_ROOT)
self.multisig_root = derive_path_cardano(root, paths.MULTISIG_ROOT)
self.minting_root = derive_path_cardano(root, paths.MINTING_ROOT)
root.__del__()
def verify_path(self, path: Bip32Path) -> None:
if not is_byron_path(path) and not is_shelley_path(path):
if not self.is_in_keychain(path):
raise wire.DataError("Forbidden key path")
def _get_path_root(self, path: Bip32Path) -> bip32.HDNode:
@ -34,18 +39,31 @@ class Keychain:
return self.byron_root
elif is_shelley_path(path):
return self.shelley_root
elif is_multisig_path(path):
return self.multisig_root
elif is_minting_path(path):
return self.minting_root
else:
raise wire.DataError("Forbidden key path")
def is_in_keychain(self, path: Bip32Path) -> bool:
return is_byron_path(path) or is_shelley_path(path)
return (
is_byron_path(path)
or is_shelley_path(path)
or is_multisig_path(path)
or is_minting_path(path)
)
def derive(self, node_path: Bip32Path) -> bip32.HDNode:
self.verify_path(node_path)
path_root = self._get_path_root(node_path)
# this is true now, so for simplicity we don't branch on path type
assert len(paths.BYRON_ROOT) == len(paths.SHELLEY_ROOT)
assert (
len(paths.BYRON_ROOT) == len(paths.SHELLEY_ROOT)
and len(paths.MULTISIG_ROOT) == len(paths.SHELLEY_ROOT)
and len(paths.MINTING_ROOT) == len(paths.SHELLEY_ROOT)
)
suffix = node_path[len(paths.SHELLEY_ROOT) :]
# derive child node from the root
@ -64,6 +82,14 @@ def is_shelley_path(path: Bip32Path) -> bool:
return path[: len(paths.SHELLEY_ROOT)] == paths.SHELLEY_ROOT
def is_multisig_path(path: Bip32Path) -> bool:
return path[: len(paths.MULTISIG_ROOT)] == paths.MULTISIG_ROOT
def is_minting_path(path: Bip32Path) -> bool:
return path[: len(paths.MINTING_ROOT)] == paths.MINTING_ROOT
def derive_path_cardano(root: bip32.HDNode, path: Bip32Path) -> bip32.HDNode:
node = root.clone()
for i in path:

Loading…
Cancel
Save