mirror of
https://github.com/trezor/trezor-firmware.git
synced 2025-06-10 10:08:46 +00:00
feat(core): update most apps to use path schemas
This commit is contained in:
parent
4ca8f7b0d6
commit
f5c8138df6
@ -1,8 +1,11 @@
|
|||||||
from trezor import wire
|
from trezor import wire
|
||||||
from trezor.messages import MessageType
|
from trezor.messages import MessageType
|
||||||
|
|
||||||
|
from apps.common.paths import PATTERN_BIP44
|
||||||
|
|
||||||
CURVE = "secp256k1"
|
CURVE = "secp256k1"
|
||||||
SLIP44_ID = 714
|
SLIP44_ID = 714
|
||||||
|
PATTERN = PATTERN_BIP44
|
||||||
|
|
||||||
|
|
||||||
def boot() -> None:
|
def boot() -> None:
|
||||||
|
@ -2,23 +2,21 @@ from trezor.messages.BinanceAddress import BinanceAddress
|
|||||||
from trezor.messages.BinanceGetAddress import BinanceGetAddress
|
from trezor.messages.BinanceGetAddress import BinanceGetAddress
|
||||||
|
|
||||||
from apps.common import paths
|
from apps.common import paths
|
||||||
from apps.common.keychain import Keychain, with_slip44_keychain
|
from apps.common.keychain import Keychain, auto_keychain
|
||||||
from apps.common.layout import address_n_to_str, show_address, show_qr
|
from apps.common.layout import address_n_to_str, show_address, show_qr
|
||||||
|
|
||||||
from . import CURVE, SLIP44_ID, helpers
|
from .helpers import address_from_public_key
|
||||||
|
|
||||||
|
|
||||||
@with_slip44_keychain(SLIP44_ID, CURVE, allow_testnet=True)
|
@auto_keychain(__name__)
|
||||||
async def get_address(ctx, msg: BinanceGetAddress, keychain: Keychain):
|
async def get_address(ctx, msg: BinanceGetAddress, keychain: Keychain):
|
||||||
HRP = "bnb"
|
HRP = "bnb"
|
||||||
|
|
||||||
await paths.validate_path(
|
await paths.validate_path(ctx, keychain, msg.address_n)
|
||||||
ctx, helpers.validate_full_path, keychain, msg.address_n, CURVE
|
|
||||||
)
|
|
||||||
|
|
||||||
node = keychain.derive(msg.address_n)
|
node = keychain.derive(msg.address_n)
|
||||||
pubkey = node.public_key()
|
pubkey = node.public_key()
|
||||||
address = helpers.address_from_public_key(pubkey, HRP)
|
address = address_from_public_key(pubkey, HRP)
|
||||||
if msg.show_display:
|
if msg.show_display:
|
||||||
desc = address_n_to_str(msg.address_n)
|
desc = address_n_to_str(msg.address_n)
|
||||||
while True:
|
while True:
|
||||||
|
@ -2,16 +2,12 @@ from trezor.messages.BinanceGetPublicKey import BinanceGetPublicKey
|
|||||||
from trezor.messages.BinancePublicKey import BinancePublicKey
|
from trezor.messages.BinancePublicKey import BinancePublicKey
|
||||||
|
|
||||||
from apps.common import layout, paths
|
from apps.common import layout, paths
|
||||||
from apps.common.keychain import Keychain, with_slip44_keychain
|
from apps.common.keychain import Keychain, auto_keychain
|
||||||
|
|
||||||
from . import CURVE, SLIP44_ID, helpers
|
|
||||||
|
|
||||||
|
|
||||||
@with_slip44_keychain(SLIP44_ID, CURVE, allow_testnet=True)
|
@auto_keychain(__name__)
|
||||||
async def get_public_key(ctx, msg: BinanceGetPublicKey, keychain: Keychain):
|
async def get_public_key(ctx, msg: BinanceGetPublicKey, keychain: Keychain):
|
||||||
await paths.validate_path(
|
await paths.validate_path(ctx, keychain, msg.address_n)
|
||||||
ctx, helpers.validate_full_path, keychain, msg.address_n, CURVE
|
|
||||||
)
|
|
||||||
node = keychain.derive(msg.address_n)
|
node = keychain.derive(msg.address_n)
|
||||||
pubkey = node.public_key()
|
pubkey = node.public_key()
|
||||||
|
|
||||||
|
@ -8,8 +8,6 @@ from trezor.messages.BinanceOrderMsg import BinanceOrderMsg
|
|||||||
from trezor.messages.BinanceSignTx import BinanceSignTx
|
from trezor.messages.BinanceSignTx import BinanceSignTx
|
||||||
from trezor.messages.BinanceTransferMsg import BinanceTransferMsg
|
from trezor.messages.BinanceTransferMsg import BinanceTransferMsg
|
||||||
|
|
||||||
from apps.common import HARDENED
|
|
||||||
|
|
||||||
ENVELOPE_BLUEPRINT = '{{"account_number":"{account_number}","chain_id":"{chain_id}","data":null,"memo":"{memo}","msgs":[{msgs}],"sequence":"{sequence}","source":"{source}"}}'
|
ENVELOPE_BLUEPRINT = '{{"account_number":"{account_number}","chain_id":"{chain_id}","data":null,"memo":"{memo}","msgs":[{msgs}],"sequence":"{sequence}","source":"{source}"}}'
|
||||||
MSG_TRANSFER_BLUEPRINT = '{{"inputs":[{inputs}],"outputs":[{outputs}]}}'
|
MSG_TRANSFER_BLUEPRINT = '{{"inputs":[{inputs}],"outputs":[{outputs}]}}'
|
||||||
MSG_NEWORDER_BLUEPRINT = '{{"id":"{id}","ordertype":{ordertype},"price":{price},"quantity":{quantity},"sender":"{sender}","side":{side},"symbol":"{symbol}","timeinforce":{timeinforce}}}'
|
MSG_NEWORDER_BLUEPRINT = '{{"id":"{id}","ordertype":{ordertype},"price":{price},"quantity":{quantity},"sender":"{sender}","side":{side},"symbol":"{symbol}","timeinforce":{timeinforce}}}'
|
||||||
@ -91,25 +89,3 @@ def address_from_public_key(pubkey: bytes, hrp: str) -> str:
|
|||||||
convertedbits = bech32.convertbits(h, 8, 5, False)
|
convertedbits = bech32.convertbits(h, 8, 5, False)
|
||||||
|
|
||||||
return bech32.bech32_encode(hrp, convertedbits)
|
return bech32.bech32_encode(hrp, convertedbits)
|
||||||
|
|
||||||
|
|
||||||
def validate_full_path(path: list) -> bool:
|
|
||||||
"""
|
|
||||||
Validates derivation path to equal 44'/714'/a'/0/0,
|
|
||||||
where `a` is an account index from 0 to 1 000 000.
|
|
||||||
Similar to Ethereum this should be 44'/714'/a', but for
|
|
||||||
compatibility with other HW vendors we use 44'/714'/a'/0/0.
|
|
||||||
"""
|
|
||||||
if len(path) != 5:
|
|
||||||
return False
|
|
||||||
if path[0] != 44 | HARDENED:
|
|
||||||
return False
|
|
||||||
if path[1] != 714 | HARDENED:
|
|
||||||
return False
|
|
||||||
if path[2] < HARDENED or path[2] > 1000000 | HARDENED:
|
|
||||||
return False
|
|
||||||
if path[3] != 0:
|
|
||||||
return False
|
|
||||||
if path[4] != 0:
|
|
||||||
return False
|
|
||||||
return True
|
|
||||||
|
@ -9,20 +9,18 @@ from trezor.messages.BinanceTransferMsg import BinanceTransferMsg
|
|||||||
from trezor.messages.BinanceTxRequest import BinanceTxRequest
|
from trezor.messages.BinanceTxRequest import BinanceTxRequest
|
||||||
|
|
||||||
from apps.common import paths
|
from apps.common import paths
|
||||||
from apps.common.keychain import Keychain, with_slip44_keychain
|
from apps.common.keychain import Keychain, auto_keychain
|
||||||
|
|
||||||
from . import CURVE, SLIP44_ID, helpers, layout
|
from . import helpers, layout
|
||||||
|
|
||||||
|
|
||||||
@with_slip44_keychain(SLIP44_ID, CURVE, allow_testnet=True)
|
@auto_keychain(__name__)
|
||||||
async def sign_tx(ctx, envelope, keychain: Keychain):
|
async def sign_tx(ctx, envelope, keychain: Keychain):
|
||||||
# create transaction message -> sign it -> create signature/pubkey message -> serialize all
|
# create transaction message -> sign it -> create signature/pubkey message -> serialize all
|
||||||
if envelope.msg_count > 1:
|
if envelope.msg_count > 1:
|
||||||
raise wire.DataError("Multiple messages not supported.")
|
raise wire.DataError("Multiple messages not supported.")
|
||||||
await paths.validate_path(
|
|
||||||
ctx, helpers.validate_full_path, keychain, envelope.address_n, CURVE
|
|
||||||
)
|
|
||||||
|
|
||||||
|
await paths.validate_path(ctx, keychain, envelope.address_n)
|
||||||
node = keychain.derive(envelope.address_n)
|
node = keychain.derive(envelope.address_n)
|
||||||
|
|
||||||
tx_req = BinanceTxRequest()
|
tx_req = BinanceTxRequest()
|
||||||
|
@ -1,8 +1,11 @@
|
|||||||
from trezor import wire
|
from trezor import wire
|
||||||
from trezor.messages import MessageType
|
from trezor.messages import MessageType
|
||||||
|
|
||||||
|
from apps.common.paths import PATTERN_BIP44
|
||||||
|
|
||||||
CURVE = "secp256k1"
|
CURVE = "secp256k1"
|
||||||
SLIP44_ID = 194
|
SLIP44_ID = 194
|
||||||
|
PATTERN = PATTERN_BIP44
|
||||||
|
|
||||||
|
|
||||||
def boot() -> None:
|
def boot() -> None:
|
||||||
|
@ -4,10 +4,9 @@ from trezor.messages.EosGetPublicKey import EosGetPublicKey
|
|||||||
from trezor.messages.EosPublicKey import EosPublicKey
|
from trezor.messages.EosPublicKey import EosPublicKey
|
||||||
|
|
||||||
from apps.common import paths
|
from apps.common import paths
|
||||||
from apps.common.keychain import Keychain, with_slip44_keychain
|
from apps.common.keychain import Keychain, auto_keychain
|
||||||
|
|
||||||
from . import CURVE, SLIP44_ID
|
from .helpers import public_key_to_wif
|
||||||
from .helpers import public_key_to_wif, validate_full_path
|
|
||||||
from .layout import require_get_public_key
|
from .layout import require_get_public_key
|
||||||
|
|
||||||
if False:
|
if False:
|
||||||
@ -22,11 +21,11 @@ def _get_public_key(node: bip32.HDNode) -> Tuple[str, bytes]:
|
|||||||
return wif, public_key
|
return wif, public_key
|
||||||
|
|
||||||
|
|
||||||
@with_slip44_keychain(SLIP44_ID, CURVE)
|
@auto_keychain(__name__)
|
||||||
async def get_public_key(
|
async def get_public_key(
|
||||||
ctx: wire.Context, msg: EosGetPublicKey, keychain: Keychain
|
ctx: wire.Context, msg: EosGetPublicKey, keychain: Keychain
|
||||||
) -> EosPublicKey:
|
) -> EosPublicKey:
|
||||||
await paths.validate_path(ctx, validate_full_path, keychain, msg.address_n, CURVE)
|
await paths.validate_path(ctx, keychain, msg.address_n)
|
||||||
|
|
||||||
node = keychain.derive(msg.address_n)
|
node = keychain.derive(msg.address_n)
|
||||||
wif, public_key = _get_public_key(node)
|
wif, public_key = _get_public_key(node)
|
||||||
|
@ -2,8 +2,6 @@ from trezor import wire
|
|||||||
from trezor.crypto import base58
|
from trezor.crypto import base58
|
||||||
from trezor.messages.EosAsset import EosAsset
|
from trezor.messages.EosAsset import EosAsset
|
||||||
|
|
||||||
from apps.common import HARDENED
|
|
||||||
|
|
||||||
|
|
||||||
def base58_encode(prefix: str, sig_prefix: str, data: bytes) -> str:
|
def base58_encode(prefix: str, sig_prefix: str, data: bytes) -> str:
|
||||||
b58 = base58.encode(data + base58.ripemd160_32(data + sig_prefix.encode()))
|
b58 = base58.encode(data + base58.ripemd160_32(data + sig_prefix.encode()))
|
||||||
@ -42,28 +40,6 @@ def eos_asset_to_string(asset: EosAsset) -> str:
|
|||||||
return "{} {}".format(amount_digits, symbol)
|
return "{} {}".format(amount_digits, symbol)
|
||||||
|
|
||||||
|
|
||||||
def validate_full_path(path: list) -> bool:
|
|
||||||
"""
|
|
||||||
Validates derivation path to equal 44'/194'/a'/0/0,
|
|
||||||
where `a` is an account index from 0 to 1 000 000.
|
|
||||||
Similar to Ethereum this should be 44'/194'/a', but for
|
|
||||||
compatibility with other HW vendors we use 44'/194'/a'/0/0.
|
|
||||||
"""
|
|
||||||
if len(path) != 5:
|
|
||||||
return False
|
|
||||||
if path[0] != 44 | HARDENED:
|
|
||||||
return False
|
|
||||||
if path[1] != 194 | HARDENED:
|
|
||||||
return False
|
|
||||||
if path[2] < HARDENED or path[2] > 1000000 | HARDENED:
|
|
||||||
return False
|
|
||||||
if path[3] != 0:
|
|
||||||
return False
|
|
||||||
if path[4] != 0:
|
|
||||||
return False
|
|
||||||
return True
|
|
||||||
|
|
||||||
|
|
||||||
def public_key_to_wif(pub_key: bytes) -> str:
|
def public_key_to_wif(pub_key: bytes) -> str:
|
||||||
if pub_key[0] == 0x04 and len(pub_key) == 65:
|
if pub_key[0] == 0x04 and len(pub_key) == 65:
|
||||||
head = b"\x03" if pub_key[64] & 0x01 else b"\x02"
|
head = b"\x03" if pub_key[64] & 0x01 else b"\x02"
|
||||||
|
@ -8,15 +8,15 @@ from trezor.messages.EosTxActionRequest import EosTxActionRequest
|
|||||||
from trezor.utils import HashWriter
|
from trezor.utils import HashWriter
|
||||||
|
|
||||||
from apps.common import paths
|
from apps.common import paths
|
||||||
from apps.common.keychain import Keychain, with_slip44_keychain
|
from apps.common.keychain import Keychain, auto_keychain
|
||||||
|
|
||||||
from . import CURVE, SLIP44_ID, writers
|
from . import writers
|
||||||
from .actions import process_action
|
from .actions import process_action
|
||||||
from .helpers import base58_encode, validate_full_path
|
from .helpers import base58_encode
|
||||||
from .layout import require_sign_tx
|
from .layout import require_sign_tx
|
||||||
|
|
||||||
|
|
||||||
@with_slip44_keychain(SLIP44_ID, CURVE)
|
@auto_keychain(__name__)
|
||||||
async def sign_tx(ctx: wire.Context, msg: EosSignTx, keychain: Keychain) -> EosSignedTx:
|
async def sign_tx(ctx: wire.Context, msg: EosSignTx, keychain: Keychain) -> EosSignedTx:
|
||||||
if msg.chain_id is None:
|
if msg.chain_id is None:
|
||||||
raise wire.DataError("No chain id")
|
raise wire.DataError("No chain id")
|
||||||
@ -25,7 +25,7 @@ async def sign_tx(ctx: wire.Context, msg: EosSignTx, keychain: Keychain) -> EosS
|
|||||||
if msg.num_actions is None or msg.num_actions == 0:
|
if msg.num_actions is None or msg.num_actions == 0:
|
||||||
raise wire.DataError("No actions")
|
raise wire.DataError("No actions")
|
||||||
|
|
||||||
await paths.validate_path(ctx, validate_full_path, keychain, msg.address_n, CURVE)
|
await paths.validate_path(ctx, keychain, msg.address_n)
|
||||||
|
|
||||||
node = keychain.derive(msg.address_n)
|
node = keychain.derive(msg.address_n)
|
||||||
sha = HashWriter(sha256())
|
sha = HashWriter(sha256())
|
||||||
|
@ -2,59 +2,6 @@ from ubinascii import unhexlify
|
|||||||
|
|
||||||
from trezor import wire
|
from trezor import wire
|
||||||
|
|
||||||
from apps.common import HARDENED, paths
|
|
||||||
|
|
||||||
from . import networks
|
|
||||||
|
|
||||||
|
|
||||||
"""
|
|
||||||
We believe Ethereum should use 44'/60'/a' for everything, because it is
|
|
||||||
account-based, rather than UTXO-based. Unfortunately, lot of Ethereum
|
|
||||||
tools (MEW, Metamask) do not use such scheme and set a = 0 and then
|
|
||||||
iterate the address index i. Therefore for compatibility reasons we use
|
|
||||||
the same scheme: 44'/60'/0'/0/i and only the i is being iterated.
|
|
||||||
"""
|
|
||||||
|
|
||||||
|
|
||||||
def validate_path_for_get_public_key(path: list) -> bool:
|
|
||||||
"""
|
|
||||||
This should be 44'/60'/0', but other non-hardened items are allowed.
|
|
||||||
"""
|
|
||||||
length = len(path)
|
|
||||||
if length < 3 or length > 5:
|
|
||||||
return False
|
|
||||||
if path[0] != 44 | HARDENED:
|
|
||||||
return False
|
|
||||||
if path[1] not in networks.all_slip44_ids_hardened():
|
|
||||||
return False
|
|
||||||
if path[2] != 0 | HARDENED:
|
|
||||||
return False
|
|
||||||
if length > 3 and paths.is_hardened(path[3]):
|
|
||||||
return False
|
|
||||||
if length > 4 and paths.is_hardened(path[4]):
|
|
||||||
return False
|
|
||||||
return True
|
|
||||||
|
|
||||||
|
|
||||||
def validate_full_path(path: list) -> bool:
|
|
||||||
"""
|
|
||||||
Validates derivation path to equal 44'/60'/0'/0/i,
|
|
||||||
where `i` is an address index from 0 to 1 000 000.
|
|
||||||
"""
|
|
||||||
if len(path) != 5:
|
|
||||||
return False
|
|
||||||
if path[0] != 44 | HARDENED:
|
|
||||||
return False
|
|
||||||
if path[1] not in networks.all_slip44_ids_hardened():
|
|
||||||
return False
|
|
||||||
if path[2] != 0 | HARDENED:
|
|
||||||
return False
|
|
||||||
if path[3] != 0:
|
|
||||||
return False
|
|
||||||
if path[4] > 1000000:
|
|
||||||
return False
|
|
||||||
return True
|
|
||||||
|
|
||||||
|
|
||||||
def address_from_bytes(address_bytes: bytes, network=None) -> str:
|
def address_from_bytes(address_bytes: bytes, network=None) -> str:
|
||||||
"""
|
"""
|
||||||
|
@ -5,14 +5,14 @@ from trezor.messages.EthereumAddress import EthereumAddress
|
|||||||
from apps.common import paths
|
from apps.common import paths
|
||||||
from apps.common.layout import address_n_to_str, show_address, show_qr
|
from apps.common.layout import address_n_to_str, show_address, show_qr
|
||||||
|
|
||||||
from . import CURVE, networks
|
from . import networks
|
||||||
from .address import address_from_bytes, validate_full_path
|
from .address import address_from_bytes
|
||||||
from .keychain import with_keychain_from_path
|
from .keychain import PATTERN_ADDRESS, with_keychain_from_path
|
||||||
|
|
||||||
|
|
||||||
@with_keychain_from_path
|
@with_keychain_from_path(PATTERN_ADDRESS)
|
||||||
async def get_address(ctx, msg, keychain):
|
async def get_address(ctx, msg, keychain):
|
||||||
await paths.validate_path(ctx, validate_full_path, keychain, msg.address_n, CURVE)
|
await paths.validate_path(ctx, keychain, msg.address_n)
|
||||||
|
|
||||||
node = keychain.derive(msg.address_n)
|
node = keychain.derive(msg.address_n)
|
||||||
seckey = node.private_key()
|
seckey = node.private_key()
|
||||||
|
@ -3,15 +3,12 @@ from trezor.messages.HDNodeType import HDNodeType
|
|||||||
|
|
||||||
from apps.common import coins, layout, paths
|
from apps.common import coins, layout, paths
|
||||||
|
|
||||||
from . import CURVE, address
|
from .keychain import PATTERN_PUBKEY, with_keychain_from_path
|
||||||
from .keychain import with_keychain_from_path
|
|
||||||
|
|
||||||
|
|
||||||
@with_keychain_from_path
|
@with_keychain_from_path(PATTERN_PUBKEY)
|
||||||
async def get_public_key(ctx, msg, keychain):
|
async def get_public_key(ctx, msg, keychain):
|
||||||
await paths.validate_path(
|
await paths.validate_path(ctx, keychain, msg.address_n)
|
||||||
ctx, address.validate_path_for_get_public_key, keychain, msg.address_n, CURVE
|
|
||||||
)
|
|
||||||
node = keychain.derive(msg.address_n)
|
node = keychain.derive(msg.address_n)
|
||||||
|
|
||||||
# we use the Bitcoin format for Ethereum xpubs
|
# we use the Bitcoin format for Ethereum xpubs
|
||||||
|
@ -1,12 +1,12 @@
|
|||||||
from trezor import wire
|
from trezor import wire
|
||||||
|
|
||||||
from apps.common import HARDENED, seed
|
from apps.common import HARDENED, paths
|
||||||
from apps.common.keychain import get_keychain
|
from apps.common.keychain import get_keychain
|
||||||
|
|
||||||
from . import CURVE, networks
|
from . import CURVE, networks
|
||||||
|
|
||||||
if False:
|
if False:
|
||||||
from typing import List
|
from typing import Callable
|
||||||
from typing_extensions import Protocol
|
from typing_extensions import Protocol
|
||||||
|
|
||||||
from protobuf import MessageType
|
from protobuf import MessageType
|
||||||
@ -16,48 +16,76 @@ if False:
|
|||||||
from apps.common.keychain import MsgOut, Handler, HandlerWithKeychain
|
from apps.common.keychain import MsgOut, Handler, HandlerWithKeychain
|
||||||
|
|
||||||
class MsgWithAddressN(MessageType, Protocol):
|
class MsgWithAddressN(MessageType, Protocol):
|
||||||
address_n = ... # type: List[int]
|
address_n = ... # type: paths.Bip32Path
|
||||||
|
|
||||||
|
|
||||||
async def from_address_n(ctx: wire.Context, address_n: List[int]) -> seed.Keychain:
|
# We believe Ethereum should use 44'/60'/a' for everything, because it is
|
||||||
|
# account-based, rather than UTXO-based. Unfortunately, lot of Ethereum
|
||||||
|
# tools (MEW, Metamask) do not use such scheme and set a = 0 and then
|
||||||
|
# iterate the address index i. Therefore for compatibility reasons we use
|
||||||
|
# the same scheme: 44'/60'/0'/0/i and only the i is being iterated.
|
||||||
|
|
||||||
|
PATTERN_ADDRESS = "m/44'/coin_type'/0'/0/address_index"
|
||||||
|
PATTERN_PUBKEY = "m/44'/coin_type'/0'/*"
|
||||||
|
|
||||||
|
|
||||||
|
def _schema_from_address_n(
|
||||||
|
pattern: str, address_n: paths.Bip32Path
|
||||||
|
) -> paths.PathSchema:
|
||||||
if len(address_n) < 2:
|
if len(address_n) < 2:
|
||||||
raise wire.DataError("Forbidden key path")
|
return paths.SCHEMA_NO_MATCH
|
||||||
|
|
||||||
slip44_hardened = address_n[1]
|
slip44_hardened = address_n[1]
|
||||||
if slip44_hardened not in networks.all_slip44_ids_hardened():
|
if slip44_hardened not in networks.all_slip44_ids_hardened():
|
||||||
raise wire.DataError("Forbidden key path")
|
return paths.SCHEMA_NO_MATCH
|
||||||
namespace = [44 | HARDENED, slip44_hardened]
|
|
||||||
return await get_keychain(ctx, CURVE, [namespace])
|
if not slip44_hardened & HARDENED:
|
||||||
|
return paths.SCHEMA_ANY_PATH
|
||||||
|
|
||||||
|
slip44_id = slip44_hardened - HARDENED
|
||||||
|
return paths.PathSchema(pattern, slip44_id)
|
||||||
|
|
||||||
|
|
||||||
def with_keychain_from_path(
|
def with_keychain_from_path(
|
||||||
|
pattern: str,
|
||||||
|
) -> Callable[
|
||||||
|
[HandlerWithKeychain[MsgWithAddressN, MsgOut]], Handler[MsgWithAddressN, MsgOut]
|
||||||
|
]:
|
||||||
|
def decorator(
|
||||||
func: HandlerWithKeychain[MsgWithAddressN, MsgOut]
|
func: HandlerWithKeychain[MsgWithAddressN, MsgOut]
|
||||||
) -> Handler[MsgWithAddressN, MsgOut]:
|
) -> Handler[MsgWithAddressN, MsgOut]:
|
||||||
async def wrapper(ctx: wire.Context, msg: MsgWithAddressN) -> MsgOut:
|
async def wrapper(ctx: wire.Context, msg: MsgWithAddressN) -> MsgOut:
|
||||||
keychain = await from_address_n(ctx, msg.address_n)
|
schema = _schema_from_address_n(pattern, msg.address_n)
|
||||||
|
keychain = await get_keychain(ctx, CURVE, [schema])
|
||||||
with keychain:
|
with keychain:
|
||||||
return await func(ctx, msg, keychain)
|
return await func(ctx, msg, keychain)
|
||||||
|
|
||||||
return wrapper
|
return wrapper
|
||||||
|
|
||||||
|
return decorator
|
||||||
|
|
||||||
|
|
||||||
|
def _schema_from_chain_id(msg: EthereumSignTx) -> paths.PathSchema:
|
||||||
|
if msg.chain_id is None:
|
||||||
|
return _schema_from_address_n(PATTERN_ADDRESS, msg.address_n)
|
||||||
|
|
||||||
|
info = networks.by_chain_id(msg.chain_id)
|
||||||
|
if info is None:
|
||||||
|
return paths.SCHEMA_NO_MATCH
|
||||||
|
|
||||||
|
slip44_id = info.slip44
|
||||||
|
if networks.is_wanchain(msg.chain_id, msg.tx_type):
|
||||||
|
slip44_id = networks.SLIP44_WANCHAIN
|
||||||
|
return paths.PathSchema(PATTERN_ADDRESS, slip44_id)
|
||||||
|
|
||||||
|
|
||||||
def with_keychain_from_chain_id(
|
def with_keychain_from_chain_id(
|
||||||
func: HandlerWithKeychain[EthereumSignTx, MsgOut]
|
func: HandlerWithKeychain[EthereumSignTx, MsgOut]
|
||||||
) -> Handler[EthereumSignTx, MsgOut]:
|
) -> Handler[EthereumSignTx, MsgOut]:
|
||||||
|
# this is only for SignTx, and only PATTERN_ADDRESS is allowed
|
||||||
async def wrapper(ctx: wire.Context, msg: EthereumSignTx) -> MsgOut:
|
async def wrapper(ctx: wire.Context, msg: EthereumSignTx) -> MsgOut:
|
||||||
if msg.chain_id is None:
|
schema = _schema_from_chain_id(msg)
|
||||||
keychain = await from_address_n(ctx, msg.address_n)
|
keychain = await get_keychain(ctx, CURVE, [schema])
|
||||||
else:
|
|
||||||
info = networks.by_chain_id(msg.chain_id)
|
|
||||||
if info is None:
|
|
||||||
raise wire.DataError("Unsupported chain id")
|
|
||||||
|
|
||||||
slip44 = info.slip44
|
|
||||||
if networks.is_wanchain(msg.chain_id, msg.tx_type):
|
|
||||||
slip44 = networks.SLIP44_WANCHAIN
|
|
||||||
|
|
||||||
namespace = [44 | HARDENED, slip44 | HARDENED]
|
|
||||||
keychain = await get_keychain(ctx, CURVE, [namespace])
|
|
||||||
|
|
||||||
with keychain:
|
with keychain:
|
||||||
return await func(ctx, msg, keychain)
|
return await func(ctx, msg, keychain)
|
||||||
|
|
||||||
|
@ -6,8 +6,8 @@ from trezor.utils import HashWriter
|
|||||||
from apps.common import paths
|
from apps.common import paths
|
||||||
from apps.common.signverify import require_confirm_sign_message
|
from apps.common.signverify import require_confirm_sign_message
|
||||||
|
|
||||||
from . import CURVE, address
|
from . import address
|
||||||
from .keychain import with_keychain_from_path
|
from .keychain import PATTERN_ADDRESS, with_keychain_from_path
|
||||||
|
|
||||||
|
|
||||||
def message_digest(message):
|
def message_digest(message):
|
||||||
@ -19,11 +19,9 @@ def message_digest(message):
|
|||||||
return h.get_digest()
|
return h.get_digest()
|
||||||
|
|
||||||
|
|
||||||
@with_keychain_from_path
|
@with_keychain_from_path(PATTERN_ADDRESS)
|
||||||
async def sign_message(ctx, msg, keychain):
|
async def sign_message(ctx, msg, keychain):
|
||||||
await paths.validate_path(
|
await paths.validate_path(ctx, keychain, msg.address_n)
|
||||||
ctx, address.validate_full_path, keychain, msg.address_n, CURVE
|
|
||||||
)
|
|
||||||
await require_confirm_sign_message(ctx, "ETH", msg.message)
|
await require_confirm_sign_message(ctx, "ETH", msg.message)
|
||||||
|
|
||||||
node = keychain.derive(msg.address_n)
|
node = keychain.derive(msg.address_n)
|
||||||
|
@ -9,8 +9,7 @@ from trezor.utils import HashWriter
|
|||||||
|
|
||||||
from apps.common import paths
|
from apps.common import paths
|
||||||
|
|
||||||
from . import CURVE, address, tokens
|
from . import address, tokens
|
||||||
from .address import validate_full_path
|
|
||||||
from .keychain import with_keychain_from_chain_id
|
from .keychain import with_keychain_from_chain_id
|
||||||
from .layout import require_confirm_data, require_confirm_fee, require_confirm_tx
|
from .layout import require_confirm_data, require_confirm_fee, require_confirm_tx
|
||||||
|
|
||||||
@ -22,7 +21,7 @@ MAX_CHAIN_ID = 2147483629
|
|||||||
async def sign_tx(ctx, msg, keychain):
|
async def sign_tx(ctx, msg, keychain):
|
||||||
msg = sanitize(msg)
|
msg = sanitize(msg)
|
||||||
check(msg)
|
check(msg)
|
||||||
await paths.validate_path(ctx, validate_full_path, keychain, msg.address_n, CURVE)
|
await paths.validate_path(ctx, keychain, msg.address_n)
|
||||||
|
|
||||||
data_total = msg.data_length
|
data_total = msg.data_length
|
||||||
|
|
||||||
|
@ -1,8 +1,11 @@
|
|||||||
from trezor import wire
|
from trezor import wire
|
||||||
from trezor.messages import MessageType
|
from trezor.messages import MessageType
|
||||||
|
|
||||||
|
from apps.common.paths import PATTERN_SEP5
|
||||||
|
|
||||||
CURVE = "ed25519"
|
CURVE = "ed25519"
|
||||||
SLIP44_ID = 134
|
SLIP44_ID = 134
|
||||||
|
PATTERN = PATTERN_SEP5
|
||||||
|
|
||||||
|
|
||||||
def boot() -> None:
|
def boot() -> None:
|
||||||
|
@ -1,16 +1,15 @@
|
|||||||
from trezor.messages.LiskAddress import LiskAddress
|
from trezor.messages.LiskAddress import LiskAddress
|
||||||
|
|
||||||
from apps.common import paths
|
from apps.common import paths
|
||||||
from apps.common.keychain import with_slip44_keychain
|
from apps.common.keychain import auto_keychain
|
||||||
from apps.common.layout import address_n_to_str, show_address, show_qr
|
from apps.common.layout import address_n_to_str, show_address, show_qr
|
||||||
|
|
||||||
from . import CURVE, SLIP44_ID
|
from .helpers import get_address_from_public_key
|
||||||
from .helpers import get_address_from_public_key, validate_full_path
|
|
||||||
|
|
||||||
|
|
||||||
@with_slip44_keychain(SLIP44_ID, CURVE, allow_testnet=True)
|
@auto_keychain(__name__)
|
||||||
async def get_address(ctx, msg, keychain):
|
async def get_address(ctx, msg, keychain):
|
||||||
await paths.validate_path(ctx, validate_full_path, keychain, msg.address_n, CURVE)
|
await paths.validate_path(ctx, keychain, msg.address_n)
|
||||||
|
|
||||||
node = keychain.derive(msg.address_n)
|
node = keychain.derive(msg.address_n)
|
||||||
pubkey = node.public_key()
|
pubkey = node.public_key()
|
||||||
|
@ -1,15 +1,12 @@
|
|||||||
from trezor.messages.LiskPublicKey import LiskPublicKey
|
from trezor.messages.LiskPublicKey import LiskPublicKey
|
||||||
|
|
||||||
from apps.common import layout, paths
|
from apps.common import layout, paths
|
||||||
from apps.common.keychain import with_slip44_keychain
|
from apps.common.keychain import auto_keychain
|
||||||
|
|
||||||
from . import CURVE, SLIP44_ID
|
|
||||||
from .helpers import validate_full_path
|
|
||||||
|
|
||||||
|
|
||||||
@with_slip44_keychain(SLIP44_ID, CURVE, allow_testnet=True)
|
@auto_keychain(__name__)
|
||||||
async def get_public_key(ctx, msg, keychain):
|
async def get_public_key(ctx, msg, keychain):
|
||||||
await paths.validate_path(ctx, validate_full_path, keychain, msg.address_n, CURVE)
|
await paths.validate_path(ctx, keychain, msg.address_n)
|
||||||
|
|
||||||
node = keychain.derive(msg.address_n)
|
node = keychain.derive(msg.address_n)
|
||||||
pubkey = node.public_key()
|
pubkey = node.public_key()
|
||||||
|
@ -1,7 +1,5 @@
|
|||||||
from trezor.crypto.hashlib import sha256
|
from trezor.crypto.hashlib import sha256
|
||||||
|
|
||||||
from apps.common import HARDENED
|
|
||||||
|
|
||||||
|
|
||||||
def get_address_from_public_key(pubkey):
|
def get_address_from_public_key(pubkey):
|
||||||
pubkeyhash = sha256(pubkey).digest()
|
pubkeyhash = sha256(pubkey).digest()
|
||||||
@ -31,19 +29,3 @@ def get_vote_tx_text(votes):
|
|||||||
|
|
||||||
def _text_with_plural(txt, value):
|
def _text_with_plural(txt, value):
|
||||||
return "%s %s %s" % (txt, value, ("votes" if value != 1 else "vote"))
|
return "%s %s %s" % (txt, value, ("votes" if value != 1 else "vote"))
|
||||||
|
|
||||||
|
|
||||||
def validate_full_path(path: list) -> bool:
|
|
||||||
"""
|
|
||||||
Validates derivation path to equal 44'/134'/a',
|
|
||||||
where `a` is an account index from 0 to 1 000 000.
|
|
||||||
"""
|
|
||||||
if len(path) != 3:
|
|
||||||
return False
|
|
||||||
if path[0] != 44 | HARDENED:
|
|
||||||
return False
|
|
||||||
if path[1] != 134 | HARDENED:
|
|
||||||
return False
|
|
||||||
if path[2] < HARDENED or path[2] > 1000000 | HARDENED:
|
|
||||||
return False
|
|
||||||
return True
|
|
||||||
|
@ -4,13 +4,10 @@ from trezor.messages.LiskMessageSignature import LiskMessageSignature
|
|||||||
from trezor.utils import HashWriter
|
from trezor.utils import HashWriter
|
||||||
|
|
||||||
from apps.common import paths
|
from apps.common import paths
|
||||||
from apps.common.keychain import with_slip44_keychain
|
from apps.common.keychain import auto_keychain
|
||||||
from apps.common.signverify import require_confirm_sign_message
|
from apps.common.signverify import require_confirm_sign_message
|
||||||
from apps.common.writers import write_bitcoin_varint
|
from apps.common.writers import write_bitcoin_varint
|
||||||
|
|
||||||
from . import CURVE, SLIP44_ID
|
|
||||||
from .helpers import validate_full_path
|
|
||||||
|
|
||||||
|
|
||||||
def message_digest(message):
|
def message_digest(message):
|
||||||
h = HashWriter(sha256())
|
h = HashWriter(sha256())
|
||||||
@ -22,9 +19,9 @@ def message_digest(message):
|
|||||||
return sha256(h.get_digest()).digest()
|
return sha256(h.get_digest()).digest()
|
||||||
|
|
||||||
|
|
||||||
@with_slip44_keychain(SLIP44_ID, CURVE, allow_testnet=True)
|
@auto_keychain(__name__)
|
||||||
async def sign_message(ctx, msg, keychain):
|
async def sign_message(ctx, msg, keychain):
|
||||||
await paths.validate_path(ctx, validate_full_path, keychain, msg.address_n, CURVE)
|
await paths.validate_path(ctx, keychain, msg.address_n)
|
||||||
await require_confirm_sign_message(ctx, "Lisk", msg.message)
|
await require_confirm_sign_message(ctx, "Lisk", msg.message)
|
||||||
|
|
||||||
node = keychain.derive(msg.address_n)
|
node = keychain.derive(msg.address_n)
|
||||||
|
@ -8,15 +8,15 @@ from trezor.messages.LiskSignedTx import LiskSignedTx
|
|||||||
from trezor.utils import HashWriter
|
from trezor.utils import HashWriter
|
||||||
|
|
||||||
from apps.common import paths
|
from apps.common import paths
|
||||||
from apps.common.keychain import with_slip44_keychain
|
from apps.common.keychain import auto_keychain
|
||||||
|
|
||||||
from . import CURVE, SLIP44_ID, layout
|
from . import layout
|
||||||
from .helpers import get_address_from_public_key, validate_full_path
|
from .helpers import get_address_from_public_key
|
||||||
|
|
||||||
|
|
||||||
@with_slip44_keychain(SLIP44_ID, CURVE, allow_testnet=True)
|
@auto_keychain(__name__)
|
||||||
async def sign_tx(ctx, msg, keychain):
|
async def sign_tx(ctx, msg, keychain):
|
||||||
await paths.validate_path(ctx, validate_full_path, keychain, msg.address_n, CURVE)
|
await paths.validate_path(ctx, keychain, msg.address_n)
|
||||||
|
|
||||||
pubkey, seckey = _get_keys(keychain, msg)
|
pubkey, seckey = _get_keys(keychain, msg)
|
||||||
transaction = _update_raw_tx(msg.transaction, pubkey)
|
transaction = _update_raw_tx(msg.transaction, pubkey)
|
||||||
|
@ -5,10 +5,11 @@ from trezor.ui.text import Text
|
|||||||
|
|
||||||
from apps.common.confirm import require_confirm
|
from apps.common.confirm import require_confirm
|
||||||
from apps.common.keychain import get_keychain
|
from apps.common.keychain import get_keychain
|
||||||
|
from apps.common.paths import AlwaysMatchingSchema
|
||||||
|
|
||||||
|
|
||||||
async def cipher_key_value(ctx, msg):
|
async def cipher_key_value(ctx, msg):
|
||||||
keychain = await get_keychain(ctx, "secp256k1", [[]])
|
keychain = await get_keychain(ctx, "secp256k1", [AlwaysMatchingSchema])
|
||||||
|
|
||||||
if len(msg.value) % 16 > 0:
|
if len(msg.value) % 16 > 0:
|
||||||
raise wire.DataError("Value length must be a multiple of 16")
|
raise wire.DataError("Value length must be a multiple of 16")
|
||||||
|
@ -9,6 +9,7 @@ from trezor.utils import chunks
|
|||||||
from apps.common import HARDENED
|
from apps.common import HARDENED
|
||||||
from apps.common.confirm import require_confirm
|
from apps.common.confirm import require_confirm
|
||||||
from apps.common.keychain import get_keychain
|
from apps.common.keychain import get_keychain
|
||||||
|
from apps.common.paths import AlwaysMatchingSchema
|
||||||
|
|
||||||
from .sign_identity import serialize_identity, serialize_identity_without_proto
|
from .sign_identity import serialize_identity, serialize_identity_without_proto
|
||||||
|
|
||||||
@ -17,7 +18,7 @@ async def get_ecdh_session_key(ctx, msg):
|
|||||||
if msg.ecdsa_curve_name is None:
|
if msg.ecdsa_curve_name is None:
|
||||||
msg.ecdsa_curve_name = "secp256k1"
|
msg.ecdsa_curve_name = "secp256k1"
|
||||||
|
|
||||||
keychain = await get_keychain(ctx, msg.ecdsa_curve_name, [[]])
|
keychain = await get_keychain(ctx, msg.ecdsa_curve_name, [AlwaysMatchingSchema])
|
||||||
identity = serialize_identity(msg.identity)
|
identity = serialize_identity(msg.identity)
|
||||||
|
|
||||||
await require_confirm_ecdh_session_key(ctx, msg.identity)
|
await require_confirm_ecdh_session_key(ctx, msg.identity)
|
||||||
|
@ -9,13 +9,14 @@ from trezor.utils import chunks
|
|||||||
from apps.common import HARDENED, coins
|
from apps.common import HARDENED, coins
|
||||||
from apps.common.confirm import require_confirm
|
from apps.common.confirm import require_confirm
|
||||||
from apps.common.keychain import get_keychain
|
from apps.common.keychain import get_keychain
|
||||||
|
from apps.common.paths import AlwaysMatchingSchema
|
||||||
|
|
||||||
|
|
||||||
async def sign_identity(ctx, msg):
|
async def sign_identity(ctx, msg):
|
||||||
if msg.ecdsa_curve_name is None:
|
if msg.ecdsa_curve_name is None:
|
||||||
msg.ecdsa_curve_name = "secp256k1"
|
msg.ecdsa_curve_name = "secp256k1"
|
||||||
|
|
||||||
keychain = await get_keychain(ctx, msg.ecdsa_curve_name, [[]])
|
keychain = await get_keychain(ctx, msg.ecdsa_curve_name, [AlwaysMatchingSchema])
|
||||||
identity = serialize_identity(msg.identity)
|
identity = serialize_identity(msg.identity)
|
||||||
|
|
||||||
await require_confirm_sign_identity(ctx, msg.identity, msg.challenge_visual)
|
await require_confirm_sign_identity(ctx, msg.identity, msg.challenge_visual)
|
||||||
|
@ -1,8 +1,11 @@
|
|||||||
from trezor import wire
|
from trezor import wire
|
||||||
from trezor.messages import MessageType
|
from trezor.messages import MessageType
|
||||||
|
|
||||||
|
from apps.common.paths import PATTERN_SEP5
|
||||||
|
|
||||||
CURVE = "ed25519"
|
CURVE = "ed25519"
|
||||||
SLIP44_ID = 128
|
SLIP44_ID = 128
|
||||||
|
PATTERN = PATTERN_SEP5
|
||||||
|
|
||||||
|
|
||||||
def boot() -> None:
|
def boot() -> None:
|
||||||
|
@ -1,19 +1,17 @@
|
|||||||
from trezor.messages.MoneroAddress import MoneroAddress
|
from trezor.messages.MoneroAddress import MoneroAddress
|
||||||
|
|
||||||
from apps.common import paths
|
from apps.common import paths
|
||||||
from apps.common.keychain import with_slip44_keychain
|
from apps.common.keychain import auto_keychain
|
||||||
from apps.common.layout import address_n_to_str, show_qr
|
from apps.common.layout import address_n_to_str, show_qr
|
||||||
from apps.monero import CURVE, SLIP44_ID, misc
|
from apps.monero import misc
|
||||||
from apps.monero.layout import confirms
|
from apps.monero.layout import confirms
|
||||||
from apps.monero.xmr import addresses, crypto, monero
|
from apps.monero.xmr import addresses, crypto, monero
|
||||||
from apps.monero.xmr.networks import net_version
|
from apps.monero.xmr.networks import net_version
|
||||||
|
|
||||||
|
|
||||||
@with_slip44_keychain(SLIP44_ID, CURVE, allow_testnet=True)
|
@auto_keychain(__name__)
|
||||||
async def get_address(ctx, msg, keychain):
|
async def get_address(ctx, msg, keychain):
|
||||||
await paths.validate_path(
|
await paths.validate_path(ctx, keychain, msg.address_n)
|
||||||
ctx, misc.validate_full_path, keychain, msg.address_n, CURVE
|
|
||||||
)
|
|
||||||
|
|
||||||
creds = misc.get_creds(keychain, msg.address_n, msg.network_type)
|
creds = misc.get_creds(keychain, msg.address_n, msg.network_type)
|
||||||
addr = creds.address
|
addr = creds.address
|
||||||
|
@ -20,8 +20,8 @@ from trezor.messages.MoneroGetTxKeyAck import MoneroGetTxKeyAck
|
|||||||
from trezor.messages.MoneroGetTxKeyRequest import MoneroGetTxKeyRequest
|
from trezor.messages.MoneroGetTxKeyRequest import MoneroGetTxKeyRequest
|
||||||
|
|
||||||
from apps.common import paths
|
from apps.common import paths
|
||||||
from apps.common.keychain import with_slip44_keychain
|
from apps.common.keychain import auto_keychain
|
||||||
from apps.monero import CURVE, SLIP44_ID, misc
|
from apps.monero import misc
|
||||||
from apps.monero.layout import confirms
|
from apps.monero.layout import confirms
|
||||||
from apps.monero.xmr import crypto
|
from apps.monero.xmr import crypto
|
||||||
from apps.monero.xmr.crypto import chacha_poly
|
from apps.monero.xmr.crypto import chacha_poly
|
||||||
@ -30,11 +30,9 @@ _GET_TX_KEY_REASON_TX_KEY = 0
|
|||||||
_GET_TX_KEY_REASON_TX_DERIVATION = 1
|
_GET_TX_KEY_REASON_TX_DERIVATION = 1
|
||||||
|
|
||||||
|
|
||||||
@with_slip44_keychain(SLIP44_ID, CURVE, allow_testnet=True)
|
@auto_keychain(__name__)
|
||||||
async def get_tx_keys(ctx, msg: MoneroGetTxKeyRequest, keychain):
|
async def get_tx_keys(ctx, msg: MoneroGetTxKeyRequest, keychain):
|
||||||
await paths.validate_path(
|
await paths.validate_path(ctx, keychain, msg.address_n)
|
||||||
ctx, misc.validate_full_path, keychain, msg.address_n, CURVE
|
|
||||||
)
|
|
||||||
|
|
||||||
do_deriv = msg.reason == _GET_TX_KEY_REASON_TX_DERIVATION
|
do_deriv = msg.reason == _GET_TX_KEY_REASON_TX_DERIVATION
|
||||||
await confirms.require_confirm_tx_key(ctx, export_key=not do_deriv)
|
await confirms.require_confirm_tx_key(ctx, export_key=not do_deriv)
|
||||||
|
@ -2,17 +2,15 @@ from trezor.messages.MoneroGetWatchKey import MoneroGetWatchKey
|
|||||||
from trezor.messages.MoneroWatchKey import MoneroWatchKey
|
from trezor.messages.MoneroWatchKey import MoneroWatchKey
|
||||||
|
|
||||||
from apps.common import paths
|
from apps.common import paths
|
||||||
from apps.common.keychain import with_slip44_keychain
|
from apps.common.keychain import auto_keychain
|
||||||
from apps.monero import CURVE, SLIP44_ID, misc
|
from apps.monero import misc
|
||||||
from apps.monero.layout import confirms
|
from apps.monero.layout import confirms
|
||||||
from apps.monero.xmr import crypto
|
from apps.monero.xmr import crypto
|
||||||
|
|
||||||
|
|
||||||
@with_slip44_keychain(SLIP44_ID, CURVE, allow_testnet=True)
|
@auto_keychain(__name__)
|
||||||
async def get_watch_only(ctx, msg: MoneroGetWatchKey, keychain):
|
async def get_watch_only(ctx, msg: MoneroGetWatchKey, keychain):
|
||||||
await paths.validate_path(
|
await paths.validate_path(ctx, keychain, msg.address_n)
|
||||||
ctx, misc.validate_full_path, keychain, msg.address_n, CURVE
|
|
||||||
)
|
|
||||||
|
|
||||||
await confirms.require_confirm_watchkey(ctx)
|
await confirms.require_confirm_watchkey(ctx)
|
||||||
|
|
||||||
|
@ -11,14 +11,14 @@ from trezor.messages.MoneroKeyImageSyncStepAck import MoneroKeyImageSyncStepAck
|
|||||||
from trezor.messages.MoneroKeyImageSyncStepRequest import MoneroKeyImageSyncStepRequest
|
from trezor.messages.MoneroKeyImageSyncStepRequest import MoneroKeyImageSyncStepRequest
|
||||||
|
|
||||||
from apps.common import paths
|
from apps.common import paths
|
||||||
from apps.common.keychain import with_slip44_keychain
|
from apps.common.keychain import auto_keychain
|
||||||
from apps.monero import CURVE, SLIP44_ID, misc
|
from apps.monero import misc
|
||||||
from apps.monero.layout import confirms
|
from apps.monero.layout import confirms
|
||||||
from apps.monero.xmr import crypto, key_image, monero
|
from apps.monero.xmr import crypto, key_image, monero
|
||||||
from apps.monero.xmr.crypto import chacha_poly
|
from apps.monero.xmr.crypto import chacha_poly
|
||||||
|
|
||||||
|
|
||||||
@with_slip44_keychain(SLIP44_ID, CURVE, allow_testnet=True)
|
@auto_keychain(__name__)
|
||||||
async def key_image_sync(ctx, msg, keychain):
|
async def key_image_sync(ctx, msg, keychain):
|
||||||
state = KeyImageSync()
|
state = KeyImageSync()
|
||||||
|
|
||||||
@ -45,9 +45,7 @@ class KeyImageSync:
|
|||||||
|
|
||||||
|
|
||||||
async def _init_step(s, ctx, msg, keychain):
|
async def _init_step(s, ctx, msg, keychain):
|
||||||
await paths.validate_path(
|
await paths.validate_path(ctx, keychain, msg.address_n)
|
||||||
ctx, misc.validate_full_path, keychain, msg.address_n, CURVE
|
|
||||||
)
|
|
||||||
|
|
||||||
s.creds = misc.get_creds(keychain, msg.address_n, msg.network_type)
|
s.creds = misc.get_creds(keychain, msg.address_n, msg.network_type)
|
||||||
|
|
||||||
|
@ -10,14 +10,14 @@ from trezor.messages.MoneroLiveRefreshStepAck import MoneroLiveRefreshStepAck
|
|||||||
from trezor.messages.MoneroLiveRefreshStepRequest import MoneroLiveRefreshStepRequest
|
from trezor.messages.MoneroLiveRefreshStepRequest import MoneroLiveRefreshStepRequest
|
||||||
|
|
||||||
from apps.common import paths
|
from apps.common import paths
|
||||||
from apps.common.keychain import with_slip44_keychain
|
from apps.common.keychain import auto_keychain
|
||||||
from apps.monero import CURVE, SLIP44_ID, misc
|
from apps.monero import misc
|
||||||
from apps.monero.layout import confirms
|
from apps.monero.layout import confirms
|
||||||
from apps.monero.xmr import crypto, key_image, monero
|
from apps.monero.xmr import crypto, key_image, monero
|
||||||
from apps.monero.xmr.crypto import chacha_poly
|
from apps.monero.xmr.crypto import chacha_poly
|
||||||
|
|
||||||
|
|
||||||
@with_slip44_keychain(SLIP44_ID, CURVE, allow_testnet=True)
|
@auto_keychain(__name__)
|
||||||
async def live_refresh(ctx, msg: MoneroLiveRefreshStartRequest, keychain):
|
async def live_refresh(ctx, msg: MoneroLiveRefreshStartRequest, keychain):
|
||||||
state = LiveRefreshState()
|
state = LiveRefreshState()
|
||||||
|
|
||||||
@ -47,9 +47,7 @@ class LiveRefreshState:
|
|||||||
async def _init_step(
|
async def _init_step(
|
||||||
s: LiveRefreshState, ctx, msg: MoneroLiveRefreshStartRequest, keychain
|
s: LiveRefreshState, ctx, msg: MoneroLiveRefreshStartRequest, keychain
|
||||||
):
|
):
|
||||||
await paths.validate_path(
|
await paths.validate_path(ctx, keychain, msg.address_n)
|
||||||
ctx, misc.validate_full_path, keychain, msg.address_n, CURVE
|
|
||||||
)
|
|
||||||
|
|
||||||
if not storage.cache.get(storage.cache.APP_MONERO_LIVE_REFRESH):
|
if not storage.cache.get(storage.cache.APP_MONERO_LIVE_REFRESH):
|
||||||
await confirms.require_confirm_live_refresh(ctx)
|
await confirms.require_confirm_live_refresh(ctx)
|
||||||
|
@ -1,5 +1,3 @@
|
|||||||
from apps.common import HARDENED
|
|
||||||
|
|
||||||
if False:
|
if False:
|
||||||
from typing import Tuple
|
from typing import Tuple
|
||||||
from apps.monero.xmr.types import Sc25519
|
from apps.monero.xmr.types import Sc25519
|
||||||
@ -18,22 +16,6 @@ def get_creds(keychain, address_n=None, network_type=None):
|
|||||||
return creds
|
return creds
|
||||||
|
|
||||||
|
|
||||||
def validate_full_path(path: list) -> bool:
|
|
||||||
"""
|
|
||||||
Validates derivation path to equal 44'/128'/a',
|
|
||||||
where `a` is an account index from 0 to 1 000 000.
|
|
||||||
"""
|
|
||||||
if len(path) != 3:
|
|
||||||
return False
|
|
||||||
if path[0] != 44 | HARDENED:
|
|
||||||
return False
|
|
||||||
if path[1] != 128 | HARDENED:
|
|
||||||
return False
|
|
||||||
if path[2] < HARDENED or path[2] > 1000000 | HARDENED:
|
|
||||||
return False
|
|
||||||
return True
|
|
||||||
|
|
||||||
|
|
||||||
def compute_tx_key(
|
def compute_tx_key(
|
||||||
spend_key_private: Sc25519,
|
spend_key_private: Sc25519,
|
||||||
tx_prefix_hash: bytes,
|
tx_prefix_hash: bytes,
|
||||||
|
@ -3,12 +3,11 @@ import gc
|
|||||||
from trezor import log, utils, wire
|
from trezor import log, utils, wire
|
||||||
from trezor.messages import MessageType
|
from trezor.messages import MessageType
|
||||||
|
|
||||||
from apps.common.keychain import with_slip44_keychain
|
from apps.common.keychain import auto_keychain
|
||||||
from apps.monero import CURVE, SLIP44_ID
|
|
||||||
from apps.monero.signing.state import State
|
from apps.monero.signing.state import State
|
||||||
|
|
||||||
|
|
||||||
@with_slip44_keychain(SLIP44_ID, CURVE, allow_testnet=True)
|
@auto_keychain(__name__)
|
||||||
async def sign_tx(ctx, received_msg, keychain):
|
async def sign_tx(ctx, received_msg, keychain):
|
||||||
state = State(ctx)
|
state = State(ctx)
|
||||||
mods = utils.unimport_begin()
|
mods = utils.unimport_begin()
|
||||||
|
@ -4,7 +4,7 @@ Initializes a new transaction.
|
|||||||
|
|
||||||
import gc
|
import gc
|
||||||
|
|
||||||
from apps.monero import CURVE, misc, signing
|
from apps.monero import misc, signing
|
||||||
from apps.monero.layout import confirms
|
from apps.monero.layout import confirms
|
||||||
from apps.monero.signing.state import State
|
from apps.monero.signing.state import State
|
||||||
from apps.monero.xmr import crypto, monero
|
from apps.monero.xmr import crypto, monero
|
||||||
@ -31,9 +31,7 @@ async def init_transaction(
|
|||||||
from apps.monero.signing import offloading_keys
|
from apps.monero.signing import offloading_keys
|
||||||
from apps.common import paths
|
from apps.common import paths
|
||||||
|
|
||||||
await paths.validate_path(
|
await paths.validate_path(state.ctx, keychain, address_n)
|
||||||
state.ctx, misc.validate_full_path, keychain, address_n, CURVE
|
|
||||||
)
|
|
||||||
|
|
||||||
state.creds = misc.get_creds(keychain, address_n, network_type)
|
state.creds = misc.get_creds(keychain, address_n, network_type)
|
||||||
state.client_version = tsx_data.client_version or 0
|
state.client_version = tsx_data.client_version or 0
|
||||||
|
@ -1,9 +1,16 @@
|
|||||||
from trezor import wire
|
from trezor import wire
|
||||||
from trezor.messages import MessageType
|
from trezor.messages import MessageType
|
||||||
|
|
||||||
|
from apps.common.paths import PATTERN_SEP5
|
||||||
|
|
||||||
CURVE = "ed25519-keccak"
|
CURVE = "ed25519-keccak"
|
||||||
SLIP44_ID = 43
|
SLIP44_ID = 43
|
||||||
|
|
||||||
|
PATTERNS = (
|
||||||
|
PATTERN_SEP5,
|
||||||
|
"m/44'/coin_type'/account'/0'/0'", # NanoWallet compatibility
|
||||||
|
)
|
||||||
|
|
||||||
|
|
||||||
def boot() -> None:
|
def boot() -> None:
|
||||||
wire.add(MessageType.NEMGetAddress, __name__, "get_address")
|
wire.add(MessageType.NEMGetAddress, __name__, "get_address")
|
||||||
|
@ -4,16 +4,16 @@ from apps.common.keychain import with_slip44_keychain
|
|||||||
from apps.common.layout import address_n_to_str, show_address, show_qr
|
from apps.common.layout import address_n_to_str, show_address, show_qr
|
||||||
from apps.common.paths import validate_path
|
from apps.common.paths import validate_path
|
||||||
|
|
||||||
from . import CURVE, SLIP44_ID
|
from . import CURVE, PATTERNS, SLIP44_ID
|
||||||
from .helpers import check_path, get_network_str
|
from .helpers import check_path, get_network_str
|
||||||
from .validators import validate_network
|
from .validators import validate_network
|
||||||
|
|
||||||
|
|
||||||
@with_slip44_keychain(SLIP44_ID, CURVE, allow_testnet=True)
|
@with_slip44_keychain(*PATTERNS, slip44_id=SLIP44_ID, curve=CURVE)
|
||||||
async def get_address(ctx, msg, keychain):
|
async def get_address(ctx, msg, keychain):
|
||||||
network = validate_network(msg.network)
|
network = validate_network(msg.network)
|
||||||
await validate_path(
|
await validate_path(
|
||||||
ctx, check_path, keychain, msg.address_n, CURVE, network=network
|
ctx, keychain, msg.address_n, check_path(msg.address_n, msg.network)
|
||||||
)
|
)
|
||||||
|
|
||||||
node = keychain.derive(msg.address_n)
|
node = keychain.derive(msg.address_n)
|
||||||
|
@ -1,6 +1,8 @@
|
|||||||
from micropython import const
|
from micropython import const
|
||||||
|
|
||||||
from apps.common import HARDENED
|
from apps.common import HARDENED, paths
|
||||||
|
|
||||||
|
from . import SLIP44_ID
|
||||||
|
|
||||||
NEM_NETWORK_MAINNET = const(0x68)
|
NEM_NETWORK_MAINNET = const(0x68)
|
||||||
NEM_NETWORK_TESTNET = const(0x98)
|
NEM_NETWORK_TESTNET = const(0x98)
|
||||||
@ -38,26 +40,18 @@ def get_network_str(network: int) -> str:
|
|||||||
return "Mijin"
|
return "Mijin"
|
||||||
|
|
||||||
|
|
||||||
def check_path(path: list, network=None) -> bool:
|
def check_path(path: paths.Bip32Path, network: int) -> bool:
|
||||||
"""
|
"""Validates that the appropriate coin_type is set for the given network."""
|
||||||
Validates derivation path to fit 44'/43'/a' or 44'/43'/a'/0'/0',
|
if len(path) < 2:
|
||||||
where `a` is an account number. We believe the path should be
|
|
||||||
44'/43'/a', but for compatibility reasons with NEM's NanoWallet
|
|
||||||
we allow 44'/43'/a'/0'/0' as well.
|
|
||||||
Testnet is also allowed: 44'/1'/a'{/0'/0'}
|
|
||||||
"""
|
|
||||||
length = len(path)
|
|
||||||
if length != 3 and length != 5:
|
|
||||||
return False
|
return False
|
||||||
if path[0] != 44 | HARDENED:
|
|
||||||
|
coin_type = path[1] - HARDENED
|
||||||
|
|
||||||
|
if network == NEM_NETWORK_TESTNET:
|
||||||
|
return coin_type == 1
|
||||||
|
|
||||||
|
if network in (NEM_NETWORK_MAINNET, NEM_NETWORK_MIJIN):
|
||||||
|
return coin_type == SLIP44_ID
|
||||||
|
|
||||||
|
# unknown network
|
||||||
return False
|
return False
|
||||||
if not (
|
|
||||||
path[1] == 43 | HARDENED
|
|
||||||
or (network == NEM_NETWORK_TESTNET and path[1] == 1 | HARDENED)
|
|
||||||
):
|
|
||||||
return False
|
|
||||||
if path[2] < HARDENED or path[2] > 1000000 | HARDENED:
|
|
||||||
return False
|
|
||||||
if length == 5 and (path[3] != 0 | HARDENED or path[4] != 0 | HARDENED):
|
|
||||||
return False
|
|
||||||
return True
|
|
||||||
|
@ -7,22 +7,20 @@ from apps.common import seed
|
|||||||
from apps.common.keychain import with_slip44_keychain
|
from apps.common.keychain import with_slip44_keychain
|
||||||
from apps.common.paths import validate_path
|
from apps.common.paths import validate_path
|
||||||
|
|
||||||
from . import CURVE, SLIP44_ID, mosaic, multisig, namespace, transfer
|
from . import CURVE, PATTERNS, SLIP44_ID, mosaic, multisig, namespace, transfer
|
||||||
from .helpers import NEM_HASH_ALG, check_path
|
from .helpers import NEM_HASH_ALG, check_path
|
||||||
from .validators import validate
|
from .validators import validate
|
||||||
|
|
||||||
|
|
||||||
@with_slip44_keychain(SLIP44_ID, CURVE, allow_testnet=True)
|
@with_slip44_keychain(*PATTERNS, slip44_id=SLIP44_ID, curve=CURVE)
|
||||||
async def sign_tx(ctx, msg: NEMSignTx, keychain):
|
async def sign_tx(ctx, msg: NEMSignTx, keychain):
|
||||||
validate(msg)
|
validate(msg)
|
||||||
|
|
||||||
await validate_path(
|
await validate_path(
|
||||||
ctx,
|
ctx,
|
||||||
check_path,
|
|
||||||
keychain,
|
keychain,
|
||||||
msg.transaction.address_n,
|
msg.transaction.address_n,
|
||||||
CURVE,
|
check_path(msg.transaction.address_n, msg.transaction.network),
|
||||||
network=msg.transaction.network,
|
|
||||||
)
|
)
|
||||||
|
|
||||||
node = keychain.derive(msg.transaction.address_n)
|
node = keychain.derive(msg.transaction.address_n)
|
||||||
|
@ -1,8 +1,11 @@
|
|||||||
from trezor import wire
|
from trezor import wire
|
||||||
from trezor.messages import MessageType
|
from trezor.messages import MessageType
|
||||||
|
|
||||||
|
from apps.common.paths import PATTERN_BIP44
|
||||||
|
|
||||||
CURVE = "secp256k1"
|
CURVE = "secp256k1"
|
||||||
SLIP44_ID = 144
|
SLIP44_ID = 144
|
||||||
|
PATTERN = PATTERN_BIP44
|
||||||
|
|
||||||
|
|
||||||
def boot() -> None:
|
def boot() -> None:
|
||||||
|
@ -2,21 +2,19 @@ from trezor.messages.RippleAddress import RippleAddress
|
|||||||
from trezor.messages.RippleGetAddress import RippleGetAddress
|
from trezor.messages.RippleGetAddress import RippleGetAddress
|
||||||
|
|
||||||
from apps.common import paths
|
from apps.common import paths
|
||||||
from apps.common.keychain import with_slip44_keychain
|
from apps.common.keychain import auto_keychain
|
||||||
from apps.common.layout import address_n_to_str, show_address, show_qr
|
from apps.common.layout import address_n_to_str, show_address, show_qr
|
||||||
|
|
||||||
from . import CURVE, SLIP44_ID, helpers
|
from .helpers import address_from_public_key
|
||||||
|
|
||||||
|
|
||||||
@with_slip44_keychain(SLIP44_ID, CURVE, allow_testnet=True)
|
@auto_keychain(__name__)
|
||||||
async def get_address(ctx, msg: RippleGetAddress, keychain):
|
async def get_address(ctx, msg: RippleGetAddress, keychain):
|
||||||
await paths.validate_path(
|
await paths.validate_path(ctx, keychain, msg.address_n)
|
||||||
ctx, helpers.validate_full_path, keychain, msg.address_n, CURVE
|
|
||||||
)
|
|
||||||
|
|
||||||
node = keychain.derive(msg.address_n)
|
node = keychain.derive(msg.address_n)
|
||||||
pubkey = node.public_key()
|
pubkey = node.public_key()
|
||||||
address = helpers.address_from_public_key(pubkey)
|
address = address_from_public_key(pubkey)
|
||||||
|
|
||||||
if msg.show_display:
|
if msg.show_display:
|
||||||
desc = address_n_to_str(msg.address_n)
|
desc = address_n_to_str(msg.address_n)
|
||||||
|
@ -2,8 +2,6 @@ from micropython import const
|
|||||||
|
|
||||||
from trezor.crypto.hashlib import ripemd160, sha256
|
from trezor.crypto.hashlib import ripemd160, sha256
|
||||||
|
|
||||||
from apps.common import HARDENED
|
|
||||||
|
|
||||||
from . import base58_ripple
|
from . import base58_ripple
|
||||||
|
|
||||||
# HASH_TX_ID = const(0x54584E00) # 'TXN'
|
# HASH_TX_ID = const(0x54584E00) # 'TXN'
|
||||||
@ -50,25 +48,3 @@ def decode_address(address: str):
|
|||||||
"""Returns so called Account ID"""
|
"""Returns so called Account ID"""
|
||||||
adr = base58_ripple.decode_check(address)
|
adr = base58_ripple.decode_check(address)
|
||||||
return adr[1:]
|
return adr[1:]
|
||||||
|
|
||||||
|
|
||||||
def validate_full_path(path: list) -> bool:
|
|
||||||
"""
|
|
||||||
Validates derivation path to equal 44'/144'/a'/0/0,
|
|
||||||
where `a` is an account index from 0 to 1 000 000.
|
|
||||||
Similar to Ethereum this should be 44'/144'/a', but for
|
|
||||||
compatibility with other HW vendors we use 44'/144'/a'/0/0.
|
|
||||||
"""
|
|
||||||
if len(path) != 5:
|
|
||||||
return False
|
|
||||||
if path[0] != 44 | HARDENED:
|
|
||||||
return False
|
|
||||||
if path[1] != 144 | HARDENED:
|
|
||||||
return False
|
|
||||||
if path[2] < HARDENED or path[2] > 1000000 | HARDENED:
|
|
||||||
return False
|
|
||||||
if path[3] != 0:
|
|
||||||
return False
|
|
||||||
if path[4] != 0:
|
|
||||||
return False
|
|
||||||
return True
|
|
||||||
|
@ -6,19 +6,16 @@ from trezor.messages.RippleSignTx import RippleSignTx
|
|||||||
from trezor.wire import ProcessError
|
from trezor.wire import ProcessError
|
||||||
|
|
||||||
from apps.common import paths
|
from apps.common import paths
|
||||||
from apps.common.keychain import with_slip44_keychain
|
from apps.common.keychain import auto_keychain
|
||||||
|
|
||||||
from . import CURVE, SLIP44_ID, helpers, layout
|
from . import helpers, layout
|
||||||
from .serialize import serialize
|
from .serialize import serialize
|
||||||
|
|
||||||
|
|
||||||
@with_slip44_keychain(SLIP44_ID, CURVE, allow_testnet=True)
|
@auto_keychain(__name__)
|
||||||
async def sign_tx(ctx, msg: RippleSignTx, keychain):
|
async def sign_tx(ctx, msg: RippleSignTx, keychain):
|
||||||
validate(msg)
|
validate(msg)
|
||||||
|
await paths.validate_path(ctx, keychain, msg.address_n)
|
||||||
await paths.validate_path(
|
|
||||||
ctx, helpers.validate_full_path, keychain, msg.address_n, CURVE
|
|
||||||
)
|
|
||||||
|
|
||||||
node = keychain.derive(msg.address_n)
|
node = keychain.derive(msg.address_n)
|
||||||
source_address = helpers.address_from_public_key(node.public_key())
|
source_address = helpers.address_from_public_key(node.public_key())
|
||||||
|
@ -1,8 +1,11 @@
|
|||||||
from trezor import wire
|
from trezor import wire
|
||||||
from trezor.messages import MessageType
|
from trezor.messages import MessageType
|
||||||
|
|
||||||
|
from apps.common.paths import PATTERN_SEP5
|
||||||
|
|
||||||
CURVE = "ed25519"
|
CURVE = "ed25519"
|
||||||
SLIP44_ID = 148
|
SLIP44_ID = 148
|
||||||
|
PATTERN = PATTERN_SEP5
|
||||||
|
|
||||||
|
|
||||||
def boot() -> None:
|
def boot() -> None:
|
||||||
|
@ -2,17 +2,15 @@ from trezor.messages.StellarAddress import StellarAddress
|
|||||||
from trezor.messages.StellarGetAddress import StellarGetAddress
|
from trezor.messages.StellarGetAddress import StellarGetAddress
|
||||||
|
|
||||||
from apps.common import paths, seed
|
from apps.common import paths, seed
|
||||||
from apps.common.keychain import with_slip44_keychain
|
from apps.common.keychain import auto_keychain
|
||||||
from apps.common.layout import address_n_to_str, show_address, show_qr
|
from apps.common.layout import address_n_to_str, show_address, show_qr
|
||||||
|
|
||||||
from . import CURVE, SLIP44_ID, helpers
|
from . import helpers
|
||||||
|
|
||||||
|
|
||||||
@with_slip44_keychain(SLIP44_ID, CURVE, allow_testnet=True)
|
@auto_keychain(__name__)
|
||||||
async def get_address(ctx, msg: StellarGetAddress, keychain):
|
async def get_address(ctx, msg: StellarGetAddress, keychain):
|
||||||
await paths.validate_path(
|
await paths.validate_path(ctx, keychain, msg.address_n)
|
||||||
ctx, helpers.validate_full_path, keychain, msg.address_n, CURVE
|
|
||||||
)
|
|
||||||
|
|
||||||
node = keychain.derive(msg.address_n)
|
node = keychain.derive(msg.address_n)
|
||||||
pubkey = seed.remove_ed25519_prefix(node.public_key())
|
pubkey = seed.remove_ed25519_prefix(node.public_key())
|
||||||
|
@ -3,8 +3,6 @@ import ustruct
|
|||||||
from trezor.crypto import base32
|
from trezor.crypto import base32
|
||||||
from trezor.wire import ProcessError
|
from trezor.wire import ProcessError
|
||||||
|
|
||||||
from apps.common import HARDENED
|
|
||||||
|
|
||||||
|
|
||||||
def public_key_from_address(address: str) -> bytes:
|
def public_key_from_address(address: str) -> bytes:
|
||||||
"""Extracts public key from an address
|
"""Extracts public key from an address
|
||||||
@ -26,22 +24,6 @@ def address_from_public_key(pubkey: bytes):
|
|||||||
return base32.encode(address)
|
return base32.encode(address)
|
||||||
|
|
||||||
|
|
||||||
def validate_full_path(path: list) -> bool:
|
|
||||||
"""
|
|
||||||
Validates derivation path to equal 44'/148'/a',
|
|
||||||
where `a` is an account index from 0 to 1 000 000.
|
|
||||||
"""
|
|
||||||
if len(path) != 3:
|
|
||||||
return False
|
|
||||||
if path[0] != 44 | HARDENED:
|
|
||||||
return False
|
|
||||||
if path[1] != 148 | HARDENED:
|
|
||||||
return False
|
|
||||||
if path[2] < HARDENED or path[2] > 1000000 | HARDENED:
|
|
||||||
return False
|
|
||||||
return True
|
|
||||||
|
|
||||||
|
|
||||||
def _crc16_checksum_verify(data: bytes, checksum: bytes):
|
def _crc16_checksum_verify(data: bytes, checksum: bytes):
|
||||||
if _crc16_checksum(data) != checksum:
|
if _crc16_checksum(data) != checksum:
|
||||||
raise ProcessError("Invalid address checksum")
|
raise ProcessError("Invalid address checksum")
|
||||||
|
@ -8,17 +8,15 @@ from trezor.messages.StellarTxOpRequest import StellarTxOpRequest
|
|||||||
from trezor.wire import ProcessError
|
from trezor.wire import ProcessError
|
||||||
|
|
||||||
from apps.common import paths, seed
|
from apps.common import paths, seed
|
||||||
from apps.common.keychain import with_slip44_keychain
|
from apps.common.keychain import auto_keychain
|
||||||
|
|
||||||
from . import CURVE, SLIP44_ID, consts, helpers, layout, writers
|
from . import consts, helpers, layout, writers
|
||||||
from .operations import process_operation
|
from .operations import process_operation
|
||||||
|
|
||||||
|
|
||||||
@with_slip44_keychain(SLIP44_ID, CURVE, allow_testnet=True)
|
@auto_keychain(__name__)
|
||||||
async def sign_tx(ctx, msg: StellarSignTx, keychain):
|
async def sign_tx(ctx, msg: StellarSignTx, keychain):
|
||||||
await paths.validate_path(
|
await paths.validate_path(ctx, keychain, msg.address_n)
|
||||||
ctx, helpers.validate_full_path, keychain, msg.address_n, CURVE
|
|
||||||
)
|
|
||||||
|
|
||||||
node = keychain.derive(msg.address_n)
|
node = keychain.derive(msg.address_n)
|
||||||
pubkey = seed.remove_ed25519_prefix(node.public_key())
|
pubkey = seed.remove_ed25519_prefix(node.public_key())
|
||||||
|
@ -1,8 +1,14 @@
|
|||||||
from trezor import wire
|
from trezor import wire
|
||||||
from trezor.messages import MessageType
|
from trezor.messages import MessageType
|
||||||
|
|
||||||
|
from apps.common.paths import PATTERN_SEP5
|
||||||
|
|
||||||
CURVE = "ed25519"
|
CURVE = "ed25519"
|
||||||
SLIP44_ID = 1729
|
SLIP44_ID = 1729
|
||||||
|
PATTERNS = (
|
||||||
|
PATTERN_SEP5,
|
||||||
|
"m/44'/coin_type'/0'/account'", # Ledger compatibility
|
||||||
|
)
|
||||||
|
|
||||||
|
|
||||||
def boot() -> None:
|
def boot() -> None:
|
||||||
|
@ -5,14 +5,12 @@ from apps.common import paths, seed
|
|||||||
from apps.common.keychain import with_slip44_keychain
|
from apps.common.keychain import with_slip44_keychain
|
||||||
from apps.common.layout import address_n_to_str, show_address, show_qr
|
from apps.common.layout import address_n_to_str, show_address, show_qr
|
||||||
|
|
||||||
from . import CURVE, SLIP44_ID, helpers
|
from . import CURVE, PATTERNS, SLIP44_ID, helpers
|
||||||
|
|
||||||
|
|
||||||
@with_slip44_keychain(SLIP44_ID, CURVE, allow_testnet=True)
|
@with_slip44_keychain(*PATTERNS, slip44_id=SLIP44_ID, curve=CURVE)
|
||||||
async def get_address(ctx, msg, keychain):
|
async def get_address(ctx, msg, keychain):
|
||||||
await paths.validate_path(
|
await paths.validate_path(ctx, keychain, msg.address_n)
|
||||||
ctx, helpers.validate_full_path, keychain, msg.address_n, CURVE
|
|
||||||
)
|
|
||||||
|
|
||||||
node = keychain.derive(msg.address_n)
|
node = keychain.derive(msg.address_n)
|
||||||
|
|
||||||
|
@ -8,14 +8,12 @@ from apps.common import paths, seed
|
|||||||
from apps.common.confirm import require_confirm
|
from apps.common.confirm import require_confirm
|
||||||
from apps.common.keychain import with_slip44_keychain
|
from apps.common.keychain import with_slip44_keychain
|
||||||
|
|
||||||
from . import CURVE, SLIP44_ID, helpers
|
from . import CURVE, PATTERNS, SLIP44_ID, helpers
|
||||||
|
|
||||||
|
|
||||||
@with_slip44_keychain(SLIP44_ID, CURVE, allow_testnet=True)
|
@with_slip44_keychain(*PATTERNS, slip44_id=SLIP44_ID, curve=CURVE)
|
||||||
async def get_public_key(ctx, msg, keychain):
|
async def get_public_key(ctx, msg, keychain):
|
||||||
await paths.validate_path(
|
await paths.validate_path(ctx, keychain, msg.address_n)
|
||||||
ctx, helpers.validate_full_path, keychain, msg.address_n, CURVE
|
|
||||||
)
|
|
||||||
|
|
||||||
node = keychain.derive(msg.address_n)
|
node = keychain.derive(msg.address_n)
|
||||||
pk = seed.remove_ed25519_prefix(node.public_key())
|
pk = seed.remove_ed25519_prefix(node.public_key())
|
||||||
|
@ -2,7 +2,6 @@ from micropython import const
|
|||||||
|
|
||||||
from trezor.crypto import base58
|
from trezor.crypto import base58
|
||||||
|
|
||||||
from apps.common import HARDENED
|
|
||||||
from apps.common.writers import write_bytes_unchecked, write_uint8
|
from apps.common.writers import write_bytes_unchecked, write_uint8
|
||||||
|
|
||||||
TEZOS_AMOUNT_DECIMALS = const(6)
|
TEZOS_AMOUNT_DECIMALS = const(6)
|
||||||
@ -66,31 +65,6 @@ def base58_decode_check(enc, prefix=None):
|
|||||||
return decoded
|
return decoded
|
||||||
|
|
||||||
|
|
||||||
def validate_full_path(path: list) -> bool:
|
|
||||||
"""
|
|
||||||
Validates derivation path to equal 44'/1729'/a',
|
|
||||||
where `a` is an account index from 0 to 1 000 000.
|
|
||||||
Additional component added to allow ledger migration
|
|
||||||
44'/1729'/0'/b' where `b` is an account index from 0 to 1 000 000
|
|
||||||
"""
|
|
||||||
length = len(path)
|
|
||||||
if length < 3 or length > 4:
|
|
||||||
return False
|
|
||||||
if path[0] != 44 | HARDENED:
|
|
||||||
return False
|
|
||||||
if path[1] != 1729 | HARDENED:
|
|
||||||
return False
|
|
||||||
if length == 3:
|
|
||||||
if path[2] < HARDENED or path[2] > 1000000 | HARDENED:
|
|
||||||
return False
|
|
||||||
if length == 4:
|
|
||||||
if path[2] != 0 | HARDENED:
|
|
||||||
return False
|
|
||||||
if path[3] < HARDENED or path[3] > 1000000 | HARDENED:
|
|
||||||
return False
|
|
||||||
return True
|
|
||||||
|
|
||||||
|
|
||||||
def write_bool(w: bytearray, boolean: bool):
|
def write_bool(w: bytearray, boolean: bool):
|
||||||
if boolean:
|
if boolean:
|
||||||
write_uint8(w, 255)
|
write_uint8(w, 255)
|
||||||
|
@ -10,16 +10,14 @@ from apps.common import paths
|
|||||||
from apps.common.keychain import with_slip44_keychain
|
from apps.common.keychain import with_slip44_keychain
|
||||||
from apps.common.writers import write_bytes_unchecked, write_uint8, write_uint32_be
|
from apps.common.writers import write_bytes_unchecked, write_uint8, write_uint32_be
|
||||||
|
|
||||||
from . import CURVE, SLIP44_ID, helpers, layout
|
from . import CURVE, PATTERNS, SLIP44_ID, helpers, layout
|
||||||
|
|
||||||
PROPOSAL_LENGTH = const(32)
|
PROPOSAL_LENGTH = const(32)
|
||||||
|
|
||||||
|
|
||||||
@with_slip44_keychain(SLIP44_ID, CURVE, allow_testnet=True)
|
@with_slip44_keychain(*PATTERNS, slip44_id=SLIP44_ID, curve=CURVE)
|
||||||
async def sign_tx(ctx, msg, keychain):
|
async def sign_tx(ctx, msg, keychain):
|
||||||
await paths.validate_path(
|
await paths.validate_path(ctx, keychain, msg.address_n)
|
||||||
ctx, helpers.validate_full_path, keychain, msg.address_n, CURVE
|
|
||||||
)
|
|
||||||
|
|
||||||
node = keychain.derive(msg.address_n)
|
node = keychain.derive(msg.address_n)
|
||||||
|
|
||||||
|
Loading…
Reference in New Issue
Block a user