Add support for script addresses in tx outputs

pull/1145/head
gabrielkerekes 4 years ago committed by Tomas Susanka
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",
"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",
"invalid_address_too_short": {
"address": "addr1q89s8py7y68e3x66sscs0wkhlg5ssfrfs65084jry45scvehcr",
"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…
Cancel
Save