feat(core/cardano): add support for catalyst voting registration

pull/1582/head
gabrielkerekes 3 years ago committed by matejcik
parent 2c503b16f5
commit 2313293477

@ -116,17 +116,19 @@ message CardanoPublicKey {
* @next Failure
*/
message CardanoSignTx {
repeated CardanoTxInputType inputs = 1; // inputs to be used in transaction
repeated CardanoTxOutputType outputs = 2; // outputs to be used in transaction
// optional uint32 transactions_count = 3; // left as a comment so we know to skip the id 3 in the future
required uint32 protocol_magic = 5; // network's protocol magic
required uint64 fee = 6; // transaction fee - added in shelley
optional uint64 ttl = 7; // transaction ttl - added in shelley
required uint32 network_id = 8; // network id - mainnet or testnet
repeated CardanoTxCertificateType certificates = 9; // transaction certificates - added in shelley
repeated CardanoTxWithdrawalType withdrawals = 10; // transaction withdrawals - added in shelley
optional bytes metadata = 11; // transaction metadata - added in shelley
optional uint64 validity_interval_start = 12; // transaction validity start - added in allegra
repeated CardanoTxInputType inputs = 1; // inputs to be used in transaction
repeated CardanoTxOutputType outputs = 2; // outputs to be used in transaction
// optional uint32 transactions_count = 3; // left as a comment so we know to skip the id 3 in the future
// optional uint32 network = 4; // replaced with protocol_magic
required uint32 protocol_magic = 5; // network's protocol magic
required uint64 fee = 6; // transaction fee - added in shelley
optional uint64 ttl = 7; // transaction ttl - added in shelley
required uint32 network_id = 8; // network id - mainnet or testnet
repeated CardanoTxCertificateType certificates = 9; // transaction certificates - added in shelley
repeated CardanoTxWithdrawalType withdrawals = 10; // transaction withdrawals - added in shelley
// optional bytes metadata = 11; // replaced in Mary era with auxiliary data below
optional uint64 validity_interval_start = 12; // transaction validity start - added in allegra
optional CardanoTxAuxiliaryDataType auxiliary_data = 13; // transaction auxiliary data
/**
* Structure representing cardano transaction input
@ -218,6 +220,18 @@ message CardanoSignTx {
repeated uint32 path = 1;
required uint64 amount = 2;
}
message CardanoCatalystRegistrationParametersType {
required bytes voting_public_key = 1;
repeated uint32 staking_path = 2;
required CardanoAddressParametersType reward_address_parameters = 3;
required uint64 nonce = 4;
}
message CardanoTxAuxiliaryDataType {
optional bytes blob = 1;
optional CardanoCatalystRegistrationParametersType catalyst_registration_parameters = 2;
}
}
/**

@ -13,7 +13,7 @@
"ttl": 10,
"certificates": [],
"withdrawals": [],
"metadata": "",
"auxiliary_data": null,
"input_flow": [["SWIPE", "YES"], ["SWIPE", "YES"]],
"inputs": [
{

@ -13,7 +13,7 @@
"ttl": 10,
"certificates": [],
"withdrawals": [],
"metadata": "",
"auxiliary_data": null,
"inputs": [
{
"path": "m/44'/1815'/0'/0/1",
@ -41,7 +41,7 @@
"ttl": 10,
"certificates": [],
"withdrawals": [],
"metadata": "",
"auxiliary_data": null,
"inputs": [
{
"path": "m/44'/1815'/0'/0/1",
@ -69,7 +69,7 @@
"ttl": 10,
"certificates": [],
"withdrawals": [],
"metadata": "",
"auxiliary_data": null,
"inputs": [
{
"path": "m/44'/1815'/0'/0/1",
@ -97,7 +97,7 @@
"ttl": 10,
"certificates": [],
"withdrawals": [],
"metadata": "",
"auxiliary_data": null,
"inputs": [
{
"path": "m/44'/1815'/0'/0/1",
@ -125,7 +125,7 @@
"ttl": 10,
"certificates": [],
"withdrawals": [],
"metadata": "",
"auxiliary_data": null,
"inputs": [
{
"path": "m/1852'/1815'/0'/0/0",
@ -153,7 +153,7 @@
"ttl": 10,
"certificates": [],
"withdrawals": [],
"metadata": "",
"auxiliary_data": null,
"inputs": [
{
"path": "m/1852'/1815'/0'/0/0",
@ -181,7 +181,7 @@
"ttl": 10,
"certificates": [],
"withdrawals": [],
"metadata": "",
"auxiliary_data": null,
"inputs": [
{
"path": "m/44'/1815'/0'/0/1",
@ -214,7 +214,7 @@
"ttl": 10,
"certificates": [],
"withdrawals": [],
"metadata": "",
"auxiliary_data": null,
"inputs": [
{
"path": "m/1852'/1815'/0'/0/0",
@ -242,7 +242,7 @@
"ttl": 10,
"certificates": [],
"withdrawals": [],
"metadata": "",
"auxiliary_data": null,
"inputs": [
{
"path": "m/44'/1815'/0'/0/1",
@ -270,7 +270,7 @@
"ttl": 10,
"certificates": [],
"withdrawals": [],
"metadata": "",
"auxiliary_data": null,
"inputs": [
{
"path": "m/1852'/1815'/0'/0/0",
@ -298,7 +298,7 @@
"ttl": 10,
"certificates": [],
"withdrawals": [],
"metadata": "",
"auxiliary_data": null,
"inputs": [
{
"path": "m/1852'/1815'/0'/0/0",
@ -326,7 +326,7 @@
"ttl": 10,
"certificates": [],
"withdrawals": [],
"metadata": "",
"auxiliary_data": null,
"inputs": [
{
"path": "m/1852'/1815'/0'/0/0",
@ -354,7 +354,7 @@
"ttl": 10,
"certificates": [],
"withdrawals": [],
"metadata": "",
"auxiliary_data": null,
"inputs": [
{
"path": "m/1852'/1815'/0'/0/0",
@ -382,7 +382,7 @@
"ttl": 10,
"certificates": [],
"withdrawals": [],
"metadata": "",
"auxiliary_data": null,
"inputs": [
{
"path": "m/1852'/1815'/0'/0/0",
@ -412,7 +412,7 @@
{"type": 0, "path": "m/1852'/1815'/0'/0/0"}
],
"withdrawals": [],
"metadata": "",
"auxiliary_data": null,
"inputs": [
{
"path": "m/1852'/1815'/0'/0/0",
@ -446,7 +446,7 @@
}
],
"withdrawals": [],
"metadata": "",
"auxiliary_data": null,
"inputs": [
{
"path": "m/1852'/1815'/0'/0/0",
@ -474,7 +474,7 @@
"ttl": 10,
"certificates": [],
"withdrawals": [{"path": "m/1852'/1815'/0'/0/0", "amount": "1000"}],
"metadata": "",
"auxiliary_data": null,
"inputs": [
{
"path": "m/1852'/1815'/0'/0/0",
@ -505,7 +505,7 @@
"path": "m/1852'/1815'/0'/2/0",
"amount": "449999999199999999"
}],
"metadata": "",
"auxiliary_data": null,
"inputs": [
{
"path": "m/1852'/1815'/0'/0/0",
@ -525,7 +525,7 @@
}
},
{
"description": "Metadata too large",
"description": "Auxiliary data blob is incomplete",
"parameters": {
"protocol_magic": 764824073,
"network_id": 1,
@ -533,7 +533,9 @@
"ttl": 10,
"certificates": [],
"withdrawals": [],
"metadata": "a200a11864a118c843aa00ff01a119012c590202aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa",
"auxiliary_data": {
"blob": "a200a11864a118c843aa00ff01"
},
"inputs": [
{
"path": "m/1852'/1815'/0'/0/0",
@ -549,11 +551,11 @@
]
},
"result": {
"error_message": "Invalid metadata"
"error_message": "Invalid auxiliary data"
}
},
{
"description": "Metadata is a list",
"description": "Auxiliary data blob has leftover data",
"parameters": {
"protocol_magic": 764824073,
"network_id": 1,
@ -561,7 +563,9 @@
"ttl": 10,
"certificates": [],
"withdrawals": [],
"metadata": "82a200a11864a118c843aa00ff01a119012c590100aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa0A",
"auxiliary_data": {
"blob": "a200a11864a118c843aa00ff01a119012c590100aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa000000"
},
"inputs": [
{
"path": "m/1852'/1815'/0'/0/0",
@ -577,11 +581,11 @@
]
},
"result": {
"error_message": "Invalid metadata"
"error_message": "Invalid auxiliary data"
}
},
{
"description": "Metadata is incomplete",
"description": "transaction with catalyst registration containing byron reward address",
"parameters": {
"protocol_magic": 764824073,
"network_id": 1,
@ -589,27 +593,37 @@
"ttl": 10,
"certificates": [],
"withdrawals": [],
"metadata": "a200a11864a118c843aa00ff01",
"auxiliary_data": {
"catalyst_registration_parameters": {
"voting_public_key": "3b40265111d8bb3c3c608d95b3a0bf83461ace32d79336579a1939b3aad1c0b7",
"staking_path": "m/1852'/1815'/0'/2/0",
"nonce": 22634813,
"reward_address_parameters": {
"addressType": 8,
"path": "m/44'/1815'/0'/0/0"
}
}
},
"inputs": [
{
"path": "m/1852'/1815'/0'/0/0",
"prev_hash": "3b40265111d8bb3c3c608d95b3a0bf83461ace32d79336579a1939b3aad1c0b7",
"prev_hash": "1af8fa0b754ff99253d983894e63a2b09cbb56c833ba18c3384210163f63dcfc",
"prev_index": 0
}
],
"outputs": [
{
"address": "Ae2tdPwUPEZCanmBz5g2GEwFqKTKpNJcGYPKfDxoNeKZ8bRHr8366kseiK2",
"amount": "3003112"
"address": "addr1q84sh2j72ux0l03fxndjnhctdg7hcppsaejafsa84vh7lwgmcs5wgus8qt4atk45lvt4xfxpjtwfhdmvchdf2m3u3hlsd5tq5r",
"amount": "1"
}
]
},
"result": {
"error_message": "Invalid metadata"
"error_message": "Invalid auxiliary data"
}
},
{
"description": "Metadata has leftover data",
"description": "transaction with both auxiliary data blob and catalyst registration",
"parameters": {
"protocol_magic": 764824073,
"network_id": 1,
@ -617,23 +631,35 @@
"ttl": 10,
"certificates": [],
"withdrawals": [],
"metadata": "a200a11864a118c843aa00ff01a119012c590100aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa000000",
"auxiliary_data": {
"blob": "a200a11864a118c843aa00ff01a119012c590100aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa",
"catalyst_registration_parameters": {
"voting_public_key": "38DA0B509D45BF6C87BD55594B92F97081D3923B8C1334B9B8D0BF13FC1C12D0",
"staking_path": "m/1852'/1815'/0'/2/0",
"reward_address_parameters": {
"addressType": 0,
"path": "m/1852'/1815'/0'/0/0",
"stakingPath": "m/1852'/1815'/0'/2/0"
},
"nonce": 140
}
},
"inputs": [
{
"path": "m/1852'/1815'/0'/0/0",
"prev_hash": "3b40265111d8bb3c3c608d95b3a0bf83461ace32d79336579a1939b3aad1c0b7",
"prev_hash": "1af8fa0b754ff99253d983894e63a2b09cbb56c833ba18c3384210163f63dcfc",
"prev_index": 0
}
],
"outputs": [
{
"address": "Ae2tdPwUPEZCanmBz5g2GEwFqKTKpNJcGYPKfDxoNeKZ8bRHr8366kseiK2",
"amount": "3003112"
"address": "addr1q84sh2j72ux0l03fxndjnhctdg7hcppsaejafsa84vh7lwgmcs5wgus8qt4atk45lvt4xfxpjtwfhdmvchdf2m3u3hlsd5tq5r",
"amount": "1"
}
]
},
"result": {
"error_message": "Invalid metadata"
"error_message": "Invalid auxiliary data"
}
},
{
@ -645,7 +671,7 @@
"ttl": 10,
"certificates": [],
"withdrawals": [],
"metadata": "",
"auxiliary_data": null,
"input_flow": [["SWIPE", "YES"]],
"inputs": [
{
@ -680,7 +706,7 @@
"ttl": 10,
"certificates": [],
"withdrawals": [],
"metadata": "",
"auxiliary_data": null,
"input_flow": [["SWIPE", "YES"]],
"inputs": [
{
@ -720,7 +746,7 @@
}
],
"withdrawals": [],
"metadata": "",
"auxiliary_data": null,
"input_flow": [["SWIPE", "YES"]],
"inputs": [
{
@ -749,7 +775,7 @@
"ttl": 10,
"certificates": [],
"withdrawals": [],
"metadata": "",
"auxiliary_data": null,
"inputs": [
{
"path": "m/1852'/1815'/0'/0/0",
@ -792,7 +818,7 @@
"ttl": 10,
"certificates": [],
"withdrawals": [],
"metadata": "",
"auxiliary_data": null,
"inputs": [
{
"path": "m/1852'/1815'/0'/0/0",

@ -13,7 +13,7 @@
"ttl": 10,
"certificates": [],
"withdrawals": [],
"metadata": "",
"auxiliary_data": null,
"input_flow": [["SWIPE", "YES"], ["SWIPE", "YES"]],
"inputs": [
{
@ -43,7 +43,7 @@
"ttl": 10,
"certificates": [],
"withdrawals": [],
"metadata": "",
"auxiliary_data": null,
"input_flow": [["SWIPE", "YES"], ["YES"], ["SWIPE", "YES"]],
"inputs": [
{
@ -78,7 +78,7 @@
"ttl": 10,
"certificates": [],
"withdrawals": [],
"metadata": "",
"auxiliary_data": null,
"input_flow": [["SWIPE", "YES"], ["SWIPE", "YES"]],
"inputs": [
{
@ -114,7 +114,7 @@
"ttl": 10,
"certificates": [],
"withdrawals": [],
"metadata": "",
"auxiliary_data": null,
"input_flow": [["SWIPE", "YES"], ["SWIPE", "YES"]],
"inputs": [
{
@ -159,7 +159,7 @@
"ttl": 10,
"certificates": [],
"withdrawals": [],
"metadata": "",
"auxiliary_data": null,
"input_flow": [["SWIPE", "YES"], ["SWIPE", "YES"]],
"inputs": [
{
@ -196,7 +196,7 @@
"ttl": 10,
"certificates": [],
"withdrawals": [],
"metadata": "",
"auxiliary_data": null,
"input_flow": [["SWIPE", "YES"], ["YES"], ["YES"], ["SWIPE", "YES"], ["SWIPE", "YES"]],
"inputs": [
{
@ -233,7 +233,7 @@
"ttl": 10,
"certificates": [],
"withdrawals": [],
"metadata": "",
"auxiliary_data": null,
"input_flow": [["SWIPE", "YES"], ["YES"], ["SWIPE", "YES"], ["SWIPE", "YES"]],
"inputs": [
{
@ -269,7 +269,7 @@
"ttl": 10,
"certificates": [],
"withdrawals": [],
"metadata": "",
"auxiliary_data": null,
"input_flow": [["SWIPE", "YES"], ["SWIPE", "YES"], ["SWIPE", "YES"]],
"inputs": [
{
@ -305,7 +305,7 @@
"ttl": 10,
"certificates": [],
"withdrawals": [],
"metadata": "",
"auxiliary_data": null,
"input_flow": [["SWIPE", "YES"], ["SWIPE", "YES"], ["SWIPE", "YES"]],
"inputs": [
{
@ -343,7 +343,7 @@
"ttl": 10,
"certificates": [],
"withdrawals": [],
"metadata": "",
"auxiliary_data": null,
"input_flow": [["SWIPE", "YES"], ["YES"], ["SWIPE", "YES"]],
"inputs": [
{
@ -383,7 +383,7 @@
}
],
"withdrawals": [],
"metadata": "",
"auxiliary_data": null,
"input_flow": [["SWIPE", "YES"], ["YES"], ["SWIPE", "YES"]],
"inputs": [
{
@ -418,7 +418,7 @@
}
],
"withdrawals": [],
"metadata": "",
"auxiliary_data": null,
"input_flow": [["YES"], ["SWIPE", "YES"], ["SWIPE", "YES"]],
"inputs": [
{
@ -454,7 +454,7 @@
}
],
"withdrawals": [],
"metadata": "",
"auxiliary_data": null,
"input_flow": [["SWIPE", "YES"], ["YES"], ["SWIPE", "YES"], ["SWIPE", "YES"]],
"inputs": [
{
@ -486,7 +486,7 @@
{"type": 1, "path": "m/1852'/1815'/0'/2/0"}
],
"withdrawals": [],
"metadata": "",
"auxiliary_data": null,
"input_flow": [["SWIPE", "YES"], ["YES"], ["SWIPE", "YES"]],
"inputs": [
{
@ -526,7 +526,7 @@
"amount": "1000"
}
],
"metadata": "",
"auxiliary_data": null,
"input_flow": [["SWIPE", "YES"], ["YES"], ["YES"], ["SWIPE", "YES"]],
"inputs": [
{
@ -562,7 +562,7 @@
}
],
"withdrawals": [],
"metadata": "",
"auxiliary_data": null,
"input_flow": [["SWIPE", "YES"], ["YES"], ["YES"], ["SWIPE", "YES"]],
"inputs": [
{
@ -584,7 +584,7 @@
}
},
{
"description": "transaction with metadata",
"description": "transaction with auxiliary data blob",
"parameters": {
"protocol_magic": 764824073,
"network_id": 1,
@ -592,8 +592,10 @@
"ttl": 10,
"certificates": [],
"withdrawals": [],
"metadata": "a200a11864a118c843aa00ff01a119012c590100aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa",
"input_flow": [["SWIPE", "YES"], ["SWIPE", "YES"]],
"auxiliary_data": {
"blob": "a200a11864a118c843aa00ff01a119012c590100aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa"
},
"input_flow": [["SWIPE", "YES"], ["YES"], ["SWIPE", "YES"]],
"inputs": [
{
"path": "m/1852'/1815'/0'/0/0",
@ -613,6 +615,47 @@
"serialized_tx": "83a500818258203b40265111d8bb3c3c608d95b3a0bf83461ace32d79336579a1939b3aad1c0b700018182583901eb0baa5e570cffbe2934db29df0b6a3d7c0430ee65d4c3a7ab2fefb91bc428e4720702ebd5dab4fb175324c192dc9bb76cc5da956e3c8dff0102182a030a075820ea4c91860dd5ec5449f8f985d227946ff39086b17f10b5afb93d12ee87050b6aa100818258205d010cf16fdeff40955633d6c565f3844a288a24967cf6b76acbeb271b4f13c15840b2015772a91043aeb04b98111744a098afdade0db5e30206538d7f2814965a5800d45240137f4d0dc81845a71e67cda38beaf816a520d73c4decbf7cbf0f6d08a200a11864a118c843aa00ff01a119012c590100aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa"
}
},
{
"description": "transaction with catalyst registration",
"parameters": {
"protocol_magic": 764824073,
"network_id": 1,
"fee": 42,
"ttl": 10,
"certificates": [],
"withdrawals": [],
"auxiliary_data": {
"catalyst_registration_parameters": {
"voting_public_key": "1af8fa0b754ff99253d983894e63a2b09cbb56c833ba18c3384210163f63dcfc",
"staking_path": "m/1852'/1815'/0'/2/0",
"reward_address_parameters": {
"addressType": 0,
"path": "m/1852'/1815'/0'/0/0",
"stakingPath": "m/1852'/1815'/0'/2/0"
},
"nonce": 22634813
}
},
"input_flow": [["SWIPE", "SWIPE", "YES"], ["SWIPE", "SWIPE", "SWIPE", "SWIPE", "SWIPE", "YES"], ["YES"], ["SWIPE", "YES"]],
"inputs": [
{
"path": "m/1852'/1815'/0'/0/0",
"prev_hash": "3b40265111d8bb3c3c608d95b3a0bf83461ace32d79336579a1939b3aad1c0b7",
"prev_index": 0
}
],
"outputs": [
{
"address": "addr1q84sh2j72ux0l03fxndjnhctdg7hcppsaejafsa84vh7lwgmcs5wgus8qt4atk45lvt4xfxpjtwfhdmvchdf2m3u3hlsd5tq5r",
"amount": "1"
}
]
},
"result": {
"tx_hash": "839a587109358e0aa81b8fb3d5fa74665fac303425ec544a4db7f6ba4e882dff",
"serialized_tx": "83a500818258203b40265111d8bb3c3c608d95b3a0bf83461ace32d79336579a1939b3aad1c0b700018182583901eb0baa5e570cffbe2934db29df0b6a3d7c0430ee65d4c3a7ab2fefb91bc428e4720702ebd5dab4fb175324c192dc9bb76cc5da956e3c8dff0102182a030a075820a943e9166f1bb6d767b175384d3bd7d23645170df36fc1861fbf344135d8e120a100818258205d010cf16fdeff40955633d6c565f3844a288a24967cf6b76acbeb271b4f13c15840187ecd899e01390272a8d8289088199b3453945fa076819b5b5df60c325c10315477cc801044dfb553e780a300d79627ef5c09e64c6f953cc33bbc59152c900282a219ef64a40158201af8fa0b754ff99253d983894e63a2b09cbb56c833ba18c3384210163f63dcfc025820bc65be1b0b9d7531778a1317c2aa6de936963c3f9ac7d5ee9e9eda25e0c97c5e0358390180f9e2c88e6c817008f3a812ed889b4a4da8e0bd103f86e7335422aa122a946b9ad3d2ddf029d3a828f0468aece76895f15c9efbd69b4277041a0159613d19ef65a101584074f27d877bbb4a5fc4f7c56869905c11f70bad0af3de24b23afaa1d024e750930f434ecc4b73e5d1723c2cb8548e8bf6098ac876487b3a6ed0891cb76994d40980"
}
},
{
"description": "Testnet transaction",
"parameters": {
@ -622,7 +665,7 @@
"ttl": 10,
"certificates": [],
"withdrawals": [],
"metadata": "",
"auxiliary_data": null,
"input_flow": [["SWIPE", "YES"], ["SWIPE", "YES"], ["YES"], ["SWIPE", "YES"]],
"inputs": [
{
@ -662,7 +705,7 @@
"validity_interval_start": 47,
"certificates": [],
"withdrawals": [],
"metadata": "",
"auxiliary_data": null,
"input_flow": [["YES"], ["SWIPE", "YES"], ["SWIPE", "SWIPE", "YES"], ["SWIPE", "YES"]],
"inputs": [
{
@ -710,7 +753,7 @@
"validity_interval_start": 47,
"certificates": [],
"withdrawals": [],
"metadata": "",
"auxiliary_data": null,
"input_flow": [["YES"], ["SWIPE", "YES"], ["SWIPE", "YES"], ["SWIPE", "YES"], ["SWIPE", "SWIPE", "YES"], ["SWIPE", "YES"]],
"inputs": [
{
@ -769,7 +812,7 @@
"fee": 42,
"certificates": [],
"withdrawals": [],
"metadata": "",
"auxiliary_data": null,
"input_flow": [["YES"]],
"inputs": [
{
@ -800,7 +843,7 @@
"fee": 42,
"certificates": [],
"withdrawals": [],
"metadata": "",
"auxiliary_data": null,
"input_flow": [["YES"], ["YES"]],
"inputs": [
{

@ -17,7 +17,7 @@
"ttl": 10,
"certificates": [],
"withdrawals": [],
"metadata": "",
"auxiliary_data": null,
"input_flow": [["YES"], ["YES"], ["SWIPE", "YES"], ["SWIPE", "YES"]],
"inputs": [
{
@ -47,7 +47,7 @@
"ttl": 10,
"certificates": [],
"withdrawals": [],
"metadata": "",
"auxiliary_data": null,
"input_flow": [["YES"], ["YES"], ["SWIPE", "YES"], ["YES"], ["SWIPE", "YES"]],
"inputs": [
{
@ -82,7 +82,7 @@
"ttl": 10,
"certificates": [],
"withdrawals": [],
"metadata": "",
"auxiliary_data": null,
"input_flow": [["YES"], ["YES"], ["SWIPE", "YES"], ["YES"], ["SWIPE", "YES"]],
"inputs": [
{

@ -35,7 +35,7 @@
}
],
"withdrawals": [],
"metadata": "",
"auxiliary_data": null,
"inputs": [
{
"prev_hash": "3b40265111d8bb3c3c608d95b3a0bf83461ace32d79336579a1939b3aad1c0b7",
@ -87,7 +87,7 @@
}
],
"withdrawals": [],
"metadata": "",
"auxiliary_data": null,
"inputs": [
{
"prev_hash": "3b40265111d8bb3c3c608d95b3a0bf83461ace32d79336579a1939b3aad1c0b7",
@ -136,7 +136,7 @@
}
],
"withdrawals": [],
"metadata": "",
"auxiliary_data": null,
"inputs": [
{
"prev_hash": "3b40265111d8bb3c3c608d95b3a0bf83461ace32d79336579a1939b3aad1c0b7",
@ -185,7 +185,7 @@
}
],
"withdrawals": [],
"metadata": "",
"auxiliary_data": null,
"inputs": [
{
"prev_hash": "3b40265111d8bb3c3c608d95b3a0bf83461ace32d79336579a1939b3aad1c0b7",
@ -238,7 +238,7 @@
}
],
"withdrawals": [],
"metadata": "",
"auxiliary_data": null,
"inputs": [
{
"prev_hash": "3b40265111d8bb3c3c608d95b3a0bf83461ace32d79336579a1939b3aad1c0b7",
@ -292,7 +292,7 @@
"amount": "1000"
}
],
"metadata": "",
"auxiliary_data": null,
"inputs": [
{
"prev_hash": "3b40265111d8bb3c3c608d95b3a0bf83461ace32d79336579a1939b3aad1c0b7",
@ -340,7 +340,7 @@
}
],
"withdrawals": [],
"metadata": "",
"auxiliary_data": null,
"inputs": [
{
"path": "m/1852'/1815'/0'/0/0",
@ -389,7 +389,7 @@
}
],
"withdrawals": [],
"metadata": "",
"auxiliary_data": null,
"inputs": [
{
"prev_hash": "3b40265111d8bb3c3c608d95b3a0bf83461ace32d79336579a1939b3aad1c0b7",
@ -437,7 +437,7 @@
}
],
"withdrawals": [],
"metadata": "",
"auxiliary_data": null,
"inputs": [
{
"prev_hash": "3b40265111d8bb3c3c608d95b3a0bf83461ace32d79336579a1939b3aad1c0b7",
@ -518,7 +518,7 @@
}
],
"withdrawals": [],
"metadata": "",
"auxiliary_data": null,
"input_flow": [["SWIPE", "SWIPE", "YES"]],
"inputs": [
{

@ -67,7 +67,7 @@
}
],
"withdrawals": [],
"metadata": "",
"auxiliary_data": null,
"input_flow": [["SWIPE", "SWIPE", "YES"], ["SWIPE", "YES"], ["SWIPE", "YES"], ["YES"], ["YES"]],
"inputs": [
{
@ -151,7 +151,7 @@
}
],
"withdrawals": [],
"metadata": "",
"auxiliary_data": null,
"input_flow": [["SWIPE", "SWIPE", "YES"], ["SWIPE", "YES"], ["SWIPE", "YES"], ["YES"], ["YES"]],
"inputs": [
{
@ -236,7 +236,7 @@
}
],
"withdrawals": [],
"metadata": "",
"auxiliary_data": null,
"input_flow": [["SWIPE", "SWIPE", "YES"], ["YES"], ["SWIPE", "YES"], ["SWIPE", "YES"], ["YES"], ["YES"]],
"inputs": [
{
@ -287,7 +287,7 @@
}
],
"withdrawals": [],
"metadata": "",
"auxiliary_data": null,
"input_flow": [["SWIPE", "SWIPE", "YES"], ["YES"], ["YES"], ["YES"], ["YES"]],
"inputs": [
{
@ -338,7 +338,7 @@
}
],
"withdrawals": [],
"metadata": "",
"auxiliary_data": null,
"input_flow": [["SWIPE", "SWIPE", "YES"], ["YES"], ["YES"], ["YES"], ["YES"]],
"inputs": [
{
@ -358,6 +358,93 @@
"tx_hash": "12921b4f8e77f815e0c8ed97c541fbd5ba38a6d3323f4ff1af0cb934b8ac6b39",
"serialized_tx": "83a500818258203b40265111d8bb3c3c608d95b3a0bf83461ace32d79336579a1939b3aad1c0b700018182581d60cb03849e268f989b5a843107bad7fa2908246986a8f3d643f8c184800102182a030a04818a03581cf61c42cbf7c8c53af3f520508212ad3e72f674f957fe23ff0acb49735820198890ad6c92e80fbdab554dda02da9fb49d001bbd96181f3e07f7a6ab0d06401a1dcd65001a1443fd00d81e820102581de03a7f09d3df4cf66a7399c2b05bfa234d5a29560c311fc5db4c49071181581c122a946b9ad3d2ddf029d3a828f0468aece76895f15c9efbd69b427780f6a10081825820bc65be1b0b9d7531778a1317c2aa6de936963c3f9ac7d5ee9e9eda25e0c97c5e584027cab81902d04b2491d7aa2bf57bd9db59d33c2df1502dae0412d5225c6b0b8f7b057de6a7e7eae25016ed6ea1f6e6239fb36a285216c6ee4a3cb3376287a300f6"
}
},
{
"description": "Sample stake pool registration certificate with auxiliary data",
"parameters": {
"protocol_magic": 764824073,
"network_id": 1,
"fee": 42,
"ttl": 10,
"certificates": [
{
"type": 3,
"pool_parameters": {
"pool_id": "f61c42cbf7c8c53af3f520508212ad3e72f674f957fe23ff0acb4973",
"vrf_key_hash": "198890ad6c92e80fbdab554dda02da9fb49d001bbd96181f3e07f7a6ab0d0640",
"pledge": 500000000,
"cost": 340000000,
"margin": {
"numerator": 1,
"denominator": 2
},
"reward_account": "stake1uya87zwnmax0v6nnn8ptqkl6ydx4522kpsc3l3wmf3yswygwx45el",
"owners": [
{
"staking_key_path": "m/1852'/1815'/0'/2/0"
},
{
"staking_key_hash": "3a7f09d3df4cf66a7399c2b05bfa234d5a29560c311fc5db4c490711"
}
],
"relays": [
{
"type": 0,
"ipv4_address": "192.168.0.1",
"ipv6_address": "2001:0db8:85a3:0000:0000:8a2e:0370:7334",
"port": 1234
},
{
"type": 0,
"ipv6_address": "2001:0db8:85a3:0000:0000:8a2e:0370:7334",
"port": 1234
},
{
"type": 0,
"ipv4_address": "192.168.0.1",
"port": 1234
},
{
"type": 1,
"host_name": "www.test.test",
"port": 1234
},
{
"type": 2,
"host_name": "www.test2.test"
}
],
"metadata": {
"url": "https://www.test.test",
"hash": "914c57c1f12bbf4a82b12d977d4f274674856a11ed4b9b95bd70f5d41c5064a6"
}
}
}
],
"withdrawals": [],
"auxiliary_data": {
"type": 0,
"blob": "a200a11864a118c843aa00ff01a119012c590100aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa"
},
"input_flow": [["SWIPE", "SWIPE", "YES"], ["SWIPE", "YES"], ["SWIPE", "YES"], ["YES"], ["YES"], ["YES"]],
"inputs": [
{
"path": null,
"prev_hash": "3b40265111d8bb3c3c608d95b3a0bf83461ace32d79336579a1939b3aad1c0b7",
"prev_index": 0
}
],
"outputs": [
{
"address": "addr1q84sh2j72ux0l03fxndjnhctdg7hcppsaejafsa84vh7lwgmcs5wgus8qt4atk45lvt4xfxpjtwfhdmvchdf2m3u3hlsd5tq5r",
"amount": "1"
}
]
},
"result": {
"tx_hash": "880fafab19a36407e9af300c2905e2f6bc8a8debd8b625005f56994d242ba460",
"serialized_tx": "83a600818258203b40265111d8bb3c3c608d95b3a0bf83461ace32d79336579a1939b3aad1c0b700018182583901eb0baa5e570cffbe2934db29df0b6a3d7c0430ee65d4c3a7ab2fefb91bc428e4720702ebd5dab4fb175324c192dc9bb76cc5da956e3c8dff0102182a030a04818a03581cf61c42cbf7c8c53af3f520508212ad3e72f674f957fe23ff0acb49735820198890ad6c92e80fbdab554dda02da9fb49d001bbd96181f3e07f7a6ab0d06401a1dcd65001a1443fd00d81e820102581de13a7f09d3df4cf66a7399c2b05bfa234d5a29560c311fc5db4c49071182581c122a946b9ad3d2ddf029d3a828f0468aece76895f15c9efbd69b4277581c3a7f09d3df4cf66a7399c2b05bfa234d5a29560c311fc5db4c4907118584001904d244c0a8000150b80d01200000a3852e8a00003473700384001904d2f650b80d01200000a3852e8a00003473700384001904d244c0a80001f683011904d26d7777772e746573742e7465737482026e7777772e74657374322e74657374827568747470733a2f2f7777772e746573742e746573745820914c57c1f12bbf4a82b12d977d4f274674856a11ed4b9b95bd70f5d41c5064a6075820ea4c91860dd5ec5449f8f985d227946ff39086b17f10b5afb93d12ee87050b6aa10081825820bc65be1b0b9d7531778a1317c2aa6de936963c3f9ac7d5ee9e9eda25e0c97c5e584073dbc58bd6f6bc0d91a2b5852706dde05da7acbfde035481b88b1219518ea8609dc045ea3309b1ffb01830ec64578e80c70db37a1041e72d52649be20ff80009a200a11864a118c843aa00ff01a119012c590100aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa"
}
}
]
}

@ -20,8 +20,6 @@ REVIEWER = Jan Matejek <jan.matejek@satoshilabs.com>, Tomas Susanka <tomas.susan
## Important notes
Unfortunately we are aware of the fact that currently at most ~14 inputs are supported per transaction. To resolve this, the cardano app will have to be rewritten to support transaction streaming.
Cardano requires a custom `seed.py` file and `Keychain` class. This is because the original Cardano derivation schemes don't separate seed generation from key tree derivation and also because we need to support both Byron (44') and Shelley (1852') purposes. More on this can be found [here](https://github.com/satoshilabs/slips/blob/master/slip-0023.md) and [here](https://github.com/input-output-hk/implementation-decisions/blob/e2d1bed5e617f0907bc5e12cf1c3f3302a4a7c42/text/1852-hd-chimeric.md).
Cardano uses extended public keys. This also means that the transaction signature is built using the `ed25519.sign_ext` function.
@ -126,8 +124,6 @@ Transaction outputs may include custom tokens on top of ADA tokens:
Please see the transaction below for more details.
**The serialized transaction output size is currently limited to 512 bytes. This limitation is a mitigation measure to prevent sending large (especially change) outputs containing many tokens that Trezor would not be able to spend given that currently the full Cardano transaction is held in-memory. Once Cardano-transaction signing is refactored to be streamed, this limit can be lifted**
#### Certificates
Certificates are posted to the blockchain via transactions and they mark a certain action, thus there are multiple certificate types:
@ -151,11 +147,17 @@ Withdrawals are posted to the blockchain via transactions and they are used to w
You can read more on withdrawals in the [delegation design spec](https://hydra.iohk.io/build/2006688/download/1/delegation_design_spec.pdf) (there is not a dedicated section to withdrawals, simply search for 'withdrawal').
#### Metadata
#### Auxiliary data
_Auxiliary data have replaced metadata in the Cardano Mary era_
Each transaction may contain auxiliary data. Auxiliary data format can be found [here](https://github.com/input-output-hk/cardano-ledger-specs/blob/57c27d168b8d4288534ce74e77c1df33870e756a/shelley-ma/shelley-ma-test/cddl-files/shelley-ma.cddl#L212).
Each transaction may contain metadata. Metadata format can be found [here](https://github.com/input-output-hk/cardano-ledger-specs/blob/097890495cbb0e8b62106bcd090a5721c3f4b36f/shelley-ma/shelley-ma-test/cddl-files/shelley-ma.cddl#L212). It's basically a CBOR serialized map and can contain numbers, bytes, strings or nested maps/lists.
Auxiliary data can be sent to Trezor as a blob or as an object with parameters. The blob will be included in the transaction as is.
Due to memory limitations we currently enforce a maximum size of 500 bytes for metadata.
The only object currently supported is Catalyst voting key registration. To be in compliance with the CDDL and other Cardano tools, Catalyst voting key registration object is being wrapped in a tuple and an empty tuple follows it. The empty tuple represents `auxiliary_scripts` which are not yet supported on Trezor and are thus always empty. Byron addresses are not supported as Catalyst reward addresses.
[Catalyst Registration Transaction Metadata Format](https://github.com/cardano-foundation/CIPs/blob/749f22eccd78e05fcdc4552c49639bb3bbd0a458/CIP-0015/CIP-0015.md)
#### Transaction Explorer
@ -170,7 +172,7 @@ Cardano uses [CBOR](https://www.rfc-editor.org/info/rfc7049) as a serialization
#### Raw transaction example
```
83a700818258203b40265111d8bb3c3c608d95b3a0bf83461ace32d79336579a1939b3aad1c0b700018282583901eb0baa5e570cffbe2934db29df0b6a3d7c0430ee65d4c3a7ab2fefb91bc428e4720702ebd5dab4fb175324c192dc9bb76cc5da956e3c8dff821904d2a1581c95a292ffee938be03e9bae5657982a74e9014eb4960108c9e23a5b39a14874652474436f696e1910e18258390180f9e2c88e6c817008f3a812ed889b4a4da8e0bd103f86e7335422aa122a946b9ad3d2ddf029d3a828f0468aece76895f15c9efbd69b427719115c02182a030a048182008200581c122a946b9ad3d2ddf029d3a828f0468aece76895f15c9efbd69b427705a1581de1122a946b9ad3d2ddf029d3a828f0468aece76895f15c9efbd69b42771903e80814a10082825820bc65be1b0b9d7531778a1317c2aa6de936963c3f9ac7d5ee9e9eda25e0c97c5e5840c6e85c7eec254f765ddc119b1f40ef50944dcb1882822c3d61641785bbc312d1049ed0a92ded74745986f5d464d0d0caafc9f0c66285a056309d3d39cf19b20e8258205d010cf16fdeff40955633d6c565f3844a288a24967cf6b76acbeb271b4f13c158401feabb9e56bca7d3cb75f0942d1ebaec92f167193c70fb9b416e9ae3d3e0f368f49fde3f4a862eb6a02f9a27834d0b7c1f6dd689616809432c99f3ab7249ad0ef6
83a800818258203b40265111d8bb3c3c608d95b3a0bf83461ace32d79336579a1939b3aad1c0b700018282583901eb0baa5e570cffbe2934db29df0b6a3d7c0430ee65d4c3a7ab2fefb91bc428e4720702ebd5dab4fb175324c192dc9bb76cc5da956e3c8dff821904d2a1581c95a292ffee938be03e9bae5657982a74e9014eb4960108c9e23a5b39a14874652474436f696e1910e18258390180f9e2c88e6c817008f3a812ed889b4a4da8e0bd103f86e7335422aa122a946b9ad3d2ddf029d3a828f0468aece76895f15c9efbd69b427719115c02182a030a048182008200581c122a946b9ad3d2ddf029d3a828f0468aece76895f15c9efbd69b427705a1581de1122a946b9ad3d2ddf029d3a828f0468aece76895f15c9efbd69b42771903e80758205410cfffe33d9da8b3ab789068f12e0464fad13f586f92d8c8c2fcac68c1a9c00814a100828258205d010cf16fdeff40955633d6c565f3844a288a24967cf6b76acbeb271b4f13c158406478ca1a1d1bab66688a19e983fbff9e7f9120f0035d9663ae8eb917cf01ce1c4b47834d06f41cf0c7c5218be0224ab1d88de97b20572d6fdc3cb1e40b662300825820bc65be1b0b9d7531778a1317c2aa6de936963c3f9ac7d5ee9e9eda25e0c97c5e584023ddaf5c9f5c9a22fd646f1c1c5a3f1a84c3a43d90d2211e919450c35df53bcded772e0badb33a898c03f3c227765bc21e678d85b716e0055ca9d89274d6660e82a219ef64a4015820cdea4080a301fdfda7a6b9c8b5283273f51af5f34ae587e05c5492f90a2ae54f025820bc65be1b0b9d7531778a1317c2aa6de936963c3f9ac7d5ee9e9eda25e0c97c5e0358390180f9e2c88e6c817008f3a812ed889b4a4da8e0bd103f86e7335422aa122a946b9ad3d2ddf029d3a828f0468aece76895f15c9efbd69b4277041a015d76c419ef65a101584017ed3f6a8ef2d0f1212e3aa49766fcf22b087c6cfa5cf247ecbc6c27069d7c17f189f2ca0acf6f1d54e1999e12fc37ac695c693982df96430896b54e0bcff10780
```
#### The same transactions with structure description
@ -220,6 +222,9 @@ Cardano uses [CBOR](https://www.rfc-editor.org/info/rfc7049) as a serialization
# uint(5), map(1), bytes(29), uint(7204944340)
5: {h'E11...': 1000},
# auxiliary data hash
7: h'541...',
# validity_interval_start
# uint(8), uint(20)
8: 20
@ -231,14 +236,30 @@ Cardano uses [CBOR](https://www.rfc-editor.org/info/rfc7049) as a serialization
# uint(0), array(2)
0: [
# array(2), bytes(32), bytes(64)
[h'BC6...', h'C6E...'],
[h'5D0...', h'647...'],
# array(2), bytes(32), bytes(64)
[h'5D0...', h'1FE...']
[h'BC6...', h'23D...']
]
},
# metadata
# primitive(22)
null
# auxiliary data - catalyst voting key registration
# array(2)
[
# map(2)
{
# uint(61284), map(4), uint(1), bytes(32), uint(2), bytes(32), uint(3), bytes(57), uint(4), uint(22902468)
61284: {
1: h'CDE...',
2: h'BC6...',
3: h'018...',
4: 22902468
},
# uint(61285), map(1), bytes(64)
61285: {
1:h'17E...'
}
},
# array(0)
[]
]
]
```

@ -0,0 +1,241 @@
from trezor.crypto import hashlib
from trezor.crypto.curve import ed25519
from trezor.messages import CardanoAddressType
from apps.common import cbor
from ..common.seed import remove_ed25519_prefix
from .address import derive_address_bytes, derive_human_readable_address
from .helpers import INVALID_AUXILIARY_DATA, bech32
from .helpers.bech32 import HRP_JORMUN_PUBLIC_KEY
from .helpers.paths import SCHEMA_STAKING_ANY_ACCOUNT
from .layout import confirm_catalyst_registration, show_auxiliary_data_hash
if False:
from typing import Union
from trezor import wire
from trezor.messages.CardanoCatalystRegistrationParametersType import (
CardanoCatalystRegistrationParametersType,
)
from trezor.messages.CardanoTxAuxiliaryDataType import CardanoTxAuxiliaryDataType
CatalystRegistrationPayload = dict[int, Union[bytes, int]]
CatalystRegistrationSignature = dict[int, bytes]
CatalystRegistration = dict[
int, Union[CatalystRegistrationPayload, CatalystRegistrationSignature]
]
from . import seed
AUXILIARY_DATA_HASH_SIZE = 32
CATALYST_VOTING_PUBLIC_KEY_LENGTH = 32
CATALYST_REGISTRATION_HASH_SIZE = 32
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:
if not auxiliary_data:
return
fields_provided = 0
if auxiliary_data.blob:
fields_provided += 1
_validate_auxiliary_data_blob(auxiliary_data.blob)
if auxiliary_data.catalyst_registration_parameters:
fields_provided += 1
_validate_catalyst_registration_parameters(
keychain,
auxiliary_data.catalyst_registration_parameters,
protocol_magic,
network_id,
)
if fields_provided != 1:
raise INVALID_AUXILIARY_DATA
def _validate_auxiliary_data_blob(auxiliary_data_blob: bytes) -> None:
try:
# validation to prevent CBOR injection and invalid CBOR
# we don't validate data format, just that it's a valid CBOR
cbor.decode(auxiliary_data_blob)
except Exception:
raise INVALID_AUXILIARY_DATA
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)
!= CATALYST_VOTING_PUBLIC_KEY_LENGTH
):
raise INVALID_AUXILIARY_DATA
if not SCHEMA_STAKING_ANY_ACCOUNT.match(
catalyst_registration_parameters.staking_path
):
raise INVALID_AUXILIARY_DATA
address_parameters = catalyst_registration_parameters.reward_address_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)
async def show_auxiliary_data(
ctx: wire.Context,
keychain: seed.Keychain,
auxiliary_data: CardanoTxAuxiliaryDataType | None,
protocol_magic: int,
network_id: int,
) -> None:
if not auxiliary_data:
return
if auxiliary_data.catalyst_registration_parameters:
await _show_catalyst_registration(
ctx,
keychain,
auxiliary_data.catalyst_registration_parameters,
protocol_magic,
network_id,
)
auxiliary_data_bytes = get_auxiliary_data_cbor(
keychain, auxiliary_data, protocol_magic, network_id
)
auxiliary_data_hash = hash_auxiliary_data(bytes(auxiliary_data_bytes))
await show_auxiliary_data_hash(ctx, auxiliary_data_hash)
async def _show_catalyst_registration(
ctx: wire.Context,
keychain: seed.Keychain,
catalyst_registration_parameters: CardanoCatalystRegistrationParametersType,
protocol_magic: int,
network_id: int,
) -> None:
public_key = catalyst_registration_parameters.voting_public_key
encoded_public_key = bech32.encode(HRP_JORMUN_PUBLIC_KEY, public_key)
staking_path = catalyst_registration_parameters.staking_path
reward_address = derive_human_readable_address(
keychain,
catalyst_registration_parameters.reward_address_parameters,
protocol_magic,
network_id,
)
nonce = catalyst_registration_parameters.nonce
await confirm_catalyst_registration(
ctx, encoded_public_key, staking_path, reward_address, nonce
)
def get_auxiliary_data_cbor(
keychain: seed.Keychain,
auxiliary_data: CardanoTxAuxiliaryDataType,
protocol_magic: int,
network_id: int,
) -> bytes:
if auxiliary_data.blob:
return auxiliary_data.blob
elif auxiliary_data.catalyst_registration_parameters:
cborized_catalyst_registration = _cborize_catalyst_registration(
keychain,
auxiliary_data.catalyst_registration_parameters,
protocol_magic,
network_id,
)
return cbor.encode(_wrap_metadata(cborized_catalyst_registration))
else:
raise INVALID_AUXILIARY_DATA
def _cborize_catalyst_registration(
keychain: seed.Keychain,
catalyst_registration_parameters: CardanoCatalystRegistrationParametersType,
protocol_magic: int,
network_id: int,
) -> CatalystRegistration:
staking_node = keychain.derive(catalyst_registration_parameters.staking_path)
staking_key = remove_ed25519_prefix(staking_node.public_key())
catalyst_registration_payload: CatalystRegistrationPayload = {
1: catalyst_registration_parameters.voting_public_key,
2: staking_key,
3: derive_address_bytes(
keychain,
catalyst_registration_parameters.reward_address_parameters,
protocol_magic,
network_id,
),
4: catalyst_registration_parameters.nonce,
}
catalyst_registration_payload_signature = (
_create_catalyst_registration_payload_signature(
keychain,
catalyst_registration_payload,
catalyst_registration_parameters.staking_path,
)
)
catalyst_registration_signature = {1: catalyst_registration_payload_signature}
return {
METADATA_KEY_CATALYST_REGISTRATION: catalyst_registration_payload,
METADATA_KEY_CATALYST_REGISTRATION_SIGNATURE: catalyst_registration_signature,
}
def _create_catalyst_registration_payload_signature(
keychain: seed.Keychain,
catalyst_registration_payload: CatalystRegistrationPayload,
path: list[int],
) -> bytes:
node = keychain.derive(path)
encoded_catalyst_registration = cbor.encode(
{METADATA_KEY_CATALYST_REGISTRATION: catalyst_registration_payload}
)
catalyst_registration_hash = hashlib.blake2b(
data=encoded_catalyst_registration,
outlen=CATALYST_REGISTRATION_HASH_SIZE,
).digest()
return ed25519.sign_ext(
node.private_key(), node.private_key_ext(), catalyst_registration_hash
)
def _wrap_metadata(metadata: dict) -> tuple[dict, tuple]:
"""
A new structure of metadata is used after Cardano Mary era. The metadata
is wrapped in a tuple and auxiliary_scripts may follow it. Cardano
tooling uses this new format of "wrapped" metadata even if no
auxiliary_scripts are included. So we do the same here.
https://github.com/input-output-hk/cardano-ledger-specs/blob/f7deb22be14d31b535f56edc3ca542c548244c67/shelley-ma/shelley-ma-test/cddl-files/shelley-ma.cddl#L212
"""
return metadata, ()
def hash_auxiliary_data(auxiliary_data: bytes) -> bytes:
return hashlib.blake2b(
data=auxiliary_data, outlen=AUXILIARY_DATA_HASH_SIZE
).digest()

@ -5,7 +5,7 @@ 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")
INVALID_METADATA = wire.ProcessError("Invalid metadata")
INVALID_AUXILIARY_DATA = wire.ProcessError("Invalid auxiliary data")
INVALID_STAKE_POOL_REGISTRATION_TX_STRUCTURE = wire.ProcessError(
"Stakepool registration transaction cannot contain other certificates nor withdrawals"
)

@ -2,10 +2,13 @@ from trezor.crypto import bech32
HRP_SEPARATOR = "1"
# CIP-0005 prefixes - https://github.com/cardano-foundation/CIPs/blob/master/CIP-0005/CIP-0005.md
HRP_ADDRESS = "addr"
HRP_TESTNET_ADDRESS = "addr_test"
HRP_REWARD_ADDRESS = "stake"
HRP_TESTNET_REWARD_ADDRESS = "stake_test"
# Jormungandr public key prefix - https://github.com/input-output-hk/voting-tools-lib/blob/18dae637e80db72444476606ab264b973bcf1a9d/src/Cardano/API/Extended.hs#L226
HRP_JORMUN_PUBLIC_KEY = "ed25519_pk"
def encode(hrp: str, data: bytes) -> str:

@ -215,7 +215,6 @@ async def confirm_transaction(
protocol_magic: int,
ttl: int | None,
validity_interval_start: int | None,
has_metadata: bool,
is_network_id_verifiable: bool,
) -> None:
pages: list[ui.Component] = []
@ -235,12 +234,6 @@ async def confirm_transaction(
page2.normal("TTL: %s" % format_optional_int(ttl))
pages.append(page2)
if has_metadata:
page3 = Text("Confirm transaction", ui.ICON_SEND, ui.GREEN)
page3.normal("Transaction contains")
page3.normal("metadata")
pages.append(page3)
await require_hold_to_confirm(ctx, Paginated(pages))
@ -393,6 +386,69 @@ async def confirm_withdrawal(
await require_confirm(ctx, page1)
async def confirm_catalyst_registration(
ctx: wire.Context,
public_key: str,
staking_path: list[int],
reward_address: str,
nonce: int,
) -> None:
pages: list[ui.Component] = []
page1 = Text("Confirm transaction", ui.ICON_SEND, ui.GREEN)
page1.bold("Catalyst voting key")
page1.bold("registration")
pages.append(page1)
page2 = Text("Confirm transaction", ui.ICON_SEND, ui.GREEN)
page2.normal("Voting public key:")
page2.bold(*chunks(public_key, 17))
pages.append(page2)
page3 = Text("Confirm transaction", ui.ICON_SEND, ui.GREEN)
page3.normal("Staking key for")
page3.normal("account %s:" % format_account_number(staking_path))
page3.bold(address_n_to_str(staking_path))
pages.append(page3)
page4 = Text("Confirm transaction", ui.ICON_SEND, ui.GREEN)
page4.normal("Rewards go to:")
lines_per_page = 5
lines_used_on_first_page = 1
address_lines = list(chunks(reward_address, 17))
for address_line in address_lines[: lines_per_page - lines_used_on_first_page]:
page4.bold(address_line)
pages.append(page4)
pages.extend(
_paginate_lines(
address_lines,
lines_per_page - lines_used_on_first_page,
"Confirm transaction",
ui.ICON_SEND,
5,
)
)
last_page = Text("Confirm transaction", ui.ICON_SEND, ui.GREEN)
last_page.normal("Nonce: %s" % nonce)
pages.append(last_page)
await require_confirm(ctx, Paginated(pages))
async def show_auxiliary_data_hash(
ctx: wire.Context, auxiliary_data_hash: bytes
) -> None:
page1 = Text("Confirm transaction", ui.ICON_SEND, ui.GREEN)
page1.normal("Auxiliary data hash:")
page1.bold(hexlify(auxiliary_data_hash).decode())
await require_confirm(ctx, page1)
async def show_address(
ctx: wire.Context,
address: str,

@ -18,10 +18,15 @@ from .address import (
get_address_bytes_unsafe,
validate_output_address,
)
from .auxiliary_data import (
get_auxiliary_data_cbor,
hash_auxiliary_data,
show_auxiliary_data,
validate_auxiliary_data,
)
from .byron_address import get_address_attributes
from .certificates import cborize_certificate, validate_certificate
from .helpers import (
INVALID_METADATA,
INVALID_STAKE_POOL_REGISTRATION_TX_STRUCTURE,
INVALID_STAKEPOOL_REGISTRATION_TX_INPUTS,
INVALID_TOKEN_BUNDLE_OUTPUT,
@ -83,9 +88,7 @@ if False:
CborizedSignedTx = tuple[dict, dict, Optional[cbor.Raw]]
TxHash = bytes
METADATA_HASH_SIZE = 32
MINTING_POLICY_ID_LENGTH = 28
MAX_METADATA_LENGTH = 500
MAX_ASSET_NAME_LENGTH = 32
MAX_TX_CHUNK_SIZE = 256
@ -132,7 +135,9 @@ async def _sign_ordinary_tx(
_validate_outputs(keychain, msg.outputs, msg.protocol_magic, msg.network_id)
_validate_certificates(msg.certificates, msg.protocol_magic, msg.network_id)
_validate_withdrawals(msg.withdrawals)
_validate_metadata(msg.metadata)
validate_auxiliary_data(
keychain, msg.auxiliary_data, msg.protocol_magic, msg.network_id
)
# display the transaction in UI
await _show_standard_tx(ctx, keychain, msg)
@ -160,7 +165,9 @@ async def _sign_stake_pool_registration_tx(
_ensure_no_signing_inputs(msg.inputs)
_validate_outputs(keychain, msg.outputs, msg.protocol_magic, msg.network_id)
_validate_certificates(msg.certificates, msg.protocol_magic, msg.network_id)
_validate_metadata(msg.metadata)
validate_auxiliary_data(
keychain, msg.auxiliary_data, msg.protocol_magic, msg.network_id
)
await _show_stake_pool_registration_tx(ctx, keychain, msg)
@ -274,23 +281,6 @@ def _validate_withdrawals(withdrawals: list[CardanoTxWithdrawalType]) -> None:
raise INVALID_WITHDRAWAL
def _validate_metadata(metadata: bytes | None) -> None:
if not metadata:
return
if len(metadata) > MAX_METADATA_LENGTH:
raise INVALID_METADATA
try:
# this also raises an error if there's some data remaining
decoded = cbor.decode(metadata)
except Exception:
raise INVALID_METADATA
if not isinstance(decoded, dict):
raise INVALID_METADATA
def _cborize_signed_tx(
keychain: seed.Keychain, msg: CardanoSignTx
) -> tuple[CborizedSignedTx, TxHash]:
@ -306,11 +296,14 @@ def _cborize_signed_tx(
msg.protocol_magic,
)
metadata = None
if msg.metadata:
metadata = cbor.Raw(bytes(msg.metadata))
auxiliary_data = None
if msg.auxiliary_data:
auxiliary_data_cbor = get_auxiliary_data_cbor(
keychain, msg.auxiliary_data, msg.protocol_magic, msg.network_id
)
auxiliary_data = cbor.Raw(auxiliary_data_cbor)
return (tx_body, witnesses, metadata), tx_hash
return (tx_body, witnesses, auxiliary_data), tx_hash
def _cborize_tx_body(keychain: seed.Keychain, msg: CardanoSignTx) -> dict:
@ -340,8 +333,11 @@ def _cborize_tx_body(keychain: seed.Keychain, msg: CardanoSignTx) -> dict:
# tx_body[6] is for protocol updates, which we don't support
if msg.metadata:
tx_body[7] = _hash_metadata(bytes(msg.metadata))
if msg.auxiliary_data:
auxiliary_data_cbor = get_auxiliary_data_cbor(
keychain, msg.auxiliary_data, msg.protocol_magic, msg.network_id
)
tx_body[7] = hash_auxiliary_data(bytes(auxiliary_data_cbor))
if msg.validity_interval_start:
tx_body[8] = msg.validity_interval_start
@ -432,10 +428,6 @@ def _cborize_withdrawals(
return result
def _hash_metadata(metadata: bytes) -> bytes:
return hashlib.blake2b(data=metadata, outlen=METADATA_HASH_SIZE).digest()
def _hash_tx_body(tx_body: dict) -> bytes:
tx_body_cbor_chunks = cbor.encode_streamed(tx_body)
@ -573,7 +565,10 @@ async def _show_standard_tx(
for withdrawal in msg.withdrawals:
await confirm_withdrawal(ctx, withdrawal)
has_metadata = bool(msg.metadata)
await show_auxiliary_data(
ctx, keychain, msg.auxiliary_data, msg.protocol_magic, msg.network_id
)
await confirm_transaction(
ctx=ctx,
amount=total_amount,
@ -581,7 +576,6 @@ async def _show_standard_tx(
protocol_magic=msg.protocol_magic,
ttl=msg.ttl,
validity_interval_start=msg.validity_interval_start,
has_metadata=has_metadata,
is_network_id_verifiable=is_network_id_verifiable,
)
@ -616,6 +610,9 @@ async def _show_stake_pool_registration_tx(
await confirm_transaction_network_ttl(
ctx, msg.protocol_magic, msg.ttl, msg.validity_interval_start
)
await show_auxiliary_data(
ctx, keychain, msg.auxiliary_data, msg.protocol_magic, msg.network_id
)
await confirm_stake_pool_registration_final(ctx)

@ -0,0 +1,37 @@
# Automatically generated by pb2py
# fmt: off
import protobuf as p
from .CardanoAddressParametersType import CardanoAddressParametersType
if __debug__:
try:
from typing import Dict, List, Optional # noqa: F401
from typing_extensions import Literal # noqa: F401
except ImportError:
pass
class CardanoCatalystRegistrationParametersType(p.MessageType):
def __init__(
self,
*,
voting_public_key: bytes,
reward_address_parameters: CardanoAddressParametersType,
nonce: int,
staking_path: Optional[List[int]] = None,
) -> None:
self.staking_path = staking_path if staking_path is not None else []
self.voting_public_key = voting_public_key
self.reward_address_parameters = reward_address_parameters
self.nonce = nonce
@classmethod
def get_fields(cls) -> Dict:
return {
1: ('voting_public_key', p.BytesType, p.FLAG_REQUIRED),
2: ('staking_path', p.UVarintType, p.FLAG_REPEATED),
3: ('reward_address_parameters', CardanoAddressParametersType, p.FLAG_REQUIRED),
4: ('nonce', p.UVarintType, p.FLAG_REQUIRED),
}

@ -2,6 +2,7 @@
# fmt: off
import protobuf as p
from .CardanoTxAuxiliaryDataType import CardanoTxAuxiliaryDataType
from .CardanoTxCertificateType import CardanoTxCertificateType
from .CardanoTxInputType import CardanoTxInputType
from .CardanoTxOutputType import CardanoTxOutputType
@ -29,8 +30,8 @@ class CardanoSignTx(p.MessageType):
certificates: Optional[List[CardanoTxCertificateType]] = None,
withdrawals: Optional[List[CardanoTxWithdrawalType]] = None,
ttl: Optional[int] = None,
metadata: Optional[bytes] = None,
validity_interval_start: Optional[int] = None,
auxiliary_data: Optional[CardanoTxAuxiliaryDataType] = None,
) -> None:
self.inputs = inputs if inputs is not None else []
self.outputs = outputs if outputs is not None else []
@ -40,8 +41,8 @@ class CardanoSignTx(p.MessageType):
self.fee = fee
self.network_id = network_id
self.ttl = ttl
self.metadata = metadata
self.validity_interval_start = validity_interval_start
self.auxiliary_data = auxiliary_data
@classmethod
def get_fields(cls) -> Dict:
@ -54,6 +55,6 @@ class CardanoSignTx(p.MessageType):
8: ('network_id', p.UVarintType, p.FLAG_REQUIRED),
9: ('certificates', CardanoTxCertificateType, p.FLAG_REPEATED),
10: ('withdrawals', CardanoTxWithdrawalType, p.FLAG_REPEATED),
11: ('metadata', p.BytesType, None),
12: ('validity_interval_start', p.UVarintType, None),
13: ('auxiliary_data', CardanoTxAuxiliaryDataType, None),
}

@ -2,13 +2,14 @@
# fmt: off
import protobuf as p
from .CardanoTxMetadataType import CardanoTxMetadataType
from .CardanoCatalystRegistrationParametersType import (
CardanoCatalystRegistrationParametersType,
)
if __debug__:
try:
from typing import Dict, List, Optional # noqa: F401
from typing_extensions import Literal # noqa: F401
EnumTypeCardanoAuxiliaryDataType = Literal[0, 1]
except ImportError:
pass
@ -18,18 +19,15 @@ class CardanoTxAuxiliaryDataType(p.MessageType):
def __init__(
self,
*,
type: EnumTypeCardanoAuxiliaryDataType,
blob: Optional[bytes] = None,
metadata: Optional[CardanoTxMetadataType] = None,
catalyst_registration_parameters: Optional[CardanoCatalystRegistrationParametersType] = None,
) -> None:
self.type = type
self.blob = blob
self.metadata = metadata
self.catalyst_registration_parameters = catalyst_registration_parameters
@classmethod
def get_fields(cls) -> Dict:
return {
1: ('type', p.EnumType("CardanoAuxiliaryDataType", (0, 1,)), p.FLAG_REQUIRED),
2: ('blob', p.BytesType, None),
3: ('metadata', CardanoTxMetadataType, None),
1: ('blob', p.BytesType, None),
2: ('catalyst_registration_parameters', CardanoCatalystRegistrationParametersType, None),
}

@ -38,6 +38,12 @@ REQUIRED_FIELDS_POOL_PARAMETERS = (
REQUIRED_FIELDS_WITHDRAWAL = ("path", "amount")
REQUIRED_FIELDS_TOKEN_GROUP = ("policy_id", "tokens")
REQUIRED_FIELDS_TOKEN = ("asset_name_bytes", "amount")
REQUIRED_FIELDS_CATALYST_REGISTRATION = (
"voting_public_key",
"staking_path",
"nonce",
"reward_address_parameters",
)
INCOMPLETE_OUTPUT_ERROR_MESSAGE = "The output is missing some fields"
@ -118,7 +124,7 @@ def create_output(output) -> messages.CardanoTxOutputType:
if contains_address:
address = output["address"]
else:
address_parameters = _create_change_output_address_parameters(output)
address_parameters = _create_address_parameters_internal(output)
if "token_bundle" in output:
token_bundle = _create_token_bundle(output["token_bundle"])
@ -163,24 +169,24 @@ def _create_tokens(tokens) -> List[messages.CardanoTokenType]:
return result
def _create_change_output_address_parameters(
output,
def _create_address_parameters_internal(
address_parameters,
) -> messages.CardanoAddressParametersType:
if "path" not in output:
if "path" not in address_parameters:
raise ValueError(INCOMPLETE_OUTPUT_ERROR_MESSAGE)
staking_key_hash_bytes = None
if "stakingKeyHash" in output:
staking_key_hash_bytes = bytes.fromhex(output.get("stakingKeyHash"))
if "stakingKeyHash" in address_parameters:
staking_key_hash_bytes = bytes.fromhex(address_parameters.get("stakingKeyHash"))
return create_address_parameters(
int(output["addressType"]),
tools.parse_path(output["path"]),
tools.parse_path(output.get("stakingPath")),
int(address_parameters["addressType"]),
tools.parse_path(address_parameters["path"]),
tools.parse_path(address_parameters.get("stakingPath")),
staking_key_hash_bytes,
output.get("blockIndex"),
output.get("txIndex"),
output.get("certificateIndex"),
address_parameters.get("blockIndex"),
address_parameters.get("txIndex"),
address_parameters.get("certificateIndex"),
)
@ -315,6 +321,49 @@ def create_withdrawal(withdrawal) -> messages.CardanoTxWithdrawalType:
)
def create_auxiliary_data(auxiliary_data) -> messages.CardanoTxAuxiliaryDataType:
if auxiliary_data is None:
return None
AUXILIARY_DATA_MISSING_FIELDS_ERROR = ValueError(
"Auxiliary data is missing some fields"
)
# include all provided fields so we can test validation in FW
blob = None
if "blob" in auxiliary_data:
blob = bytes.fromhex(auxiliary_data["blob"])
catalyst_registration_parameters = None
if "catalyst_registration_parameters" in auxiliary_data:
catalyst_registration = auxiliary_data["catalyst_registration_parameters"]
if not all(
k in catalyst_registration for k in REQUIRED_FIELDS_CATALYST_REGISTRATION
):
raise AUXILIARY_DATA_MISSING_FIELDS_ERROR
catalyst_registration_parameters = (
messages.CardanoCatalystRegistrationParametersType(
voting_public_key=bytes.fromhex(
catalyst_registration["voting_public_key"]
),
staking_path=tools.parse_path(catalyst_registration["staking_path"]),
nonce=catalyst_registration["nonce"],
reward_address_parameters=_create_address_parameters_internal(
catalyst_registration["reward_address_parameters"]
),
)
)
if blob is None and catalyst_registration_parameters is None:
raise AUXILIARY_DATA_MISSING_FIELDS_ERROR
return messages.CardanoTxAuxiliaryDataType(
blob=blob,
catalyst_registration_parameters=catalyst_registration_parameters,
)
# ====== Client functions ====== #
@ -351,9 +400,9 @@ def sign_tx(
validity_interval_start: Optional[int],
certificates: List[messages.CardanoTxCertificateType] = (),
withdrawals: List[messages.CardanoTxWithdrawalType] = (),
metadata: bytes = None,
protocol_magic: int = PROTOCOL_MAGICS["mainnet"],
network_id: int = NETWORK_IDS["mainnet"],
auxiliary_data: messages.CardanoTxAuxiliaryDataType = None,
) -> messages.CardanoSignedTx:
response = client.call(
messages.CardanoSignTx(
@ -364,9 +413,9 @@ def sign_tx(
validity_interval_start=validity_interval_start,
certificates=certificates,
withdrawals=withdrawals,
metadata=metadata,
protocol_magic=protocol_magic,
network_id=network_id,
auxiliary_data=auxiliary_data,
)
)

@ -67,9 +67,7 @@ def sign_tx(client, file, protocol_magic, network_id, testnet):
cardano.create_withdrawal(withdrawal)
for withdrawal in transaction.get("withdrawals", ())
]
metadata = None
if "metadata" in transaction:
metadata = bytes.fromhex(transaction["metadata"])
auxiliary_data = cardano.create_auxiliary_data(transaction.get("auxiliary_data"))
signed_transaction = cardano.sign_tx(
client,
@ -80,9 +78,9 @@ def sign_tx(client, file, protocol_magic, network_id, testnet):
validity_interval_start,
certificates,
withdrawals,
metadata,
protocol_magic,
network_id,
auxiliary_data,
)
return {

@ -0,0 +1,37 @@
# Automatically generated by pb2py
# fmt: off
from .. import protobuf as p
from .CardanoAddressParametersType import CardanoAddressParametersType
if __debug__:
try:
from typing import Dict, List, Optional # noqa: F401
from typing_extensions import Literal # noqa: F401
except ImportError:
pass
class CardanoCatalystRegistrationParametersType(p.MessageType):
def __init__(
self,
*,
voting_public_key: bytes,
reward_address_parameters: CardanoAddressParametersType,
nonce: int,
staking_path: Optional[List[int]] = None,
) -> None:
self.staking_path = staking_path if staking_path is not None else []
self.voting_public_key = voting_public_key
self.reward_address_parameters = reward_address_parameters
self.nonce = nonce
@classmethod
def get_fields(cls) -> Dict:
return {
1: ('voting_public_key', p.BytesType, p.FLAG_REQUIRED),
2: ('staking_path', p.UVarintType, p.FLAG_REPEATED),
3: ('reward_address_parameters', CardanoAddressParametersType, p.FLAG_REQUIRED),
4: ('nonce', p.UVarintType, p.FLAG_REQUIRED),
}

@ -2,6 +2,7 @@
# fmt: off
from .. import protobuf as p
from .CardanoTxAuxiliaryDataType import CardanoTxAuxiliaryDataType
from .CardanoTxCertificateType import CardanoTxCertificateType
from .CardanoTxInputType import CardanoTxInputType
from .CardanoTxOutputType import CardanoTxOutputType
@ -29,8 +30,8 @@ class CardanoSignTx(p.MessageType):
certificates: Optional[List[CardanoTxCertificateType]] = None,
withdrawals: Optional[List[CardanoTxWithdrawalType]] = None,
ttl: Optional[int] = None,
metadata: Optional[bytes] = None,
validity_interval_start: Optional[int] = None,
auxiliary_data: Optional[CardanoTxAuxiliaryDataType] = None,
) -> None:
self.inputs = inputs if inputs is not None else []
self.outputs = outputs if outputs is not None else []
@ -40,8 +41,8 @@ class CardanoSignTx(p.MessageType):
self.fee = fee
self.network_id = network_id
self.ttl = ttl
self.metadata = metadata
self.validity_interval_start = validity_interval_start
self.auxiliary_data = auxiliary_data
@classmethod
def get_fields(cls) -> Dict:
@ -54,6 +55,6 @@ class CardanoSignTx(p.MessageType):
8: ('network_id', p.UVarintType, p.FLAG_REQUIRED),
9: ('certificates', CardanoTxCertificateType, p.FLAG_REPEATED),
10: ('withdrawals', CardanoTxWithdrawalType, p.FLAG_REPEATED),
11: ('metadata', p.BytesType, None),
12: ('validity_interval_start', p.UVarintType, None),
13: ('auxiliary_data', CardanoTxAuxiliaryDataType, None),
}

@ -2,13 +2,12 @@
# fmt: off
from .. import protobuf as p
from .CardanoTxMetadataType import CardanoTxMetadataType
from .CardanoCatalystRegistrationParametersType import CardanoCatalystRegistrationParametersType
if __debug__:
try:
from typing import Dict, List, Optional # noqa: F401
from typing_extensions import Literal # noqa: F401
EnumTypeCardanoAuxiliaryDataType = Literal[0, 1]
except ImportError:
pass
@ -18,18 +17,15 @@ class CardanoTxAuxiliaryDataType(p.MessageType):
def __init__(
self,
*,
type: EnumTypeCardanoAuxiliaryDataType,
blob: Optional[bytes] = None,
metadata: Optional[CardanoTxMetadataType] = None,
catalyst_registration_parameters: Optional[CardanoCatalystRegistrationParametersType] = None,
) -> None:
self.type = type
self.blob = blob
self.metadata = metadata
self.catalyst_registration_parameters = catalyst_registration_parameters
@classmethod
def get_fields(cls) -> Dict:
return {
1: ('type', p.EnumType("CardanoAuxiliaryDataType", (0, 1,)), p.FLAG_REQUIRED),
2: ('blob', p.BytesType, None),
3: ('metadata', CardanoTxMetadataType, None),
1: ('blob', p.BytesType, None),
2: ('catalyst_registration_parameters', CardanoCatalystRegistrationParametersType, None),
}

@ -26,6 +26,7 @@ from .CardanoAddress import CardanoAddress
from .CardanoAddressParametersType import CardanoAddressParametersType
from .CardanoAssetGroupType import CardanoAssetGroupType
from .CardanoBlockchainPointerType import CardanoBlockchainPointerType
from .CardanoCatalystRegistrationParametersType import CardanoCatalystRegistrationParametersType
from .CardanoGetAddress import CardanoGetAddress
from .CardanoGetPublicKey import CardanoGetPublicKey
from .CardanoPoolMetadataType import CardanoPoolMetadataType
@ -38,6 +39,7 @@ from .CardanoSignedTx import CardanoSignedTx
from .CardanoSignedTxChunk import CardanoSignedTxChunk
from .CardanoSignedTxChunkAck import CardanoSignedTxChunkAck
from .CardanoTokenType import CardanoTokenType
from .CardanoTxAuxiliaryDataType import CardanoTxAuxiliaryDataType
from .CardanoTxCertificateType import CardanoTxCertificateType
from .CardanoTxInputType import CardanoTxInputType
from .CardanoTxOutputType import CardanoTxOutputType

@ -38,6 +38,7 @@ def test_cardano_sign_tx(client, parameters, result):
outputs = [cardano.create_output(o) for o in parameters["outputs"]]
certificates = [cardano.create_certificate(c) for c in parameters["certificates"]]
withdrawals = [cardano.create_withdrawal(w) for w in parameters["withdrawals"]]
auxiliary_data = cardano.create_auxiliary_data(parameters["auxiliary_data"])
input_flow = parameters.get("input_flow", ())
@ -60,9 +61,9 @@ def test_cardano_sign_tx(client, parameters, result):
validity_interval_start=parameters.get("validity_interval_start"),
certificates=certificates,
withdrawals=withdrawals,
metadata=bytes.fromhex(parameters["metadata"]),
protocol_magic=parameters["protocol_magic"],
network_id=parameters["network_id"],
auxiliary_data=auxiliary_data,
)
assert response.tx_hash.hex() == result["tx_hash"]
assert response.serialized_tx.hex() == result["serialized_tx"]
@ -76,6 +77,7 @@ def test_cardano_sign_tx_failed(client, parameters, result):
outputs = [cardano.create_output(o) for o in parameters["outputs"]]
certificates = [cardano.create_certificate(c) for c in parameters["certificates"]]
withdrawals = [cardano.create_withdrawal(w) for w in parameters["withdrawals"]]
auxiliary_data = cardano.create_auxiliary_data(parameters["auxiliary_data"])
input_flow = parameters.get("input_flow", ())
@ -92,9 +94,9 @@ def test_cardano_sign_tx_failed(client, parameters, result):
validity_interval_start=parameters.get("validity_interval_start"),
certificates=certificates,
withdrawals=withdrawals,
metadata=bytes.fromhex(parameters["metadata"]),
protocol_magic=parameters["protocol_magic"],
network_id=parameters["network_id"],
auxiliary_data=auxiliary_data,
)
@ -104,6 +106,7 @@ def test_cardano_sign_tx_with_multiple_chunks(client, parameters, result):
outputs = [cardano.create_output(o) for o in parameters["outputs"]]
certificates = [cardano.create_certificate(c) for c in parameters["certificates"]]
withdrawals = [cardano.create_withdrawal(w) for w in parameters["withdrawals"]]
auxiliary_data = cardano.create_auxiliary_data(parameters["auxiliary_data"])
input_flow = parameters.get("input_flow", ())
@ -133,9 +136,9 @@ def test_cardano_sign_tx_with_multiple_chunks(client, parameters, result):
validity_interval_start=parameters.get("validity_interval_start"),
certificates=certificates,
withdrawals=withdrawals,
metadata=bytes.fromhex(parameters["metadata"]),
protocol_magic=parameters["protocol_magic"],
network_id=parameters["network_id"],
auxiliary_data=auxiliary_data,
)
assert response.tx_hash.hex() == result["tx_hash"]
assert response.serialized_tx.hex() == result["serialized_tx"]

@ -9,6 +9,7 @@
"cardano-test_sign_tx.py::test_cardano_sign_tx[mary_era_transaction_with_multiasset_output]": "d0a58ab8b68fcd9f1191f309de52efb6be9157383357f5f9c0e0d116fccc08e4",
"cardano-test_sign_tx.py::test_cardano_sign_tx[mary_era_transaction_with_no_ttl-validity_start]": "db76676358164a3b3dab5148f09ba5515d079212366b79c44f95e2ba613abc71",
"cardano-test_sign_tx.py::test_cardano_sign_tx[sample_stake_pool_registration_certificate]": "f56482d4a0f2c07fe04291a7d9c29ed4aedfd31e6a80fed1563d80e3a4c4005c",
"cardano-test_sign_tx.py::test_cardano_sign_tx[sample_stake_pool_registration_certificate_wi-336f4a44": "6acd2406b1013917c859482bce3ae9b457f406537734398037e20784116c18f2",
"cardano-test_sign_tx.py::test_cardano_sign_tx[sample_stake_pool_registration_certificate_wi-d3427614": "629ccaa5b660247843b366582c1bc505831c1800e028474a784b0f8b35fc473a",
"cardano-test_sign_tx.py::test_cardano_sign_tx[sample_stake_pool_registration_with_zero_margin]": "802c6f1fcf232cf05ed64868d39913449918bc70fda39fcf9735f2d5db51ef3f",
"cardano-test_sign_tx.py::test_cardano_sign_tx[simple_transaction_with_base_address_change_o-0c37e6dc": "a9bbc7137d32d71acc1b4d4b7c19aacf7ec8b63c06fe53c16759bf81f5d0ad96",
@ -20,9 +21,10 @@
"cardano-test_sign_tx.py::test_cardano_sign_tx[stake_pool_registration_on_testnet]": "998043271c02cb725b27ba335efebf4895365d602b84df0fe04e26fa3c0bd3fa",
"cardano-test_sign_tx.py::test_cardano_sign_tx[testnet_transaction0]": "7178cb7c264c15ab13152a87fe14c39fbdfa8571c166ddcda6e7c65680bbc784",
"cardano-test_sign_tx.py::test_cardano_sign_tx[testnet_transaction1]": "fcd2bfb85ff1b0ec7a204b2d525c8adf4204afbdcc726d4485820ff36ded4b2c",
"cardano-test_sign_tx.py::test_cardano_sign_tx[transaction_with_auxiliary_data_blob]": "75934c7942a85a1adfaafb44570e102c57c3e66d45bb73cd09df269145ac0212",
"cardano-test_sign_tx.py::test_cardano_sign_tx[transaction_with_base_address_change_output_p-3c7243e1": "32458c03d03f4cfc2d83369a7b4a766a7b410452cb27682d5959a09a78d19b90",
"cardano-test_sign_tx.py::test_cardano_sign_tx[transaction_with_base_address_change_output_s-20438873": "e1dba216b8ff68de35ff87c1c430bc5170d4a9a3c09047d8f9f7e12982f93139",
"cardano-test_sign_tx.py::test_cardano_sign_tx[transaction_with_metadata]": "466a7245ae2d643bc35061321e28ff6d80cbe42faabb10ea613cfc92fee31c06",
"cardano-test_sign_tx.py::test_cardano_sign_tx[transaction_with_catalyst_registration]": "e3b4acd594c894b139a6e66b33fc9cfb81c759a4777524019d1502dc4a46f8c1",
"cardano-test_sign_tx.py::test_cardano_sign_tx[transaction_with_stake_deregistration]": "555219b1572cd91037379ebd95e2a979c5e0486148cb0c00f837277820cb4cbe",
"cardano-test_sign_tx.py::test_cardano_sign_tx[transaction_with_stake_deregistration_and_withdrawal]": "7d7915b4300974d5f45a8308da218b7e4bac938a2d033a6db2b6dccdbec5e4d8",
"cardano-test_sign_tx.py::test_cardano_sign_tx[transaction_with_stake_deregistration_with_ac-9ca046f0": "e5b8662ef9abe58a835d6d5765e413ee1dc63cc870e2c6627f9da6a93c5ead9f",
@ -30,6 +32,8 @@
"cardano-test_sign_tx.py::test_cardano_sign_tx[transaction_with_stake_registration_certifica-e7bd462a": "5a983375390be55cb4fca80a58546cc333148101a02ccfc8c80e1a64b9f47b57",
"cardano-test_sign_tx.py::test_cardano_sign_tx[transaction_with_stake_registration_certificate]": "367088bed7ede0e6f317d3662f990b4300f93fcff2ccd6309c6c4f50fd8da6f9",
"cardano-test_sign_tx.py::test_cardano_sign_tx_failed[all_tx_inputs_must_be_external_(without_path)]": "612dad8ab8762162a186ec9279d7de0bdfc589c52b4e4f4eba0545a00f21c3f0",
"cardano-test_sign_tx.py::test_cardano_sign_tx_failed[auxiliary_data_blob_has_leftover_data]": "612dad8ab8762162a186ec9279d7de0bdfc589c52b4e4f4eba0545a00f21c3f0",
"cardano-test_sign_tx.py::test_cardano_sign_tx_failed[auxiliary_data_blob_is_incomplete]": "612dad8ab8762162a186ec9279d7de0bdfc589c52b4e4f4eba0545a00f21c3f0",
"cardano-test_sign_tx.py::test_cardano_sign_tx_failed[certificate_has_invalid_pool_size]": "612dad8ab8762162a186ec9279d7de0bdfc589c52b4e4f4eba0545a00f21c3f0",
"cardano-test_sign_tx.py::test_cardano_sign_tx_failed[certificate_has_non_staking_path]": "612dad8ab8762162a186ec9279d7de0bdfc589c52b4e4f4eba0545a00f21c3f0",
"cardano-test_sign_tx.py::test_cardano_sign_tx_failed[change_output_path_larger_than_100]": "ffae5d78193ba3e989f025b67c544ce77ac4fde9d547e4588a9fe6f90354a4c2",
@ -41,10 +45,6 @@
"cardano-test_sign_tx.py::test_cardano_sign_tx_failed[mainnet_protocol_magic_with_testnet_network_id]": "612dad8ab8762162a186ec9279d7de0bdfc589c52b4e4f4eba0545a00f21c3f0",
"cardano-test_sign_tx.py::test_cardano_sign_tx_failed[mainnet_transaction_with_testnet_output]": "612dad8ab8762162a186ec9279d7de0bdfc589c52b4e4f4eba0545a00f21c3f0",
"cardano-test_sign_tx.py::test_cardano_sign_tx_failed[margin_higher_than_1]": "612dad8ab8762162a186ec9279d7de0bdfc589c52b4e4f4eba0545a00f21c3f0",
"cardano-test_sign_tx.py::test_cardano_sign_tx_failed[metadata_has_leftover_data]": "612dad8ab8762162a186ec9279d7de0bdfc589c52b4e4f4eba0545a00f21c3f0",
"cardano-test_sign_tx.py::test_cardano_sign_tx_failed[metadata_is_a_list]": "612dad8ab8762162a186ec9279d7de0bdfc589c52b4e4f4eba0545a00f21c3f0",
"cardano-test_sign_tx.py::test_cardano_sign_tx_failed[metadata_is_incomplete]": "612dad8ab8762162a186ec9279d7de0bdfc589c52b4e4f4eba0545a00f21c3f0",
"cardano-test_sign_tx.py::test_cardano_sign_tx_failed[metadata_too_large]": "612dad8ab8762162a186ec9279d7de0bdfc589c52b4e4f4eba0545a00f21c3f0",
"cardano-test_sign_tx.py::test_cardano_sign_tx_failed[missing_owner_with_path]": "612dad8ab8762162a186ec9279d7de0bdfc589c52b4e4f4eba0545a00f21c3f0",
"cardano-test_sign_tx.py::test_cardano_sign_tx_failed[output_address_has_invalid_crc]": "612dad8ab8762162a186ec9279d7de0bdfc589c52b4e4f4eba0545a00f21c3f0",
"cardano-test_sign_tx.py::test_cardano_sign_tx_failed[output_address_is_a_valid_cbor_but_inv-ea3da215": "612dad8ab8762162a186ec9279d7de0bdfc589c52b4e4f4eba0545a00f21c3f0",
@ -62,6 +62,8 @@
"cardano-test_sign_tx.py::test_cardano_sign_tx_failed[stake_deregistration_account_larger_than_100]": "ffae5d78193ba3e989f025b67c544ce77ac4fde9d547e4588a9fe6f90354a4c2",
"cardano-test_sign_tx.py::test_cardano_sign_tx_failed[testnet_protocol_magic_with_mainnet_network_id]": "612dad8ab8762162a186ec9279d7de0bdfc589c52b4e4f4eba0545a00f21c3f0",
"cardano-test_sign_tx.py::test_cardano_sign_tx_failed[testnet_transaction_with_mainnet_output]": "612dad8ab8762162a186ec9279d7de0bdfc589c52b4e4f4eba0545a00f21c3f0",
"cardano-test_sign_tx.py::test_cardano_sign_tx_failed[transaction_with_both_auxiliary_data_b-64274ac4": "612dad8ab8762162a186ec9279d7de0bdfc589c52b4e4f4eba0545a00f21c3f0",
"cardano-test_sign_tx.py::test_cardano_sign_tx_failed[transaction_with_catalyst_registration-11533421": "612dad8ab8762162a186ec9279d7de0bdfc589c52b4e4f4eba0545a00f21c3f0",
"cardano-test_sign_tx.py::test_cardano_sign_tx_failed[two_owners_with_path]": "612dad8ab8762162a186ec9279d7de0bdfc589c52b4e4f4eba0545a00f21c3f0",
"cardano-test_sign_tx.py::test_cardano_sign_tx_failed[unsupported_address_type]": "612dad8ab8762162a186ec9279d7de0bdfc589c52b4e4f4eba0545a00f21c3f0",
"cardano-test_sign_tx.py::test_cardano_sign_tx_failed[withdrawal_amount_is_too_large]": "612dad8ab8762162a186ec9279d7de0bdfc589c52b4e4f4eba0545a00f21c3f0",

Loading…
Cancel
Save