mirror of
https://github.com/trezor/trezor-firmware.git
synced 2025-01-11 07:50:57 +00:00
Add support for script addresses in tx outputs
This commit is contained in:
parent
f1b6056edb
commit
b5f3511c1c
@ -9,13 +9,20 @@ import "messages-common.proto";
|
||||
|
||||
/**
|
||||
* Values correspond to address header values given by the spec.
|
||||
* Script addresses are only supported in transaction outputs.
|
||||
*/
|
||||
enum CardanoAddressType {
|
||||
BASE = 0;
|
||||
BASE_SCRIPT_KEY = 1;
|
||||
BASE_KEY_SCRIPT = 2;
|
||||
BASE_SCRIPT_SCRIPT = 3;
|
||||
POINTER = 4;
|
||||
POINTER_SCRIPT = 5;
|
||||
ENTERPRISE = 6;
|
||||
ENTERPRISE_SCRIPT = 7;
|
||||
BYRON = 8;
|
||||
REWARD = 14;
|
||||
REWARD_SCRIPT = 15;
|
||||
}
|
||||
|
||||
/**
|
||||
|
@ -20,31 +20,18 @@ if False:
|
||||
|
||||
ADDRESS_TYPES_SHELLEY = (
|
||||
CardanoAddressType.BASE,
|
||||
CardanoAddressType.BASE_SCRIPT_KEY,
|
||||
CardanoAddressType.BASE_KEY_SCRIPT,
|
||||
CardanoAddressType.BASE_SCRIPT_SCRIPT,
|
||||
CardanoAddressType.POINTER,
|
||||
CardanoAddressType.POINTER_SCRIPT,
|
||||
CardanoAddressType.ENTERPRISE,
|
||||
CardanoAddressType.ENTERPRISE_SCRIPT,
|
||||
CardanoAddressType.REWARD,
|
||||
CardanoAddressType.REWARD_SCRIPT,
|
||||
)
|
||||
|
||||
HEADER_LENGTH = 1
|
||||
HASH_LENGTH = 28
|
||||
MIN_POINTER_SIZE = 0
|
||||
MAX_POINTER_SIZE = 12
|
||||
|
||||
ADDRESS_BYTES_MIN_LENGTHS = {
|
||||
CardanoAddressType.BASE: HEADER_LENGTH + HASH_LENGTH + HASH_LENGTH,
|
||||
CardanoAddressType.POINTER: HEADER_LENGTH + HASH_LENGTH + MIN_POINTER_SIZE,
|
||||
CardanoAddressType.ENTERPRISE: HEADER_LENGTH + HASH_LENGTH,
|
||||
CardanoAddressType.REWARD: HEADER_LENGTH + HASH_LENGTH,
|
||||
}
|
||||
|
||||
ADDRESS_BYTES_MAX_LENGTHS = {
|
||||
CardanoAddressType.BASE: ADDRESS_BYTES_MIN_LENGTHS[CardanoAddressType.BASE],
|
||||
CardanoAddressType.POINTER: HEADER_LENGTH + HASH_LENGTH + MAX_POINTER_SIZE,
|
||||
CardanoAddressType.ENTERPRISE: ADDRESS_BYTES_MIN_LENGTHS[
|
||||
CardanoAddressType.ENTERPRISE
|
||||
],
|
||||
CardanoAddressType.REWARD: ADDRESS_BYTES_MIN_LENGTHS[CardanoAddressType.REWARD],
|
||||
}
|
||||
MIN_ADDRESS_BYTES_LENGTH = 29
|
||||
MAX_ADDRESS_BYTES_LENGTH = 65
|
||||
|
||||
|
||||
def validate_full_path(path: List[int]) -> bool:
|
||||
@ -104,7 +91,10 @@ def _validate_output_shelley_address(
|
||||
) -> None:
|
||||
address_type = _get_address_type(address_bytes)
|
||||
# reward address cannot be an output address
|
||||
if address_type == CardanoAddressType.REWARD:
|
||||
if (
|
||||
address_type == CardanoAddressType.REWARD
|
||||
or address_type == CardanoAddressType.REWARD_SCRIPT
|
||||
):
|
||||
raise INVALID_ADDRESS
|
||||
|
||||
_validate_address_size(address_bytes, address_type)
|
||||
@ -115,11 +105,7 @@ def _validate_output_shelley_address(
|
||||
def _validate_address_size(
|
||||
address_bytes: bytes, address_type: EnumTypeCardanoAddressType
|
||||
) -> None:
|
||||
if not (
|
||||
ADDRESS_BYTES_MIN_LENGTHS[address_type]
|
||||
<= len(address_bytes)
|
||||
<= ADDRESS_BYTES_MAX_LENGTHS[address_type]
|
||||
):
|
||||
if not (MIN_ADDRESS_BYTES_LENGTH <= len(address_bytes) <= MAX_ADDRESS_BYTES_LENGTH):
|
||||
raise INVALID_ADDRESS
|
||||
|
||||
|
||||
|
@ -8,7 +8,7 @@ if __debug__:
|
||||
try:
|
||||
from typing import Dict, List # noqa: F401
|
||||
from typing_extensions import Literal # noqa: F401
|
||||
EnumTypeCardanoAddressType = Literal[0, 4, 6, 8, 14]
|
||||
EnumTypeCardanoAddressType = Literal[0, 1, 2, 3, 4, 5, 6, 7, 8, 14, 15]
|
||||
except ImportError:
|
||||
pass
|
||||
|
||||
@ -32,7 +32,7 @@ class CardanoAddressParametersType(p.MessageType):
|
||||
@classmethod
|
||||
def get_fields(cls) -> Dict:
|
||||
return {
|
||||
1: ('address_type', p.EnumType("CardanoAddressType", (0, 4, 6, 8, 14)), 0),
|
||||
1: ('address_type', p.EnumType("CardanoAddressType", (0, 1, 2, 3, 4, 5, 6, 7, 8, 14, 15)), 0),
|
||||
2: ('address_n', p.UVarintType, p.FLAG_REPEATED),
|
||||
3: ('address_n_staking', p.UVarintType, p.FLAG_REPEATED),
|
||||
4: ('staking_key_hash', p.BytesType, 0),
|
||||
|
@ -4,7 +4,13 @@ if False:
|
||||
from typing_extensions import Literal
|
||||
|
||||
BASE = 0 # type: Literal[0]
|
||||
BASE_SCRIPT_KEY = 1 # type: Literal[1]
|
||||
BASE_KEY_SCRIPT = 2 # type: Literal[2]
|
||||
BASE_SCRIPT_SCRIPT = 3 # type: Literal[3]
|
||||
POINTER = 4 # type: Literal[4]
|
||||
POINTER_SCRIPT = 5 # type: Literal[5]
|
||||
ENTERPRISE = 6 # type: Literal[6]
|
||||
ENTERPRISE_SCRIPT = 7 # type: Literal[7]
|
||||
BYRON = 8 # type: Literal[8]
|
||||
REWARD = 14 # type: Literal[14]
|
||||
REWARD_SCRIPT = 15 # type: Literal[15]
|
||||
|
@ -8,7 +8,7 @@ if __debug__:
|
||||
try:
|
||||
from typing import Dict, List # noqa: F401
|
||||
from typing_extensions import Literal # noqa: F401
|
||||
EnumTypeCardanoAddressType = Literal[0, 4, 6, 8, 14]
|
||||
EnumTypeCardanoAddressType = Literal[0, 1, 2, 3, 4, 5, 6, 7, 8, 14, 15]
|
||||
except ImportError:
|
||||
pass
|
||||
|
||||
@ -32,7 +32,7 @@ class CardanoAddressParametersType(p.MessageType):
|
||||
@classmethod
|
||||
def get_fields(cls) -> Dict:
|
||||
return {
|
||||
1: ('address_type', p.EnumType("CardanoAddressType", (0, 4, 6, 8, 14)), 0),
|
||||
1: ('address_type', p.EnumType("CardanoAddressType", (0, 1, 2, 3, 4, 5, 6, 7, 8, 14, 15)), 0),
|
||||
2: ('address_n', p.UVarintType, p.FLAG_REPEATED),
|
||||
3: ('address_n_staking', p.UVarintType, p.FLAG_REPEATED),
|
||||
4: ('staking_key_hash', p.BytesType, 0),
|
||||
|
@ -4,7 +4,13 @@ if False:
|
||||
from typing_extensions import Literal
|
||||
|
||||
BASE = 0 # type: Literal[0]
|
||||
BASE_SCRIPT_KEY = 1 # type: Literal[1]
|
||||
BASE_KEY_SCRIPT = 2 # type: Literal[2]
|
||||
BASE_SCRIPT_SCRIPT = 3 # type: Literal[3]
|
||||
POINTER = 4 # type: Literal[4]
|
||||
POINTER_SCRIPT = 5 # type: Literal[5]
|
||||
ENTERPRISE = 6 # type: Literal[6]
|
||||
ENTERPRISE_SCRIPT = 7 # type: Literal[7]
|
||||
BYRON = 8 # type: Literal[8]
|
||||
REWARD = 14 # type: Literal[14]
|
||||
REWARD_SCRIPT = 15 # type: Literal[15]
|
||||
|
@ -59,6 +59,10 @@ SAMPLE_OUTPUTS = {
|
||||
"address": "addr1q84sh2j72ux0l03fxndjnhctdg7hcppsaejafsa84vh7lwgmcs5wgus8qt4atk45lvt4xfxpjtwfhdmvchdf2m3u3hlsd5tq5r",
|
||||
"amount": "1",
|
||||
},
|
||||
"base_address_with_script_output": {
|
||||
"address": "addr1z90z7zqwhya6mpk5q929ur897g3pp9kkgalpreny8y304r2dcrtx0sf3dluyu4erzr3xtmdnzvcyfzekkuteu2xagx0qeva0pr",
|
||||
"amount": "7120787",
|
||||
},
|
||||
"base_address_change_output": {
|
||||
"addressType": 0,
|
||||
"path": "m/1852'/1815'/0'/0/0",
|
||||
@ -96,34 +100,23 @@ SAMPLE_OUTPUTS = {
|
||||
"address": "Ae2tdPwUPEZ5YUb8sM3eS8JqKgrRLzhiu71crfuH2MFtqaYr5ACNRZR3Mbm",
|
||||
"amount": "3003112",
|
||||
},
|
||||
"invalid_base_address_too_short": {
|
||||
"address": "addr1q89s8py7y68e3x66sscs0wkhlg5ssfrfs65084jrlrqcfqqj922xhxkn6twlq2wn4q50q352annk3903tj00h45mggqvpjcf",
|
||||
"invalid_address_too_short": {
|
||||
"address": "addr1q89s8py7y68e3x66sscs0wkhlg5ssfrfs65084jry45scvehcr",
|
||||
"amount": "3003112",
|
||||
},
|
||||
"invalid_base_address_too_long": {
|
||||
"address": "addr1q89s8py7y68e3x66sscs0wkhlg5ssfrfs65084jrlrqcfqqj922xhxkn6twlq2wn4q50q352annk3903tj00h45mgfm5zhnjqfc",
|
||||
"amount": "3003112",
|
||||
},
|
||||
"invalid_pointer_address_too_short": {
|
||||
"address": "addr1g89s8py7y68e3x66sscs0wkhlg5ssfrfs65084jrlrqcgrfjd3l",
|
||||
"amount": "3003112",
|
||||
},
|
||||
"invalid_pointer_address_too_long": {
|
||||
"address": "addr1g89s8py7y68e3x66sscs0wkhlg5ssfrfs65084jrlrqcfqysszqgqqysszqgqqysszqgqqzpqv0wa7",
|
||||
"amount": "3003112",
|
||||
},
|
||||
"invalid_enterprise_address_too_short": {
|
||||
"address": "addr1v89s8py7y68e3x66sscs0wkhlg5ssfrfs65084jrlrqcg0c7m2w",
|
||||
"amount": "3003112",
|
||||
},
|
||||
"invalid_enterprise_address_too_long": {
|
||||
"address": "addr1v89s8py7y68e3x66sscs0wkhlg5ssfrfs65084jrlrqcfqzp9v4srv",
|
||||
"invalid_address_too_long": {
|
||||
"address": "addr1q89s8py7y68e3x66sscs0wkhlg5ssfrfs65084jrlrqcfqqj922xhxkn6twlq2wn4q50q352annk3903tj00h45mgfm5z3vcwsfrvkr5zglq4rxu",
|
||||
"amount": "3003112",
|
||||
},
|
||||
"large_simple_byron_output": {
|
||||
"address": "Ae2tdPwUPEZCanmBz5g2GEwFqKTKpNJcGYPKfDxoNeKZ8bRHr8366kseiK2",
|
||||
"amount": "449999999199999999",
|
||||
},
|
||||
# address type 10
|
||||
"unsupported_address_type": {
|
||||
"address": "addr1590z7zqwhya6mpk5q929ur897g3pp9kkgalpreny8y304r2dcrtx0sf3dluyu4erzr3xtmdnzvcyfzekkuteu2xagx0qt7gvvj",
|
||||
"amount": "3003112",
|
||||
},
|
||||
"testnet_output": {
|
||||
"address": "2657WMsDfac7BteXkJq5Jzdog4h47fPbkwUM49isuWbYAr2cFRHa3rURP236h9PBe",
|
||||
"amount": "3003112",
|
||||
@ -205,6 +198,30 @@ VALID_VECTORS = [
|
||||
# tx body
|
||||
"83a400818258203b40265111d8bb3c3c608d95b3a0bf83461ace32d79336579a1939b3aad1c0b700018282583901eb0baa5e570cffbe2934db29df0b6a3d7c0430ee65d4c3a7ab2fefb91bc428e4720702ebd5dab4fb175324c192dc9bb76cc5da956e3c8dff018258390180f9e2c88e6c817008f3a812ed889b4a4da8e0bd103f86e7335422aa122a946b9ad3d2ddf029d3a828f0468aece76895f15c9efbd69b42771a006ca79302182a030aa100818258205d010cf16fdeff40955633d6c565f3844a288a24967cf6b76acbeb271b4f13c158406a78f07836dcf4a303448d2b16b217265a9226be3984a69a04dba5d04f4dbb2a47b5e1cbb345f474c0b9634a2f37b921ab26e6a65d5dfd015dacb4455fb8430af6",
|
||||
),
|
||||
# simple transaction with base script address change output
|
||||
(
|
||||
# protocol magic
|
||||
PROTOCOL_MAGICS["mainnet"],
|
||||
# network id
|
||||
NETWORK_IDS["mainnet"],
|
||||
# inputs
|
||||
[SAMPLE_INPUTS["shelley_input"]],
|
||||
# outputs
|
||||
[
|
||||
SAMPLE_OUTPUTS["base_address_with_script_output"],
|
||||
SAMPLE_OUTPUTS["base_address_change_output"],
|
||||
],
|
||||
# fee
|
||||
42,
|
||||
# ttl
|
||||
10,
|
||||
# input flow
|
||||
[[InputAction.SWIPE, InputAction.YES], [InputAction.SWIPE, InputAction.YES]],
|
||||
# tx hash
|
||||
"5ddbb530b8a89e2b08fc91db03950c876c4a9c1c3fb6e628c4cab638b1c97648",
|
||||
# tx body
|
||||
"83a400818258203b40265111d8bb3c3c608d95b3a0bf83461ace32d79336579a1939b3aad1c0b7000182825839115e2f080eb93bad86d401545e0ce5f2221096d6477e11e6643922fa8d4dc0d667c1316ff84e572310e265edb31330448b36b7179e28dd419e1a006ca7938258390180f9e2c88e6c817008f3a812ed889b4a4da8e0bd103f86e7335422aa122a946b9ad3d2ddf029d3a828f0468aece76895f15c9efbd69b42771a006ca79302182a030aa100818258205d010cf16fdeff40955633d6c565f3844a288a24967cf6b76acbeb271b4f13c15840e0bdaa59016f2a521d31179b60364eacdcb53c34ae01c56b339afa62d312f5f89783579691cac777e3d5f2e7810aa8fe554ba545a8d1578c55405af5ae51b30ff6",
|
||||
),
|
||||
# simple transaction with base address change output with staking key hash
|
||||
(
|
||||
# protocol magic
|
||||
@ -373,7 +390,7 @@ INVALID_VECTORS = [
|
||||
# error message
|
||||
"Invalid address",
|
||||
),
|
||||
# Output base address is too short
|
||||
# Output address is too short
|
||||
(
|
||||
# protocol magic (mainnet)
|
||||
PROTOCOL_MAGICS["mainnet"],
|
||||
@ -382,7 +399,7 @@ INVALID_VECTORS = [
|
||||
# inputs
|
||||
[SAMPLE_INPUTS["shelley_input"]],
|
||||
# outputs
|
||||
[SAMPLE_OUTPUTS["invalid_base_address_too_short"]],
|
||||
[SAMPLE_OUTPUTS["invalid_address_too_short"]],
|
||||
# fee
|
||||
42,
|
||||
# ttl
|
||||
@ -390,7 +407,7 @@ INVALID_VECTORS = [
|
||||
# error message
|
||||
"Invalid address",
|
||||
),
|
||||
# Output base address is too long
|
||||
# Output address is too long
|
||||
(
|
||||
# protocol magic (mainnet)
|
||||
PROTOCOL_MAGICS["mainnet"],
|
||||
@ -399,75 +416,7 @@ INVALID_VECTORS = [
|
||||
# inputs
|
||||
[SAMPLE_INPUTS["shelley_input"]],
|
||||
# outputs
|
||||
[SAMPLE_OUTPUTS["invalid_base_address_too_long"]],
|
||||
# fee
|
||||
42,
|
||||
# ttl
|
||||
10,
|
||||
# error message
|
||||
"Invalid address",
|
||||
),
|
||||
# Output pointer address is too short
|
||||
(
|
||||
# protocol magic (mainnet)
|
||||
PROTOCOL_MAGICS["mainnet"],
|
||||
# network id
|
||||
NETWORK_IDS["mainnet"],
|
||||
# inputs
|
||||
[SAMPLE_INPUTS["shelley_input"]],
|
||||
# outputs
|
||||
[SAMPLE_OUTPUTS["invalid_pointer_address_too_short"]],
|
||||
# fee
|
||||
42,
|
||||
# ttl
|
||||
10,
|
||||
# error message
|
||||
"Invalid address",
|
||||
),
|
||||
# Output pointer address is too long
|
||||
(
|
||||
# protocol magic (mainnet)
|
||||
PROTOCOL_MAGICS["mainnet"],
|
||||
# network id
|
||||
NETWORK_IDS["mainnet"],
|
||||
# inputs
|
||||
[SAMPLE_INPUTS["shelley_input"]],
|
||||
# outputs
|
||||
[SAMPLE_OUTPUTS["invalid_pointer_address_too_long"]],
|
||||
# fee
|
||||
42,
|
||||
# ttl
|
||||
10,
|
||||
# error message
|
||||
"Invalid address",
|
||||
),
|
||||
# Output enterprise address is too short
|
||||
(
|
||||
# protocol magic (mainnet)
|
||||
PROTOCOL_MAGICS["mainnet"],
|
||||
# network id
|
||||
NETWORK_IDS["mainnet"],
|
||||
# inputs
|
||||
[SAMPLE_INPUTS["shelley_input"]],
|
||||
# outputs
|
||||
[SAMPLE_OUTPUTS["invalid_enterprise_address_too_short"]],
|
||||
# fee
|
||||
42,
|
||||
# ttl
|
||||
10,
|
||||
# error message
|
||||
"Invalid address",
|
||||
),
|
||||
# Output enterprise address is too long
|
||||
(
|
||||
# protocol magic (mainnet)
|
||||
PROTOCOL_MAGICS["mainnet"],
|
||||
# network id
|
||||
NETWORK_IDS["mainnet"],
|
||||
# inputs
|
||||
[SAMPLE_INPUTS["shelley_input"]],
|
||||
# outputs
|
||||
[SAMPLE_OUTPUTS["invalid_enterprise_address_too_long"]],
|
||||
[SAMPLE_OUTPUTS["invalid_address_too_long"]],
|
||||
# fee
|
||||
42,
|
||||
# ttl
|
||||
@ -614,6 +563,23 @@ INVALID_VECTORS = [
|
||||
# error message
|
||||
"Invalid network id/protocol magic combination!",
|
||||
),
|
||||
# Unsupported address type
|
||||
(
|
||||
# protocol magic
|
||||
PROTOCOL_MAGICS["mainnet"],
|
||||
# network id
|
||||
NETWORK_IDS["mainnet"],
|
||||
# inputs
|
||||
[SAMPLE_INPUTS["shelley_input"]],
|
||||
# outputs
|
||||
[SAMPLE_OUTPUTS["unsupported_address_type"]],
|
||||
# fee
|
||||
42,
|
||||
# ttl
|
||||
10,
|
||||
# error message
|
||||
"Invalid address",
|
||||
),
|
||||
]
|
||||
|
||||
|
||||
|
Loading…
Reference in New Issue
Block a user