You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
trezor-firmware/core/tests/test_apps.ethereum.keychain.py

217 lines
7.0 KiB

from common import *
from storage import cache
from trezor import wire
from trezor.crypto import bip39
from apps.common.paths import HARDENED
if not utils.BITCOIN_ONLY:
from apps.ethereum.keychain import (
from_address_n,
with_keychain_from_path,
with_keychain_from_chain_id,
)
from apps.ethereum.networks import by_chain_id, by_slip44
from trezor.messages.EthereumGetAddress import EthereumGetAddress
from trezor.messages.EthereumSignTx import EthereumSignTx
@unittest.skipUnless(not utils.BITCOIN_ONLY, "altcoin")
class TestEthereumKeychain(unittest.TestCase):
def _check_keychain(self, keychain, slip44_id):
# valid address should succeed
valid_addresses = (
[44 | HARDENED, slip44_id | HARDENED],
[44 | HARDENED, slip44_id | HARDENED, 0 | HARDENED],
[44 | HARDENED, slip44_id | HARDENED, 19 | HARDENED],
[44 | HARDENED, slip44_id | HARDENED, 0 | HARDENED, 0, 0],
)
for addr in valid_addresses:
keychain.derive(addr)
# invalid address should fail
invalid_addresses = (
[44 | HARDENED],
[44 | HARDENED, 0 | HARDENED],
[42 | HARDENED, slip44_id | HARDENED],
[0 | HARDENED, slip44_id | HARDENED, 0 | HARDENED],
)
for addr in invalid_addresses:
self.assertRaises(
wire.DataError, keychain.derive, addr,
)
def setUp(self):
cache.start_session()
seed = bip39.seed(" ".join(["all"] * 12), "")
cache.set(cache.APP_COMMON_SEED, seed)
def test_from_address_n(self):
# valid keychain m/44'/60'/0'
keychain = await_result(
from_address_n(
wire.DUMMY_CONTEXT, [44 | HARDENED, 60 | HARDENED, 0 | HARDENED]
)
)
self._check_keychain(keychain, 60)
def test_from_address_n_unknown(self):
# try Bitcoin slip44 id m/44'/0'/0'
with self.assertRaises(wire.DataError):
await_result(
from_address_n(
wire.DUMMY_CONTEXT, [44 | HARDENED, 0 | HARDENED, 0 | HARDENED]
)
)
def test_bad_address_n(self):
# keychain generated from valid slip44 id but invalid address m/0'/60'/0'
keychain = await_result(
from_address_n(
wire.DUMMY_CONTEXT, [0 | HARDENED, 60 | HARDENED, 0 | HARDENED]
)
)
self._check_keychain(keychain, 60)
def test_with_keychain_from_path(self):
@with_keychain_from_path
async def handler(ctx, msg, keychain):
self._check_keychain(keychain, msg.address_n[1] & ~HARDENED)
await_result(
handler(
wire.DUMMY_CONTEXT,
EthereumGetAddress(
address_n=[44 | HARDENED, 60 | HARDENED, 0 | HARDENED]
),
)
)
await_result(
handler(
wire.DUMMY_CONTEXT,
EthereumGetAddress(
address_n=[44 | HARDENED, 108 | HARDENED, 0 | HARDENED]
),
)
)
with self.assertRaises(wire.DataError):
await_result(
handler(
wire.DUMMY_CONTEXT,
EthereumGetAddress(
address_n=[44 | HARDENED, 0 | HARDENED, 0 | HARDENED]
),
)
)
def test_with_keychain_from_chain_id(self):
@with_keychain_from_chain_id
async def handler_chain_id(ctx, msg, keychain):
network = by_chain_id(msg.chain_id)
# standard tests
self._check_keychain(keychain, network.slip44)
# provided address should succeed too
keychain.derive(msg.address_n)
await_result( # Ethereum
handler_chain_id(
wire.DUMMY_CONTEXT,
EthereumSignTx(
address_n=[44 | HARDENED, 60 | HARDENED, 0 | HARDENED],
chain_id=1,
),
)
)
await_result( # Ethereum Classic
handler_chain_id(
wire.DUMMY_CONTEXT,
EthereumSignTx(
address_n=[44 | HARDENED, 61 | HARDENED, 0 | HARDENED],
chain_id=61,
),
)
)
with self.assertRaises(wire.DataError):
await_result( # unknown chain_id
handler_chain_id(
wire.DUMMY_CONTEXT,
EthereumSignTx(
address_n=[44 | HARDENED, 60 | HARDENED, 0 | HARDENED],
chain_id=123456789,
),
)
)
with self.assertRaises(wire.DataError):
await_result( # chain_id and network mismatch
handler_chain_id(
wire.DUMMY_CONTEXT,
EthereumSignTx(
address_n=[44 | HARDENED, 60 | HARDENED, 0 | HARDENED],
chain_id=2,
),
)
)
def test_missing_chain_id(self):
@with_keychain_from_chain_id
async def handler_chain_id(ctx, msg, keychain):
network = by_slip44(msg.address_n[1] & ~HARDENED)
# standard tests
self._check_keychain(keychain, network.slip44)
# provided address should succeed too
keychain.derive(msg.address_n)
await_result( # Ethereum
handler_chain_id(
wire.DUMMY_CONTEXT,
EthereumSignTx(
address_n=[44 | HARDENED, 60 | HARDENED, 0 | HARDENED],
chain_id=None,
),
)
)
await_result( # Ethereum Classic
handler_chain_id(
wire.DUMMY_CONTEXT,
EthereumSignTx(
address_n=[44 | HARDENED, 61 | HARDENED, 0 | HARDENED],
),
)
)
with self.assertRaises(wire.DataError):
await_result( # unknown slip44 id
handler_chain_id(
wire.DUMMY_CONTEXT,
EthereumSignTx(
address_n=[44 | HARDENED, 0 | HARDENED, 0 | HARDENED],
),
)
)
def test_wanchain(self):
@with_keychain_from_chain_id
async def handler_wanchain(ctx, msg, keychain):
self._check_keychain(keychain, 5718350)
# provided address should succeed too
keychain.derive(msg.address_n)
await_result(
handler_wanchain(
wire.DUMMY_CONTEXT,
EthereumSignTx(
address_n=[44 | HARDENED, 5718350 | HARDENED, 0 | HARDENED],
chain_id=3,
tx_type=6,
),
)
)
if __name__ == "__main__":
unittest.main()