mirror of
https://github.com/trezor/trezor-firmware.git
synced 2025-02-05 20:31:01 +00:00
refactor(core/cardano): decouple address parameters validation
This commit is contained in:
parent
d6776d988e
commit
597402eab8
@ -8,7 +8,6 @@
|
||||
"parameters": {
|
||||
"path": "m/1852'/1815'/0'/0/0",
|
||||
"address_type": "enterprise",
|
||||
"staking_key_hash": "1bc428e4720702ebd5dab4fb175324c192dc9bb76cc5da956e3c8dff",
|
||||
"network_id": 1,
|
||||
"protocol_magic": 764824073
|
||||
},
|
||||
@ -20,7 +19,6 @@
|
||||
"parameters": {
|
||||
"path": "m/1852'/1815'/0'/0/0",
|
||||
"address_type": "enterprise",
|
||||
"staking_key_hash": "1bc428e4720702ebd5dab4fb175324c192dc9bb76cc5da956e3c8dff",
|
||||
"network_id": 0,
|
||||
"protocol_magic": 42
|
||||
},
|
||||
|
@ -230,7 +230,7 @@
|
||||
]
|
||||
},
|
||||
"result": {
|
||||
"error_message": "Output address network mismatch!"
|
||||
"error_message": "Output address network mismatch"
|
||||
}
|
||||
},
|
||||
{
|
||||
@ -258,7 +258,7 @@
|
||||
]
|
||||
},
|
||||
"result": {
|
||||
"error_message": "Output address network mismatch!"
|
||||
"error_message": "Output address network mismatch"
|
||||
}
|
||||
},
|
||||
{
|
||||
|
@ -1,9 +1,15 @@
|
||||
from trezor import wire
|
||||
from trezor.crypto import base58, hashlib
|
||||
from trezor.enums import CardanoAddressType
|
||||
|
||||
from .byron_address import derive_byron_address, validate_byron_address
|
||||
from .helpers import INVALID_ADDRESS, NETWORK_MISMATCH, bech32, network_ids
|
||||
from .helpers import (
|
||||
ADDRESS_KEY_HASH_SIZE,
|
||||
INVALID_ADDRESS,
|
||||
INVALID_ADDRESS_PARAMETERS,
|
||||
NETWORK_MISMATCH,
|
||||
bech32,
|
||||
network_ids,
|
||||
)
|
||||
from .helpers.paths import SCHEMA_STAKING_ANY_ACCOUNT
|
||||
from .helpers.utils import derive_public_key, variable_length_encode
|
||||
from .seed import is_byron_path, is_shelley_path
|
||||
@ -31,6 +37,70 @@ MIN_ADDRESS_BYTES_LENGTH = 29
|
||||
MAX_ADDRESS_BYTES_LENGTH = 65
|
||||
|
||||
|
||||
def validate_address_parameters(parameters: CardanoAddressParametersType) -> None:
|
||||
_validate_address_parameters_structure(parameters)
|
||||
|
||||
if parameters.address_type == CardanoAddressType.BYRON:
|
||||
if not is_byron_path(parameters.address_n):
|
||||
raise INVALID_ADDRESS_PARAMETERS
|
||||
elif parameters.address_type in ADDRESS_TYPES_SHELLEY:
|
||||
if not is_shelley_path(parameters.address_n):
|
||||
raise INVALID_ADDRESS_PARAMETERS
|
||||
|
||||
if parameters.address_type == CardanoAddressType.BASE:
|
||||
_validate_base_address_staking_info(
|
||||
parameters.address_n_staking, parameters.staking_key_hash
|
||||
)
|
||||
elif parameters.address_type == CardanoAddressType.POINTER:
|
||||
if parameters.certificate_pointer is None:
|
||||
raise INVALID_ADDRESS_PARAMETERS
|
||||
elif parameters.address_type == CardanoAddressType.REWARD:
|
||||
if not SCHEMA_STAKING_ANY_ACCOUNT.match(parameters.address_n):
|
||||
raise INVALID_ADDRESS_PARAMETERS
|
||||
else:
|
||||
raise INVALID_ADDRESS_PARAMETERS
|
||||
|
||||
|
||||
def _validate_address_parameters_structure(
|
||||
parameters: CardanoAddressParametersType,
|
||||
) -> None:
|
||||
address_n_staking = parameters.address_n_staking
|
||||
staking_key_hash = parameters.staking_key_hash
|
||||
certificate_pointer = parameters.certificate_pointer
|
||||
|
||||
fields_to_be_empty: tuple = ()
|
||||
if parameters.address_type in (
|
||||
CardanoAddressType.BYRON,
|
||||
CardanoAddressType.REWARD,
|
||||
CardanoAddressType.ENTERPRISE,
|
||||
):
|
||||
fields_to_be_empty = (address_n_staking, staking_key_hash, certificate_pointer)
|
||||
elif parameters.address_type == CardanoAddressType.BASE:
|
||||
fields_to_be_empty = (certificate_pointer,)
|
||||
elif parameters.address_type == CardanoAddressType.POINTER:
|
||||
fields_to_be_empty = (address_n_staking, staking_key_hash)
|
||||
|
||||
if any(fields_to_be_empty):
|
||||
raise INVALID_ADDRESS_PARAMETERS
|
||||
|
||||
|
||||
def _validate_base_address_staking_info(
|
||||
staking_path: list[int],
|
||||
staking_key_hash: bytes | None,
|
||||
) -> None:
|
||||
if staking_key_hash and staking_path:
|
||||
raise INVALID_ADDRESS_PARAMETERS
|
||||
|
||||
if staking_key_hash:
|
||||
if len(staking_key_hash) != ADDRESS_KEY_HASH_SIZE:
|
||||
raise INVALID_ADDRESS_PARAMETERS
|
||||
elif staking_path:
|
||||
if not SCHEMA_STAKING_ANY_ACCOUNT.match(staking_path):
|
||||
raise INVALID_ADDRESS_PARAMETERS
|
||||
else:
|
||||
raise INVALID_ADDRESS_PARAMETERS
|
||||
|
||||
|
||||
def _validate_address_and_get_type(
|
||||
address: str, protocol_magic: int, network_id: int
|
||||
) -> int:
|
||||
@ -142,7 +212,7 @@ def _get_address_network_id(address: bytes) -> int:
|
||||
|
||||
def get_public_key_hash(keychain: seed.Keychain, path: list[int]) -> bytes:
|
||||
public_key = derive_public_key(keychain, path)
|
||||
return hashlib.blake2b(data=public_key, outlen=28).digest()
|
||||
return hashlib.blake2b(data=public_key, outlen=ADDRESS_KEY_HASH_SIZE).digest()
|
||||
|
||||
|
||||
def derive_human_readable_address(
|
||||
@ -180,31 +250,18 @@ def derive_address_bytes(
|
||||
is_byron_address = parameters.address_type == CardanoAddressType.BYRON
|
||||
|
||||
if is_byron_address:
|
||||
address = _derive_byron_address(keychain, parameters.address_n, protocol_magic)
|
||||
address = derive_byron_address(keychain, parameters.address_n, protocol_magic)
|
||||
else:
|
||||
address = _derive_shelley_address(keychain, parameters, network_id)
|
||||
|
||||
return address
|
||||
|
||||
|
||||
def _derive_byron_address(
|
||||
keychain: seed.Keychain, path: list[int], protocol_magic: int
|
||||
) -> bytes:
|
||||
if not is_byron_path(path):
|
||||
raise wire.DataError("Invalid path for byron address!")
|
||||
|
||||
address = derive_byron_address(keychain, path, protocol_magic)
|
||||
return address
|
||||
|
||||
|
||||
def _derive_shelley_address(
|
||||
keychain: seed.Keychain,
|
||||
parameters: CardanoAddressParametersType,
|
||||
network_id: int,
|
||||
) -> bytes:
|
||||
if not is_shelley_path(parameters.address_n):
|
||||
raise wire.DataError("Invalid path for shelley address!")
|
||||
|
||||
if parameters.address_type == CardanoAddressType.BASE:
|
||||
address = _derive_base_address(
|
||||
keychain,
|
||||
@ -213,21 +270,22 @@ def _derive_shelley_address(
|
||||
parameters.staking_key_hash,
|
||||
network_id,
|
||||
)
|
||||
elif parameters.address_type == CardanoAddressType.ENTERPRISE:
|
||||
address = _derive_enterprise_address(keychain, parameters.address_n, network_id)
|
||||
elif parameters.address_type == CardanoAddressType.POINTER:
|
||||
if parameters.certificate_pointer is None:
|
||||
raise wire.DataError("Certificate pointer data missing!")
|
||||
# ensured by validate_address_parameters
|
||||
assert parameters.certificate_pointer is not None
|
||||
|
||||
address = _derive_pointer_address(
|
||||
keychain,
|
||||
parameters.address_n,
|
||||
parameters.certificate_pointer,
|
||||
network_id,
|
||||
)
|
||||
elif parameters.address_type == CardanoAddressType.ENTERPRISE:
|
||||
address = _derive_enterprise_address(keychain, parameters.address_n, network_id)
|
||||
elif parameters.address_type == CardanoAddressType.REWARD:
|
||||
address = _derive_reward_address(keychain, parameters.address_n, network_id)
|
||||
else:
|
||||
raise wire.DataError("Invalid address type!")
|
||||
raise INVALID_ADDRESS_PARAMETERS
|
||||
|
||||
return address
|
||||
|
||||
@ -247,27 +305,12 @@ def _derive_base_address(
|
||||
header = _create_address_header(CardanoAddressType.BASE, network_id)
|
||||
spending_key_hash = get_public_key_hash(keychain, path)
|
||||
|
||||
_validate_base_address_staking_info(staking_path, staking_key_hash)
|
||||
|
||||
if staking_key_hash is None:
|
||||
staking_key_hash = get_public_key_hash(keychain, staking_path)
|
||||
|
||||
return header + spending_key_hash + staking_key_hash
|
||||
|
||||
|
||||
def _validate_base_address_staking_info(
|
||||
staking_path: list[int],
|
||||
staking_key_hash: bytes | None,
|
||||
) -> None:
|
||||
if (staking_key_hash is None) == (not staking_path):
|
||||
raise wire.DataError(
|
||||
"Base address needs either a staking path or a staking key hash!"
|
||||
)
|
||||
|
||||
if staking_key_hash is None and not SCHEMA_STAKING_ANY_ACCOUNT.match(staking_path):
|
||||
raise wire.DataError("Invalid staking path!")
|
||||
|
||||
|
||||
def _derive_pointer_address(
|
||||
keychain: seed.Keychain,
|
||||
path: list[int],
|
||||
@ -305,9 +348,6 @@ def _derive_reward_address(
|
||||
path: list[int],
|
||||
network_id: int,
|
||||
) -> bytes:
|
||||
if not SCHEMA_STAKING_ANY_ACCOUNT.match(path):
|
||||
raise wire.DataError("Invalid path for reward address!")
|
||||
|
||||
staking_key_hash = get_public_key_hash(keychain, path)
|
||||
|
||||
return pack_reward_address_bytes(staking_key_hash, network_id)
|
||||
|
@ -4,7 +4,11 @@ from trezor.enums import CardanoAddressType
|
||||
|
||||
from apps.common import cbor
|
||||
|
||||
from .address import derive_address_bytes, derive_human_readable_address
|
||||
from .address import (
|
||||
derive_address_bytes,
|
||||
derive_human_readable_address,
|
||||
validate_address_parameters,
|
||||
)
|
||||
from .helpers import INVALID_AUXILIARY_DATA, bech32
|
||||
from .helpers.bech32 import HRP_JORMUN_PUBLIC_KEY
|
||||
from .helpers.paths import SCHEMA_STAKING_ANY_ACCOUNT
|
||||
@ -36,12 +40,7 @@ METADATA_KEY_CATALYST_REGISTRATION = 61284
|
||||
METADATA_KEY_CATALYST_REGISTRATION_SIGNATURE = 61285
|
||||
|
||||
|
||||
def validate_auxiliary_data(
|
||||
keychain: seed.Keychain,
|
||||
auxiliary_data: CardanoTxAuxiliaryDataType | None,
|
||||
protocol_magic: int,
|
||||
network_id: int,
|
||||
) -> None:
|
||||
def validate_auxiliary_data(auxiliary_data: CardanoTxAuxiliaryDataType | None) -> None:
|
||||
if not auxiliary_data:
|
||||
return
|
||||
|
||||
@ -52,10 +51,7 @@ def validate_auxiliary_data(
|
||||
if auxiliary_data.catalyst_registration_parameters:
|
||||
fields_provided += 1
|
||||
_validate_catalyst_registration_parameters(
|
||||
keychain,
|
||||
auxiliary_data.catalyst_registration_parameters,
|
||||
protocol_magic,
|
||||
network_id,
|
||||
auxiliary_data.catalyst_registration_parameters
|
||||
)
|
||||
|
||||
if fields_provided != 1:
|
||||
@ -72,10 +68,7 @@ def _validate_auxiliary_data_blob(auxiliary_data_blob: bytes) -> None:
|
||||
|
||||
|
||||
def _validate_catalyst_registration_parameters(
|
||||
keychain: seed.Keychain,
|
||||
catalyst_registration_parameters: CardanoCatalystRegistrationParametersType,
|
||||
protocol_magic: int,
|
||||
network_id: int,
|
||||
) -> None:
|
||||
if (
|
||||
len(catalyst_registration_parameters.voting_public_key)
|
||||
@ -92,8 +85,7 @@ def _validate_catalyst_registration_parameters(
|
||||
if address_parameters.address_type == CardanoAddressType.BYRON:
|
||||
raise INVALID_AUXILIARY_DATA
|
||||
|
||||
# try to derive the address to validate it
|
||||
derive_address_bytes(keychain, address_parameters, protocol_magic, network_id)
|
||||
validate_address_parameters(address_parameters)
|
||||
|
||||
|
||||
async def show_auxiliary_data(
|
||||
|
@ -7,7 +7,7 @@ from .address import (
|
||||
get_public_key_hash,
|
||||
validate_reward_address,
|
||||
)
|
||||
from .helpers import INVALID_CERTIFICATE, LOVELACE_MAX_SUPPLY
|
||||
from .helpers import ADDRESS_KEY_HASH_SIZE, INVALID_CERTIFICATE, LOVELACE_MAX_SUPPLY
|
||||
from .helpers.paths import SCHEMA_STAKING_ANY_ACCOUNT
|
||||
|
||||
if False:
|
||||
@ -26,7 +26,6 @@ if False:
|
||||
POOL_HASH_SIZE = 28
|
||||
VRF_KEY_HASH_SIZE = 32
|
||||
POOL_METADATA_HASH_SIZE = 32
|
||||
PUBLIC_KEY_HASH_SIZE = 28
|
||||
IPV4_ADDRESS_SIZE = 4
|
||||
IPV6_ADDRESS_SIZE = 16
|
||||
|
||||
@ -140,7 +139,9 @@ def _validate_pool_owners(owners: list[CardanoPoolOwnerType]) -> None:
|
||||
owner.staking_key_hash is not None or owner.staking_key_path is not None
|
||||
)
|
||||
if owner.staking_key_hash is not None:
|
||||
assert_certificate_cond(len(owner.staking_key_hash) == PUBLIC_KEY_HASH_SIZE)
|
||||
assert_certificate_cond(
|
||||
len(owner.staking_key_hash) == ADDRESS_KEY_HASH_SIZE
|
||||
)
|
||||
if owner.staking_key_path:
|
||||
assert_certificate_cond(
|
||||
SCHEMA_STAKING_ANY_ACCOUNT.match(owner.staking_key_path)
|
||||
|
@ -5,7 +5,7 @@ from apps.common import paths
|
||||
from apps.common.layout import address_n_to_str, show_qr
|
||||
|
||||
from . import seed
|
||||
from .address import derive_human_readable_address
|
||||
from .address import derive_human_readable_address, validate_address_parameters
|
||||
from .helpers import protocol_magics, staking_use_cases
|
||||
from .helpers.paths import SCHEMA_ADDRESS
|
||||
from .helpers.utils import to_account_path
|
||||
@ -38,6 +38,7 @@ async def get_address(
|
||||
)
|
||||
|
||||
validate_network_info(msg.network_id, msg.protocol_magic)
|
||||
validate_address_parameters(address_parameters)
|
||||
|
||||
try:
|
||||
address = derive_human_readable_address(
|
||||
|
@ -1,7 +1,8 @@
|
||||
from trezor import wire
|
||||
|
||||
INVALID_ADDRESS = wire.ProcessError("Invalid address")
|
||||
NETWORK_MISMATCH = wire.ProcessError("Output address network mismatch!")
|
||||
INVALID_ADDRESS_PARAMETERS = wire.ProcessError("Invalid address parameters")
|
||||
NETWORK_MISMATCH = wire.ProcessError("Output address network mismatch")
|
||||
INVALID_CERTIFICATE = wire.ProcessError("Invalid certificate")
|
||||
INVALID_WITHDRAWAL = wire.ProcessError("Invalid withdrawal")
|
||||
INVALID_TOKEN_BUNDLE_OUTPUT = wire.ProcessError("Invalid token bundle in output")
|
||||
@ -14,3 +15,4 @@ INVALID_STAKEPOOL_REGISTRATION_TX_INPUTS = wire.ProcessError(
|
||||
)
|
||||
|
||||
LOVELACE_MAX_SUPPLY = 45_000_000_000 * 1_000_000
|
||||
ADDRESS_KEY_HASH_SIZE = 28
|
||||
|
@ -17,6 +17,7 @@ from .address import (
|
||||
derive_address_bytes,
|
||||
derive_human_readable_address,
|
||||
get_address_bytes_unsafe,
|
||||
validate_address_parameters,
|
||||
validate_output_address,
|
||||
)
|
||||
from .auxiliary_data import (
|
||||
@ -135,12 +136,10 @@ async def _sign_ordinary_tx(
|
||||
ctx, keychain, i.address_n, SCHEMA_ADDRESS.match(i.address_n)
|
||||
)
|
||||
|
||||
_validate_outputs(keychain, msg.outputs, msg.protocol_magic, msg.network_id)
|
||||
_validate_outputs(msg.outputs, msg.protocol_magic, msg.network_id)
|
||||
_validate_certificates(msg.certificates, msg.protocol_magic, msg.network_id)
|
||||
_validate_withdrawals(msg.withdrawals)
|
||||
validate_auxiliary_data(
|
||||
keychain, msg.auxiliary_data, msg.protocol_magic, msg.network_id
|
||||
)
|
||||
validate_auxiliary_data(msg.auxiliary_data)
|
||||
|
||||
# display the transaction in UI
|
||||
await _show_standard_tx(ctx, keychain, msg)
|
||||
@ -166,11 +165,9 @@ async def _sign_stake_pool_registration_tx(
|
||||
_validate_stake_pool_registration_tx_structure(msg)
|
||||
|
||||
_ensure_no_signing_inputs(msg.inputs)
|
||||
_validate_outputs(keychain, msg.outputs, msg.protocol_magic, msg.network_id)
|
||||
_validate_outputs(msg.outputs, msg.protocol_magic, msg.network_id)
|
||||
_validate_certificates(msg.certificates, msg.protocol_magic, msg.network_id)
|
||||
validate_auxiliary_data(
|
||||
keychain, msg.auxiliary_data, msg.protocol_magic, msg.network_id
|
||||
)
|
||||
validate_auxiliary_data(msg.auxiliary_data)
|
||||
|
||||
await _show_stake_pool_registration_tx(ctx, keychain, msg)
|
||||
|
||||
@ -209,7 +206,6 @@ def _validate_stake_pool_registration_tx_structure(msg: CardanoSignTx) -> None:
|
||||
|
||||
|
||||
def _validate_outputs(
|
||||
keychain: seed.Keychain,
|
||||
outputs: list[CardanoTxOutputType],
|
||||
protocol_magic: int,
|
||||
network_id: int,
|
||||
@ -218,10 +214,7 @@ def _validate_outputs(
|
||||
for output in outputs:
|
||||
total_amount += output.amount
|
||||
if output.address_parameters:
|
||||
# try to derive the address to validate it
|
||||
derive_address_bytes(
|
||||
keychain, output.address_parameters, protocol_magic, network_id
|
||||
)
|
||||
validate_address_parameters(output.address_parameters)
|
||||
elif output.address is not None:
|
||||
validate_output_address(output.address, protocol_magic, network_id)
|
||||
else:
|
||||
|
@ -8,7 +8,7 @@ from trezor.messages import CardanoBlockchainPointerType
|
||||
from apps.common import HARDENED, seed
|
||||
|
||||
if not utils.BITCOIN_ONLY:
|
||||
from apps.cardano.address import derive_human_readable_address
|
||||
from apps.cardano.address import derive_human_readable_address, validate_address_parameters
|
||||
from apps.cardano.byron_address import _address_hash
|
||||
from apps.cardano.helpers import network_ids, protocol_magics
|
||||
from apps.cardano.seed import Keychain
|
||||
@ -335,32 +335,6 @@ class TestCardanoAddress(unittest.TestCase):
|
||||
|
||||
self.assertEqual(actual_address, expected_address)
|
||||
|
||||
def test_base_address_with_invalid_parameters(self):
|
||||
mnemonic = "test walk nut penalty hip pave soap entry language right filter choice"
|
||||
passphrase = ""
|
||||
node = bip32.from_mnemonic_cardano(mnemonic, passphrase)
|
||||
keychain = Keychain(node)
|
||||
|
||||
# both address_n_staking and staking_key_hash are None
|
||||
with self.assertRaises(wire.DataError):
|
||||
address_parameters = CardanoAddressParametersType(
|
||||
address_type=CardanoAddressType.BASE,
|
||||
address_n=[1852 | HARDENED, 1815 | HARDENED, 0 | HARDENED, 0, 0],
|
||||
address_n_staking=None,
|
||||
staking_key_hash=None,
|
||||
)
|
||||
derive_human_readable_address(keychain, address_parameters, 0, 0)
|
||||
|
||||
# address_n_staking is not a staking path
|
||||
with self.assertRaises(wire.DataError):
|
||||
address_parameters = CardanoAddressParametersType(
|
||||
address_type=CardanoAddressType.BASE,
|
||||
address_n=[1852 | HARDENED, 1815 | HARDENED, 0 | HARDENED, 0, 0],
|
||||
address_n_staking=[1852 | HARDENED, 1815 | HARDENED, 0 | HARDENED, 0, 0],
|
||||
staking_key_hash=None,
|
||||
)
|
||||
derive_human_readable_address(keychain, address_parameters, 0, 0)
|
||||
|
||||
def test_enterprise_address(self):
|
||||
mnemonic = "test walk nut penalty hip pave soap entry language right filter choice"
|
||||
passphrase = ""
|
||||
@ -404,21 +378,6 @@ class TestCardanoAddress(unittest.TestCase):
|
||||
|
||||
self.assertEqual(actual_address, expected_address)
|
||||
|
||||
def test_pointer_address_invalid_pointers(self):
|
||||
mnemonic = "test walk nut penalty hip pave soap entry language right filter choice"
|
||||
passphrase = ""
|
||||
node = bip32.from_mnemonic_cardano(mnemonic, passphrase)
|
||||
keychain = Keychain(node)
|
||||
|
||||
# pointer is None
|
||||
with self.assertRaises(wire.DataError):
|
||||
address_parameters = CardanoAddressParametersType(
|
||||
address_type=CardanoAddressType.POINTER,
|
||||
address_n=[1852 | HARDENED, 1815 | HARDENED, 0 | HARDENED, 0, 0],
|
||||
certificate_pointer=None,
|
||||
)
|
||||
derive_human_readable_address(keychain, address_parameters, 0, 0)
|
||||
|
||||
def test_reward_address(self):
|
||||
mnemonic = "test walk nut penalty hip pave soap entry language right filter choice"
|
||||
passphrase = ""
|
||||
@ -440,75 +399,6 @@ class TestCardanoAddress(unittest.TestCase):
|
||||
|
||||
self.assertEqual(actual_address, expected_address)
|
||||
|
||||
def test_reward_address_with_non_staking_path(self):
|
||||
mnemonic = "test walk nut penalty hip pave soap entry language right filter choice"
|
||||
passphrase = ""
|
||||
node = bip32.from_mnemonic_cardano(mnemonic, passphrase)
|
||||
keychain = Keychain(node)
|
||||
|
||||
with self.assertRaises(wire.DataError):
|
||||
address_parameters = CardanoAddressParametersType(
|
||||
address_type=CardanoAddressType.REWARD,
|
||||
address_n=[44 | HARDENED, 1815 | HARDENED, 0 | HARDENED, 0, 0]
|
||||
)
|
||||
derive_human_readable_address(keychain, address_parameters, 0, 0)
|
||||
|
||||
def test_shelley_address_with_byron_namespace(self):
|
||||
"""
|
||||
It shouldn't be possible to derive Shelley addresses
|
||||
(Base, Pointer, Enterprise, Reward) with a Byron namespace (44')
|
||||
"""
|
||||
mnemonic = "test walk nut penalty hip pave soap entry language right filter choice"
|
||||
passphrase = ""
|
||||
node = bip32.from_mnemonic_cardano(mnemonic, passphrase)
|
||||
keychain = Keychain(node)
|
||||
|
||||
with self.assertRaises(wire.DataError):
|
||||
address_parameters = CardanoAddressParametersType(
|
||||
address_type=CardanoAddressType.BASE,
|
||||
address_n=[44 | HARDENED, 1815 | HARDENED, 0 | HARDENED, 0, 0]
|
||||
)
|
||||
derive_human_readable_address(keychain, address_parameters, 0, 0)
|
||||
|
||||
with self.assertRaises(wire.DataError):
|
||||
address_parameters = CardanoAddressParametersType(
|
||||
address_type=CardanoAddressType.POINTER,
|
||||
address_n=[44 | HARDENED, 1815 | HARDENED, 0 | HARDENED, 0, 0],
|
||||
certificate_pointer=CardanoBlockchainPointerType(block_index=0, tx_index=0, certificate_index=0)
|
||||
)
|
||||
derive_human_readable_address(keychain, address_parameters, 0, 0)
|
||||
|
||||
with self.assertRaises(wire.DataError):
|
||||
address_parameters = CardanoAddressParametersType(
|
||||
address_type=CardanoAddressType.ENTERPRISE,
|
||||
address_n=[44 | HARDENED, 1815 | HARDENED, 0 | HARDENED, 0, 0],
|
||||
)
|
||||
derive_human_readable_address(keychain, address_parameters, 0, 0)
|
||||
|
||||
with self.assertRaises(wire.DataError):
|
||||
address_parameters = CardanoAddressParametersType(
|
||||
address_type=CardanoAddressType.REWARD,
|
||||
address_n=[44 | HARDENED, 1815 | HARDENED, 0 | HARDENED, 0, 0],
|
||||
)
|
||||
derive_human_readable_address(keychain, address_parameters, 0, 0)
|
||||
|
||||
def test_byron_address_with_shelley_namespace(self):
|
||||
"""
|
||||
It shouldn't be possible to derive Byron addresses
|
||||
with a Shelley namespace (1852')
|
||||
"""
|
||||
mnemonic = "all all all all all all all all all all all all"
|
||||
passphrase = ""
|
||||
node = bip32.from_mnemonic_cardano(mnemonic, passphrase)
|
||||
keychain = Keychain(node)
|
||||
|
||||
with self.assertRaises(wire.DataError):
|
||||
address_parameters = CardanoAddressParametersType(
|
||||
address_type=CardanoAddressType.BYRON,
|
||||
address_n=[1852 | HARDENED, 1815 | HARDENED, 0 | HARDENED, 0, 0],
|
||||
)
|
||||
derive_human_readable_address(keychain, address_parameters, 0, 0)
|
||||
|
||||
def test_testnet_byron_address(self):
|
||||
mnemonic = "all all all all all all all all all all all all"
|
||||
passphrase = ""
|
||||
@ -530,5 +420,78 @@ class TestCardanoAddress(unittest.TestCase):
|
||||
address = derive_human_readable_address(keychain, address_parameters, protocol_magics.TESTNET, 0)
|
||||
self.assertEqual(expected, address)
|
||||
|
||||
def test_validate_address_parameters(self):
|
||||
test_vectors = [
|
||||
# base address - both address_n_staking and staking_key_hash are None
|
||||
CardanoAddressParametersType(
|
||||
address_type=CardanoAddressType.BASE,
|
||||
address_n=[1852 | HARDENED, 1815 | HARDENED, 0 | HARDENED, 0, 0],
|
||||
address_n_staking=None,
|
||||
staking_key_hash=None,
|
||||
),
|
||||
# base address - both address_n_staking and staking_key_hash are set
|
||||
CardanoAddressParametersType(
|
||||
address_type=CardanoAddressType.BASE,
|
||||
address_n=[1852 | HARDENED, 1815 | HARDENED, 0 | HARDENED, 0, 0],
|
||||
address_n_staking=[1852 | HARDENED, 1815 | HARDENED, 0 | HARDENED, 2, 0],
|
||||
staking_key_hash=unhexlify("1bc428e4720702ebd5dab4fb175324c192dc9bb76cc5da956e3c8dff"),
|
||||
),
|
||||
# base address - staking_key_hash is too short
|
||||
CardanoAddressParametersType(
|
||||
address_type=CardanoAddressType.BASE,
|
||||
address_n=[1852 | HARDENED, 1815 | HARDENED, 0 | HARDENED, 0, 0],
|
||||
address_n_staking=None,
|
||||
staking_key_hash=unhexlify("1bc428e4720702ebd5dab4fb175324c192dc9bb76cc5da956e3c8d"),
|
||||
),
|
||||
# base address - address_n_staking is not a staking path
|
||||
CardanoAddressParametersType(
|
||||
address_type=CardanoAddressType.BASE,
|
||||
address_n=[1852 | HARDENED, 1815 | HARDENED, 0 | HARDENED, 0, 0],
|
||||
address_n_staking=[1852 | HARDENED, 1815 | HARDENED, 0 | HARDENED, 0, 0],
|
||||
staking_key_hash=None,
|
||||
),
|
||||
# pointer address - pointer is None
|
||||
CardanoAddressParametersType(
|
||||
address_type=CardanoAddressType.POINTER,
|
||||
address_n=[1852 | HARDENED, 1815 | HARDENED, 0 | HARDENED, 0, 0],
|
||||
certificate_pointer=None,
|
||||
),
|
||||
# reward address - non staking path
|
||||
CardanoAddressParametersType(
|
||||
address_type=CardanoAddressType.REWARD,
|
||||
address_n=[1852 | HARDENED, 1815 | HARDENED, 0 | HARDENED, 0, 0]
|
||||
),
|
||||
|
||||
# Shelley addresses with Byron namespace
|
||||
CardanoAddressParametersType(
|
||||
address_type=CardanoAddressType.BASE,
|
||||
address_n=[44 | HARDENED, 1815 | HARDENED, 0 | HARDENED, 0, 0]
|
||||
),
|
||||
CardanoAddressParametersType(
|
||||
address_type=CardanoAddressType.POINTER,
|
||||
address_n=[44 | HARDENED, 1815 | HARDENED, 0 | HARDENED, 0, 0],
|
||||
certificate_pointer=CardanoBlockchainPointerType(block_index=0, tx_index=0, certificate_index=0)
|
||||
),
|
||||
CardanoAddressParametersType(
|
||||
address_type=CardanoAddressType.ENTERPRISE,
|
||||
address_n=[44 | HARDENED, 1815 | HARDENED, 0 | HARDENED, 0, 0],
|
||||
),
|
||||
CardanoAddressParametersType(
|
||||
address_type=CardanoAddressType.REWARD,
|
||||
address_n=[44 | HARDENED, 1815 | HARDENED, 0 | HARDENED, 0, 0],
|
||||
),
|
||||
|
||||
# Byron address with Shelley namespace
|
||||
CardanoAddressParametersType(
|
||||
address_type=CardanoAddressType.BYRON,
|
||||
address_n=[1852 | HARDENED, 1815 | HARDENED, 0 | HARDENED, 0, 0],
|
||||
)
|
||||
]
|
||||
|
||||
for address_parameters in test_vectors:
|
||||
with self.assertRaises(wire.ProcessError):
|
||||
validate_address_parameters(address_parameters)
|
||||
|
||||
|
||||
if __name__ == '__main__':
|
||||
unittest.main()
|
||||
|
Loading…
Reference in New Issue
Block a user