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

core/tests: add new keychain tests

This commit is contained in:
matejcik 2020-05-14 17:09:06 +02:00 committed by matejcik
parent d5b4a570ff
commit 3e06f4779a
3 changed files with 384 additions and 1 deletions

View File

@ -1,6 +1,8 @@
from common import *
from storage import cache
from apps.common import HARDENED, coins
from apps.common.seed import Keychain, Slip21Node, _path_hardened
from apps.common.seed import Keychain, Slip21Node, _path_hardened, get_keychain, with_slip44_keychain
from apps.wallet.sign_tx import scripts, addresses
from trezor import wire
from trezor.crypto import bip39
@ -112,6 +114,63 @@ class TestKeychain(unittest.TestCase):
with self.assertRaises(wire.DataError):
keychain.derive([b"SLIP-9999", b"Authentication key"]).key()
def test_get_keychain(self):
seed = bip39.seed(' '.join(['all'] * 12), '')
cache.start_session()
cache.set(cache.APP_COMMON_SEED, seed)
namespaces = [("secp256k1", [44 | HARDENED])]
keychain = await_result(get_keychain(wire.DUMMY_CONTEXT, namespaces))
# valid path:
self.assertIsNotNone(keychain.derive([44 | HARDENED, 1 | HARDENED]))
# invalid path:
with self.assertRaises(wire.DataError):
keychain.derive([44])
def test_with_slip44(self):
seed = bip39.seed(' '.join(['all'] * 12), '')
cache.start_session()
cache.set(cache.APP_COMMON_SEED, seed)
slip44_id = 42
valid_path = [44 | HARDENED, slip44_id | HARDENED]
invalid_path = [44 | HARDENED, 99 | HARDENED]
testnet_path = [44 | HARDENED, 1 | HARDENED]
def check_valid_paths(keychain, *paths):
for path in paths:
self.assertIsNotNone(keychain.derive(path))
def check_invalid_paths(keychain, *paths):
for path in paths:
self.assertRaises(wire.DataError, keychain.derive, path)
@with_slip44_keychain(slip44_id)
async def func_id_only(ctx, msg, keychain):
check_valid_paths(keychain, valid_path)
check_invalid_paths(keychain, testnet_path, invalid_path)
@with_slip44_keychain(slip44_id, allow_testnet=True)
async def func_allow_testnet(ctx, msg, keychain):
check_valid_paths(keychain, valid_path, testnet_path)
check_invalid_paths(keychain, invalid_path)
@with_slip44_keychain(slip44_id, curve="ed25519")
async def func_with_curve(ctx, msg, keychain):
check_valid_paths(keychain, valid_path)
check_invalid_paths(keychain, testnet_path, invalid_path)
i, _ = keychain.match_path(valid_path)
ns_curve, ns = keychain.namespaces[i]
self.assertEqual(ns_curve, "ed25519")
await_result(func_id_only(wire.DUMMY_CONTEXT, None))
await_result(func_allow_testnet(wire.DUMMY_CONTEXT, None))
await_result(func_with_curve(wire.DUMMY_CONTEXT, None))
if __name__ == '__main__':
unittest.main()

View File

@ -0,0 +1,216 @@
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()

View File

@ -0,0 +1,108 @@
from common import *
from storage import cache
from trezor import wire
from trezor.crypto import bip39
from apps.common.paths import HARDENED
from apps.wallet.keychain import get_keychain_for_coin
class TestBitcoinKeychain(unittest.TestCase):
def setUp(self):
cache.start_session()
seed = bip39.seed(" ".join(["all"] * 12), "")
cache.set(cache.APP_COMMON_SEED, seed)
def test_bitcoin(self):
keychain, coin = await_result(
get_keychain_for_coin(wire.DUMMY_CONTEXT, "Bitcoin")
)
self.assertEqual(coin.coin_name, "Bitcoin")
valid_addresses = (
[44 | HARDENED, 0 | HARDENED],
[45 | HARDENED, 123456],
[48 | HARDENED, 0 | HARDENED],
[49 | HARDENED, 0 | HARDENED],
[84 | HARDENED, 0 | HARDENED],
)
invalid_addresses = (
[43 | HARDENED, 0 | HARDENED],
[44 | HARDENED, 1 | HARDENED],
)
for addr in valid_addresses:
keychain.derive(addr)
for addr in invalid_addresses:
self.assertRaises(wire.DataError, keychain.derive, addr)
def test_testnet(self):
keychain, coin = await_result(
get_keychain_for_coin(wire.DUMMY_CONTEXT, "Testnet")
)
self.assertEqual(coin.coin_name, "Testnet")
valid_addresses = (
[44 | HARDENED, 1 | HARDENED],
[45 | HARDENED, 123456],
[48 | HARDENED, 1 | HARDENED],
[49 | HARDENED, 1 | HARDENED],
[84 | HARDENED, 1 | HARDENED],
)
invalid_addresses = (
[43 | HARDENED, 1 | HARDENED],
[44 | HARDENED, 0 | HARDENED],
)
for addr in valid_addresses:
keychain.derive(addr)
for addr in invalid_addresses:
self.assertRaises(wire.DataError, keychain.derive, addr)
def test_unspecified(self):
keychain, coin = await_result(get_keychain_for_coin(wire.DUMMY_CONTEXT, None))
self.assertEqual(coin.coin_name, "Bitcoin")
keychain.derive([44 | HARDENED, 0 | HARDENED])
def test_unknown(self):
with self.assertRaises(wire.DataError):
await_result(get_keychain_for_coin(wire.DUMMY_CONTEXT, "MadeUpCoin2020"))
@unittest.skipUnless(not utils.BITCOIN_ONLY, "altcoin")
class TestAltcoinKeychains(unittest.TestCase):
def setUp(self):
cache.start_session()
seed = bip39.seed(" ".join(["all"] * 12), "")
cache.set(cache.APP_COMMON_SEED, seed)
def test_bcash(self):
keychain, coin = await_result(
get_keychain_for_coin(wire.DUMMY_CONTEXT, "Bcash")
)
self.assertEqual(coin.coin_name, "Bcash")
self.assertFalse(coin.segwit)
valid_addresses = (
[44 | HARDENED, 145 | HARDENED],
[45 | HARDENED, 123456],
[48 | HARDENED, 145 | HARDENED],
)
invalid_addresses = (
[43 | HARDENED, 145 | HARDENED],
[44 | HARDENED, 0 | HARDENED],
[49 | HARDENED, 145 | HARDENED],
[84 | HARDENED, 145 | HARDENED],
)
for addr in valid_addresses:
keychain.derive(addr)
for addr in invalid_addresses:
self.assertRaises(wire.DataError, keychain.derive, addr)
if __name__ == "__main__":
unittest.main()