mirror of
https://github.com/trezor/trezor-firmware.git
synced 2024-12-28 00:58:09 +00:00
feat(cardano): update transaction signing for multisig
This commit is contained in:
parent
21281d7cf4
commit
1f33ab420d
@ -61,6 +61,7 @@ enum CardanoTxAuxiliaryDataSupplementType {
|
||||
enum CardanoTxSigningMode {
|
||||
ORDINARY_TRANSACTION = 0;
|
||||
POOL_REGISTRATION_AS_OWNER = 1;
|
||||
MULTISIG_TRANSACTION = 2;
|
||||
}
|
||||
|
||||
enum CardanoTxWitnessType {
|
||||
@ -193,6 +194,7 @@ message CardanoSignTxInit {
|
||||
required bool has_auxiliary_data = 10;
|
||||
optional uint64 validity_interval_start = 11;
|
||||
required uint32 witness_requests_count = 12;
|
||||
required uint32 minting_asset_groups_count = 13;
|
||||
}
|
||||
|
||||
/**
|
||||
@ -230,7 +232,8 @@ message CardanoAssetGroup {
|
||||
*/
|
||||
message CardanoToken {
|
||||
required bytes asset_name_bytes = 1; // asset name as bytestring (may be either ascii string or hash)
|
||||
required uint64 amount = 2; // asset amount
|
||||
optional uint64 amount = 2; // asset amount
|
||||
optional sint64 mint_amount = 3; // mint amount (can also be negative in which case the tokens are burnt)
|
||||
}
|
||||
|
||||
/**
|
||||
@ -288,9 +291,10 @@ message CardanoPoolParametersType {
|
||||
*/
|
||||
message CardanoTxCertificate {
|
||||
required CardanoCertificateType type = 1; // certificate type
|
||||
repeated uint32 path = 2; // BIP-32 path to derive (staking) key
|
||||
repeated uint32 path = 2; // stake credential key path
|
||||
optional bytes pool = 3; // pool hash
|
||||
optional CardanoPoolParametersType pool_parameters = 4; // used for stake pool registration certificate
|
||||
optional bytes script_hash = 5; // stake credential script hash
|
||||
}
|
||||
|
||||
/**
|
||||
@ -298,8 +302,9 @@ message CardanoPoolParametersType {
|
||||
* @next CardanoTxItemAck
|
||||
*/
|
||||
message CardanoTxWithdrawal {
|
||||
repeated uint32 path = 1;
|
||||
repeated uint32 path = 1; // stake credential key path
|
||||
required uint64 amount = 2;
|
||||
optional bytes script_hash = 3; // stake credential script hash
|
||||
}
|
||||
|
||||
/**
|
||||
@ -322,6 +327,14 @@ message CardanoTxAuxiliaryData {
|
||||
optional bytes hash = 2;
|
||||
}
|
||||
|
||||
/**
|
||||
* Request: Transaction mint
|
||||
* @next CardanoTxItemAck
|
||||
*/
|
||||
message CardanoTxMint {
|
||||
required uint32 asset_groups_count = 1;
|
||||
}
|
||||
|
||||
/**
|
||||
* Response: Acknowledgement of the last transaction item received
|
||||
* @next CardanoTxInput
|
||||
@ -334,6 +347,7 @@ message CardanoTxAuxiliaryData {
|
||||
* @next CardanoTxWithdrawal
|
||||
* @next CardanoTxAuxiliaryData
|
||||
* @next CardanoTxWitnessRequest
|
||||
* @next CardanoTxMint
|
||||
*/
|
||||
message CardanoTxItemAck {
|
||||
}
|
||||
@ -442,7 +456,7 @@ message CardanoSignTx {
|
||||
|
||||
message CardanoTokenType {
|
||||
required bytes asset_name_bytes = 1; // asset name as bytestring (may be either ascii string or hash)
|
||||
required uint64 amount = 2; // asset amount
|
||||
required uint64 amount = 2; // asset amount
|
||||
}
|
||||
|
||||
/**
|
||||
|
@ -264,7 +264,8 @@ enum MessageType {
|
||||
MessageType_CardanoPoolOwner = 328 [(wire_in) = true];
|
||||
MessageType_CardanoPoolRelayParameters = 329 [(wire_in) = true];
|
||||
MessageType_CardanoGetNativeScriptHash = 330 [(wire_in) = true];
|
||||
MessageType_CardanoNativeScriptHash = 331 [(wire_in) = true, (wire_out) = true];
|
||||
MessageType_CardanoNativeScriptHash = 331 [(wire_out) = true];
|
||||
MessageType_CardanoTxMint = 332 [(wire_in) = true];
|
||||
|
||||
// Ripple
|
||||
MessageType_RippleGetAddress = 400 [(wire_in) = true];
|
||||
|
739
common/tests/fixtures/cardano/sign_tx.failed.json
vendored
739
common/tests/fixtures/cardano/sign_tx.failed.json
vendored
@ -27,7 +27,9 @@
|
||||
"amount": "3003112"
|
||||
}
|
||||
],
|
||||
"signing_mode": "ORDINARY_TRANSACTION"
|
||||
"mint": [],
|
||||
"signing_mode": "ORDINARY_TRANSACTION",
|
||||
"additional_witness_requests": []
|
||||
},
|
||||
"result": {
|
||||
"error_message": "Invalid address"
|
||||
@ -56,7 +58,9 @@
|
||||
"amount": "3003112"
|
||||
}
|
||||
],
|
||||
"signing_mode": "ORDINARY_TRANSACTION"
|
||||
"mint": [],
|
||||
"signing_mode": "ORDINARY_TRANSACTION",
|
||||
"additional_witness_requests": []
|
||||
},
|
||||
"result": {
|
||||
"error_message": "Invalid address"
|
||||
@ -85,7 +89,9 @@
|
||||
"amount": "3003112"
|
||||
}
|
||||
],
|
||||
"signing_mode": "ORDINARY_TRANSACTION"
|
||||
"mint": [],
|
||||
"signing_mode": "ORDINARY_TRANSACTION",
|
||||
"additional_witness_requests": []
|
||||
},
|
||||
"result": {
|
||||
"error_message": "Invalid address"
|
||||
@ -114,7 +120,9 @@
|
||||
"amount": "3003112"
|
||||
}
|
||||
],
|
||||
"signing_mode": "ORDINARY_TRANSACTION"
|
||||
"mint": [],
|
||||
"signing_mode": "ORDINARY_TRANSACTION",
|
||||
"additional_witness_requests": []
|
||||
},
|
||||
"result": {
|
||||
"error_message": "Invalid address"
|
||||
@ -143,7 +151,9 @@
|
||||
"amount": "3003112"
|
||||
}
|
||||
],
|
||||
"signing_mode": "ORDINARY_TRANSACTION"
|
||||
"mint": [],
|
||||
"signing_mode": "ORDINARY_TRANSACTION",
|
||||
"additional_witness_requests": []
|
||||
},
|
||||
"result": {
|
||||
"error_message": "Invalid address"
|
||||
@ -172,7 +182,9 @@
|
||||
"amount": "3003112"
|
||||
}
|
||||
],
|
||||
"signing_mode": "ORDINARY_TRANSACTION"
|
||||
"mint": [],
|
||||
"signing_mode": "ORDINARY_TRANSACTION",
|
||||
"additional_witness_requests": []
|
||||
},
|
||||
"result": {
|
||||
"error_message": "Fee is out of range"
|
||||
@ -206,7 +218,9 @@
|
||||
"amount": "1000000"
|
||||
}
|
||||
],
|
||||
"signing_mode": "ORDINARY_TRANSACTION"
|
||||
"mint": [],
|
||||
"signing_mode": "ORDINARY_TRANSACTION",
|
||||
"additional_witness_requests": []
|
||||
},
|
||||
"result": {
|
||||
"error_message": "Total transaction amount is out of range!"
|
||||
@ -235,7 +249,9 @@
|
||||
"amount": "3003112"
|
||||
}
|
||||
],
|
||||
"signing_mode": "ORDINARY_TRANSACTION"
|
||||
"mint": [],
|
||||
"signing_mode": "ORDINARY_TRANSACTION",
|
||||
"additional_witness_requests": []
|
||||
},
|
||||
"result": {
|
||||
"error_message": "Output address network mismatch"
|
||||
@ -264,7 +280,9 @@
|
||||
"amount": "3003112"
|
||||
}
|
||||
],
|
||||
"signing_mode": "ORDINARY_TRANSACTION"
|
||||
"mint": [],
|
||||
"signing_mode": "ORDINARY_TRANSACTION",
|
||||
"additional_witness_requests": []
|
||||
},
|
||||
"result": {
|
||||
"error_message": "Output address network mismatch"
|
||||
@ -293,7 +311,9 @@
|
||||
"amount": "1"
|
||||
}
|
||||
],
|
||||
"signing_mode": "ORDINARY_TRANSACTION"
|
||||
"mint": [],
|
||||
"signing_mode": "ORDINARY_TRANSACTION",
|
||||
"additional_witness_requests": []
|
||||
},
|
||||
"result": {
|
||||
"error_message": "Invalid address"
|
||||
@ -322,7 +342,9 @@
|
||||
"amount": "1"
|
||||
}
|
||||
],
|
||||
"signing_mode": "ORDINARY_TRANSACTION"
|
||||
"mint": [],
|
||||
"signing_mode": "ORDINARY_TRANSACTION",
|
||||
"additional_witness_requests": []
|
||||
},
|
||||
"result": {
|
||||
"error_message": "Invalid address"
|
||||
@ -351,7 +373,9 @@
|
||||
"amount": "1"
|
||||
}
|
||||
],
|
||||
"signing_mode": "ORDINARY_TRANSACTION"
|
||||
"mint": [],
|
||||
"signing_mode": "ORDINARY_TRANSACTION",
|
||||
"additional_witness_requests": []
|
||||
},
|
||||
"result": {
|
||||
"error_message": "Invalid network id/protocol magic combination!"
|
||||
@ -380,7 +404,9 @@
|
||||
"amount": "1"
|
||||
}
|
||||
],
|
||||
"signing_mode": "ORDINARY_TRANSACTION"
|
||||
"mint": [],
|
||||
"signing_mode": "ORDINARY_TRANSACTION",
|
||||
"additional_witness_requests": []
|
||||
},
|
||||
"result": {
|
||||
"error_message": "Invalid network id/protocol magic combination!"
|
||||
@ -409,7 +435,9 @@
|
||||
"amount": "3003112"
|
||||
}
|
||||
],
|
||||
"signing_mode": "ORDINARY_TRANSACTION"
|
||||
"mint": [],
|
||||
"signing_mode": "ORDINARY_TRANSACTION",
|
||||
"additional_witness_requests": []
|
||||
},
|
||||
"result": {
|
||||
"error_message": "Invalid address"
|
||||
@ -441,7 +469,9 @@
|
||||
"amount": "1"
|
||||
}
|
||||
],
|
||||
"signing_mode": "ORDINARY_TRANSACTION"
|
||||
"mint": [],
|
||||
"signing_mode": "ORDINARY_TRANSACTION",
|
||||
"additional_witness_requests": []
|
||||
},
|
||||
"result": {
|
||||
"error_message": "Invalid output"
|
||||
@ -475,7 +505,118 @@
|
||||
"amount": "3003112"
|
||||
}
|
||||
],
|
||||
"signing_mode": "ORDINARY_TRANSACTION"
|
||||
"mint": [],
|
||||
"signing_mode": "ORDINARY_TRANSACTION",
|
||||
"additional_witness_requests": []
|
||||
},
|
||||
"result": {
|
||||
"error_message": "Invalid certificate"
|
||||
}
|
||||
},
|
||||
{
|
||||
"description": "Certificate has multisig path",
|
||||
"parameters": {
|
||||
"protocol_magic": 764824073,
|
||||
"network_id": 1,
|
||||
"fee": 42,
|
||||
"ttl": 10,
|
||||
"certificates": [
|
||||
{
|
||||
"type": 0,
|
||||
"path": "m/1854'/1815'/0'/0/0"
|
||||
}
|
||||
],
|
||||
"withdrawals": [],
|
||||
"auxiliary_data": null,
|
||||
"inputs": [
|
||||
{
|
||||
"path": "m/1852'/1815'/0'/0/0",
|
||||
"prev_hash": "3b40265111d8bb3c3c608d95b3a0bf83461ace32d79336579a1939b3aad1c0b7",
|
||||
"prev_index": 0
|
||||
}
|
||||
],
|
||||
"outputs": [
|
||||
{
|
||||
"address": "Ae2tdPwUPEZCanmBz5g2GEwFqKTKpNJcGYPKfDxoNeKZ8bRHr8366kseiK2",
|
||||
"amount": "3003112"
|
||||
}
|
||||
],
|
||||
"mint": [],
|
||||
"signing_mode": "ORDINARY_TRANSACTION",
|
||||
"additional_witness_requests": []
|
||||
},
|
||||
"result": {
|
||||
"error_message": "Invalid certificate"
|
||||
}
|
||||
},
|
||||
{
|
||||
"description": "Certificate has script hash",
|
||||
"parameters": {
|
||||
"protocol_magic": 764824073,
|
||||
"network_id": 1,
|
||||
"fee": 42,
|
||||
"ttl": 10,
|
||||
"certificates": [
|
||||
{
|
||||
"type": 0,
|
||||
"script_hash": "29fb5fd4aa8cadd6705acc8263cee0fc62edca5ac38db593fec2f9fd"
|
||||
}
|
||||
],
|
||||
"withdrawals": [],
|
||||
"auxiliary_data": null,
|
||||
"inputs": [
|
||||
{
|
||||
"path": "m/1852'/1815'/0'/0/0",
|
||||
"prev_hash": "3b40265111d8bb3c3c608d95b3a0bf83461ace32d79336579a1939b3aad1c0b7",
|
||||
"prev_index": 0
|
||||
}
|
||||
],
|
||||
"outputs": [
|
||||
{
|
||||
"address": "Ae2tdPwUPEZCanmBz5g2GEwFqKTKpNJcGYPKfDxoNeKZ8bRHr8366kseiK2",
|
||||
"amount": "3003112"
|
||||
}
|
||||
],
|
||||
"mint": [],
|
||||
"signing_mode": "ORDINARY_TRANSACTION",
|
||||
"additional_witness_requests": []
|
||||
},
|
||||
"result": {
|
||||
"error_message": "Invalid certificate"
|
||||
}
|
||||
},
|
||||
{
|
||||
"description": "Certificate has both path and script_hash",
|
||||
"parameters": {
|
||||
"protocol_magic": 764824073,
|
||||
"network_id": 1,
|
||||
"fee": 42,
|
||||
"ttl": 10,
|
||||
"certificates": [
|
||||
{
|
||||
"type": 0,
|
||||
"path": "m/1852'/1815'/0'/0/0",
|
||||
"script_hash": "29fb5fd4aa8cadd6705acc8263cee0fc62edca5ac38db593fec2f9fd"
|
||||
}
|
||||
],
|
||||
"withdrawals": [],
|
||||
"auxiliary_data": null,
|
||||
"inputs": [
|
||||
{
|
||||
"path": "m/1852'/1815'/0'/0/0",
|
||||
"prev_hash": "3b40265111d8bb3c3c608d95b3a0bf83461ace32d79336579a1939b3aad1c0b7",
|
||||
"prev_index": 0
|
||||
}
|
||||
],
|
||||
"outputs": [
|
||||
{
|
||||
"address": "Ae2tdPwUPEZCanmBz5g2GEwFqKTKpNJcGYPKfDxoNeKZ8bRHr8366kseiK2",
|
||||
"amount": "3003112"
|
||||
}
|
||||
],
|
||||
"mint": [],
|
||||
"signing_mode": "ORDINARY_TRANSACTION",
|
||||
"additional_witness_requests": []
|
||||
},
|
||||
"result": {
|
||||
"error_message": "Invalid certificate"
|
||||
@ -510,7 +651,9 @@
|
||||
"amount": "3003112"
|
||||
}
|
||||
],
|
||||
"signing_mode": "ORDINARY_TRANSACTION"
|
||||
"mint": [],
|
||||
"signing_mode": "ORDINARY_TRANSACTION",
|
||||
"additional_witness_requests": []
|
||||
},
|
||||
"result": {
|
||||
"error_message": "Invalid certificate"
|
||||
@ -544,7 +687,81 @@
|
||||
"amount": "3003112"
|
||||
}
|
||||
],
|
||||
"signing_mode": "ORDINARY_TRANSACTION"
|
||||
"mint": [],
|
||||
"signing_mode": "ORDINARY_TRANSACTION",
|
||||
"additional_witness_requests": []
|
||||
},
|
||||
"result": {
|
||||
"error_message": "Invalid withdrawal"
|
||||
}
|
||||
},
|
||||
{
|
||||
"description": "Withdrawal has multisig path",
|
||||
"parameters": {
|
||||
"protocol_magic": 764824073,
|
||||
"network_id": 1,
|
||||
"fee": 42,
|
||||
"ttl": 10,
|
||||
"certificates": [],
|
||||
"withdrawals": [
|
||||
{
|
||||
"path": "m/1854'/1815'/0'/0/0",
|
||||
"amount": "1000"
|
||||
}
|
||||
],
|
||||
"auxiliary_data": null,
|
||||
"inputs": [
|
||||
{
|
||||
"path": "m/1852'/1815'/0'/0/0",
|
||||
"prev_hash": "3b40265111d8bb3c3c608d95b3a0bf83461ace32d79336579a1939b3aad1c0b7",
|
||||
"prev_index": 0
|
||||
}
|
||||
],
|
||||
"outputs": [
|
||||
{
|
||||
"address": "Ae2tdPwUPEZCanmBz5g2GEwFqKTKpNJcGYPKfDxoNeKZ8bRHr8366kseiK2",
|
||||
"amount": "3003112"
|
||||
}
|
||||
],
|
||||
"mint": [],
|
||||
"signing_mode": "ORDINARY_TRANSACTION",
|
||||
"additional_witness_requests": []
|
||||
},
|
||||
"result": {
|
||||
"error_message": "Invalid withdrawal"
|
||||
}
|
||||
},
|
||||
{
|
||||
"description": "Withdrawal has script hash",
|
||||
"parameters": {
|
||||
"protocol_magic": 764824073,
|
||||
"network_id": 1,
|
||||
"fee": 42,
|
||||
"ttl": 10,
|
||||
"certificates": [],
|
||||
"withdrawals": [
|
||||
{
|
||||
"script_hash": "29fb5fd4aa8cadd6705acc8263cee0fc62edca5ac38db593fec2f9fd",
|
||||
"amount": "1000"
|
||||
}
|
||||
],
|
||||
"auxiliary_data": null,
|
||||
"inputs": [
|
||||
{
|
||||
"path": "m/1852'/1815'/0'/0/0",
|
||||
"prev_hash": "3b40265111d8bb3c3c608d95b3a0bf83461ace32d79336579a1939b3aad1c0b7",
|
||||
"prev_index": 0
|
||||
}
|
||||
],
|
||||
"outputs": [
|
||||
{
|
||||
"address": "Ae2tdPwUPEZCanmBz5g2GEwFqKTKpNJcGYPKfDxoNeKZ8bRHr8366kseiK2",
|
||||
"amount": "3003112"
|
||||
}
|
||||
],
|
||||
"mint": [],
|
||||
"signing_mode": "ORDINARY_TRANSACTION",
|
||||
"additional_witness_requests": []
|
||||
},
|
||||
"result": {
|
||||
"error_message": "Invalid withdrawal"
|
||||
@ -578,7 +795,46 @@
|
||||
"amount": "3003112"
|
||||
}
|
||||
],
|
||||
"signing_mode": "ORDINARY_TRANSACTION"
|
||||
"mint": [],
|
||||
"signing_mode": "ORDINARY_TRANSACTION",
|
||||
"additional_witness_requests": []
|
||||
},
|
||||
"result": {
|
||||
"error_message": "Invalid withdrawal"
|
||||
}
|
||||
},
|
||||
{
|
||||
"description": "Withdrawal contains both path and script_hash",
|
||||
"parameters": {
|
||||
"protocol_magic": 764824073,
|
||||
"network_id": 1,
|
||||
"fee": 42,
|
||||
"ttl": 10,
|
||||
"certificates": [],
|
||||
"withdrawals": [
|
||||
{
|
||||
"path": "m/1852'/1815'/0'/2/0",
|
||||
"amount": "1000",
|
||||
"script_hash": "29fb5fd4aa8cadd6705acc8263cee0fc62edca5ac38db593fec2f9fd"
|
||||
}
|
||||
],
|
||||
"auxiliary_data": null,
|
||||
"inputs": [
|
||||
{
|
||||
"path": "m/1852'/1815'/0'/0/0",
|
||||
"prev_hash": "3b40265111d8bb3c3c608d95b3a0bf83461ace32d79336579a1939b3aad1c0b7",
|
||||
"prev_index": 0
|
||||
}
|
||||
],
|
||||
"outputs": [
|
||||
{
|
||||
"address": "Ae2tdPwUPEZCanmBz5g2GEwFqKTKpNJcGYPKfDxoNeKZ8bRHr8366kseiK2",
|
||||
"amount": "3003112"
|
||||
}
|
||||
],
|
||||
"mint": [],
|
||||
"signing_mode": "ORDINARY_TRANSACTION",
|
||||
"additional_witness_requests": []
|
||||
},
|
||||
"result": {
|
||||
"error_message": "Invalid withdrawal"
|
||||
@ -616,7 +872,9 @@
|
||||
"amount": "3003112"
|
||||
}
|
||||
],
|
||||
"signing_mode": "ORDINARY_TRANSACTION"
|
||||
"mint": [],
|
||||
"signing_mode": "ORDINARY_TRANSACTION",
|
||||
"additional_witness_requests": []
|
||||
},
|
||||
"result": {
|
||||
"error_message": "Duplicate withdrawals"
|
||||
@ -647,7 +905,9 @@
|
||||
"amount": "3003112"
|
||||
}
|
||||
],
|
||||
"signing_mode": "ORDINARY_TRANSACTION"
|
||||
"mint": [],
|
||||
"signing_mode": "ORDINARY_TRANSACTION",
|
||||
"additional_witness_requests": []
|
||||
},
|
||||
"result": {
|
||||
"error_message": "Invalid auxiliary data"
|
||||
@ -686,7 +946,9 @@
|
||||
"amount": "1"
|
||||
}
|
||||
],
|
||||
"signing_mode": "ORDINARY_TRANSACTION"
|
||||
"mint": [],
|
||||
"signing_mode": "ORDINARY_TRANSACTION",
|
||||
"additional_witness_requests": []
|
||||
},
|
||||
"result": {
|
||||
"error_message": "Invalid auxiliary data"
|
||||
@ -727,7 +989,9 @@
|
||||
"amount": "1"
|
||||
}
|
||||
],
|
||||
"signing_mode": "ORDINARY_TRANSACTION"
|
||||
"mint": [],
|
||||
"signing_mode": "ORDINARY_TRANSACTION",
|
||||
"additional_witness_requests": []
|
||||
},
|
||||
"result": {
|
||||
"error_message": "Invalid auxiliary data"
|
||||
@ -762,7 +1026,9 @@
|
||||
"amount": "7120787"
|
||||
}
|
||||
],
|
||||
"signing_mode": "ORDINARY_TRANSACTION"
|
||||
"mint": [],
|
||||
"signing_mode": "ORDINARY_TRANSACTION",
|
||||
"additional_witness_requests": []
|
||||
},
|
||||
"result": {
|
||||
"error_message": "Invalid change output path"
|
||||
@ -797,12 +1063,82 @@
|
||||
"amount": "7120787"
|
||||
}
|
||||
],
|
||||
"signing_mode": "ORDINARY_TRANSACTION"
|
||||
"mint": [],
|
||||
"signing_mode": "ORDINARY_TRANSACTION",
|
||||
"additional_witness_requests": []
|
||||
},
|
||||
"result": {
|
||||
"error_message": "Invalid change output staking path"
|
||||
}
|
||||
},
|
||||
{
|
||||
"description": "Change output with script in payment part",
|
||||
"parameters": {
|
||||
"protocol_magic": 764824073,
|
||||
"network_id": 1,
|
||||
"fee": 42,
|
||||
"ttl": 10,
|
||||
"certificates": [],
|
||||
"withdrawals": [],
|
||||
"auxiliary_data": null,
|
||||
"inputs": [
|
||||
{
|
||||
"path": "m/1852'/1815'/0'/0/0",
|
||||
"prev_hash": "3b40265111d8bb3c3c608d95b3a0bf83461ace32d79336579a1939b3aad1c0b7",
|
||||
"prev_index": 0
|
||||
}
|
||||
],
|
||||
"outputs": [
|
||||
{
|
||||
"address": "addr1q84sh2j72ux0l03fxndjnhctdg7hcppsaejafsa84vh7lwgmcs5wgus8qt4atk45lvt4xfxpjtwfhdmvchdf2m3u3hlsd5tq5r",
|
||||
"amount": "1"
|
||||
},
|
||||
{
|
||||
"addressType": 1,
|
||||
"scriptPaymentHash": "0d5acbf6a1dfb0c8724e60df314987315ccbf78bb6c0f9b6f3d568fe",
|
||||
"stakingPath": "m/1852'/1815'/0'/2/0",
|
||||
"amount": "7120787"
|
||||
}
|
||||
],
|
||||
"mint": [],
|
||||
"signing_mode": "ORDINARY_TRANSACTION",
|
||||
"additional_witness_requests": []
|
||||
},
|
||||
"result": {
|
||||
"error_message": "Invalid address parameters"
|
||||
}
|
||||
},
|
||||
{
|
||||
"description": "Output with reward address",
|
||||
"parameters": {
|
||||
"protocol_magic": 764824073,
|
||||
"network_id": 1,
|
||||
"fee": 42,
|
||||
"ttl": 10,
|
||||
"certificates": [],
|
||||
"withdrawals": [],
|
||||
"auxiliary_data": null,
|
||||
"inputs": [
|
||||
{
|
||||
"path": "m/1852'/1815'/0'/0/0",
|
||||
"prev_hash": "3b40265111d8bb3c3c608d95b3a0bf83461ace32d79336579a1939b3aad1c0b7",
|
||||
"prev_index": 0
|
||||
}
|
||||
],
|
||||
"outputs": [
|
||||
{
|
||||
"address": "stake1uyfz49rtntfa9h0s98f6s28sg69weemgjhc4e8hm66d5yacalmqha",
|
||||
"amount": "1"
|
||||
}
|
||||
],
|
||||
"mint": [],
|
||||
"signing_mode": "ORDINARY_TRANSACTION",
|
||||
"additional_witness_requests": []
|
||||
},
|
||||
"result": {
|
||||
"error_message": "Invalid address"
|
||||
}
|
||||
},
|
||||
{
|
||||
"description": "Stake deregistration account larger than 100",
|
||||
"parameters": {
|
||||
@ -831,7 +1167,9 @@
|
||||
"amount": "1"
|
||||
}
|
||||
],
|
||||
"signing_mode": "ORDINARY_TRANSACTION"
|
||||
"mint": [],
|
||||
"signing_mode": "ORDINARY_TRANSACTION",
|
||||
"additional_witness_requests": []
|
||||
},
|
||||
"result": {
|
||||
"error_message": "Invalid certificate path"
|
||||
@ -875,7 +1213,9 @@
|
||||
]
|
||||
}
|
||||
],
|
||||
"signing_mode": "ORDINARY_TRANSACTION"
|
||||
"mint": [],
|
||||
"signing_mode": "ORDINARY_TRANSACTION",
|
||||
"additional_witness_requests": []
|
||||
},
|
||||
"result": {
|
||||
"error_message": "Invalid token bundle in output"
|
||||
@ -924,12 +1264,323 @@
|
||||
]
|
||||
}
|
||||
],
|
||||
"signing_mode": "ORDINARY_TRANSACTION"
|
||||
"mint": [],
|
||||
"signing_mode": "ORDINARY_TRANSACTION",
|
||||
"additional_witness_requests": []
|
||||
},
|
||||
"result": {
|
||||
"error_message": "Invalid token bundle in output"
|
||||
}
|
||||
},
|
||||
{
|
||||
"description": "Additional witness requests in ORDINARY_TRANSACTION",
|
||||
"parameters": {
|
||||
"protocol_magic": 764824073,
|
||||
"network_id": 1,
|
||||
"fee": 42,
|
||||
"ttl": 10,
|
||||
"certificates": [],
|
||||
"withdrawals": [],
|
||||
"auxiliary_data": null,
|
||||
"inputs": [
|
||||
{
|
||||
"path": "m/1852'/1815'/0'/0/0",
|
||||
"prev_hash": "3b40265111d8bb3c3c608d95b3a0bf83461ace32d79336579a1939b3aad1c0b7",
|
||||
"prev_index": 0
|
||||
}
|
||||
],
|
||||
"outputs": [
|
||||
{
|
||||
"address": "Ae2tdPwUPEZCanmBz5g2GEwFqKTKpNJcGYPKfDxoNeKZ8bRHr8366kseiK2",
|
||||
"amount": "3003112"
|
||||
}
|
||||
],
|
||||
"mint": [],
|
||||
"signing_mode": "ORDINARY_TRANSACTION",
|
||||
"additional_witness_requests": [
|
||||
{
|
||||
"path": "m/1854'/1815'/0'/0/0"
|
||||
}
|
||||
]
|
||||
},
|
||||
"result": {
|
||||
"error_message": "Invalid witness request"
|
||||
}
|
||||
},
|
||||
{
|
||||
"description": "1854 input path in ORDINARY_TRANSACTION",
|
||||
"parameters": {
|
||||
"protocol_magic": 764824073,
|
||||
"network_id": 1,
|
||||
"fee": 42,
|
||||
"ttl": 10,
|
||||
"certificates": [],
|
||||
"withdrawals": [],
|
||||
"auxiliary_data": null,
|
||||
"inputs": [
|
||||
{
|
||||
"path": "m/1854'/1815'/0'/0/0",
|
||||
"prev_hash": "3b40265111d8bb3c3c608d95b3a0bf83461ace32d79336579a1939b3aad1c0b7",
|
||||
"prev_index": 0
|
||||
}
|
||||
],
|
||||
"outputs": [
|
||||
{
|
||||
"address": "Ae2tdPwUPEZCanmBz5g2GEwFqKTKpNJcGYPKfDxoNeKZ8bRHr8366kseiK2",
|
||||
"amount": "3003112"
|
||||
}
|
||||
],
|
||||
"mint": [],
|
||||
"signing_mode": "ORDINARY_TRANSACTION",
|
||||
"additional_witness_requests": [
|
||||
{
|
||||
"path": "m/1854'/1815'/0'/0/0"
|
||||
}
|
||||
]
|
||||
},
|
||||
"result": {
|
||||
"error_message": "Invalid witness request"
|
||||
}
|
||||
},
|
||||
{
|
||||
"description": "1854 change output path in ORDINARY_TRANSACTION",
|
||||
"parameters": {
|
||||
"protocol_magic": 764824073,
|
||||
"network_id": 1,
|
||||
"fee": 42,
|
||||
"ttl": 10,
|
||||
"certificates": [],
|
||||
"withdrawals": [],
|
||||
"auxiliary_data": null,
|
||||
"inputs": [
|
||||
{
|
||||
"path": "m/1852'/1815'/0'/0/0",
|
||||
"prev_hash": "3b40265111d8bb3c3c608d95b3a0bf83461ace32d79336579a1939b3aad1c0b7",
|
||||
"prev_index": 0
|
||||
}
|
||||
],
|
||||
"outputs": [
|
||||
{
|
||||
"addressType": 0,
|
||||
"path": "m/1854'/1815'/0'/0/0",
|
||||
"stakingPath": "m/1852'/1815'/0'/2/0",
|
||||
"amount": "7120787"
|
||||
}
|
||||
],
|
||||
"mint": [],
|
||||
"signing_mode": "ORDINARY_TRANSACTION",
|
||||
"additional_witness_requests": []
|
||||
},
|
||||
"result": {
|
||||
"error_message": "Invalid address parameters"
|
||||
}
|
||||
},
|
||||
{
|
||||
"description": "Ordinary transaction with token minting with 1854 path",
|
||||
"parameters": {
|
||||
"protocol_magic": 764824073,
|
||||
"network_id": 1,
|
||||
"fee": 42,
|
||||
"ttl": 10,
|
||||
"validity_interval_start": 47,
|
||||
"certificates": [],
|
||||
"withdrawals": [],
|
||||
"auxiliary_data": null,
|
||||
"inputs": [
|
||||
{
|
||||
"path": "m/1852'/1815'/0'/0/0",
|
||||
"prev_hash": "3b40265111d8bb3c3c608d95b3a0bf83461ace32d79336579a1939b3aad1c0b7",
|
||||
"prev_index": 0
|
||||
}
|
||||
],
|
||||
"outputs": [
|
||||
{
|
||||
"address": "addr1q84sh2j72ux0l03fxndjnhctdg7hcppsaejafsa84vh7lwgmcs5wgus8qt4atk45lvt4xfxpjtwfhdmvchdf2m3u3hlsd5tq5r",
|
||||
"amount": "1234",
|
||||
"token_bundle": [
|
||||
{
|
||||
"policy_id": "95a292ffee938be03e9bae5657982a74e9014eb4960108c9e23a5b39",
|
||||
"tokens": [
|
||||
{
|
||||
"asset_name_bytes": "74652474436f696e",
|
||||
"amount": "100"
|
||||
}
|
||||
]
|
||||
},
|
||||
{
|
||||
"policy_id": "a5a292ffee938be03e9bae5657982a74e9014eb4960108c9e23a5b39",
|
||||
"tokens": [
|
||||
{
|
||||
"asset_name_bytes": "74652474436f696e",
|
||||
"amount": "100"
|
||||
}
|
||||
]
|
||||
}
|
||||
]
|
||||
}
|
||||
],
|
||||
"mint": [
|
||||
{
|
||||
"policy_id": "95a292ffee938be03e9bae5657982a74e9014eb4960108c9e23a5b39",
|
||||
"tokens": [
|
||||
{
|
||||
"asset_name_bytes": "74652474436f696e",
|
||||
"mint_amount": "100"
|
||||
},
|
||||
{
|
||||
"asset_name_bytes": "75652474436f696e",
|
||||
"mint_amount": "-100"
|
||||
}
|
||||
]
|
||||
},
|
||||
{
|
||||
"policy_id": "a5a292ffee938be03e9bae5657982a74e9014eb4960108c9e23a5b39",
|
||||
"tokens": [
|
||||
{
|
||||
"asset_name_bytes": "74652474436f696e",
|
||||
"mint_amount": "100"
|
||||
},
|
||||
{
|
||||
"asset_name_bytes": "75652474436f696e",
|
||||
"mint_amount": "-100"
|
||||
}
|
||||
]
|
||||
}
|
||||
],
|
||||
"signing_mode": "ORDINARY_TRANSACTION",
|
||||
"additional_witness_requests": [
|
||||
{
|
||||
"path": "m/1854'/1815'/0'/0/0"
|
||||
}
|
||||
]
|
||||
},
|
||||
"result": {
|
||||
"error_message": "Invalid witness request"
|
||||
}
|
||||
},
|
||||
{
|
||||
"description": "Ordinary transaction without token minting but with a 1855 additional witness request",
|
||||
"parameters": {
|
||||
"protocol_magic": 764824073,
|
||||
"network_id": 1,
|
||||
"fee": 42,
|
||||
"ttl": 10,
|
||||
"validity_interval_start": 47,
|
||||
"certificates": [],
|
||||
"withdrawals": [],
|
||||
"auxiliary_data": null,
|
||||
"inputs": [
|
||||
{
|
||||
"path": "m/1852'/1815'/0'/0/0",
|
||||
"prev_hash": "3b40265111d8bb3c3c608d95b3a0bf83461ace32d79336579a1939b3aad1c0b7",
|
||||
"prev_index": 0
|
||||
}
|
||||
],
|
||||
"outputs": [
|
||||
{
|
||||
"address": "addr1q84sh2j72ux0l03fxndjnhctdg7hcppsaejafsa84vh7lwgmcs5wgus8qt4atk45lvt4xfxpjtwfhdmvchdf2m3u3hlsd5tq5r",
|
||||
"amount": "1234"
|
||||
}
|
||||
],
|
||||
"mint": [],
|
||||
"signing_mode": "ORDINARY_TRANSACTION",
|
||||
"additional_witness_requests": [
|
||||
{
|
||||
"path": "m/1855'/1815'/0'"
|
||||
}
|
||||
]
|
||||
},
|
||||
"result": {
|
||||
"error_message": "Invalid witness request"
|
||||
}
|
||||
},
|
||||
{
|
||||
"description": "Ordinary transaction with long token minting path",
|
||||
"parameters": {
|
||||
"protocol_magic": 764824073,
|
||||
"network_id": 1,
|
||||
"fee": 42,
|
||||
"ttl": 10,
|
||||
"validity_interval_start": 47,
|
||||
"certificates": [],
|
||||
"withdrawals": [],
|
||||
"auxiliary_data": null,
|
||||
"inputs": [
|
||||
{
|
||||
"path": "m/1852'/1815'/0'/0/0",
|
||||
"prev_hash": "3b40265111d8bb3c3c608d95b3a0bf83461ace32d79336579a1939b3aad1c0b7",
|
||||
"prev_index": 0
|
||||
}
|
||||
],
|
||||
"outputs": [
|
||||
{
|
||||
"address": "addr1q84sh2j72ux0l03fxndjnhctdg7hcppsaejafsa84vh7lwgmcs5wgus8qt4atk45lvt4xfxpjtwfhdmvchdf2m3u3hlsd5tq5r",
|
||||
"amount": "2000000",
|
||||
"token_bundle": [
|
||||
{
|
||||
"policy_id": "95a292ffee938be03e9bae5657982a74e9014eb4960108c9e23a5b39",
|
||||
"tokens": [
|
||||
{
|
||||
"asset_name_bytes": "74652474436f696e",
|
||||
"amount": "7878754"
|
||||
}
|
||||
]
|
||||
},
|
||||
{
|
||||
"policy_id": "96a292ffee938be03e9bae5657982a74e9014eb4960108c9e23a5b39",
|
||||
"tokens": [
|
||||
{
|
||||
"asset_name_bytes": "74652474436f696e",
|
||||
"amount": "7878754"
|
||||
},
|
||||
{
|
||||
"asset_name_bytes": "75652474436f696e",
|
||||
"amount": "1234"
|
||||
}
|
||||
]
|
||||
}
|
||||
]
|
||||
}
|
||||
],
|
||||
"mint": [
|
||||
{
|
||||
"policy_id": "95a292ffee938be03e9bae5657982a74e9014eb4960108c9e23a5b39",
|
||||
"tokens": [
|
||||
{
|
||||
"asset_name_bytes": "74652474436f696e",
|
||||
"mint_amount": "7878754"
|
||||
},
|
||||
{
|
||||
"asset_name_bytes": "75652474436f696e",
|
||||
"mint_amount": "-7878754"
|
||||
}
|
||||
]
|
||||
},
|
||||
{
|
||||
"policy_id": "96a292ffee938be03e9bae5657982a74e9014eb4960108c9e23a5b39",
|
||||
"tokens": [
|
||||
{
|
||||
"asset_name_bytes": "74652474436f696e",
|
||||
"mint_amount": "7878754"
|
||||
},
|
||||
{
|
||||
"asset_name_bytes": "75652474436f696e",
|
||||
"mint_amount": "-1234"
|
||||
}
|
||||
]
|
||||
}
|
||||
],
|
||||
"signing_mode": "ORDINARY_TRANSACTION",
|
||||
"additional_witness_requests": [
|
||||
{
|
||||
"path": "m/1855'/1815'/0'/0/0"
|
||||
}
|
||||
]
|
||||
},
|
||||
"result": {
|
||||
"error_message": "Invalid witness request"
|
||||
}
|
||||
},
|
||||
{
|
||||
"description": "Input and change output account mismatch",
|
||||
"parameters": {
|
||||
@ -959,7 +1610,9 @@
|
||||
"amount": "7120787"
|
||||
}
|
||||
],
|
||||
"signing_mode": "ORDINARY_TRANSACTION"
|
||||
"mint": [],
|
||||
"signing_mode": "ORDINARY_TRANSACTION",
|
||||
"additional_witness_requests": []
|
||||
},
|
||||
"result": {
|
||||
"error_message": "Invalid witness request"
|
||||
@ -993,7 +1646,9 @@
|
||||
"amount": "1"
|
||||
}
|
||||
],
|
||||
"signing_mode": "ORDINARY_TRANSACTION"
|
||||
"mint": [],
|
||||
"signing_mode": "ORDINARY_TRANSACTION",
|
||||
"additional_witness_requests": []
|
||||
},
|
||||
"result": {
|
||||
"error_message": "Invalid witness request"
|
||||
@ -1027,7 +1682,9 @@
|
||||
"amount": "1"
|
||||
}
|
||||
],
|
||||
"signing_mode": "ORDINARY_TRANSACTION"
|
||||
"mint": [],
|
||||
"signing_mode": "ORDINARY_TRANSACTION",
|
||||
"additional_witness_requests": []
|
||||
},
|
||||
"result": {
|
||||
"error_message": "Invalid witness request"
|
||||
@ -1067,7 +1724,9 @@
|
||||
"amount": "7120787"
|
||||
}
|
||||
],
|
||||
"signing_mode": "ORDINARY_TRANSACTION"
|
||||
"mint": [],
|
||||
"signing_mode": "ORDINARY_TRANSACTION",
|
||||
"additional_witness_requests": []
|
||||
},
|
||||
"result": {
|
||||
"error_message": "Invalid certificate"
|
||||
@ -1107,7 +1766,9 @@
|
||||
"amount": "7120787"
|
||||
}
|
||||
],
|
||||
"signing_mode": "ORDINARY_TRANSACTION"
|
||||
"mint": [],
|
||||
"signing_mode": "ORDINARY_TRANSACTION",
|
||||
"additional_witness_requests": []
|
||||
},
|
||||
"result": {
|
||||
"error_message": "Invalid withdrawal"
|
||||
@ -1146,7 +1807,9 @@
|
||||
"amount": "1"
|
||||
}
|
||||
],
|
||||
"signing_mode": "ORDINARY_TRANSACTION"
|
||||
"mint": [],
|
||||
"signing_mode": "ORDINARY_TRANSACTION",
|
||||
"additional_witness_requests": []
|
||||
},
|
||||
"result": {
|
||||
"error_message": "Invalid withdrawal"
|
||||
@ -1179,7 +1842,9 @@
|
||||
"amount": "1"
|
||||
}
|
||||
],
|
||||
"signing_mode": "ORDINARY_TRANSACTION"
|
||||
"mint": [],
|
||||
"signing_mode": "ORDINARY_TRANSACTION",
|
||||
"additional_witness_requests": []
|
||||
},
|
||||
"result": {
|
||||
"error_message": "Invalid witness request"
|
||||
@ -1209,7 +1874,9 @@
|
||||
"amount": "7120787"
|
||||
}
|
||||
],
|
||||
"signing_mode": "ORDINARY_TRANSACTION"
|
||||
"mint": [],
|
||||
"signing_mode": "ORDINARY_TRANSACTION",
|
||||
"additional_witness_requests": []
|
||||
},
|
||||
"result": {
|
||||
"error_message": "Invalid witness request"
|
||||
|
205
common/tests/fixtures/cardano/sign_tx.json
vendored
205
common/tests/fixtures/cardano/sign_tx.json
vendored
@ -27,7 +27,9 @@
|
||||
"amount": "3003112"
|
||||
}
|
||||
],
|
||||
"signing_mode": "ORDINARY_TRANSACTION"
|
||||
"mint": [],
|
||||
"signing_mode": "ORDINARY_TRANSACTION",
|
||||
"additional_witness_requests": []
|
||||
},
|
||||
"result": {
|
||||
"tx_hash": "73e09bdebf98a9e0f17f86a2d11e0f14f4f8dae77cdf26ff1678e821f20c8db6",
|
||||
@ -69,7 +71,9 @@
|
||||
"amount": "1000000"
|
||||
}
|
||||
],
|
||||
"signing_mode": "ORDINARY_TRANSACTION"
|
||||
"mint": [],
|
||||
"signing_mode": "ORDINARY_TRANSACTION",
|
||||
"additional_witness_requests": []
|
||||
},
|
||||
"result": {
|
||||
"tx_hash": "81b14b7e62972127eb33c0b1198de6430540ad3a98eec621a3194f2baac43a43",
|
||||
@ -112,7 +116,9 @@
|
||||
"amount": "7120787"
|
||||
}
|
||||
],
|
||||
"signing_mode": "ORDINARY_TRANSACTION"
|
||||
"mint": [],
|
||||
"signing_mode": "ORDINARY_TRANSACTION",
|
||||
"additional_witness_requests": []
|
||||
},
|
||||
"result": {
|
||||
"tx_hash": "16fe72bb198be423677577e6326f1f648ec5fc11263b072006382d8125a6edda",
|
||||
@ -164,7 +170,9 @@
|
||||
"amount": "3003112"
|
||||
}
|
||||
],
|
||||
"signing_mode": "ORDINARY_TRANSACTION"
|
||||
"mint": [],
|
||||
"signing_mode": "ORDINARY_TRANSACTION",
|
||||
"additional_witness_requests": []
|
||||
},
|
||||
"result": {
|
||||
"tx_hash": "7e16a0b47bdfc37abf4ddd3143f7481af07ffe7abd68f752676f5b0b2890d05b",
|
||||
@ -225,7 +233,9 @@
|
||||
"amount": "7120787"
|
||||
}
|
||||
],
|
||||
"signing_mode": "ORDINARY_TRANSACTION"
|
||||
"mint": [],
|
||||
"signing_mode": "ORDINARY_TRANSACTION",
|
||||
"additional_witness_requests": []
|
||||
},
|
||||
"result": {
|
||||
"tx_hash": "5ddbb530b8a89e2b08fc91db03950c876c4a9c1c3fb6e628c4cab638b1c97648",
|
||||
@ -269,7 +279,9 @@
|
||||
"amount": "7120787"
|
||||
}
|
||||
],
|
||||
"signing_mode": "ORDINARY_TRANSACTION"
|
||||
"mint": [],
|
||||
"signing_mode": "ORDINARY_TRANSACTION",
|
||||
"additional_witness_requests": []
|
||||
},
|
||||
"result": {
|
||||
"tx_hash": "1fc82ce2420c173a0947eaf49af76fcd6f4e400e2bfb5fa152a482ea12dde24b",
|
||||
@ -313,7 +325,9 @@
|
||||
"amount": "7120787"
|
||||
}
|
||||
],
|
||||
"signing_mode": "ORDINARY_TRANSACTION"
|
||||
"mint": [],
|
||||
"signing_mode": "ORDINARY_TRANSACTION",
|
||||
"additional_witness_requests": []
|
||||
},
|
||||
"result": {
|
||||
"tx_hash": "abd1b24ac0638251398444ee136110f952738df32a512ce35894f8453d0e8edf",
|
||||
@ -356,7 +370,9 @@
|
||||
"amount": "7120787"
|
||||
}
|
||||
],
|
||||
"signing_mode": "ORDINARY_TRANSACTION"
|
||||
"mint": [],
|
||||
"signing_mode": "ORDINARY_TRANSACTION",
|
||||
"additional_witness_requests": []
|
||||
},
|
||||
"result": {
|
||||
"tx_hash": "d1610bb89bece22ed3158738bc1fbb31c6af0685053e2993361e3380f49afad9",
|
||||
@ -401,7 +417,9 @@
|
||||
"amount": "7120787"
|
||||
}
|
||||
],
|
||||
"signing_mode": "ORDINARY_TRANSACTION"
|
||||
"mint": [],
|
||||
"signing_mode": "ORDINARY_TRANSACTION",
|
||||
"additional_witness_requests": []
|
||||
},
|
||||
"result": {
|
||||
"tx_hash": "40535fa8f88515f1da008d3cdf544cf9dbf1675c3cb0adb13b74b9293f1b7096",
|
||||
@ -443,7 +461,9 @@
|
||||
"amount": "7120787"
|
||||
}
|
||||
],
|
||||
"signing_mode": "ORDINARY_TRANSACTION"
|
||||
"mint": [],
|
||||
"signing_mode": "ORDINARY_TRANSACTION",
|
||||
"additional_witness_requests": []
|
||||
},
|
||||
"result": {
|
||||
"tx_hash": "d3570557b197604109481a80aeb66cd2cfabc57f802ad593bacc12eb658e5d72",
|
||||
@ -485,7 +505,9 @@
|
||||
"amount": "1"
|
||||
}
|
||||
],
|
||||
"signing_mode": "ORDINARY_TRANSACTION"
|
||||
"mint": [],
|
||||
"signing_mode": "ORDINARY_TRANSACTION",
|
||||
"additional_witness_requests": []
|
||||
},
|
||||
"result": {
|
||||
"tx_hash": "1a3a295908afd8b2afc368071272d6964be6ee0af062bb765aea65ca454dc0c9",
|
||||
@ -522,7 +544,9 @@
|
||||
}
|
||||
],
|
||||
"outputs": [],
|
||||
"signing_mode": "ORDINARY_TRANSACTION"
|
||||
"mint": [],
|
||||
"signing_mode": "ORDINARY_TRANSACTION",
|
||||
"additional_witness_requests": []
|
||||
},
|
||||
"result": {
|
||||
"tx_hash": "03535791d04fc1b4457fada025f1c1f7778b5c2d7fa580bbac8abd53b85d3255",
|
||||
@ -569,7 +593,9 @@
|
||||
"amount": "1"
|
||||
}
|
||||
],
|
||||
"signing_mode": "ORDINARY_TRANSACTION"
|
||||
"mint": [],
|
||||
"signing_mode": "ORDINARY_TRANSACTION",
|
||||
"additional_witness_requests": []
|
||||
},
|
||||
"result": {
|
||||
"tx_hash": "439764b5f7e08839881536a3191faeaf111e75d9f00f83b102c5c1c6fa9fcaf9",
|
||||
@ -617,7 +643,9 @@
|
||||
"amount": "1"
|
||||
}
|
||||
],
|
||||
"signing_mode": "ORDINARY_TRANSACTION"
|
||||
"mint": [],
|
||||
"signing_mode": "ORDINARY_TRANSACTION",
|
||||
"additional_witness_requests": []
|
||||
},
|
||||
"result": {
|
||||
"tx_hash": "3aca1784d151dc75bdbb80fae71bda3f4b26af3f5fd71bd5e9e9bbcdd2b64ad1",
|
||||
@ -670,7 +698,9 @@
|
||||
"amount": "1"
|
||||
}
|
||||
],
|
||||
"signing_mode": "ORDINARY_TRANSACTION"
|
||||
"mint": [],
|
||||
"signing_mode": "ORDINARY_TRANSACTION",
|
||||
"additional_witness_requests": []
|
||||
},
|
||||
"result": {
|
||||
"tx_hash": "22c67f12e6f6aa0f2f09fd27d472b19c7208ccd7c3af4b09604fd5d462c1de2b",
|
||||
@ -719,7 +749,9 @@
|
||||
"amount": "1"
|
||||
}
|
||||
],
|
||||
"signing_mode": "ORDINARY_TRANSACTION"
|
||||
"mint": [],
|
||||
"signing_mode": "ORDINARY_TRANSACTION",
|
||||
"additional_witness_requests": []
|
||||
},
|
||||
"result": {
|
||||
"tx_hash": "cc068a25994ef6a90cdab8adfbe302d6f742de9901ba2495dd64a09f2ef951f5",
|
||||
@ -764,7 +796,9 @@
|
||||
"amount": "1"
|
||||
}
|
||||
],
|
||||
"signing_mode": "ORDINARY_TRANSACTION"
|
||||
"mint": [],
|
||||
"signing_mode": "ORDINARY_TRANSACTION",
|
||||
"additional_witness_requests": []
|
||||
},
|
||||
"result": {
|
||||
"tx_hash": "1875f1d59a53f1cb4c43949867d72bcfd857fa3b64feb88f41b78ddaa1a21cbf",
|
||||
@ -812,7 +846,9 @@
|
||||
"amount": "1"
|
||||
}
|
||||
],
|
||||
"signing_mode": "ORDINARY_TRANSACTION"
|
||||
"mint": [],
|
||||
"signing_mode": "ORDINARY_TRANSACTION",
|
||||
"additional_witness_requests": []
|
||||
},
|
||||
"result": {
|
||||
"tx_hash": "839a587109358e0aa81b8fb3d5fa74665fac303425ec544a4db7f6ba4e882dff",
|
||||
@ -863,7 +899,9 @@
|
||||
"amount": "1000000"
|
||||
}
|
||||
],
|
||||
"signing_mode": "ORDINARY_TRANSACTION"
|
||||
"mint": [],
|
||||
"signing_mode": "ORDINARY_TRANSACTION",
|
||||
"additional_witness_requests": []
|
||||
},
|
||||
"result": {
|
||||
"tx_hash": "47cf79f20c6c62edb4162b3b232a57afc1bd0b57c7fd8389555276408a004776",
|
||||
@ -918,7 +956,9 @@
|
||||
"amount": "7120787"
|
||||
}
|
||||
],
|
||||
"signing_mode": "ORDINARY_TRANSACTION"
|
||||
"mint": [],
|
||||
"signing_mode": "ORDINARY_TRANSACTION",
|
||||
"additional_witness_requests": []
|
||||
},
|
||||
"result": {
|
||||
"tx_hash": "b7269ddc59e4094a6581c653e0d5dc1e553e3a5fb6ffae47d3d094dff1cfe87b",
|
||||
@ -986,7 +1026,9 @@
|
||||
"amount": "7120787"
|
||||
}
|
||||
],
|
||||
"signing_mode": "ORDINARY_TRANSACTION"
|
||||
"mint": [],
|
||||
"signing_mode": "ORDINARY_TRANSACTION",
|
||||
"additional_witness_requests": []
|
||||
},
|
||||
"result": {
|
||||
"tx_hash": "0b929def7bd9f44f5602f809bc0f9be30521f6b93d625525cf33b956993bfb22",
|
||||
@ -1024,7 +1066,9 @@
|
||||
"amount": "7120787"
|
||||
}
|
||||
],
|
||||
"signing_mode": "ORDINARY_TRANSACTION"
|
||||
"mint": [],
|
||||
"signing_mode": "ORDINARY_TRANSACTION",
|
||||
"additional_witness_requests": []
|
||||
},
|
||||
"result": {
|
||||
"tx_hash": "b621e22f7cb9aac1a70a3362fde88bdfd31fc100e20f3f3c24a7b853536b4f50",
|
||||
@ -1071,7 +1115,9 @@
|
||||
"amount": "7120787"
|
||||
}
|
||||
],
|
||||
"signing_mode": "ORDINARY_TRANSACTION"
|
||||
"mint": [],
|
||||
"signing_mode": "ORDINARY_TRANSACTION",
|
||||
"additional_witness_requests": []
|
||||
},
|
||||
"result": {
|
||||
"tx_hash": "00d393f7fc9a8c17b3efccb44dad9d7e15fdaf2d942a3a455b52b5be016066dd",
|
||||
@ -1120,7 +1166,9 @@
|
||||
"amount": "7120787"
|
||||
}
|
||||
],
|
||||
"signing_mode": "ORDINARY_TRANSACTION"
|
||||
"mint": [],
|
||||
"signing_mode": "ORDINARY_TRANSACTION",
|
||||
"additional_witness_requests": []
|
||||
},
|
||||
"result": {
|
||||
"tx_hash": "f4b7315ec080d05024d1f7bf6795dd234c6624970d8e272a245702de539feaa2",
|
||||
@ -1164,7 +1212,9 @@
|
||||
"amount": "7120787"
|
||||
}
|
||||
],
|
||||
"signing_mode": "ORDINARY_TRANSACTION"
|
||||
"mint": [],
|
||||
"signing_mode": "ORDINARY_TRANSACTION",
|
||||
"additional_witness_requests": []
|
||||
},
|
||||
"result": {
|
||||
"tx_hash": "cabc87a76ad8944e8a97a7cbf9c893a77ed7d1bd963c428c3786d663adb7f0dd",
|
||||
@ -1299,7 +1349,9 @@
|
||||
"nonce": 22634813
|
||||
}
|
||||
},
|
||||
"signing_mode": "ORDINARY_TRANSACTION"
|
||||
"mint": [],
|
||||
"signing_mode": "ORDINARY_TRANSACTION",
|
||||
"additional_witness_requests": []
|
||||
},
|
||||
"result": {
|
||||
"tx_hash": "ee0dfef8b97857ebe7aa8935af50e9f8f608ff4054c0c034600750d722d90631",
|
||||
@ -1335,6 +1387,107 @@
|
||||
"catalyst_signature": "74f27d877bbb4a5fc4f7c56869905c11f70bad0af3de24b23afaa1d024e750930f434ecc4b73e5d1723c2cb8548e8bf6098ac876487b3a6ed0891cb76994d409"
|
||||
}
|
||||
}
|
||||
},
|
||||
{
|
||||
"description": "Ordinary transaction with token minting",
|
||||
"parameters": {
|
||||
"protocol_magic": 764824073,
|
||||
"network_id": 1,
|
||||
"fee": 42,
|
||||
"ttl": 10,
|
||||
"validity_interval_start": 47,
|
||||
"certificates": [],
|
||||
"withdrawals": [],
|
||||
"auxiliary_data": null,
|
||||
"inputs": [
|
||||
{
|
||||
"path": "m/1852'/1815'/0'/0/0",
|
||||
"prev_hash": "3b40265111d8bb3c3c608d95b3a0bf83461ace32d79336579a1939b3aad1c0b7",
|
||||
"prev_index": 0
|
||||
}
|
||||
],
|
||||
"outputs": [
|
||||
{
|
||||
"address": "addr1q84sh2j72ux0l03fxndjnhctdg7hcppsaejafsa84vh7lwgmcs5wgus8qt4atk45lvt4xfxpjtwfhdmvchdf2m3u3hlsd5tq5r",
|
||||
"amount": "2000000",
|
||||
"token_bundle": [
|
||||
{
|
||||
"policy_id": "95a292ffee938be03e9bae5657982a74e9014eb4960108c9e23a5b39",
|
||||
"tokens": [
|
||||
{
|
||||
"asset_name_bytes": "74652474436f696e",
|
||||
"amount": "7878754"
|
||||
}
|
||||
]
|
||||
},
|
||||
{
|
||||
"policy_id": "96a292ffee938be03e9bae5657982a74e9014eb4960108c9e23a5b39",
|
||||
"tokens": [
|
||||
{
|
||||
"asset_name_bytes": "74652474436f696e",
|
||||
"amount": "7878754"
|
||||
},
|
||||
{
|
||||
"asset_name_bytes": "75652474436f696e",
|
||||
"amount": "1234"
|
||||
}
|
||||
]
|
||||
}
|
||||
]
|
||||
}
|
||||
],
|
||||
"mint": [
|
||||
{
|
||||
"policy_id": "95a292ffee938be03e9bae5657982a74e9014eb4960108c9e23a5b39",
|
||||
"tokens": [
|
||||
{
|
||||
"asset_name_bytes": "74652474436f696e",
|
||||
"mint_amount": "7878754"
|
||||
},
|
||||
{
|
||||
"asset_name_bytes": "75652474436f696e",
|
||||
"mint_amount": "-7878754"
|
||||
}
|
||||
]
|
||||
},
|
||||
{
|
||||
"policy_id": "96a292ffee938be03e9bae5657982a74e9014eb4960108c9e23a5b39",
|
||||
"tokens": [
|
||||
{
|
||||
"asset_name_bytes": "74652474436f696e",
|
||||
"mint_amount": "7878754"
|
||||
},
|
||||
{
|
||||
"asset_name_bytes": "75652474436f696e",
|
||||
"mint_amount": "-1234"
|
||||
}
|
||||
]
|
||||
}
|
||||
],
|
||||
"signing_mode": "ORDINARY_TRANSACTION",
|
||||
"additional_witness_requests": [
|
||||
{
|
||||
"path": "m/1855'/1815'/0'"
|
||||
}
|
||||
]
|
||||
},
|
||||
"result": {
|
||||
"tx_hash": "042c1d3a6eab693d2ea6b186a88aed038159e7eb581da80464bca7339fb9afe0",
|
||||
"witnesses": [
|
||||
{
|
||||
"type": 1,
|
||||
"pub_key": "5d010cf16fdeff40955633d6c565f3844a288a24967cf6b76acbeb271b4f13c1",
|
||||
"signature": "ff10637250efa74970675169585720dd5b663c49ecf523ac6214e11a74858f80ec6ef4c86ea66666ec7102fe78c92bcc4e76d50a7bff1fd9660757e94863ba09",
|
||||
"chain_code": null
|
||||
},
|
||||
{
|
||||
"type": 1,
|
||||
"pub_key": "b75258e4f61eb7b313d8554c2fe10673cf214ca2d762bfd53ec3b7846e2ee872",
|
||||
"signature": "d42665ef7855bfe6898b440476ec8967f8ce786a30865a27e0c091b912b8fd87cad2f7d2f1adeb0e2a7201f2ca020a41f48fb982cb3b7f278dab848192d42e0d",
|
||||
"chain_code": null
|
||||
}
|
||||
]
|
||||
}
|
||||
}
|
||||
]
|
||||
}
|
||||
|
319
common/tests/fixtures/cardano/sign_tx.multisig.failed.json
vendored
Normal file
319
common/tests/fixtures/cardano/sign_tx.multisig.failed.json
vendored
Normal file
@ -0,0 +1,319 @@
|
||||
{
|
||||
"setup": {
|
||||
"mnemonic": "all all all all all all all all all all all all",
|
||||
"passphrase": ""
|
||||
},
|
||||
"tests": [
|
||||
{
|
||||
"description": "Multisig transaction with stake registration certificate containing a path",
|
||||
"parameters": {
|
||||
"protocol_magic": 764824073,
|
||||
"network_id": 1,
|
||||
"fee": 42,
|
||||
"ttl": 10,
|
||||
"certificates": [
|
||||
{
|
||||
"type": 0,
|
||||
"path": "m/1852'/1815'/0'/0/0"
|
||||
}
|
||||
],
|
||||
"withdrawals": [],
|
||||
"auxiliary_data": null,
|
||||
"inputs": [
|
||||
{
|
||||
"prev_hash": "3b40265111d8bb3c3c608d95b3a0bf83461ace32d79336579a1939b3aad1c0b7",
|
||||
"prev_index": 0
|
||||
}
|
||||
],
|
||||
"outputs": [
|
||||
{
|
||||
"address": "addr1q84sh2j72ux0l03fxndjnhctdg7hcppsaejafsa84vh7lwgmcs5wgus8qt4atk45lvt4xfxpjtwfhdmvchdf2m3u3hlsd5tq5r",
|
||||
"amount": "1"
|
||||
}
|
||||
],
|
||||
"mint": [],
|
||||
"signing_mode": "MULTISIG_TRANSACTION",
|
||||
"additional_witness_requests": [
|
||||
{
|
||||
"path": "m/1854'/1815'/0'/0/0"
|
||||
}
|
||||
]
|
||||
},
|
||||
"result": {
|
||||
"error_message": "Invalid certificate"
|
||||
}
|
||||
},
|
||||
{
|
||||
"description": "Multisig transaction with stake deregistration certificate containing a path",
|
||||
"parameters": {
|
||||
"protocol_magic": 764824073,
|
||||
"network_id": 1,
|
||||
"fee": 42,
|
||||
"ttl": 10,
|
||||
"certificates": [
|
||||
{
|
||||
"type": 1,
|
||||
"path": "m/1852'/1815'/0'/0/0"
|
||||
}
|
||||
],
|
||||
"withdrawals": [],
|
||||
"auxiliary_data": null,
|
||||
"inputs": [
|
||||
{
|
||||
"prev_hash": "3b40265111d8bb3c3c608d95b3a0bf83461ace32d79336579a1939b3aad1c0b7",
|
||||
"prev_index": 0
|
||||
}
|
||||
],
|
||||
"outputs": [
|
||||
{
|
||||
"address": "addr1q84sh2j72ux0l03fxndjnhctdg7hcppsaejafsa84vh7lwgmcs5wgus8qt4atk45lvt4xfxpjtwfhdmvchdf2m3u3hlsd5tq5r",
|
||||
"amount": "1"
|
||||
}
|
||||
],
|
||||
"mint": [],
|
||||
"signing_mode": "MULTISIG_TRANSACTION",
|
||||
"additional_witness_requests": [
|
||||
{
|
||||
"path": "m/1854'/1815'/0'/0/0"
|
||||
},
|
||||
{
|
||||
"path": "m/1854'/1815'/2'/0/0"
|
||||
}
|
||||
]
|
||||
},
|
||||
"result": {
|
||||
"error_message": "Invalid certificate"
|
||||
}
|
||||
},
|
||||
{
|
||||
"description": "Multisig transaction with stake delegation certificate containing a path",
|
||||
"parameters": {
|
||||
"protocol_magic": 764824073,
|
||||
"network_id": 1,
|
||||
"fee": 42,
|
||||
"ttl": 10,
|
||||
"certificates": [
|
||||
{
|
||||
"type": 2,
|
||||
"path": "m/1852'/1815'/0'/0/0",
|
||||
"pool": "f61c42cbf7c8c53af3f520508212ad3e72f674f957fe23ff0acb4973"
|
||||
}
|
||||
],
|
||||
"withdrawals": [],
|
||||
"auxiliary_data": null,
|
||||
"inputs": [
|
||||
{
|
||||
"prev_hash": "3b40265111d8bb3c3c608d95b3a0bf83461ace32d79336579a1939b3aad1c0b7",
|
||||
"prev_index": 0
|
||||
}
|
||||
],
|
||||
"outputs": [
|
||||
{
|
||||
"address": "addr1q84sh2j72ux0l03fxndjnhctdg7hcppsaejafsa84vh7lwgmcs5wgus8qt4atk45lvt4xfxpjtwfhdmvchdf2m3u3hlsd5tq5r",
|
||||
"amount": "1"
|
||||
}
|
||||
],
|
||||
"mint": [],
|
||||
"signing_mode": "MULTISIG_TRANSACTION",
|
||||
"additional_witness_requests": [
|
||||
{
|
||||
"path": "m/1854'/1815'/0'/0/0"
|
||||
}
|
||||
]
|
||||
},
|
||||
"result": {
|
||||
"error_message": "Invalid certificate"
|
||||
}
|
||||
},
|
||||
{
|
||||
"description": "Multisig transaction with 1852 multisig witness request",
|
||||
"parameters": {
|
||||
"protocol_magic": 764824073,
|
||||
"network_id": 1,
|
||||
"fee": 42,
|
||||
"ttl": 10,
|
||||
"certificates": [],
|
||||
"withdrawals": [],
|
||||
"auxiliary_data": null,
|
||||
"inputs": [
|
||||
{
|
||||
"prev_hash": "3b40265111d8bb3c3c608d95b3a0bf83461ace32d79336579a1939b3aad1c0b7",
|
||||
"prev_index": 0
|
||||
}
|
||||
],
|
||||
"outputs": [
|
||||
{
|
||||
"address": "addr1q84sh2j72ux0l03fxndjnhctdg7hcppsaejafsa84vh7lwgmcs5wgus8qt4atk45lvt4xfxpjtwfhdmvchdf2m3u3hlsd5tq5r",
|
||||
"amount": "1"
|
||||
}
|
||||
],
|
||||
"mint": [],
|
||||
"signing_mode": "MULTISIG_TRANSACTION",
|
||||
"additional_witness_requests": [
|
||||
{
|
||||
"path": "m/1852'/1815'/0'/0/0"
|
||||
}
|
||||
]
|
||||
},
|
||||
"result": {
|
||||
"error_message": "Invalid witness request"
|
||||
}
|
||||
},
|
||||
{
|
||||
"description": "Multisig transaction with output containing address parameters",
|
||||
"parameters": {
|
||||
"protocol_magic": 764824073,
|
||||
"network_id": 1,
|
||||
"fee": 42,
|
||||
"ttl": 10,
|
||||
"certificates": [],
|
||||
"withdrawals": [],
|
||||
"auxiliary_data": null,
|
||||
"inputs": [
|
||||
{
|
||||
"prev_hash": "3b40265111d8bb3c3c608d95b3a0bf83461ace32d79336579a1939b3aad1c0b7",
|
||||
"prev_index": 0
|
||||
}
|
||||
],
|
||||
"outputs": [
|
||||
{
|
||||
"addressType": 0,
|
||||
"path": "m/1852'/1815'/0'/0/0",
|
||||
"stakingPath": "m/1852'/1815'/0'/2/0",
|
||||
"amount": "7120787"
|
||||
}
|
||||
],
|
||||
"mint": [],
|
||||
"signing_mode": "MULTISIG_TRANSACTION",
|
||||
"additional_witness_requests": [
|
||||
{
|
||||
"path": "m/1854'/1815'/0'/0/0"
|
||||
}
|
||||
]
|
||||
},
|
||||
"result": {
|
||||
"error_message": "Invalid output"
|
||||
}
|
||||
},
|
||||
{
|
||||
"description": "Multisig transaction without minting but with a 1855 additional witness request",
|
||||
"parameters": {
|
||||
"protocol_magic": 764824073,
|
||||
"network_id": 1,
|
||||
"fee": 42,
|
||||
"ttl": 10,
|
||||
"certificates": [],
|
||||
"withdrawals": [],
|
||||
"auxiliary_data": null,
|
||||
"inputs": [
|
||||
{
|
||||
"prev_hash": "3b40265111d8bb3c3c608d95b3a0bf83461ace32d79336579a1939b3aad1c0b7",
|
||||
"prev_index": 0
|
||||
}
|
||||
],
|
||||
"outputs": [
|
||||
{
|
||||
"address": "addr1q84sh2j72ux0l03fxndjnhctdg7hcppsaejafsa84vh7lwgmcs5wgus8qt4atk45lvt4xfxpjtwfhdmvchdf2m3u3hlsd5tq5r",
|
||||
"amount": "1"
|
||||
}
|
||||
],
|
||||
"mint": [],
|
||||
"signing_mode": "MULTISIG_TRANSACTION",
|
||||
"additional_witness_requests": [
|
||||
{
|
||||
"path": "m/1855'/1815'/0'"
|
||||
}
|
||||
]
|
||||
},
|
||||
"result": {
|
||||
"error_message": "Invalid witness request"
|
||||
}
|
||||
},
|
||||
{
|
||||
"description": "Multisig transaction with long token minting path",
|
||||
"parameters": {
|
||||
"protocol_magic": 764824073,
|
||||
"network_id": 1,
|
||||
"fee": 42,
|
||||
"ttl": 10,
|
||||
"validity_interval_start": 47,
|
||||
"certificates": [],
|
||||
"withdrawals": [],
|
||||
"auxiliary_data": null,
|
||||
"inputs": [
|
||||
{
|
||||
"prev_hash": "3b40265111d8bb3c3c608d95b3a0bf83461ace32d79336579a1939b3aad1c0b7",
|
||||
"prev_index": 0
|
||||
}
|
||||
],
|
||||
"outputs": [
|
||||
{
|
||||
"address": "addr1q84sh2j72ux0l03fxndjnhctdg7hcppsaejafsa84vh7lwgmcs5wgus8qt4atk45lvt4xfxpjtwfhdmvchdf2m3u3hlsd5tq5r",
|
||||
"amount": "2000000",
|
||||
"token_bundle": [
|
||||
{
|
||||
"policy_id": "95a292ffee938be03e9bae5657982a74e9014eb4960108c9e23a5b39",
|
||||
"tokens": [
|
||||
{
|
||||
"asset_name_bytes": "74652474436f696e",
|
||||
"amount": "7878754"
|
||||
}
|
||||
]
|
||||
},
|
||||
{
|
||||
"policy_id": "96a292ffee938be03e9bae5657982a74e9014eb4960108c9e23a5b39",
|
||||
"tokens": [
|
||||
{
|
||||
"asset_name_bytes": "74652474436f696e",
|
||||
"amount": "7878754"
|
||||
},
|
||||
{
|
||||
"asset_name_bytes": "75652474436f696e",
|
||||
"amount": "1234"
|
||||
}
|
||||
]
|
||||
}
|
||||
]
|
||||
}
|
||||
],
|
||||
"mint": [
|
||||
{
|
||||
"policy_id": "95a292ffee938be03e9bae5657982a74e9014eb4960108c9e23a5b39",
|
||||
"tokens": [
|
||||
{
|
||||
"asset_name_bytes": "74652474436f696e",
|
||||
"mint_amount": "7878754"
|
||||
},
|
||||
{
|
||||
"asset_name_bytes": "75652474436f696e",
|
||||
"mint_amount": "-7878754"
|
||||
}
|
||||
]
|
||||
},
|
||||
{
|
||||
"policy_id": "96a292ffee938be03e9bae5657982a74e9014eb4960108c9e23a5b39",
|
||||
"tokens": [
|
||||
{
|
||||
"asset_name_bytes": "74652474436f696e",
|
||||
"mint_amount": "7878754"
|
||||
},
|
||||
{
|
||||
"asset_name_bytes": "75652474436f696e",
|
||||
"mint_amount": "-1234"
|
||||
}
|
||||
]
|
||||
}
|
||||
],
|
||||
"signing_mode": "MULTISIG_TRANSACTION",
|
||||
"additional_witness_requests": [
|
||||
{
|
||||
"path": "m/1855'/1815'/0'/0/0"
|
||||
}
|
||||
]
|
||||
},
|
||||
"result": {
|
||||
"error_message": "Invalid witness request"
|
||||
}
|
||||
}
|
||||
]
|
||||
}
|
443
common/tests/fixtures/cardano/sign_tx.multisig.json
vendored
Normal file
443
common/tests/fixtures/cardano/sign_tx.multisig.json
vendored
Normal file
@ -0,0 +1,443 @@
|
||||
{
|
||||
"setup": {
|
||||
"mnemonic": "all all all all all all all all all all all all",
|
||||
"passphrase": ""
|
||||
},
|
||||
"tests": [
|
||||
{
|
||||
"description": "Multisig transaction with token minting",
|
||||
"parameters": {
|
||||
"protocol_magic": 764824073,
|
||||
"network_id": 1,
|
||||
"fee": 42,
|
||||
"ttl": 10,
|
||||
"validity_interval_start": 47,
|
||||
"certificates": [],
|
||||
"withdrawals": [],
|
||||
"auxiliary_data": null,
|
||||
"inputs": [
|
||||
{
|
||||
"prev_hash": "3b40265111d8bb3c3c608d95b3a0bf83461ace32d79336579a1939b3aad1c0b7",
|
||||
"prev_index": 0
|
||||
}
|
||||
],
|
||||
"outputs": [
|
||||
{
|
||||
"address": "addr1q84sh2j72ux0l03fxndjnhctdg7hcppsaejafsa84vh7lwgmcs5wgus8qt4atk45lvt4xfxpjtwfhdmvchdf2m3u3hlsd5tq5r",
|
||||
"amount": "2000000",
|
||||
"token_bundle": [
|
||||
{
|
||||
"policy_id": "95a292ffee938be03e9bae5657982a74e9014eb4960108c9e23a5b39",
|
||||
"tokens": [
|
||||
{
|
||||
"asset_name_bytes": "74652474436f696e",
|
||||
"amount": "7878754"
|
||||
}
|
||||
]
|
||||
},
|
||||
{
|
||||
"policy_id": "96a292ffee938be03e9bae5657982a74e9014eb4960108c9e23a5b39",
|
||||
"tokens": [
|
||||
{
|
||||
"asset_name_bytes": "74652474436f696e",
|
||||
"amount": "7878754"
|
||||
},
|
||||
{
|
||||
"asset_name_bytes": "75652474436f696e",
|
||||
"amount": "1234"
|
||||
}
|
||||
]
|
||||
}
|
||||
]
|
||||
}
|
||||
],
|
||||
"mint": [
|
||||
{
|
||||
"policy_id": "95a292ffee938be03e9bae5657982a74e9014eb4960108c9e23a5b39",
|
||||
"tokens": [
|
||||
{
|
||||
"asset_name_bytes": "74652474436f696e",
|
||||
"mint_amount": "7878754"
|
||||
},
|
||||
{
|
||||
"asset_name_bytes": "75652474436f696e",
|
||||
"mint_amount": "-7878754"
|
||||
}
|
||||
]
|
||||
},
|
||||
{
|
||||
"policy_id": "96a292ffee938be03e9bae5657982a74e9014eb4960108c9e23a5b39",
|
||||
"tokens": [
|
||||
{
|
||||
"asset_name_bytes": "74652474436f696e",
|
||||
"mint_amount": "7878754"
|
||||
},
|
||||
{
|
||||
"asset_name_bytes": "75652474436f696e",
|
||||
"mint_amount": "-1234"
|
||||
}
|
||||
]
|
||||
}
|
||||
],
|
||||
"signing_mode": "MULTISIG_TRANSACTION",
|
||||
"additional_witness_requests": [
|
||||
{
|
||||
"path": "m/1854'/1815'/0'/0/0"
|
||||
},
|
||||
{
|
||||
"path": "m/1855'/1815'/0'"
|
||||
}
|
||||
]
|
||||
},
|
||||
"result": {
|
||||
"tx_hash": "042c1d3a6eab693d2ea6b186a88aed038159e7eb581da80464bca7339fb9afe0",
|
||||
"witnesses": [
|
||||
{
|
||||
"type": 1,
|
||||
"pub_key": "b10be5c0d11ad8292bbe69e220ca0cfbe154610b3041a8e72f9d515c226ab3b1",
|
||||
"signature": "ef08436c998df4fd4aade2ce240d92d8851783b688a949c167aa070e885ffb592943767ddae0b826265a307405cf9865b6f66fbfa2e5a39797950104b7b13d0d",
|
||||
"chain_code": null
|
||||
},
|
||||
{
|
||||
"type": 1,
|
||||
"pub_key": "b75258e4f61eb7b313d8554c2fe10673cf214ca2d762bfd53ec3b7846e2ee872",
|
||||
"signature": "d42665ef7855bfe6898b440476ec8967f8ce786a30865a27e0c091b912b8fd87cad2f7d2f1adeb0e2a7201f2ca020a41f48fb982cb3b7f278dab848192d42e0d",
|
||||
"chain_code": null
|
||||
}
|
||||
]
|
||||
}
|
||||
},
|
||||
{
|
||||
"description": "Multisig transaction with stake registration certificate",
|
||||
"parameters": {
|
||||
"protocol_magic": 764824073,
|
||||
"network_id": 1,
|
||||
"fee": 42,
|
||||
"ttl": 10,
|
||||
"certificates": [
|
||||
{
|
||||
"type": 0,
|
||||
"script_hash": "29fb5fd4aa8cadd6705acc8263cee0fc62edca5ac38db593fec2f9fd"
|
||||
}
|
||||
],
|
||||
"withdrawals": [],
|
||||
"auxiliary_data": null,
|
||||
"inputs": [
|
||||
{
|
||||
"prev_hash": "3b40265111d8bb3c3c608d95b3a0bf83461ace32d79336579a1939b3aad1c0b7",
|
||||
"prev_index": 0
|
||||
}
|
||||
],
|
||||
"outputs": [
|
||||
{
|
||||
"address": "addr1q84sh2j72ux0l03fxndjnhctdg7hcppsaejafsa84vh7lwgmcs5wgus8qt4atk45lvt4xfxpjtwfhdmvchdf2m3u3hlsd5tq5r",
|
||||
"amount": "1"
|
||||
}
|
||||
],
|
||||
"mint": [],
|
||||
"signing_mode": "MULTISIG_TRANSACTION",
|
||||
"additional_witness_requests": [
|
||||
{
|
||||
"path": "m/1854'/1815'/0'/0/0"
|
||||
}
|
||||
]
|
||||
},
|
||||
"result": {
|
||||
"tx_hash": "ed9fc2755091fa72b58e9dd06db05cce87c0c6f3962f587d5fc348fe478f0752",
|
||||
"witnesses": [
|
||||
{
|
||||
"type": 1,
|
||||
"pub_key": "b10be5c0d11ad8292bbe69e220ca0cfbe154610b3041a8e72f9d515c226ab3b1",
|
||||
"signature": "dccfcce8a2a17673c0e465a60a334eabbe326127d3dd04b727702ea486ed7c231259353c0890cfcb8209169eda7a139aeec42c77ce87231b0b9c250efb64450e",
|
||||
"chain_code": null
|
||||
}
|
||||
]
|
||||
}
|
||||
},
|
||||
{
|
||||
"description": "Multisig transaction with stake registration and stake delegation certificates",
|
||||
"parameters": {
|
||||
"protocol_magic": 764824073,
|
||||
"network_id": 1,
|
||||
"fee": 42,
|
||||
"ttl": 10,
|
||||
"certificates": [
|
||||
{
|
||||
"type": 0,
|
||||
"script_hash": "29fb5fd4aa8cadd6705acc8263cee0fc62edca5ac38db593fec2f9fd"
|
||||
},
|
||||
{
|
||||
"type": 2,
|
||||
"pool": "f61c42cbf7c8c53af3f520508212ad3e72f674f957fe23ff0acb4973",
|
||||
"script_hash": "29fb5fd4aa8cadd6705acc8263cee0fc62edca5ac38db593fec2f9fd"
|
||||
}
|
||||
],
|
||||
"withdrawals": [],
|
||||
"auxiliary_data": null,
|
||||
"inputs": [
|
||||
{
|
||||
"prev_hash": "3b40265111d8bb3c3c608d95b3a0bf83461ace32d79336579a1939b3aad1c0b7",
|
||||
"prev_index": 0
|
||||
}
|
||||
],
|
||||
"outputs": [
|
||||
{
|
||||
"address": "addr1q84sh2j72ux0l03fxndjnhctdg7hcppsaejafsa84vh7lwgmcs5wgus8qt4atk45lvt4xfxpjtwfhdmvchdf2m3u3hlsd5tq5r",
|
||||
"amount": "1"
|
||||
}
|
||||
],
|
||||
"mint": [],
|
||||
"signing_mode": "MULTISIG_TRANSACTION",
|
||||
"additional_witness_requests": [
|
||||
{
|
||||
"path": "m/1854'/1815'/0'/0/0"
|
||||
},
|
||||
{
|
||||
"path": "m/1854'/1815'/0'/2/0"
|
||||
}
|
||||
]
|
||||
},
|
||||
"result": {
|
||||
"tx_hash": "26fb07b23368898665829283985ffe6c4cb2ec13758e83f467b78e5061f9619b",
|
||||
"witnesses": [
|
||||
{
|
||||
"type": 1,
|
||||
"pub_key": "b10be5c0d11ad8292bbe69e220ca0cfbe154610b3041a8e72f9d515c226ab3b1",
|
||||
"signature": "c3fc7aae0a78b3b888f68775da3b9ba1e5478f2003e8c1f0b558172acd23205f2652e7e021f5041a4a1a785fad4f711ca80a9b39afd2939644d4da47d86f7b05",
|
||||
"chain_code": null
|
||||
},
|
||||
{
|
||||
"type": 1,
|
||||
"pub_key": "f2ef4ecd21ad28a8d270ca7be7e96c87f60dc821e13c0d0c5870344e9693637c",
|
||||
"signature": "982247b7a3a3625eaae74d4710f0d9a9b4bae6f0e201c31544f056ad3d7e5940e477cedf3f83fa0e37152e5f97585d910296e95395677dee047e204864187f09",
|
||||
"chain_code": null
|
||||
}
|
||||
]
|
||||
}
|
||||
},
|
||||
{
|
||||
"description": "Multisig transaction with stake deregistration",
|
||||
"parameters": {
|
||||
"protocol_magic": 764824073,
|
||||
"network_id": 1,
|
||||
"fee": 42,
|
||||
"ttl": 10,
|
||||
"certificates": [
|
||||
{
|
||||
"type": 1,
|
||||
"script_hash": "29fb5fd4aa8cadd6705acc8263cee0fc62edca5ac38db593fec2f9fd"
|
||||
}
|
||||
],
|
||||
"withdrawals": [],
|
||||
"auxiliary_data": null,
|
||||
"inputs": [
|
||||
{
|
||||
"prev_hash": "3b40265111d8bb3c3c608d95b3a0bf83461ace32d79336579a1939b3aad1c0b7",
|
||||
"prev_index": 0
|
||||
}
|
||||
],
|
||||
"outputs": [
|
||||
{
|
||||
"address": "addr1q84sh2j72ux0l03fxndjnhctdg7hcppsaejafsa84vh7lwgmcs5wgus8qt4atk45lvt4xfxpjtwfhdmvchdf2m3u3hlsd5tq5r",
|
||||
"amount": "1"
|
||||
}
|
||||
],
|
||||
"mint": [],
|
||||
"signing_mode": "MULTISIG_TRANSACTION",
|
||||
"additional_witness_requests": [
|
||||
{
|
||||
"path": "m/1854'/1815'/0'/0/0"
|
||||
},
|
||||
{
|
||||
"path": "m/1854'/1815'/0'/2/0"
|
||||
}
|
||||
]
|
||||
},
|
||||
"result": {
|
||||
"tx_hash": "c4e70484c964eca910219047542632ac9a9ac81f11f5d5afd8bb1b0ef4366d69",
|
||||
"witnesses": [
|
||||
{
|
||||
"type": 1,
|
||||
"pub_key": "b10be5c0d11ad8292bbe69e220ca0cfbe154610b3041a8e72f9d515c226ab3b1",
|
||||
"signature": "059fa17fb8e8302083d110ec4587d6ce80b3bc15baa75e0a2d449df190ce462d0e6ebc67d96f74fa6ce0b149714d1ef24f40c24846fef9d58405c6e2287e540b",
|
||||
"chain_code": null
|
||||
},
|
||||
{
|
||||
"type": 1,
|
||||
"pub_key": "f2ef4ecd21ad28a8d270ca7be7e96c87f60dc821e13c0d0c5870344e9693637c",
|
||||
"signature": "dc51848d3257f8f6783d6a53736ba638bc62c7098e5ec6d4d2b313520c78c689942f6e2542ba2b6b9749b7a57d4c8658c84fbc5b1e2847159eb0c256298bcd01",
|
||||
"chain_code": null
|
||||
}
|
||||
]
|
||||
}
|
||||
},
|
||||
{
|
||||
"description": "Multisig transaction with stake deregistration and withdrawal",
|
||||
"parameters": {
|
||||
"protocol_magic": 764824073,
|
||||
"network_id": 1,
|
||||
"fee": 42,
|
||||
"ttl": 10,
|
||||
"certificates": [
|
||||
{
|
||||
"type": 1,
|
||||
"script_hash": "29fb5fd4aa8cadd6705acc8263cee0fc62edca5ac38db593fec2f9fd"
|
||||
}
|
||||
],
|
||||
"withdrawals": [
|
||||
{
|
||||
"amount": "1000",
|
||||
"script_hash": "29fb5fd4aa8cadd6705acc8263cee0fc62edca5ac38db593fec2f9fd"
|
||||
}
|
||||
],
|
||||
"auxiliary_data": null,
|
||||
"inputs": [
|
||||
{
|
||||
"prev_hash": "3b40265111d8bb3c3c608d95b3a0bf83461ace32d79336579a1939b3aad1c0b7",
|
||||
"prev_index": 0
|
||||
}
|
||||
],
|
||||
"outputs": [
|
||||
{
|
||||
"address": "addr1q84sh2j72ux0l03fxndjnhctdg7hcppsaejafsa84vh7lwgmcs5wgus8qt4atk45lvt4xfxpjtwfhdmvchdf2m3u3hlsd5tq5r",
|
||||
"amount": "1"
|
||||
}
|
||||
],
|
||||
"mint": [],
|
||||
"signing_mode": "MULTISIG_TRANSACTION",
|
||||
"additional_witness_requests": [
|
||||
{
|
||||
"path": "m/1854'/1815'/0'/0/0"
|
||||
},
|
||||
{
|
||||
"path": "m/1854'/1815'/0'/2/0"
|
||||
}
|
||||
]
|
||||
},
|
||||
"result": {
|
||||
"tx_hash": "e02d252c5cad2a4d8f163069cd7f0822c7876d16af9ad8ac2d461655812b2d1b",
|
||||
"witnesses": [
|
||||
{
|
||||
"type": 1,
|
||||
"pub_key": "b10be5c0d11ad8292bbe69e220ca0cfbe154610b3041a8e72f9d515c226ab3b1",
|
||||
"signature": "882994b27b1886a2f7ae3b42e08f3ce2c9c5b7d82e467135e0069f396a18f89696e882dbeadce0b3af8a10edbfb55057e6909e8232ac0107cc4fbf647493720b",
|
||||
"chain_code": null
|
||||
},
|
||||
{
|
||||
"type": 1,
|
||||
"pub_key": "f2ef4ecd21ad28a8d270ca7be7e96c87f60dc821e13c0d0c5870344e9693637c",
|
||||
"signature": "cc119eb4e7f27d5c316a5d1301850a2f3e4d08c267d5422cae8e4f00178a55d053a2288ed0a55fc8ec05bd8c1cd5fee5a713da85d489a2a02ac273866e36ae06",
|
||||
"chain_code": null
|
||||
}
|
||||
]
|
||||
}
|
||||
},
|
||||
{
|
||||
"description": "Multisig transaction with most elements filled and shared with Ledger",
|
||||
"parameters": {
|
||||
"protocol_magic": 764824073,
|
||||
"network_id": 1,
|
||||
"fee": 42,
|
||||
"ttl": 10,
|
||||
"validity_interval_start": 47,
|
||||
"certificates": [
|
||||
{
|
||||
"type": 0,
|
||||
"script_hash": "29fb5fd4aa8cadd6705acc8263cee0fc62edca5ac38db593fec2f9fd"
|
||||
},
|
||||
{
|
||||
"type": 1,
|
||||
"script_hash": "29fb5fd4aa8cadd6705acc8263cee0fc62edca5ac38db593fec2f9fd"
|
||||
},
|
||||
{
|
||||
"type": 2,
|
||||
"script_hash": "29fb5fd4aa8cadd6705acc8263cee0fc62edca5ac38db593fec2f9fd",
|
||||
"pool": "f61c42cbf7c8c53af3f520508212ad3e72f674f957fe23ff0acb4973"
|
||||
}
|
||||
],
|
||||
"withdrawals": [
|
||||
{
|
||||
"amount": "1000",
|
||||
"script_hash": "29fb5fd4aa8cadd6705acc8263cee0fc62edca5ac38db593fec2f9fd"
|
||||
}
|
||||
],
|
||||
"auxiliary_data": {
|
||||
"hash": "58ec01578fcdfdc376f09631a7b2adc608eaf57e3720484c7ff37c13cff90fdf"
|
||||
},
|
||||
"inputs": [
|
||||
{
|
||||
"prev_hash": "3b40265111d8bb3c3c608d95b3a0bf83461ace32d79336579a1939b3aad1c0b7",
|
||||
"prev_index": 0
|
||||
}
|
||||
],
|
||||
"outputs": [
|
||||
{
|
||||
"address": "addr1q84sh2j72ux0l03fxndjnhctdg7hcppsaejafsa84vh7lwgmcs5wgus8qt4atk45lvt4xfxpjtwfhdmvchdf2m3u3hlsd5tq5r",
|
||||
"amount": "2000000",
|
||||
"token_bundle": [
|
||||
{
|
||||
"policy_id": "0d63e8d2c5a00cbcffbdf9112487c443466e1ea7d8c834df5ac5c425",
|
||||
"tokens": [
|
||||
{
|
||||
"asset_name_bytes": "74657374436f696e",
|
||||
"amount": "7878754"
|
||||
}
|
||||
]
|
||||
}
|
||||
]
|
||||
}
|
||||
],
|
||||
"mint": [
|
||||
{
|
||||
"policy_id": "0d63e8d2c5a00cbcffbdf9112487c443466e1ea7d8c834df5ac5c425",
|
||||
"tokens": [
|
||||
{
|
||||
"asset_name_bytes": "74657374436f696e",
|
||||
"mint_amount": "7878754"
|
||||
},
|
||||
{
|
||||
"asset_name_bytes": "75657374436f696e",
|
||||
"mint_amount": "-7878754"
|
||||
}
|
||||
]
|
||||
}
|
||||
],
|
||||
"signing_mode": "MULTISIG_TRANSACTION",
|
||||
"additional_witness_requests": [
|
||||
{
|
||||
"path": "m/1854'/1815'/0'/0/0"
|
||||
},
|
||||
{
|
||||
"path": "m/1854'/1815'/0'/2/0"
|
||||
},
|
||||
{
|
||||
"path": "m/1855'/1815'/0'"
|
||||
}
|
||||
]
|
||||
},
|
||||
"result": {
|
||||
"tx_hash": "2be64c04ea3f5bac3c224ec47a4157ade91fc6ab4fd6b83ce3d57b2e9186720b",
|
||||
"witnesses": [
|
||||
{
|
||||
"type": 1,
|
||||
"pub_key": "b10be5c0d11ad8292bbe69e220ca0cfbe154610b3041a8e72f9d515c226ab3b1",
|
||||
"signature": "38a56a46b21caef91742ffafdec202ed96809c3070c9bfd51db5c750d77edbfb8514d9cd2255ab5a857dd8a63706ae0ca29e390fba6af7a906b186aed117b809",
|
||||
"chain_code": null
|
||||
},
|
||||
{
|
||||
"type": 1,
|
||||
"pub_key": "f2ef4ecd21ad28a8d270ca7be7e96c87f60dc821e13c0d0c5870344e9693637c",
|
||||
"signature": "0c9071c421fe207ac1d9102643eac8ddf5ff29238782956b5706b9f1f084dfc5c087b4ceda6d079f8bb6438d3b556d3ac97565a87a8ec33f11856408b0480400",
|
||||
"chain_code": null
|
||||
},
|
||||
{
|
||||
"type": 1,
|
||||
"pub_key": "b75258e4f61eb7b313d8554c2fe10673cf214ca2d762bfd53ec3b7846e2ee872",
|
||||
"signature": "85bf1bc71c04c72ae8184885b9d5eadd49b2c27bd332a42bc42c35b49429509350795bbdb716a95946b7c30cb62f20e1d39e4be3df5625a141f3e3c2e3526e02",
|
||||
"chain_code": null
|
||||
}
|
||||
]
|
||||
}
|
||||
}
|
||||
]
|
||||
}
|
@ -31,7 +31,9 @@
|
||||
"amount": "3003112"
|
||||
}
|
||||
],
|
||||
"signing_mode": "ORDINARY_TRANSACTION"
|
||||
"mint": [],
|
||||
"signing_mode": "ORDINARY_TRANSACTION",
|
||||
"additional_witness_requests": []
|
||||
},
|
||||
"result": {
|
||||
"tx_hash": "73e09bdebf98a9e0f17f86a2d11e0f14f4f8dae77cdf26ff1678e821f20c8db6",
|
||||
@ -73,7 +75,9 @@
|
||||
"amount": "1000000"
|
||||
}
|
||||
],
|
||||
"signing_mode": "ORDINARY_TRANSACTION"
|
||||
"mint": [],
|
||||
"signing_mode": "ORDINARY_TRANSACTION",
|
||||
"additional_witness_requests": []
|
||||
},
|
||||
"result": {
|
||||
"tx_hash": "4c43ce4c72f145b145ae7add414722735e250d048f61c4585a5becafcbffa6ae",
|
||||
@ -115,7 +119,9 @@
|
||||
"amount": "1000000"
|
||||
}
|
||||
],
|
||||
"signing_mode": "ORDINARY_TRANSACTION"
|
||||
"mint": [],
|
||||
"signing_mode": "ORDINARY_TRANSACTION",
|
||||
"additional_witness_requests": []
|
||||
},
|
||||
"result": {
|
||||
"tx_hash": "93a2c3cfb67ef1e4bae167b0f443c3370664bdb9171bc9cd41bad98e5cc049b2",
|
||||
|
@ -48,7 +48,9 @@
|
||||
"amount": "1"
|
||||
}
|
||||
],
|
||||
"signing_mode": "POOL_REGISTRATION_AS_OWNER"
|
||||
"mint": [],
|
||||
"signing_mode": "POOL_REGISTRATION_AS_OWNER",
|
||||
"additional_witness_requests": []
|
||||
},
|
||||
"result": {
|
||||
"error_message": "Invalid certificate"
|
||||
@ -101,7 +103,9 @@
|
||||
"amount": "1"
|
||||
}
|
||||
],
|
||||
"signing_mode": "POOL_REGISTRATION_AS_OWNER"
|
||||
"mint": [],
|
||||
"signing_mode": "POOL_REGISTRATION_AS_OWNER",
|
||||
"additional_witness_requests": []
|
||||
},
|
||||
"result": {
|
||||
"error_message": "Invalid certificate"
|
||||
@ -151,7 +155,9 @@
|
||||
"amount": "1"
|
||||
}
|
||||
],
|
||||
"signing_mode": "POOL_REGISTRATION_AS_OWNER"
|
||||
"mint": [],
|
||||
"signing_mode": "POOL_REGISTRATION_AS_OWNER",
|
||||
"additional_witness_requests": []
|
||||
},
|
||||
"result": {
|
||||
"error_message": "Invalid certificate"
|
||||
@ -201,7 +207,9 @@
|
||||
"amount": "1"
|
||||
}
|
||||
],
|
||||
"signing_mode": "POOL_REGISTRATION_AS_OWNER"
|
||||
"mint": [],
|
||||
"signing_mode": "POOL_REGISTRATION_AS_OWNER",
|
||||
"additional_witness_requests": []
|
||||
},
|
||||
"result": {
|
||||
"error_message": "Invalid certificate"
|
||||
@ -272,10 +280,12 @@
|
||||
"amount": "1"
|
||||
}
|
||||
],
|
||||
"signing_mode": "POOL_REGISTRATION_AS_OWNER"
|
||||
"mint": [],
|
||||
"signing_mode": "POOL_REGISTRATION_AS_OWNER",
|
||||
"additional_witness_requests": []
|
||||
},
|
||||
"result": {
|
||||
"error_message": "Stakepool registration transaction cannot contain other certificates nor withdrawals"
|
||||
"error_message": "Stakepool registration transaction cannot contain other certificates, withdrawals or minting"
|
||||
}
|
||||
},
|
||||
{
|
||||
@ -305,7 +315,9 @@
|
||||
"amount": "1"
|
||||
}
|
||||
],
|
||||
"signing_mode": "POOL_REGISTRATION_AS_OWNER"
|
||||
"mint": [],
|
||||
"signing_mode": "POOL_REGISTRATION_AS_OWNER",
|
||||
"additional_witness_requests": []
|
||||
},
|
||||
"result": {
|
||||
"error_message": "Invalid certificate"
|
||||
@ -360,10 +372,12 @@
|
||||
"amount": "1"
|
||||
}
|
||||
],
|
||||
"signing_mode": "POOL_REGISTRATION_AS_OWNER"
|
||||
"mint": [],
|
||||
"signing_mode": "POOL_REGISTRATION_AS_OWNER",
|
||||
"additional_witness_requests": []
|
||||
},
|
||||
"result": {
|
||||
"error_message": "Stakepool registration transaction cannot contain other certificates nor withdrawals"
|
||||
"error_message": "Stakepool registration transaction cannot contain other certificates, withdrawals or minting"
|
||||
}
|
||||
},
|
||||
{
|
||||
@ -410,7 +424,9 @@
|
||||
"amount": "1"
|
||||
}
|
||||
],
|
||||
"signing_mode": "POOL_REGISTRATION_AS_OWNER"
|
||||
"mint": [],
|
||||
"signing_mode": "POOL_REGISTRATION_AS_OWNER",
|
||||
"additional_witness_requests": []
|
||||
},
|
||||
"result": {
|
||||
"error_message": "Stakepool registration transaction can only contain staking witnesses"
|
||||
@ -459,7 +475,9 @@
|
||||
"amount": "1"
|
||||
}
|
||||
],
|
||||
"signing_mode": "POOL_REGISTRATION_AS_OWNER"
|
||||
"mint": [],
|
||||
"signing_mode": "POOL_REGISTRATION_AS_OWNER",
|
||||
"additional_witness_requests": []
|
||||
},
|
||||
"result": {
|
||||
"error_message": "ProcessError: Invalid address"
|
||||
@ -508,7 +526,9 @@
|
||||
"amount": "1"
|
||||
}
|
||||
],
|
||||
"signing_mode": "POOL_REGISTRATION_AS_OWNER"
|
||||
"mint": [],
|
||||
"signing_mode": "POOL_REGISTRATION_AS_OWNER",
|
||||
"additional_witness_requests": []
|
||||
},
|
||||
"result": {
|
||||
"error_message": "ProcessError: Invalid address"
|
||||
@ -591,7 +611,9 @@
|
||||
"amount": "1"
|
||||
}
|
||||
],
|
||||
"signing_mode": "POOL_REGISTRATION_AS_OWNER"
|
||||
"mint": [],
|
||||
"signing_mode": "POOL_REGISTRATION_AS_OWNER",
|
||||
"additional_witness_requests": []
|
||||
},
|
||||
"result": {
|
||||
"error_message": "Invalid pool owner staking path"
|
||||
@ -674,11 +696,394 @@
|
||||
"amount": "1"
|
||||
}
|
||||
],
|
||||
"signing_mode": "ORDINARY_TRANSACTION"
|
||||
"mint": [],
|
||||
"signing_mode": "ORDINARY_TRANSACTION",
|
||||
"additional_witness_requests": []
|
||||
},
|
||||
"result": {
|
||||
"error_message": "Invalid certificate"
|
||||
}
|
||||
},
|
||||
{
|
||||
"description": "Sample stake pool registration certificate with 1854 additional witness request",
|
||||
"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": null,
|
||||
"inputs": [
|
||||
{
|
||||
"path": null,
|
||||
"prev_hash": "3b40265111d8bb3c3c608d95b3a0bf83461ace32d79336579a1939b3aad1c0b7",
|
||||
"prev_index": 0
|
||||
}
|
||||
],
|
||||
"outputs": [
|
||||
{
|
||||
"address": "addr1q84sh2j72ux0l03fxndjnhctdg7hcppsaejafsa84vh7lwgmcs5wgus8qt4atk45lvt4xfxpjtwfhdmvchdf2m3u3hlsd5tq5r",
|
||||
"amount": "1"
|
||||
}
|
||||
],
|
||||
"mint": [],
|
||||
"signing_mode": "POOL_REGISTRATION_AS_OWNER",
|
||||
"additional_witness_requests": [
|
||||
{
|
||||
"path": "m/1854'/1815'/0'/0/0"
|
||||
}
|
||||
]
|
||||
},
|
||||
"result": {
|
||||
"error_message": "Stakepool registration transaction can only contain staking witnesses"
|
||||
}
|
||||
},
|
||||
{
|
||||
"description": "Sample stake pool registration certificate with 1855 additional witness request",
|
||||
"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": null,
|
||||
"inputs": [
|
||||
{
|
||||
"path": null,
|
||||
"prev_hash": "3b40265111d8bb3c3c608d95b3a0bf83461ace32d79336579a1939b3aad1c0b7",
|
||||
"prev_index": 0
|
||||
}
|
||||
],
|
||||
"outputs": [
|
||||
{
|
||||
"address": "addr1q84sh2j72ux0l03fxndjnhctdg7hcppsaejafsa84vh7lwgmcs5wgus8qt4atk45lvt4xfxpjtwfhdmvchdf2m3u3hlsd5tq5r",
|
||||
"amount": "1"
|
||||
}
|
||||
],
|
||||
"mint": [],
|
||||
"signing_mode": "POOL_REGISTRATION_AS_OWNER",
|
||||
"additional_witness_requests": [
|
||||
{
|
||||
"path": "m/1855'/1815'/0'/0/0"
|
||||
}
|
||||
]
|
||||
},
|
||||
"result": {
|
||||
"error_message": "Stakepool registration transaction can only contain staking witnesses"
|
||||
}
|
||||
},
|
||||
{
|
||||
"description": "Sample stake pool registration certificate with token minting",
|
||||
"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": null,
|
||||
"inputs": [
|
||||
{
|
||||
"path": null,
|
||||
"prev_hash": "3b40265111d8bb3c3c608d95b3a0bf83461ace32d79336579a1939b3aad1c0b7",
|
||||
"prev_index": 0
|
||||
}
|
||||
],
|
||||
"outputs": [
|
||||
{
|
||||
"address": "addr1q84sh2j72ux0l03fxndjnhctdg7hcppsaejafsa84vh7lwgmcs5wgus8qt4atk45lvt4xfxpjtwfhdmvchdf2m3u3hlsd5tq5r",
|
||||
"amount": "1"
|
||||
}
|
||||
],
|
||||
"mint": [
|
||||
{
|
||||
"policy_id": "95a292ffee938be03e9bae5657982a74e9014eb4960108c9e23a5b39",
|
||||
"tokens": [
|
||||
{
|
||||
"asset_name_bytes": "74652474436f696e",
|
||||
"mint_amount": "100"
|
||||
},
|
||||
{
|
||||
"asset_name_bytes": "75652474436f696e",
|
||||
"mint_amount": "-100"
|
||||
}
|
||||
]
|
||||
},
|
||||
{
|
||||
"policy_id": "a5a292ffee938be03e9bae5657982a74e9014eb4960108c9e23a5b39",
|
||||
"tokens": [
|
||||
{
|
||||
"asset_name_bytes": "74652474436f696e",
|
||||
"mint_amount": "100"
|
||||
},
|
||||
{
|
||||
"asset_name_bytes": "75652474436f696e",
|
||||
"mint_amount": "-100"
|
||||
}
|
||||
]
|
||||
}
|
||||
],
|
||||
"signing_mode": "POOL_REGISTRATION_AS_OWNER",
|
||||
"additional_witness_requests": [
|
||||
{
|
||||
"path": "m/1855'/1815'/0'/0/0"
|
||||
}
|
||||
]
|
||||
},
|
||||
"result": {
|
||||
"error_message": "Stakepool registration transaction cannot contain other certificates, withdrawals or minting"
|
||||
}
|
||||
},
|
||||
{
|
||||
"description": "Sample stake pool registration certificate with change output",
|
||||
"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": null,
|
||||
"inputs": [
|
||||
{
|
||||
"path": null,
|
||||
"prev_hash": "3b40265111d8bb3c3c608d95b3a0bf83461ace32d79336579a1939b3aad1c0b7",
|
||||
"prev_index": 0
|
||||
}
|
||||
],
|
||||
"outputs": [
|
||||
{
|
||||
"addressType": 0,
|
||||
"path": "m/1852'/1815'/0'/0/0",
|
||||
"stakingPath": "m/1852'/1815'/0'/2/0",
|
||||
"amount": "7120787"
|
||||
}
|
||||
],
|
||||
"mint": [],
|
||||
"signing_mode": "POOL_REGISTRATION_AS_OWNER",
|
||||
"additional_witness_requests": []
|
||||
},
|
||||
"result": {
|
||||
"error_message": "Invalid output"
|
||||
}
|
||||
}
|
||||
]
|
||||
}
|
||||
|
@ -81,7 +81,9 @@
|
||||
"amount": "1"
|
||||
}
|
||||
],
|
||||
"signing_mode": "POOL_REGISTRATION_AS_OWNER"
|
||||
"mint": [],
|
||||
"signing_mode": "POOL_REGISTRATION_AS_OWNER",
|
||||
"additional_witness_requests": []
|
||||
},
|
||||
"result": {
|
||||
"tx_hash": "e3b9a5657bf62609465a930c8359d774c73944973cfc5a104a0f0ed1e1e8db21",
|
||||
@ -172,7 +174,9 @@
|
||||
"amount": "1"
|
||||
}
|
||||
],
|
||||
"signing_mode": "POOL_REGISTRATION_AS_OWNER"
|
||||
"mint": [],
|
||||
"signing_mode": "POOL_REGISTRATION_AS_OWNER",
|
||||
"additional_witness_requests": []
|
||||
},
|
||||
"result": {
|
||||
"tx_hash": "c0d944db15446cf05e8db014685414c928d4d9a3e96aea229234be56eeae34c5",
|
||||
@ -264,7 +268,9 @@
|
||||
"amount": "1"
|
||||
}
|
||||
],
|
||||
"signing_mode": "POOL_REGISTRATION_AS_OWNER"
|
||||
"mint": [],
|
||||
"signing_mode": "POOL_REGISTRATION_AS_OWNER",
|
||||
"additional_witness_requests": []
|
||||
},
|
||||
"result": {
|
||||
"tx_hash": "f3d62758ff2f520e7256e65be9d8165da60c7979a97202c19d625709412411fd",
|
||||
@ -322,7 +328,9 @@
|
||||
"amount": "1"
|
||||
}
|
||||
],
|
||||
"signing_mode": "POOL_REGISTRATION_AS_OWNER"
|
||||
"mint": [],
|
||||
"signing_mode": "POOL_REGISTRATION_AS_OWNER",
|
||||
"additional_witness_requests": []
|
||||
},
|
||||
"result": {
|
||||
"tx_hash": "504f9214142996e0b7e315103b25d88a4afa3d01dd5be22376921b52b01483c3",
|
||||
@ -380,7 +388,9 @@
|
||||
"amount": "1"
|
||||
}
|
||||
],
|
||||
"signing_mode": "POOL_REGISTRATION_AS_OWNER"
|
||||
"mint": [],
|
||||
"signing_mode": "POOL_REGISTRATION_AS_OWNER",
|
||||
"additional_witness_requests": []
|
||||
},
|
||||
"result": {
|
||||
"tx_hash": "12921b4f8e77f815e0c8ed97c541fbd5ba38a6d3323f4ff1af0cb934b8ac6b39",
|
||||
@ -473,7 +483,9 @@
|
||||
"amount": "1"
|
||||
}
|
||||
],
|
||||
"signing_mode": "POOL_REGISTRATION_AS_OWNER"
|
||||
"mint": [],
|
||||
"signing_mode": "POOL_REGISTRATION_AS_OWNER",
|
||||
"additional_witness_requests": []
|
||||
},
|
||||
"result": {
|
||||
"tx_hash": "880fafab19a36407e9af300c2905e2f6bc8a8debd8b625005f56994d242ba460",
|
||||
|
@ -209,6 +209,24 @@ def _validate_script_hash(script_hash: bytes | None) -> None:
|
||||
raise INVALID_ADDRESS_PARAMETERS
|
||||
|
||||
|
||||
def validate_output_address_parameters(
|
||||
parameters: CardanoAddressParametersType,
|
||||
) -> None:
|
||||
validate_address_parameters(parameters)
|
||||
|
||||
if parameters.address_type in (
|
||||
CardanoAddressType.BASE_SCRIPT_KEY,
|
||||
CardanoAddressType.BASE_SCRIPT_SCRIPT,
|
||||
CardanoAddressType.POINTER_SCRIPT,
|
||||
CardanoAddressType.ENTERPRISE_SCRIPT,
|
||||
CardanoAddressType.REWARD,
|
||||
CardanoAddressType.REWARD_SCRIPT,
|
||||
):
|
||||
# Change outputs with script payment part are forbidden.
|
||||
# Reward addresses are forbidden as outputs in general, see also validate_output_address
|
||||
raise INVALID_ADDRESS_PARAMETERS
|
||||
|
||||
|
||||
def _validate_address_and_get_type(
|
||||
address: str, protocol_magic: int, network_id: int
|
||||
) -> int:
|
||||
|
@ -13,8 +13,11 @@ from .address import (
|
||||
)
|
||||
from .helpers import ADDRESS_KEY_HASH_SIZE, INVALID_CERTIFICATE, LOVELACE_MAX_SUPPLY
|
||||
from .helpers.paths import SCHEMA_STAKING_ANY_ACCOUNT
|
||||
from .helpers.utils import validate_stake_credential
|
||||
|
||||
if False:
|
||||
from typing import Any
|
||||
|
||||
from trezor.messages import (
|
||||
CardanoPoolMetadataType,
|
||||
CardanoPoolOwner,
|
||||
@ -56,13 +59,16 @@ def validate_certificate(
|
||||
):
|
||||
raise INVALID_CERTIFICATE
|
||||
|
||||
_validate_certificate_structure(certificate)
|
||||
|
||||
if certificate.type in (
|
||||
CardanoCertificateType.STAKE_DELEGATION,
|
||||
CardanoCertificateType.STAKE_REGISTRATION,
|
||||
CardanoCertificateType.STAKE_DEREGISTRATION,
|
||||
):
|
||||
if not SCHEMA_STAKING_ANY_ACCOUNT.match(certificate.path):
|
||||
raise INVALID_CERTIFICATE
|
||||
validate_stake_credential(
|
||||
certificate.path, certificate.script_hash, signing_mode, INVALID_CERTIFICATE
|
||||
)
|
||||
|
||||
if certificate.type == CardanoCertificateType.STAKE_DELEGATION:
|
||||
if not certificate.pool or len(certificate.pool) != POOL_HASH_SIZE:
|
||||
@ -78,6 +84,25 @@ def validate_certificate(
|
||||
account_path_checker.add_certificate(certificate)
|
||||
|
||||
|
||||
def _validate_certificate_structure(certificate: CardanoTxCertificate) -> None:
|
||||
path = certificate.path
|
||||
script_hash = certificate.script_hash
|
||||
pool = certificate.pool
|
||||
pool_parameters = certificate.pool_parameters
|
||||
|
||||
fields_to_be_empty: dict[CardanoCertificateType, tuple[Any, ...]] = {
|
||||
CardanoCertificateType.STAKE_REGISTRATION: (pool, pool_parameters),
|
||||
CardanoCertificateType.STAKE_DELEGATION: (pool_parameters,),
|
||||
CardanoCertificateType.STAKE_DEREGISTRATION: (pool, pool_parameters),
|
||||
CardanoCertificateType.STAKE_POOL_REGISTRATION: (path, script_hash, pool),
|
||||
}
|
||||
|
||||
if certificate.type not in fields_to_be_empty or any(
|
||||
fields_to_be_empty[certificate.type]
|
||||
):
|
||||
raise INVALID_CERTIFICATE
|
||||
|
||||
|
||||
def cborize_certificate(
|
||||
keychain: seed.Keychain, certificate: CardanoTxCertificate
|
||||
) -> CborSequence:
|
||||
@ -87,18 +112,35 @@ def cborize_certificate(
|
||||
):
|
||||
return (
|
||||
certificate.type,
|
||||
(0, get_public_key_hash(keychain, certificate.path)),
|
||||
cborize_certificate_stake_credential(
|
||||
keychain, certificate.path, certificate.script_hash
|
||||
),
|
||||
)
|
||||
elif certificate.type == CardanoCertificateType.STAKE_DELEGATION:
|
||||
return (
|
||||
certificate.type,
|
||||
(0, get_public_key_hash(keychain, certificate.path)),
|
||||
cborize_certificate_stake_credential(
|
||||
keychain, certificate.path, certificate.script_hash
|
||||
),
|
||||
certificate.pool,
|
||||
)
|
||||
else:
|
||||
raise INVALID_CERTIFICATE
|
||||
|
||||
|
||||
def cborize_certificate_stake_credential(
|
||||
keychain: seed.Keychain, path: list[int], script_hash: bytes | None
|
||||
) -> tuple[int, bytes]:
|
||||
if path:
|
||||
return 0, get_public_key_hash(keychain, path)
|
||||
|
||||
if script_hash:
|
||||
return 1, script_hash
|
||||
|
||||
# should be unreachable unless there's a bug in validation
|
||||
raise INVALID_CERTIFICATE
|
||||
|
||||
|
||||
def cborize_initial_pool_registration_certificate_fields(
|
||||
certificate: CardanoTxCertificate,
|
||||
) -> CborSequence:
|
||||
|
@ -3,19 +3,21 @@ from trezor import wire
|
||||
INVALID_ADDRESS = wire.ProcessError("Invalid address")
|
||||
INVALID_ADDRESS_PARAMETERS = wire.ProcessError("Invalid address parameters")
|
||||
NETWORK_MISMATCH = wire.ProcessError("Output address network mismatch")
|
||||
INVALID_TX_SIGNING_REQUEST = wire.ProcessError("Invalid tx signing request")
|
||||
INVALID_OUTPUT = wire.ProcessError("Invalid output")
|
||||
INVALID_CERTIFICATE = wire.ProcessError("Invalid certificate")
|
||||
INVALID_WITHDRAWAL = wire.ProcessError("Invalid withdrawal")
|
||||
INVALID_TOKEN_BUNDLE_OUTPUT = wire.ProcessError("Invalid token bundle in output")
|
||||
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"
|
||||
"Stakepool registration transaction cannot contain other certificates, withdrawals or minting"
|
||||
)
|
||||
INVALID_STAKEPOOL_REGISTRATION_TX_WITNESSES = wire.ProcessError(
|
||||
"Stakepool registration transaction can only contain staking witnesses"
|
||||
)
|
||||
INVALID_WITNESS_REQUEST = wire.ProcessError("Invalid witness request")
|
||||
INVALID_NATIVE_SCRIPT = wire.ProcessError("Invalid native script")
|
||||
INVALID_TOKEN_BUNDLE_MINT = wire.ProcessError("Invalid mint token bundle")
|
||||
|
||||
LOVELACE_MAX_SUPPLY = 45_000_000_000 * 1_000_000
|
||||
ADDRESS_KEY_HASH_SIZE = 28
|
||||
|
@ -1,5 +1,5 @@
|
||||
from ...common.paths import HARDENED
|
||||
from ..seed import is_byron_path, is_shelley_path
|
||||
from ..seed import is_byron_path, is_minting_path, is_multisig_path, is_shelley_path
|
||||
from . import (
|
||||
INVALID_CERTIFICATE,
|
||||
INVALID_OUTPUT,
|
||||
@ -33,6 +33,10 @@ class AccountPathChecker:
|
||||
self.account_path: object | list[int] = self.UNDEFINED
|
||||
|
||||
def _add(self, path: list[int], error: wire.ProcessError) -> None:
|
||||
# multi-sig and minting paths are always shown and thus don't need to be checked
|
||||
if is_multisig_path(path) or is_minting_path(path):
|
||||
return
|
||||
|
||||
account_path = to_account_path(path)
|
||||
if self.account_path is self.UNDEFINED:
|
||||
self.account_path = account_path
|
||||
|
@ -1,11 +1,17 @@
|
||||
from trezor.crypto import hashlib
|
||||
from trezor.enums import CardanoTxSigningMode
|
||||
|
||||
from apps.cardano.helpers.paths import ACCOUNT_PATH_INDEX, unharden
|
||||
from apps.cardano.helpers.paths import (
|
||||
ACCOUNT_PATH_INDEX,
|
||||
SCHEMA_STAKING_ANY_ACCOUNT,
|
||||
unharden,
|
||||
)
|
||||
from apps.common.seed import remove_ed25519_prefix
|
||||
|
||||
from . import ADDRESS_KEY_HASH_SIZE, bech32
|
||||
from . import ADDRESS_KEY_HASH_SIZE, SCRIPT_HASH_SIZE, bech32
|
||||
|
||||
if False:
|
||||
from trezor import wire
|
||||
from .. import seed
|
||||
|
||||
|
||||
@ -79,3 +85,26 @@ def derive_public_key(
|
||||
node = keychain.derive(path)
|
||||
public_key = remove_ed25519_prefix(node.public_key())
|
||||
return public_key if not extended else public_key + node.chain_code()
|
||||
|
||||
|
||||
def validate_stake_credential(
|
||||
path: list[int],
|
||||
script_hash: bytes | None,
|
||||
signing_mode: CardanoTxSigningMode,
|
||||
error: wire.ProcessError,
|
||||
) -> None:
|
||||
if path and script_hash:
|
||||
raise error
|
||||
|
||||
if path:
|
||||
if signing_mode != CardanoTxSigningMode.ORDINARY_TRANSACTION:
|
||||
raise error
|
||||
if not SCHEMA_STAKING_ANY_ACCOUNT.match(path):
|
||||
raise error
|
||||
elif script_hash:
|
||||
if signing_mode != CardanoTxSigningMode.MULTISIG_TRANSACTION:
|
||||
raise error
|
||||
if len(script_hash) != SCRIPT_HASH_SIZE:
|
||||
raise error
|
||||
else:
|
||||
raise error
|
||||
|
@ -5,6 +5,7 @@ from trezor.enums import (
|
||||
CardanoCertificateType,
|
||||
CardanoNativeScriptHashDisplayFormat,
|
||||
CardanoNativeScriptType,
|
||||
CardanoTxSigningMode,
|
||||
)
|
||||
from trezor.messages import CardanoAddressParametersType
|
||||
from trezor.strings import format_amount
|
||||
@ -14,6 +15,7 @@ from trezor.ui.layouts import (
|
||||
confirm_output,
|
||||
confirm_path_warning,
|
||||
confirm_properties,
|
||||
confirm_text,
|
||||
show_address,
|
||||
)
|
||||
|
||||
@ -31,6 +33,7 @@ from .helpers.utils import (
|
||||
format_stake_pool_id,
|
||||
to_account_path,
|
||||
)
|
||||
from .seed import is_minting_path, is_multisig_path
|
||||
|
||||
if False:
|
||||
from trezor import wire
|
||||
@ -184,6 +187,20 @@ async def show_script_hash(
|
||||
)
|
||||
|
||||
|
||||
async def show_transaction_signing_mode(
|
||||
ctx: wire.Context, signing_mode: CardanoTxSigningMode
|
||||
) -> None:
|
||||
if signing_mode == CardanoTxSigningMode.MULTISIG_TRANSACTION:
|
||||
await confirm_metadata(
|
||||
ctx,
|
||||
"confirm_signing_mode",
|
||||
title="Confirm transaction",
|
||||
content="Confirming a multisig transaction.",
|
||||
larger_vspace=True,
|
||||
br_code=ButtonRequestType.Other,
|
||||
)
|
||||
|
||||
|
||||
async def confirm_sending(
|
||||
ctx: wire.Context,
|
||||
ada_amount: int,
|
||||
@ -208,6 +225,8 @@ async def confirm_sending(
|
||||
async def confirm_sending_token(
|
||||
ctx: wire.Context, policy_id: bytes, token: CardanoToken
|
||||
) -> None:
|
||||
assert token.amount is not None # _validate_token
|
||||
|
||||
await confirm_properties(
|
||||
ctx,
|
||||
"confirm_token",
|
||||
@ -315,6 +334,27 @@ async def show_warning_tx_output_contains_tokens(ctx: wire.Context) -> None:
|
||||
)
|
||||
|
||||
|
||||
async def confirm_witness_request(
|
||||
ctx: wire.Context,
|
||||
witness_path: list[int],
|
||||
) -> None:
|
||||
if is_multisig_path(witness_path):
|
||||
path_title = "multi-sig path"
|
||||
elif is_minting_path(witness_path):
|
||||
path_title = "token minting path"
|
||||
else:
|
||||
path_title = "path"
|
||||
|
||||
await confirm_text(
|
||||
ctx,
|
||||
"confirm_total",
|
||||
title="Confirm transaction",
|
||||
data=address_n_to_str(witness_path),
|
||||
description="Sign transaction with %s:" % path_title,
|
||||
br_code=ButtonRequestType.Other,
|
||||
)
|
||||
|
||||
|
||||
async def confirm_transaction(
|
||||
ctx: wire.Context,
|
||||
fee: int,
|
||||
@ -354,13 +394,21 @@ async def confirm_certificate(
|
||||
# in this call
|
||||
assert certificate.type != CardanoCertificateType.STAKE_POOL_REGISTRATION
|
||||
|
||||
props = [
|
||||
props: list[PropertyType] = [
|
||||
("Confirm:", CERTIFICATE_TYPE_NAMES[certificate.type]),
|
||||
(
|
||||
"for account %s:" % format_account_number(certificate.path),
|
||||
address_n_to_str(to_account_path(certificate.path)),
|
||||
),
|
||||
]
|
||||
|
||||
if certificate.path:
|
||||
props.append(
|
||||
(
|
||||
"for account %s:" % format_account_number(certificate.path),
|
||||
address_n_to_str(to_account_path(certificate.path)),
|
||||
),
|
||||
)
|
||||
else:
|
||||
assert certificate.script_hash is not None # validate_certificate
|
||||
props.append(("for script:", format_script_hash(certificate.script_hash)))
|
||||
|
||||
if certificate.type == CardanoCertificateType.STAKE_DELEGATION:
|
||||
assert certificate.pool is not None # validate_certificate
|
||||
props.append(("to pool:", format_stake_pool_id(certificate.pool)))
|
||||
@ -504,18 +552,28 @@ async def confirm_stake_pool_registration_final(
|
||||
async def confirm_withdrawal(
|
||||
ctx: wire.Context, withdrawal: CardanoTxWithdrawal
|
||||
) -> None:
|
||||
props: list[PropertyType] = [
|
||||
("Confirm withdrawal", None),
|
||||
]
|
||||
|
||||
if withdrawal.path:
|
||||
props.append(
|
||||
(
|
||||
"for account %s:" % format_account_number(withdrawal.path),
|
||||
address_n_to_str(to_account_path(withdrawal.path)),
|
||||
)
|
||||
)
|
||||
else:
|
||||
assert withdrawal.script_hash is not None # validate_withdrawal
|
||||
props.append(("for script:", format_script_hash(withdrawal.script_hash)))
|
||||
|
||||
props.append(("Amount:", format_coin_amount(withdrawal.amount)))
|
||||
|
||||
await confirm_properties(
|
||||
ctx,
|
||||
"confirm_withdrawal",
|
||||
title="Confirm transaction",
|
||||
props=[
|
||||
(
|
||||
"Confirm withdrawal\nfor account %s:"
|
||||
% format_account_number(withdrawal.path),
|
||||
address_n_to_str(to_account_path(withdrawal.path)),
|
||||
),
|
||||
("Amount:", format_coin_amount(withdrawal.amount)),
|
||||
],
|
||||
props=props,
|
||||
br_code=ButtonRequestType.Other,
|
||||
)
|
||||
|
||||
@ -557,43 +615,40 @@ async def show_auxiliary_data_hash(
|
||||
)
|
||||
|
||||
|
||||
async def show_warning_address_foreign_staking_key(
|
||||
ctx: wire.Context,
|
||||
account_path: list[int],
|
||||
staking_account_path: list[int],
|
||||
staking_key_hash: bytes | None,
|
||||
) -> None:
|
||||
# TODO: confirm_properties not appropriate here
|
||||
# instead, presumably, this should be a flow:
|
||||
# 1. show_warning: Mismatch! continue?
|
||||
# 2. confirm_blob(mismatched_value)
|
||||
props: list[PropertyType] = [
|
||||
(
|
||||
"Stake rights associated with this address do not match your account %s:"
|
||||
% format_account_number(account_path),
|
||||
address_n_to_str(account_path),
|
||||
)
|
||||
]
|
||||
async def show_warning_tx_contains_mint(ctx: wire.Context) -> None:
|
||||
await confirm_metadata(
|
||||
ctx,
|
||||
"confirm_tokens",
|
||||
title="Confirm transaction",
|
||||
content="The transaction contains\nminting or burning of\ntokens.",
|
||||
larger_vspace=True,
|
||||
br_code=ButtonRequestType.Other,
|
||||
)
|
||||
|
||||
if staking_account_path:
|
||||
props.append(
|
||||
(
|
||||
"Stake account %s:" % format_account_number(staking_account_path),
|
||||
address_n_to_str(staking_account_path),
|
||||
)
|
||||
)
|
||||
else:
|
||||
assert staking_key_hash is not None # _validate_base_address_staking_info
|
||||
props.append(("Staking key:", staking_key_hash))
|
||||
props.append(("Continue?", None))
|
||||
|
||||
async def confirm_token_minting(
|
||||
ctx: wire.Context, policy_id: bytes, token: CardanoToken
|
||||
) -> None:
|
||||
assert token.mint_amount is not None # _validate_token
|
||||
is_minting = token.mint_amount >= 0
|
||||
|
||||
await confirm_properties(
|
||||
ctx,
|
||||
"warning_foreign_stakingkey",
|
||||
title="Warning",
|
||||
props=props,
|
||||
icon=ui.ICON_WRONG,
|
||||
icon_color=ui.RED,
|
||||
"confirm_mint",
|
||||
title="Confirm transaction",
|
||||
props=[
|
||||
(
|
||||
"Asset fingerprint:",
|
||||
format_asset_fingerprint(
|
||||
policy_id=policy_id,
|
||||
asset_name_bytes=token.asset_name_bytes,
|
||||
),
|
||||
),
|
||||
(
|
||||
"Amount %s:" % ("minted" if is_minting else "burned"),
|
||||
format_amount(token.mint_amount, 0),
|
||||
),
|
||||
],
|
||||
br_code=ButtonRequestType.Other,
|
||||
)
|
||||
|
||||
|
@ -23,6 +23,7 @@ from trezor.messages import (
|
||||
CardanoTxHostAck,
|
||||
CardanoTxInput,
|
||||
CardanoTxItemAck,
|
||||
CardanoTxMint,
|
||||
CardanoTxOutput,
|
||||
CardanoTxWithdrawal,
|
||||
CardanoTxWitnessRequest,
|
||||
@ -36,8 +37,8 @@ from .address import (
|
||||
derive_address_bytes,
|
||||
derive_human_readable_address,
|
||||
get_address_bytes_unsafe,
|
||||
validate_address_parameters,
|
||||
validate_output_address,
|
||||
validate_output_address_parameters,
|
||||
)
|
||||
from .auxiliary_data import (
|
||||
get_auxiliary_data_hash_and_supplement,
|
||||
@ -59,8 +60,11 @@ from .helpers import (
|
||||
INVALID_OUTPUT,
|
||||
INVALID_STAKE_POOL_REGISTRATION_TX_STRUCTURE,
|
||||
INVALID_STAKEPOOL_REGISTRATION_TX_WITNESSES,
|
||||
INVALID_TOKEN_BUNDLE_MINT,
|
||||
INVALID_TOKEN_BUNDLE_OUTPUT,
|
||||
INVALID_TX_SIGNING_REQUEST,
|
||||
INVALID_WITHDRAWAL,
|
||||
INVALID_WITNESS_REQUEST,
|
||||
LOVELACE_MAX_SUPPLY,
|
||||
network_ids,
|
||||
protocol_magics,
|
||||
@ -73,12 +77,13 @@ from .helpers.paths import (
|
||||
CHANGE_OUTPUT_PATH_NAME,
|
||||
CHANGE_OUTPUT_STAKING_PATH_NAME,
|
||||
POOL_OWNER_STAKING_PATH_NAME,
|
||||
SCHEMA_MINT,
|
||||
SCHEMA_PAYMENT,
|
||||
SCHEMA_STAKING,
|
||||
SCHEMA_STAKING_ANY_ACCOUNT,
|
||||
WITNESS_PATH_NAME,
|
||||
)
|
||||
from .helpers.utils import derive_public_key, to_account_path
|
||||
from .helpers.utils import derive_public_key, validate_stake_credential
|
||||
from .layout import (
|
||||
confirm_certificate,
|
||||
confirm_sending,
|
||||
@ -87,14 +92,18 @@ from .layout import (
|
||||
confirm_stake_pool_owner,
|
||||
confirm_stake_pool_parameters,
|
||||
confirm_stake_pool_registration_final,
|
||||
confirm_token_minting,
|
||||
confirm_transaction,
|
||||
confirm_withdrawal,
|
||||
confirm_witness_request,
|
||||
show_credentials,
|
||||
show_transaction_signing_mode,
|
||||
show_warning_path,
|
||||
show_warning_tx_contains_mint,
|
||||
show_warning_tx_network_unverifiable,
|
||||
show_warning_tx_output_contains_tokens,
|
||||
)
|
||||
from .seed import is_byron_path
|
||||
from .seed import is_byron_path, is_multisig_path, is_shelley_path
|
||||
|
||||
if False:
|
||||
from typing import Any, Union
|
||||
@ -113,6 +122,7 @@ TX_BODY_KEY_CERTIFICATES = const(4)
|
||||
TX_BODY_KEY_WITHDRAWALS = const(5)
|
||||
TX_BODY_KEY_AUXILIARY_DATA = const(7)
|
||||
TX_BODY_KEY_VALIDITY_INTERVAL_START = const(8)
|
||||
TX_BODY_KEY_MINT = const(9)
|
||||
|
||||
POOL_REGISTRATION_CERTIFICATE_ITEMS_COUNT = 10
|
||||
|
||||
@ -123,6 +133,8 @@ async def sign_tx(
|
||||
) -> CardanoSignTxFinished:
|
||||
is_network_id_verifiable = await _validate_tx_signing_request(ctx, msg)
|
||||
|
||||
await show_transaction_signing_mode(ctx, msg.signing_mode)
|
||||
|
||||
# inputs, outputs and fee are mandatory fields, count the number of optional fields present
|
||||
tx_body_map_item_count = 3 + sum(
|
||||
(
|
||||
@ -131,6 +143,7 @@ async def sign_tx(
|
||||
msg.withdrawals_count > 0,
|
||||
msg.has_auxiliary_data,
|
||||
msg.validity_interval_start is not None,
|
||||
msg.minting_asset_groups_count > 0,
|
||||
)
|
||||
)
|
||||
|
||||
@ -152,8 +165,10 @@ async def sign_tx(
|
||||
tx_hash,
|
||||
msg.witness_requests_count,
|
||||
msg.signing_mode,
|
||||
msg.minting_asset_groups_count > 0,
|
||||
account_path_checker,
|
||||
)
|
||||
|
||||
await ctx.call(response_after_witness_requests, CardanoTxHostAck)
|
||||
|
||||
await ctx.call(CardanoTxBodyHash(tx_hash=tx_hash), CardanoTxHostAck)
|
||||
@ -179,6 +194,11 @@ async def _validate_tx_signing_request(
|
||||
await show_warning_tx_network_unverifiable(ctx)
|
||||
elif msg.signing_mode == CardanoTxSigningMode.POOL_REGISTRATION_AS_OWNER:
|
||||
_validate_stake_pool_registration_tx_structure(msg)
|
||||
elif msg.signing_mode == CardanoTxSigningMode.MULTISIG_TRANSACTION:
|
||||
if not is_network_id_verifiable:
|
||||
await show_warning_tx_network_unverifiable(ctx)
|
||||
else:
|
||||
raise INVALID_TX_SIGNING_REQUEST
|
||||
|
||||
return is_network_id_verifiable
|
||||
|
||||
@ -236,6 +256,7 @@ async def _process_transaction(
|
||||
keychain,
|
||||
withdrawals_dict,
|
||||
msg.withdrawals_count,
|
||||
msg.signing_mode,
|
||||
msg.protocol_magic,
|
||||
msg.network_id,
|
||||
account_path_checker,
|
||||
@ -253,13 +274,23 @@ async def _process_transaction(
|
||||
if msg.validity_interval_start is not None:
|
||||
tx_dict.add(TX_BODY_KEY_VALIDITY_INTERVAL_START, msg.validity_interval_start)
|
||||
|
||||
if msg.minting_asset_groups_count > 0:
|
||||
minting_dict: HashBuilderDict[bytes, HashBuilderDict] = HashBuilderDict(
|
||||
msg.minting_asset_groups_count
|
||||
)
|
||||
with tx_dict.add(TX_BODY_KEY_MINT, minting_dict):
|
||||
await _process_minting(ctx, minting_dict)
|
||||
|
||||
|
||||
async def _confirm_transaction(
|
||||
ctx: wire.Context,
|
||||
msg: CardanoSignTxInit,
|
||||
is_network_id_verifiable: bool,
|
||||
) -> None:
|
||||
if msg.signing_mode == CardanoTxSigningMode.ORDINARY_TRANSACTION:
|
||||
if msg.signing_mode in (
|
||||
CardanoTxSigningMode.ORDINARY_TRANSACTION,
|
||||
CardanoTxSigningMode.MULTISIG_TRANSACTION,
|
||||
):
|
||||
await confirm_transaction(
|
||||
ctx,
|
||||
msg.fee,
|
||||
@ -272,6 +303,8 @@ async def _confirm_transaction(
|
||||
await confirm_stake_pool_registration_final(
|
||||
ctx, msg.protocol_magic, msg.ttl, msg.validity_interval_start
|
||||
)
|
||||
else:
|
||||
raise ValueError
|
||||
|
||||
|
||||
async def _process_inputs(
|
||||
@ -313,7 +346,6 @@ async def _process_outputs(
|
||||
ctx,
|
||||
keychain,
|
||||
output,
|
||||
signing_mode,
|
||||
protocol_magic,
|
||||
network_id,
|
||||
)
|
||||
@ -363,7 +395,6 @@ async def _process_asset_groups(
|
||||
asset_group: CardanoAssetGroup = await ctx.call(
|
||||
CardanoTxItemAck(), CardanoAssetGroup
|
||||
)
|
||||
asset_group.policy_id = bytes(asset_group.policy_id)
|
||||
_validate_asset_group(asset_group, seen_policy_ids)
|
||||
seen_policy_ids.add(asset_group.policy_id)
|
||||
|
||||
@ -391,12 +422,12 @@ async def _process_tokens(
|
||||
seen_asset_name_bytes: set[bytes] = set()
|
||||
for _ in range(tokens_count):
|
||||
token: CardanoToken = await ctx.call(CardanoTxItemAck(), CardanoToken)
|
||||
token.asset_name_bytes = bytes(token.asset_name_bytes)
|
||||
_validate_token(token, seen_asset_name_bytes)
|
||||
seen_asset_name_bytes.add(token.asset_name_bytes)
|
||||
if should_show_tokens:
|
||||
await confirm_sending_token(ctx, policy_id, token)
|
||||
|
||||
assert token.amount is not None # _validate_token
|
||||
tokens_dict.add(token.asset_name_bytes, token.amount)
|
||||
|
||||
|
||||
@ -445,6 +476,7 @@ async def _process_certificates(
|
||||
keychain,
|
||||
pool_owners_list,
|
||||
pool_parameters.owners_count,
|
||||
protocol_magic,
|
||||
network_id,
|
||||
account_path_checker,
|
||||
)
|
||||
@ -467,6 +499,7 @@ async def _process_pool_owners(
|
||||
keychain: seed.Keychain,
|
||||
pool_owners_list: HashBuilderList[bytes],
|
||||
owners_count: int,
|
||||
protocol_magic: int,
|
||||
network_id: int,
|
||||
account_path_checker: AccountPathChecker,
|
||||
) -> None:
|
||||
@ -474,7 +507,7 @@ async def _process_pool_owners(
|
||||
for _ in range(owners_count):
|
||||
owner: CardanoPoolOwner = await ctx.call(CardanoTxItemAck(), CardanoPoolOwner)
|
||||
validate_pool_owner(owner, account_path_checker)
|
||||
await _show_pool_owner(ctx, keychain, owner, network_id)
|
||||
await _show_pool_owner(ctx, keychain, owner, protocol_magic, network_id)
|
||||
|
||||
pool_owners_list.append(cborize_pool_owner(keychain, owner))
|
||||
|
||||
@ -502,6 +535,7 @@ async def _process_withdrawals(
|
||||
keychain: seed.Keychain,
|
||||
withdrawals_dict: HashBuilderDict[bytes, int],
|
||||
withdrawals_count: int,
|
||||
signing_mode: CardanoTxSigningMode,
|
||||
protocol_magic: int,
|
||||
network_id: int,
|
||||
account_path_checker: AccountPathChecker,
|
||||
@ -512,18 +546,26 @@ async def _process_withdrawals(
|
||||
|
||||
# until the CIP with canonical CBOR is finalized storing the seen_withdrawals is the only way we can check for
|
||||
# duplicate withdrawals
|
||||
seen_withdrawals: set[tuple[int, ...]] = set()
|
||||
seen_withdrawals: set[tuple[int, ...] | bytes] = set()
|
||||
for _ in range(withdrawals_count):
|
||||
withdrawal: CardanoTxWithdrawal = await ctx.call(
|
||||
CardanoTxItemAck(), CardanoTxWithdrawal
|
||||
)
|
||||
_validate_withdrawal(withdrawal, seen_withdrawals, account_path_checker)
|
||||
_validate_withdrawal(
|
||||
withdrawal, seen_withdrawals, signing_mode, account_path_checker
|
||||
)
|
||||
await confirm_withdrawal(ctx, withdrawal)
|
||||
reward_address_type = (
|
||||
CardanoAddressType.REWARD
|
||||
if withdrawal.path
|
||||
else CardanoAddressType.REWARD_SCRIPT
|
||||
)
|
||||
reward_address = derive_address_bytes(
|
||||
keychain,
|
||||
CardanoAddressParametersType(
|
||||
address_type=CardanoAddressType.REWARD,
|
||||
address_n=withdrawal.path,
|
||||
address_type=reward_address_type,
|
||||
address_n_staking=withdrawal.path,
|
||||
script_staking_hash=withdrawal.script_hash,
|
||||
),
|
||||
protocol_magic,
|
||||
network_id,
|
||||
@ -566,25 +608,80 @@ async def _process_auxiliary_data(
|
||||
await ctx.call(auxiliary_data_supplement, CardanoTxHostAck)
|
||||
|
||||
|
||||
async def _process_minting(
|
||||
ctx: wire.Context, minting_dict: HashBuilderDict[bytes, HashBuilderDict]
|
||||
) -> None:
|
||||
"""Read, validate and serialize the asset groups of token minting."""
|
||||
token_minting: CardanoTxMint = await ctx.call(CardanoTxItemAck(), CardanoTxMint)
|
||||
|
||||
await show_warning_tx_contains_mint(ctx)
|
||||
|
||||
# until the CIP with canonical CBOR is finalized storing the seen_policy_ids is the only way we can check for
|
||||
# duplicate policy_ids
|
||||
seen_policy_ids: set[bytes] = set()
|
||||
for _ in range(token_minting.asset_groups_count):
|
||||
asset_group: CardanoAssetGroup = await ctx.call(
|
||||
CardanoTxItemAck(), CardanoAssetGroup
|
||||
)
|
||||
_validate_asset_group(asset_group, seen_policy_ids, is_mint=True)
|
||||
seen_policy_ids.add(asset_group.policy_id)
|
||||
|
||||
tokens: HashBuilderDict[bytes, int] = HashBuilderDict(asset_group.tokens_count)
|
||||
with minting_dict.add(asset_group.policy_id, tokens):
|
||||
await _process_minting_tokens(
|
||||
ctx,
|
||||
tokens,
|
||||
asset_group.policy_id,
|
||||
asset_group.tokens_count,
|
||||
)
|
||||
|
||||
|
||||
async def _process_minting_tokens(
|
||||
ctx: wire.Context,
|
||||
tokens: HashBuilderDict[bytes, int],
|
||||
policy_id: bytes,
|
||||
tokens_count: int,
|
||||
) -> None:
|
||||
"""Read, validate, confirm and serialize the tokens of an asset group."""
|
||||
# until the CIP with canonical CBOR is finalized storing the seen_asset_name_bytes is the only way we can check for
|
||||
# duplicate tokens
|
||||
seen_asset_name_bytes: set[bytes] = set()
|
||||
for _ in range(tokens_count):
|
||||
token: CardanoToken = await ctx.call(CardanoTxItemAck(), CardanoToken)
|
||||
_validate_token(token, seen_asset_name_bytes, is_mint=True)
|
||||
seen_asset_name_bytes.add(token.asset_name_bytes)
|
||||
await confirm_token_minting(ctx, policy_id, token)
|
||||
|
||||
assert token.mint_amount is not None # _validate_token
|
||||
tokens.add(token.asset_name_bytes, token.mint_amount)
|
||||
|
||||
|
||||
async def _process_witness_requests(
|
||||
ctx: wire.Context,
|
||||
keychain: seed.Keychain,
|
||||
tx_hash: bytes,
|
||||
witness_requests_count: int,
|
||||
signing_mode: CardanoTxSigningMode,
|
||||
transaction_has_token_minting: bool,
|
||||
account_path_checker: AccountPathChecker,
|
||||
) -> CardanoTxResponseType:
|
||||
response: CardanoTxResponseType = CardanoTxItemAck()
|
||||
|
||||
for _ in range(witness_requests_count):
|
||||
witness_request = await ctx.call(response, CardanoTxWitnessRequest)
|
||||
_validate_witness_request(witness_request, signing_mode, account_path_checker)
|
||||
await _show_witness(ctx, witness_request.path)
|
||||
|
||||
response = (
|
||||
_get_byron_witness(keychain, witness_request.path, tx_hash)
|
||||
if is_byron_path(witness_request.path)
|
||||
else _get_shelley_witness(keychain, witness_request.path, tx_hash)
|
||||
_validate_witness_request(
|
||||
witness_request,
|
||||
signing_mode,
|
||||
transaction_has_token_minting,
|
||||
account_path_checker,
|
||||
)
|
||||
path = witness_request.path
|
||||
await _show_witness_request(ctx, path, signing_mode)
|
||||
if is_byron_path(path):
|
||||
response = _get_byron_witness(keychain, path, tx_hash)
|
||||
else:
|
||||
response = _get_shelley_witness(keychain, path, tx_hash)
|
||||
|
||||
return response
|
||||
|
||||
|
||||
@ -633,6 +730,7 @@ def _validate_stake_pool_registration_tx_structure(msg: CardanoSignTxInit) -> No
|
||||
msg.certificates_count != 1
|
||||
or msg.signing_mode != CardanoTxSigningMode.POOL_REGISTRATION_AS_OWNER
|
||||
or msg.withdrawals_count != 0
|
||||
or msg.minting_asset_groups_count != 0
|
||||
):
|
||||
raise INVALID_STAKE_POOL_REGISTRATION_TX_STRUCTURE
|
||||
|
||||
@ -648,7 +746,10 @@ def _validate_output(
|
||||
raise INVALID_OUTPUT
|
||||
|
||||
if address_parameters := output.address_parameters:
|
||||
validate_address_parameters(address_parameters)
|
||||
if signing_mode != CardanoTxSigningMode.ORDINARY_TRANSACTION:
|
||||
raise INVALID_OUTPUT
|
||||
|
||||
validate_output_address_parameters(address_parameters)
|
||||
_fail_if_strict_and_unusual(address_parameters)
|
||||
elif output.address is not None:
|
||||
validate_output_address(output.address, protocol_magic, network_id)
|
||||
@ -679,7 +780,6 @@ async def _show_output(
|
||||
ctx: wire.Context,
|
||||
keychain: seed.Keychain,
|
||||
output: CardanoTxOutput,
|
||||
signing_mode: CardanoTxSigningMode,
|
||||
protocol_magic: int,
|
||||
network_id: int,
|
||||
) -> None:
|
||||
@ -710,21 +810,38 @@ async def _show_output(
|
||||
|
||||
|
||||
def _validate_asset_group(
|
||||
asset_group: CardanoAssetGroup, seen_policy_ids: set[bytes]
|
||||
asset_group: CardanoAssetGroup, seen_policy_ids: set[bytes], is_mint: bool = False
|
||||
) -> None:
|
||||
INVALID_TOKEN_BUNDLE = (
|
||||
INVALID_TOKEN_BUNDLE_MINT if is_mint else INVALID_TOKEN_BUNDLE_OUTPUT
|
||||
)
|
||||
|
||||
if len(asset_group.policy_id) != MINTING_POLICY_ID_LENGTH:
|
||||
raise INVALID_TOKEN_BUNDLE_OUTPUT
|
||||
raise INVALID_TOKEN_BUNDLE
|
||||
if asset_group.tokens_count == 0:
|
||||
raise INVALID_TOKEN_BUNDLE_OUTPUT
|
||||
raise INVALID_TOKEN_BUNDLE
|
||||
if asset_group.policy_id in seen_policy_ids:
|
||||
raise INVALID_TOKEN_BUNDLE_OUTPUT
|
||||
raise INVALID_TOKEN_BUNDLE
|
||||
|
||||
|
||||
def _validate_token(token: CardanoToken, seen_asset_name_bytes: set[bytes]) -> None:
|
||||
def _validate_token(
|
||||
token: CardanoToken, seen_asset_name_bytes: set[bytes], is_mint: bool = False
|
||||
) -> None:
|
||||
INVALID_TOKEN_BUNDLE = (
|
||||
INVALID_TOKEN_BUNDLE_MINT if is_mint else INVALID_TOKEN_BUNDLE_OUTPUT
|
||||
)
|
||||
|
||||
if is_mint:
|
||||
if token.mint_amount is None or token.amount is not None:
|
||||
raise INVALID_TOKEN_BUNDLE
|
||||
else:
|
||||
if token.amount is None or token.mint_amount is not None:
|
||||
raise INVALID_TOKEN_BUNDLE
|
||||
|
||||
if len(token.asset_name_bytes) > MAX_ASSET_NAME_LENGTH:
|
||||
raise INVALID_TOKEN_BUNDLE_OUTPUT
|
||||
raise INVALID_TOKEN_BUNDLE
|
||||
if token.asset_name_bytes in seen_asset_name_bytes:
|
||||
raise INVALID_TOKEN_BUNDLE_OUTPUT
|
||||
raise INVALID_TOKEN_BUNDLE
|
||||
|
||||
|
||||
async def _show_certificate(
|
||||
@ -733,30 +850,38 @@ async def _show_certificate(
|
||||
signing_mode: CardanoTxSigningMode,
|
||||
) -> None:
|
||||
if signing_mode == CardanoTxSigningMode.ORDINARY_TRANSACTION:
|
||||
assert certificate.path # validate_certificate
|
||||
await _fail_or_warn_if_invalid_path(
|
||||
ctx, SCHEMA_STAKING, certificate.path, CERTIFICATE_PATH_NAME
|
||||
)
|
||||
await confirm_certificate(ctx, certificate)
|
||||
elif signing_mode == CardanoTxSigningMode.MULTISIG_TRANSACTION:
|
||||
assert certificate.script_hash # validate_certificate
|
||||
await confirm_certificate(ctx, certificate)
|
||||
elif signing_mode == CardanoTxSigningMode.POOL_REGISTRATION_AS_OWNER:
|
||||
await _show_stake_pool_registration_certificate(ctx, certificate)
|
||||
|
||||
|
||||
def _validate_withdrawal(
|
||||
withdrawal: CardanoTxWithdrawal,
|
||||
seen_withdrawals: set[tuple[int, ...]],
|
||||
seen_withdrawals: set[tuple[int, ...] | bytes],
|
||||
signing_mode: CardanoTxSigningMode,
|
||||
account_path_checker: AccountPathChecker,
|
||||
) -> None:
|
||||
if not SCHEMA_STAKING_ANY_ACCOUNT.match(withdrawal.path):
|
||||
raise INVALID_WITHDRAWAL
|
||||
validate_stake_credential(
|
||||
withdrawal.path, withdrawal.script_hash, signing_mode, INVALID_WITHDRAWAL
|
||||
)
|
||||
|
||||
if not 0 <= withdrawal.amount < LOVELACE_MAX_SUPPLY:
|
||||
raise INVALID_WITHDRAWAL
|
||||
|
||||
path_tuple = tuple(withdrawal.path)
|
||||
if path_tuple in seen_withdrawals:
|
||||
credential = tuple(withdrawal.path) if withdrawal.path else withdrawal.script_hash
|
||||
assert credential # validate_stake_credential
|
||||
|
||||
if credential in seen_withdrawals:
|
||||
raise wire.ProcessError("Duplicate withdrawals")
|
||||
else:
|
||||
seen_withdrawals.add(path_tuple)
|
||||
seen_withdrawals.add(credential)
|
||||
|
||||
account_path_checker.add_withdrawal(withdrawal)
|
||||
|
||||
@ -818,17 +943,33 @@ async def _show_pool_owner(
|
||||
def _validate_witness_request(
|
||||
witness_request: CardanoTxWitnessRequest,
|
||||
signing_mode: CardanoTxSigningMode,
|
||||
transaction_has_token_minting: bool,
|
||||
account_path_checker: AccountPathChecker,
|
||||
) -> None:
|
||||
# witness path validation happens in _show_witness
|
||||
# further witness path validation happens in _show_witness_request
|
||||
is_minting = SCHEMA_MINT.match(witness_request.path)
|
||||
|
||||
if signing_mode == CardanoTxSigningMode.POOL_REGISTRATION_AS_OWNER:
|
||||
_ensure_no_payment_witness(witness_request)
|
||||
if signing_mode == CardanoTxSigningMode.ORDINARY_TRANSACTION:
|
||||
if not (
|
||||
is_byron_path(witness_request.path)
|
||||
or is_shelley_path(witness_request.path)
|
||||
or is_minting
|
||||
):
|
||||
raise INVALID_WITNESS_REQUEST
|
||||
if is_minting and not transaction_has_token_minting:
|
||||
raise INVALID_WITNESS_REQUEST
|
||||
elif signing_mode == CardanoTxSigningMode.POOL_REGISTRATION_AS_OWNER:
|
||||
_ensure_only_staking_witnesses(witness_request)
|
||||
elif signing_mode == CardanoTxSigningMode.MULTISIG_TRANSACTION:
|
||||
if not is_multisig_path(witness_request.path) and not is_minting:
|
||||
raise INVALID_WITNESS_REQUEST
|
||||
if is_minting and not transaction_has_token_minting:
|
||||
raise INVALID_WITNESS_REQUEST
|
||||
|
||||
account_path_checker.add_witness_request(witness_request)
|
||||
|
||||
|
||||
def _ensure_no_payment_witness(witness: CardanoTxWitnessRequest) -> None:
|
||||
def _ensure_only_staking_witnesses(witness: CardanoTxWitnessRequest) -> None:
|
||||
"""
|
||||
We have a separate tx signing flow for stake pool registration because it's a
|
||||
transaction where the witnessable entries (i.e. inputs, withdrawals, etc.)
|
||||
@ -845,15 +986,27 @@ def _ensure_no_payment_witness(witness: CardanoTxWitnessRequest) -> None:
|
||||
raise INVALID_STAKEPOOL_REGISTRATION_TX_WITNESSES
|
||||
|
||||
|
||||
async def _show_witness(
|
||||
async def _show_witness_request(
|
||||
ctx: wire.Context,
|
||||
witness_path: list[int],
|
||||
signing_mode: CardanoTxSigningMode,
|
||||
) -> None:
|
||||
is_payment = SCHEMA_PAYMENT.match(witness_path)
|
||||
is_staking = SCHEMA_STAKING.match(witness_path)
|
||||
if signing_mode == CardanoTxSigningMode.ORDINARY_TRANSACTION:
|
||||
# In an ordinary transaction we only allow payment, staking or minting paths.
|
||||
# If the path is an unusual payment or staking path, we either fail or show the path to the user
|
||||
# depending on Trezor's configuration. If it's a minting path, we always show it.
|
||||
is_payment = SCHEMA_PAYMENT.match(witness_path)
|
||||
is_staking = SCHEMA_STAKING.match(witness_path)
|
||||
is_minting = SCHEMA_MINT.match(witness_path)
|
||||
|
||||
if not is_payment and not is_staking:
|
||||
await _fail_or_warn_path(ctx, witness_path, WITNESS_PATH_NAME)
|
||||
if is_minting:
|
||||
await confirm_witness_request(ctx, witness_path)
|
||||
elif not is_payment and not is_staking:
|
||||
await _fail_or_warn_path(ctx, witness_path, WITNESS_PATH_NAME)
|
||||
elif signing_mode == CardanoTxSigningMode.MULTISIG_TRANSACTION:
|
||||
await confirm_witness_request(ctx, witness_path)
|
||||
elif signing_mode == CardanoTxSigningMode.POOL_REGISTRATION_AS_OWNER:
|
||||
await confirm_witness_request(ctx, witness_path)
|
||||
|
||||
|
||||
def _is_network_id_verifiable(msg: CardanoSignTxInit) -> bool:
|
||||
|
@ -4,3 +4,4 @@
|
||||
|
||||
ORDINARY_TRANSACTION = 0
|
||||
POOL_REGISTRATION_AS_OWNER = 1
|
||||
MULTISIG_TRANSACTION = 2
|
||||
|
@ -152,6 +152,7 @@ if not utils.BITCOIN_ONLY:
|
||||
CardanoPoolRelayParameters = 329
|
||||
CardanoGetNativeScriptHash = 330
|
||||
CardanoNativeScriptHash = 331
|
||||
CardanoTxMint = 332
|
||||
RippleGetAddress = 400
|
||||
RippleAddress = 401
|
||||
RippleSignTx = 402
|
||||
|
@ -157,6 +157,7 @@ if TYPE_CHECKING:
|
||||
CardanoPoolRelayParameters = 329
|
||||
CardanoGetNativeScriptHash = 330
|
||||
CardanoNativeScriptHash = 331
|
||||
CardanoTxMint = 332
|
||||
RippleGetAddress = 400
|
||||
RippleAddress = 401
|
||||
RippleSignTx = 402
|
||||
@ -361,6 +362,7 @@ if TYPE_CHECKING:
|
||||
class CardanoTxSigningMode(IntEnum):
|
||||
ORDINARY_TRANSACTION = 0
|
||||
POOL_REGISTRATION_AS_OWNER = 1
|
||||
MULTISIG_TRANSACTION = 2
|
||||
|
||||
class CardanoTxWitnessType(IntEnum):
|
||||
BYRON_WITNESS = 0
|
||||
|
@ -1222,6 +1222,7 @@ if TYPE_CHECKING:
|
||||
has_auxiliary_data: "bool"
|
||||
validity_interval_start: "int | None"
|
||||
witness_requests_count: "int"
|
||||
minting_asset_groups_count: "int"
|
||||
|
||||
def __init__(
|
||||
self,
|
||||
@ -1236,6 +1237,7 @@ if TYPE_CHECKING:
|
||||
withdrawals_count: "int",
|
||||
has_auxiliary_data: "bool",
|
||||
witness_requests_count: "int",
|
||||
minting_asset_groups_count: "int",
|
||||
ttl: "int | None" = None,
|
||||
validity_interval_start: "int | None" = None,
|
||||
) -> None:
|
||||
@ -1299,13 +1301,15 @@ if TYPE_CHECKING:
|
||||
|
||||
class CardanoToken(protobuf.MessageType):
|
||||
asset_name_bytes: "bytes"
|
||||
amount: "int"
|
||||
amount: "int | None"
|
||||
mint_amount: "int | None"
|
||||
|
||||
def __init__(
|
||||
self,
|
||||
*,
|
||||
asset_name_bytes: "bytes",
|
||||
amount: "int",
|
||||
amount: "int | None" = None,
|
||||
mint_amount: "int | None" = None,
|
||||
) -> None:
|
||||
pass
|
||||
|
||||
@ -1404,6 +1408,7 @@ if TYPE_CHECKING:
|
||||
path: "list[int]"
|
||||
pool: "bytes | None"
|
||||
pool_parameters: "CardanoPoolParametersType | None"
|
||||
script_hash: "bytes | None"
|
||||
|
||||
def __init__(
|
||||
self,
|
||||
@ -1412,6 +1417,7 @@ if TYPE_CHECKING:
|
||||
path: "list[int] | None" = None,
|
||||
pool: "bytes | None" = None,
|
||||
pool_parameters: "CardanoPoolParametersType | None" = None,
|
||||
script_hash: "bytes | None" = None,
|
||||
) -> None:
|
||||
pass
|
||||
|
||||
@ -1422,12 +1428,14 @@ if TYPE_CHECKING:
|
||||
class CardanoTxWithdrawal(protobuf.MessageType):
|
||||
path: "list[int]"
|
||||
amount: "int"
|
||||
script_hash: "bytes | None"
|
||||
|
||||
def __init__(
|
||||
self,
|
||||
*,
|
||||
amount: "int",
|
||||
path: "list[int] | None" = None,
|
||||
script_hash: "bytes | None" = None,
|
||||
) -> None:
|
||||
pass
|
||||
|
||||
@ -1471,6 +1479,20 @@ if TYPE_CHECKING:
|
||||
def is_type_of(cls, msg: protobuf.MessageType) -> TypeGuard["CardanoTxAuxiliaryData"]:
|
||||
return isinstance(msg, cls)
|
||||
|
||||
class CardanoTxMint(protobuf.MessageType):
|
||||
asset_groups_count: "int"
|
||||
|
||||
def __init__(
|
||||
self,
|
||||
*,
|
||||
asset_groups_count: "int",
|
||||
) -> None:
|
||||
pass
|
||||
|
||||
@classmethod
|
||||
def is_type_of(cls, msg: protobuf.MessageType) -> TypeGuard["CardanoTxMint"]:
|
||||
return isinstance(msg, cls)
|
||||
|
||||
class CardanoTxItemAck(protobuf.MessageType):
|
||||
|
||||
@classmethod
|
||||
|
357
core/tests/test_apps.cardano.certificate.py
Normal file
357
core/tests/test_apps.cardano.certificate.py
Normal file
@ -0,0 +1,357 @@
|
||||
from common import *
|
||||
from trezor import wire
|
||||
from trezor.enums import CardanoCertificateType, CardanoTxSigningMode
|
||||
from trezor.messages import CardanoTxCertificate, CardanoPoolParametersType
|
||||
|
||||
from apps.common.paths import HARDENED
|
||||
|
||||
if not utils.BITCOIN_ONLY:
|
||||
from apps.cardano.certificates import validate_certificate
|
||||
from apps.cardano.helpers import protocol_magics, network_ids
|
||||
from apps.cardano.helpers.account_path_check import AccountPathChecker
|
||||
|
||||
|
||||
@unittest.skipUnless(not utils.BITCOIN_ONLY, "altcoin")
|
||||
class TestCardanoCertificate(unittest.TestCase):
|
||||
def test_validate_certificate(self):
|
||||
valid_test_vectors = [
|
||||
(
|
||||
CardanoTxCertificate(
|
||||
type=CardanoCertificateType.STAKE_REGISTRATION,
|
||||
path=[1852 | HARDENED, 1815 | HARDENED, 0 | HARDENED, 2, 0],
|
||||
),
|
||||
CardanoTxSigningMode.ORDINARY_TRANSACTION,
|
||||
),
|
||||
(
|
||||
CardanoTxCertificate(
|
||||
type=CardanoCertificateType.STAKE_REGISTRATION,
|
||||
script_hash=unhexlify(
|
||||
"29fb5fd4aa8cadd6705acc8263cee0fc62edca5ac38db593fec2f9fd"
|
||||
),
|
||||
),
|
||||
CardanoTxSigningMode.MULTISIG_TRANSACTION,
|
||||
),
|
||||
(
|
||||
CardanoTxCertificate(
|
||||
type=CardanoCertificateType.STAKE_DELEGATION,
|
||||
path=[1852 | HARDENED, 1815 | HARDENED, 0 | HARDENED, 2, 0],
|
||||
pool=unhexlify(
|
||||
"f61c42cbf7c8c53af3f520508212ad3e72f674f957fe23ff0acb4973"
|
||||
),
|
||||
),
|
||||
CardanoTxSigningMode.ORDINARY_TRANSACTION,
|
||||
),
|
||||
(
|
||||
CardanoTxCertificate(
|
||||
type=CardanoCertificateType.STAKE_DELEGATION,
|
||||
script_hash=unhexlify(
|
||||
"29fb5fd4aa8cadd6705acc8263cee0fc62edca5ac38db593fec2f9fd"
|
||||
),
|
||||
pool=unhexlify(
|
||||
"f61c42cbf7c8c53af3f520508212ad3e72f674f957fe23ff0acb4973"
|
||||
),
|
||||
),
|
||||
CardanoTxSigningMode.MULTISIG_TRANSACTION,
|
||||
),
|
||||
(
|
||||
CardanoTxCertificate(
|
||||
type=CardanoCertificateType.STAKE_DEREGISTRATION,
|
||||
path=[1852 | HARDENED, 1815 | HARDENED, 0 | HARDENED, 2, 0],
|
||||
),
|
||||
CardanoTxSigningMode.ORDINARY_TRANSACTION,
|
||||
),
|
||||
(
|
||||
CardanoTxCertificate(
|
||||
type=CardanoCertificateType.STAKE_DEREGISTRATION,
|
||||
script_hash=unhexlify(
|
||||
"29fb5fd4aa8cadd6705acc8263cee0fc62edca5ac38db593fec2f9fd"
|
||||
),
|
||||
),
|
||||
CardanoTxSigningMode.MULTISIG_TRANSACTION,
|
||||
),
|
||||
(
|
||||
CardanoTxCertificate(
|
||||
type=CardanoCertificateType.STAKE_POOL_REGISTRATION,
|
||||
pool_parameters=CardanoPoolParametersType(
|
||||
pool_id=unhexlify(
|
||||
"f61c42cbf7c8c53af3f520508212ad3e72f674f957fe23ff0acb4973"
|
||||
),
|
||||
vrf_key_hash=unhexlify(
|
||||
"198890ad6c92e80fbdab554dda02da9fb49d001bbd96181f3e07f7a6ab0d0640"
|
||||
),
|
||||
pledge=500000000,
|
||||
cost=340000000,
|
||||
margin_numerator=1,
|
||||
margin_denominator=2,
|
||||
reward_account="stake1uya87zwnmax0v6nnn8ptqkl6ydx4522kpsc3l3wmf3yswygwx45el",
|
||||
owners_count=1,
|
||||
relays_count=1,
|
||||
metadata=None,
|
||||
),
|
||||
),
|
||||
CardanoTxSigningMode.POOL_REGISTRATION_AS_OWNER,
|
||||
),
|
||||
]
|
||||
|
||||
invalid_test_vectors = [
|
||||
# STAKE_REGISTRATION neither path or script_hash is set
|
||||
(
|
||||
CardanoTxCertificate(
|
||||
type=CardanoCertificateType.STAKE_REGISTRATION,
|
||||
),
|
||||
CardanoTxSigningMode.ORDINARY_TRANSACTION,
|
||||
),
|
||||
# STAKE_REGISTRATION both path and script_hash are set
|
||||
(
|
||||
CardanoTxCertificate(
|
||||
type=CardanoCertificateType.STAKE_REGISTRATION,
|
||||
path=[1852 | HARDENED, 1815 | HARDENED, 0 | HARDENED, 2, 0],
|
||||
script_hash=unhexlify(
|
||||
"29fb5fd4aa8cadd6705acc8263cee0fc62edca5ac38db593fec2f9fd"
|
||||
),
|
||||
),
|
||||
CardanoTxSigningMode.ORDINARY_TRANSACTION,
|
||||
),
|
||||
# STAKE_REGISTRATION pool is set
|
||||
(
|
||||
CardanoTxCertificate(
|
||||
type=CardanoCertificateType.STAKE_REGISTRATION,
|
||||
path=[1852 | HARDENED, 1815 | HARDENED, 0 | HARDENED, 2, 0],
|
||||
pool=unhexlify(
|
||||
"f61c42cbf7c8c53af3f520508212ad3e72f674f957fe23ff0acb4973"
|
||||
),
|
||||
),
|
||||
CardanoTxSigningMode.ORDINARY_TRANSACTION,
|
||||
),
|
||||
# STAKE_REGISTRATION pool parameters are set
|
||||
(
|
||||
CardanoTxCertificate(
|
||||
type=CardanoCertificateType.STAKE_REGISTRATION,
|
||||
path=[1852 | HARDENED, 1815 | HARDENED, 0 | HARDENED, 2, 0],
|
||||
pool_parameters=CardanoPoolParametersType(
|
||||
pool_id=unhexlify(
|
||||
"f61c42cbf7c8c53af3f520508212ad3e72f674f957fe23ff0acb4973"
|
||||
),
|
||||
vrf_key_hash=unhexlify(
|
||||
"198890ad6c92e80fbdab554dda02da9fb49d001bbd96181f3e07f7a6ab0d0640"
|
||||
),
|
||||
pledge=500000000,
|
||||
cost=340000000,
|
||||
margin_numerator=1,
|
||||
margin_denominator=2,
|
||||
reward_account="stake1uya87zwnmax0v6nnn8ptqkl6ydx4522kpsc3l3wmf3yswygwx45el",
|
||||
owners_count=1,
|
||||
relays_count=1,
|
||||
),
|
||||
),
|
||||
CardanoTxSigningMode.POOL_REGISTRATION_AS_OWNER,
|
||||
),
|
||||
# STAKE_DELEGATION neither path or script_hash is set
|
||||
(
|
||||
CardanoTxCertificate(
|
||||
type=CardanoCertificateType.STAKE_DELEGATION,
|
||||
pool=unhexlify(
|
||||
"f61c42cbf7c8c53af3f520508212ad3e72f674f957fe23ff0acb4973"
|
||||
),
|
||||
),
|
||||
CardanoTxSigningMode.ORDINARY_TRANSACTION,
|
||||
),
|
||||
# STAKE_DELEGATION both path and script_hash are set
|
||||
(
|
||||
CardanoTxCertificate(
|
||||
type=CardanoCertificateType.STAKE_DELEGATION,
|
||||
path=[1852 | HARDENED, 1815 | HARDENED, 0 | HARDENED, 2, 0],
|
||||
script_hash=unhexlify(
|
||||
"29fb5fd4aa8cadd6705acc8263cee0fc62edca5ac38db593fec2f9fd"
|
||||
),
|
||||
pool=unhexlify(
|
||||
"f61c42cbf7c8c53af3f520508212ad3e72f674f957fe23ff0acb4973"
|
||||
),
|
||||
),
|
||||
CardanoTxSigningMode.ORDINARY_TRANSACTION,
|
||||
),
|
||||
# STAKE_DELEGATION pool parameters are set
|
||||
(
|
||||
CardanoTxCertificate(
|
||||
type=CardanoCertificateType.STAKE_DELEGATION,
|
||||
path=[1852 | HARDENED, 1815 | HARDENED, 0 | HARDENED, 2, 0],
|
||||
pool=unhexlify(
|
||||
"f61c42cbf7c8c53af3f520508212ad3e72f674f957fe23ff0acb4973"
|
||||
),
|
||||
pool_parameters=CardanoPoolParametersType(
|
||||
pool_id=unhexlify(
|
||||
"f61c42cbf7c8c53af3f520508212ad3e72f674f957fe23ff0acb4973"
|
||||
),
|
||||
vrf_key_hash=unhexlify(
|
||||
"198890ad6c92e80fbdab554dda02da9fb49d001bbd96181f3e07f7a6ab0d0640"
|
||||
),
|
||||
pledge=500000000,
|
||||
cost=340000000,
|
||||
margin_numerator=1,
|
||||
margin_denominator=2,
|
||||
reward_account="stake1uya87zwnmax0v6nnn8ptqkl6ydx4522kpsc3l3wmf3yswygwx45el",
|
||||
owners_count=1,
|
||||
relays_count=1,
|
||||
),
|
||||
),
|
||||
CardanoTxSigningMode.POOL_REGISTRATION_AS_OWNER,
|
||||
),
|
||||
# STAKE_DEREGISTRATION neither path or script_hash is set
|
||||
(
|
||||
CardanoTxCertificate(
|
||||
type=CardanoCertificateType.STAKE_DEREGISTRATION,
|
||||
),
|
||||
CardanoTxSigningMode.ORDINARY_TRANSACTION,
|
||||
),
|
||||
# STAKE_DEREGISTRATION both path and script_hash are set
|
||||
(
|
||||
CardanoTxCertificate(
|
||||
type=CardanoCertificateType.STAKE_DEREGISTRATION,
|
||||
path=[1852 | HARDENED, 1815 | HARDENED, 0 | HARDENED, 2, 0],
|
||||
script_hash=unhexlify(
|
||||
"29fb5fd4aa8cadd6705acc8263cee0fc62edca5ac38db593fec2f9fd"
|
||||
),
|
||||
),
|
||||
CardanoTxSigningMode.ORDINARY_TRANSACTION,
|
||||
),
|
||||
# STAKE_DEREGISTRATION pool is set
|
||||
(
|
||||
CardanoTxCertificate(
|
||||
type=CardanoCertificateType.STAKE_DEREGISTRATION,
|
||||
path=[1852 | HARDENED, 1815 | HARDENED, 0 | HARDENED, 2, 0],
|
||||
pool=unhexlify(
|
||||
"f61c42cbf7c8c53af3f520508212ad3e72f674f957fe23ff0acb4973"
|
||||
),
|
||||
),
|
||||
CardanoTxSigningMode.ORDINARY_TRANSACTION,
|
||||
),
|
||||
# STAKE_DEREGISTRATION pool parameters are set
|
||||
(
|
||||
CardanoTxCertificate(
|
||||
type=CardanoCertificateType.STAKE_DEREGISTRATION,
|
||||
path=[1852 | HARDENED, 1815 | HARDENED, 0 | HARDENED, 2, 0],
|
||||
pool_parameters=CardanoPoolParametersType(
|
||||
pool_id=unhexlify(
|
||||
"f61c42cbf7c8c53af3f520508212ad3e72f674f957fe23ff0acb4973"
|
||||
),
|
||||
vrf_key_hash=unhexlify(
|
||||
"198890ad6c92e80fbdab554dda02da9fb49d001bbd96181f3e07f7a6ab0d0640"
|
||||
),
|
||||
pledge=500000000,
|
||||
cost=340000000,
|
||||
margin_numerator=1,
|
||||
margin_denominator=2,
|
||||
reward_account="stake1uya87zwnmax0v6nnn8ptqkl6ydx4522kpsc3l3wmf3yswygwx45el",
|
||||
owners_count=1,
|
||||
relays_count=1,
|
||||
),
|
||||
),
|
||||
CardanoTxSigningMode.POOL_REGISTRATION_AS_OWNER,
|
||||
),
|
||||
# STAKE_POOL_REGISTRATION pool parameters are not set
|
||||
(
|
||||
CardanoTxCertificate(
|
||||
type=CardanoCertificateType.STAKE_POOL_REGISTRATION,
|
||||
),
|
||||
CardanoTxSigningMode.ORDINARY_TRANSACTION,
|
||||
),
|
||||
# STAKE_POOL_REGISTRATION path is set
|
||||
(
|
||||
CardanoTxCertificate(
|
||||
type=CardanoCertificateType.STAKE_POOL_REGISTRATION,
|
||||
path=[1852 | HARDENED, 1815 | HARDENED, 0 | HARDENED, 2, 0],
|
||||
pool_parameters=CardanoPoolParametersType(
|
||||
pool_id=unhexlify(
|
||||
"f61c42cbf7c8c53af3f520508212ad3e72f674f957fe23ff0acb4973"
|
||||
),
|
||||
vrf_key_hash=unhexlify(
|
||||
"198890ad6c92e80fbdab554dda02da9fb49d001bbd96181f3e07f7a6ab0d0640"
|
||||
),
|
||||
pledge=500000000,
|
||||
cost=340000000,
|
||||
margin_numerator=1,
|
||||
margin_denominator=2,
|
||||
reward_account="stake1uya87zwnmax0v6nnn8ptqkl6ydx4522kpsc3l3wmf3yswygwx45el",
|
||||
owners_count=1,
|
||||
relays_count=1,
|
||||
),
|
||||
),
|
||||
CardanoTxSigningMode.POOL_REGISTRATION_AS_OWNER,
|
||||
),
|
||||
# STAKE_POOL_REGISTRATION script hash is set
|
||||
(
|
||||
CardanoTxCertificate(
|
||||
type=CardanoCertificateType.STAKE_POOL_REGISTRATION,
|
||||
script_hash=unhexlify(
|
||||
"29fb5fd4aa8cadd6705acc8263cee0fc62edca5ac38db593fec2f9fd"
|
||||
),
|
||||
pool_parameters=CardanoPoolParametersType(
|
||||
pool_id=unhexlify(
|
||||
"f61c42cbf7c8c53af3f520508212ad3e72f674f957fe23ff0acb4973"
|
||||
),
|
||||
vrf_key_hash=unhexlify(
|
||||
"198890ad6c92e80fbdab554dda02da9fb49d001bbd96181f3e07f7a6ab0d0640"
|
||||
),
|
||||
pledge=500000000,
|
||||
cost=340000000,
|
||||
margin_numerator=1,
|
||||
margin_denominator=2,
|
||||
reward_account="stake1uya87zwnmax0v6nnn8ptqkl6ydx4522kpsc3l3wmf3yswygwx45el",
|
||||
owners_count=1,
|
||||
relays_count=1,
|
||||
),
|
||||
),
|
||||
CardanoTxSigningMode.POOL_REGISTRATION_AS_OWNER,
|
||||
),
|
||||
# STAKE_POOL_REGISTRATION pool is set
|
||||
(
|
||||
CardanoTxCertificate(
|
||||
type=CardanoCertificateType.STAKE_POOL_REGISTRATION,
|
||||
script_hash=unhexlify(
|
||||
"29fb5fd4aa8cadd6705acc8263cee0fc62edca5ac38db593fec2f9fd"
|
||||
),
|
||||
pool=unhexlify(
|
||||
"f61c42cbf7c8c53af3f520508212ad3e72f674f957fe23ff0acb4973"
|
||||
),
|
||||
pool_parameters=CardanoPoolParametersType(
|
||||
pool_id=unhexlify(
|
||||
"f61c42cbf7c8c53af3f520508212ad3e72f674f957fe23ff0acb4973"
|
||||
),
|
||||
vrf_key_hash=unhexlify(
|
||||
"198890ad6c92e80fbdab554dda02da9fb49d001bbd96181f3e07f7a6ab0d0640"
|
||||
),
|
||||
pledge=500000000,
|
||||
cost=340000000,
|
||||
margin_numerator=1,
|
||||
margin_denominator=2,
|
||||
reward_account="stake1uya87zwnmax0v6nnn8ptqkl6ydx4522kpsc3l3wmf3yswygwx45el",
|
||||
owners_count=1,
|
||||
relays_count=1,
|
||||
),
|
||||
),
|
||||
CardanoTxSigningMode.POOL_REGISTRATION_AS_OWNER,
|
||||
),
|
||||
]
|
||||
|
||||
for certificate, signing_mode in valid_test_vectors:
|
||||
validate_certificate(
|
||||
certificate,
|
||||
signing_mode,
|
||||
protocol_magics.MAINNET,
|
||||
network_ids.MAINNET,
|
||||
AccountPathChecker(),
|
||||
)
|
||||
|
||||
for certificate, signing_mode in invalid_test_vectors:
|
||||
with self.assertRaises(wire.ProcessError):
|
||||
validate_certificate(
|
||||
certificate,
|
||||
signing_mode,
|
||||
protocol_magics.MAINNET,
|
||||
network_ids.MAINNET,
|
||||
AccountPathChecker(),
|
||||
)
|
||||
|
||||
|
||||
if __name__ == "__main__":
|
||||
unittest.main()
|
@ -24,6 +24,7 @@ from .tools import expect
|
||||
SIGNING_MODE_IDS = {
|
||||
"ORDINARY_TRANSACTION": messages.CardanoTxSigningMode.ORDINARY_TRANSACTION,
|
||||
"POOL_REGISTRATION_AS_OWNER": messages.CardanoTxSigningMode.POOL_REGISTRATION_AS_OWNER,
|
||||
"MULTISIG_TRANSACTION": messages.CardanoTxSigningMode.MULTISIG_TRANSACTION,
|
||||
}
|
||||
|
||||
PROTOCOL_MAGICS = {"mainnet": 764824073, "testnet": 42}
|
||||
@ -41,9 +42,7 @@ REQUIRED_FIELDS_POOL_PARAMETERS = (
|
||||
"reward_account",
|
||||
"owners",
|
||||
)
|
||||
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",
|
||||
@ -54,6 +53,7 @@ REQUIRED_FIELDS_CATALYST_REGISTRATION = (
|
||||
INCOMPLETE_OUTPUT_ERROR_MESSAGE = "The output is missing some fields"
|
||||
|
||||
INVALID_OUTPUT_TOKEN_BUNDLE_ENTRY = "The output's token_bundle entry is invalid"
|
||||
INVALID_MINT_TOKEN_BUNDLE_ENTRY = "The mint token_bundle entry is invalid"
|
||||
|
||||
InputWithPath = Tuple[messages.CardanoTxInput, List[int]]
|
||||
AssetGroupWithTokens = Tuple[messages.CardanoAssetGroup, List[messages.CardanoToken]]
|
||||
@ -66,6 +66,9 @@ CertificateItem = Union[
|
||||
messages.CardanoPoolOwner,
|
||||
messages.CardanoPoolRelayParameters,
|
||||
]
|
||||
MintItem = Union[
|
||||
messages.CardanoTxMint, messages.CardanoAssetGroup, messages.CardanoToken
|
||||
]
|
||||
PoolOwnersAndRelays = Tuple[
|
||||
List[messages.CardanoPoolOwner], List[messages.CardanoPoolRelayParameters]
|
||||
]
|
||||
@ -160,10 +163,12 @@ def parse_output(output) -> OutputWithAssetGroups:
|
||||
address = output["address"]
|
||||
|
||||
if contains_address_type:
|
||||
address_parameters = _parse_address_parameters(output)
|
||||
address_parameters = _parse_address_parameters(
|
||||
output, INCOMPLETE_OUTPUT_ERROR_MESSAGE
|
||||
)
|
||||
|
||||
if "token_bundle" in output:
|
||||
token_bundle = _parse_token_bundle(output["token_bundle"])
|
||||
token_bundle = _parse_token_bundle(output["token_bundle"], is_mint=False)
|
||||
|
||||
return (
|
||||
messages.CardanoTxOutput(
|
||||
@ -176,19 +181,26 @@ def parse_output(output) -> OutputWithAssetGroups:
|
||||
)
|
||||
|
||||
|
||||
def _parse_token_bundle(token_bundle) -> List[AssetGroupWithTokens]:
|
||||
def _parse_token_bundle(token_bundle, is_mint: bool) -> List[AssetGroupWithTokens]:
|
||||
error_message: str
|
||||
if is_mint:
|
||||
error_message = INVALID_MINT_TOKEN_BUNDLE_ENTRY
|
||||
else:
|
||||
error_message = INVALID_OUTPUT_TOKEN_BUNDLE_ENTRY
|
||||
|
||||
result = []
|
||||
for token_group in token_bundle:
|
||||
if not all(k in token_group for k in REQUIRED_FIELDS_TOKEN_GROUP):
|
||||
raise ValueError(INVALID_OUTPUT_TOKEN_BUNDLE_ENTRY)
|
||||
raise ValueError(error_message)
|
||||
|
||||
tokens = _parse_tokens(token_group["tokens"])
|
||||
tokens = _parse_tokens(token_group["tokens"], is_mint)
|
||||
|
||||
result.append(
|
||||
(
|
||||
messages.CardanoAssetGroup(
|
||||
policy_id=bytes.fromhex(token_group["policy_id"]),
|
||||
tokens_count=len(tokens),
|
||||
is_mint=is_mint,
|
||||
),
|
||||
tokens,
|
||||
)
|
||||
@ -197,16 +209,34 @@ def _parse_token_bundle(token_bundle) -> List[AssetGroupWithTokens]:
|
||||
return result
|
||||
|
||||
|
||||
def _parse_tokens(tokens) -> List[messages.CardanoToken]:
|
||||
def _parse_tokens(tokens, is_mint: bool) -> List[messages.CardanoToken]:
|
||||
error_message: str
|
||||
if is_mint:
|
||||
error_message = INVALID_MINT_TOKEN_BUNDLE_ENTRY
|
||||
else:
|
||||
error_message = INVALID_OUTPUT_TOKEN_BUNDLE_ENTRY
|
||||
|
||||
result = []
|
||||
for token in tokens:
|
||||
if not all(k in token for k in REQUIRED_FIELDS_TOKEN):
|
||||
raise ValueError(INVALID_OUTPUT_TOKEN_BUNDLE_ENTRY)
|
||||
if "asset_name_bytes" not in token:
|
||||
raise ValueError(error_message)
|
||||
|
||||
mint_amount = None
|
||||
amount = None
|
||||
if is_mint:
|
||||
if "mint_amount" not in token:
|
||||
raise ValueError(error_message)
|
||||
mint_amount = int(token["mint_amount"])
|
||||
else:
|
||||
if "amount" not in token:
|
||||
raise ValueError(error_message)
|
||||
amount = int(token["amount"])
|
||||
|
||||
result.append(
|
||||
messages.CardanoToken(
|
||||
asset_name_bytes=bytes.fromhex(token["asset_name_bytes"]),
|
||||
amount=int(token["amount"]),
|
||||
amount=amount,
|
||||
mint_amount=mint_amount,
|
||||
)
|
||||
)
|
||||
|
||||
@ -214,12 +244,12 @@ def _parse_tokens(tokens) -> List[messages.CardanoToken]:
|
||||
|
||||
|
||||
def _parse_address_parameters(
|
||||
address_parameters,
|
||||
address_parameters, error_message: str
|
||||
) -> messages.CardanoAddressParametersType:
|
||||
if "addressType" not in address_parameters:
|
||||
raise ValueError(INCOMPLETE_OUTPUT_ERROR_MESSAGE)
|
||||
raise ValueError(error_message)
|
||||
|
||||
path = tools.parse_path(address_parameters.get("path"))
|
||||
payment_path = tools.parse_path(address_parameters.get("path"))
|
||||
staking_path = tools.parse_path(address_parameters.get("stakingPath"))
|
||||
staking_key_hash_bytes = parse_optional_bytes(
|
||||
address_parameters.get("stakingKeyHash")
|
||||
@ -233,7 +263,7 @@ def _parse_address_parameters(
|
||||
|
||||
return create_address_parameters(
|
||||
int(address_parameters["addressType"]),
|
||||
path,
|
||||
payment_path,
|
||||
staking_path,
|
||||
staking_key_hash_bytes,
|
||||
address_parameters.get("blockIndex"),
|
||||
@ -287,11 +317,16 @@ def parse_certificate(certificate) -> CertificateWithPoolOwnersAndRelays:
|
||||
if "pool" not in certificate:
|
||||
raise CERTIFICATE_MISSING_FIELDS_ERROR
|
||||
|
||||
path, script_hash = _parse_path_or_script_hash(
|
||||
certificate, CERTIFICATE_MISSING_FIELDS_ERROR
|
||||
)
|
||||
|
||||
return (
|
||||
messages.CardanoTxCertificate(
|
||||
type=certificate_type,
|
||||
path=tools.parse_path(certificate["path"]),
|
||||
path=path,
|
||||
pool=bytes.fromhex(certificate["pool"]),
|
||||
script_hash=script_hash,
|
||||
),
|
||||
None,
|
||||
)
|
||||
@ -299,12 +334,13 @@ def parse_certificate(certificate) -> CertificateWithPoolOwnersAndRelays:
|
||||
messages.CardanoCertificateType.STAKE_REGISTRATION,
|
||||
messages.CardanoCertificateType.STAKE_DEREGISTRATION,
|
||||
):
|
||||
if "path" not in certificate:
|
||||
raise CERTIFICATE_MISSING_FIELDS_ERROR
|
||||
path, script_hash = _parse_path_or_script_hash(
|
||||
certificate, CERTIFICATE_MISSING_FIELDS_ERROR
|
||||
)
|
||||
|
||||
return (
|
||||
messages.CardanoTxCertificate(
|
||||
type=certificate_type,
|
||||
path=tools.parse_path(certificate["path"]),
|
||||
type=certificate_type, path=path, script_hash=script_hash
|
||||
),
|
||||
None,
|
||||
)
|
||||
@ -356,6 +392,18 @@ def parse_certificate(certificate) -> CertificateWithPoolOwnersAndRelays:
|
||||
raise ValueError("Unknown certificate type")
|
||||
|
||||
|
||||
def _parse_path_or_script_hash(
|
||||
obj, error: ValueError
|
||||
) -> Tuple[List[int], Optional[bytes]]:
|
||||
if "path" not in obj and "script_hash" not in obj:
|
||||
raise error
|
||||
|
||||
path = tools.parse_path(obj.get("path"))
|
||||
script_hash = parse_optional_bytes(obj.get("script_hash"))
|
||||
|
||||
return path, script_hash
|
||||
|
||||
|
||||
def _parse_pool_owner(pool_owner) -> messages.CardanoPoolOwner:
|
||||
if "staking_key_path" in pool_owner:
|
||||
return messages.CardanoPoolOwner(
|
||||
@ -404,13 +452,21 @@ def _parse_pool_relay(pool_relay) -> messages.CardanoPoolRelayParameters:
|
||||
|
||||
|
||||
def parse_withdrawal(withdrawal) -> messages.CardanoTxWithdrawal:
|
||||
if not all(k in withdrawal for k in REQUIRED_FIELDS_WITHDRAWAL):
|
||||
raise ValueError("Withdrawal is missing some fields")
|
||||
WITHDRAWAL_MISSING_FIELDS_ERROR = ValueError(
|
||||
"The withdrawal is missing some fields"
|
||||
)
|
||||
|
||||
if "amount" not in withdrawal:
|
||||
raise WITHDRAWAL_MISSING_FIELDS_ERROR
|
||||
|
||||
path, script_hash = _parse_path_or_script_hash(
|
||||
withdrawal, WITHDRAWAL_MISSING_FIELDS_ERROR
|
||||
)
|
||||
|
||||
path = withdrawal["path"]
|
||||
return messages.CardanoTxWithdrawal(
|
||||
path=tools.parse_path(path),
|
||||
path=path,
|
||||
amount=int(withdrawal["amount"]),
|
||||
script_hash=script_hash,
|
||||
)
|
||||
|
||||
|
||||
@ -441,7 +497,8 @@ def parse_auxiliary_data(auxiliary_data) -> messages.CardanoTxAuxiliaryData:
|
||||
staking_path=tools.parse_path(catalyst_registration["staking_path"]),
|
||||
nonce=catalyst_registration["nonce"],
|
||||
reward_address_parameters=_parse_address_parameters(
|
||||
catalyst_registration["reward_address_parameters"]
|
||||
catalyst_registration["reward_address_parameters"],
|
||||
AUXILIARY_DATA_MISSING_FIELDS_ERROR,
|
||||
),
|
||||
)
|
||||
)
|
||||
@ -455,33 +512,62 @@ def parse_auxiliary_data(auxiliary_data) -> messages.CardanoTxAuxiliaryData:
|
||||
)
|
||||
|
||||
|
||||
def _get_witness_paths(
|
||||
def parse_mint(mint) -> List[AssetGroupWithTokens]:
|
||||
return _parse_token_bundle(mint, is_mint=True)
|
||||
|
||||
|
||||
def parse_additional_witness_request(
|
||||
additional_witness_request,
|
||||
) -> Path:
|
||||
if "path" not in additional_witness_request:
|
||||
raise ValueError("Invalid additional witness request")
|
||||
|
||||
return tools.parse_path(additional_witness_request["path"])
|
||||
|
||||
|
||||
def _get_witness_requests(
|
||||
inputs: List[InputWithPath],
|
||||
certificates: List[CertificateWithPoolOwnersAndRelays],
|
||||
withdrawals: List[messages.CardanoTxWithdrawal],
|
||||
) -> List[Path]:
|
||||
additional_witness_requests: List[Path],
|
||||
signing_mode: messages.CardanoTxSigningMode,
|
||||
) -> List[messages.CardanoTxWitnessRequest]:
|
||||
paths = set()
|
||||
for _, path in inputs:
|
||||
if path:
|
||||
paths.add(tuple(path))
|
||||
for certificate, pool_owners_and_relays in certificates:
|
||||
if certificate.type in (
|
||||
messages.CardanoCertificateType.STAKE_DEREGISTRATION,
|
||||
messages.CardanoCertificateType.STAKE_DELEGATION,
|
||||
):
|
||||
paths.add(tuple(certificate.path))
|
||||
elif (
|
||||
certificate.type == messages.CardanoCertificateType.STAKE_POOL_REGISTRATION
|
||||
and pool_owners_and_relays is not None
|
||||
):
|
||||
owners, _ = pool_owners_and_relays
|
||||
for pool_owner in owners:
|
||||
if pool_owner.staking_key_path:
|
||||
paths.add(tuple(pool_owner.staking_key_path))
|
||||
for withdrawal in withdrawals:
|
||||
paths.add(tuple(withdrawal.path))
|
||||
|
||||
return sorted([list(path) for path in paths])
|
||||
# don't gather paths from tx elements in MULTISIG_TRANSACTION signing mode
|
||||
if signing_mode != messages.CardanoTxSigningMode.MULTISIG_TRANSACTION:
|
||||
for _, path in inputs:
|
||||
if path:
|
||||
paths.add(tuple(path))
|
||||
for certificate, pool_owners_and_relays in certificates:
|
||||
if (
|
||||
certificate.type
|
||||
in (
|
||||
messages.CardanoCertificateType.STAKE_DEREGISTRATION,
|
||||
messages.CardanoCertificateType.STAKE_DELEGATION,
|
||||
)
|
||||
and certificate.path
|
||||
):
|
||||
paths.add(tuple(certificate.path))
|
||||
elif (
|
||||
certificate.type
|
||||
== messages.CardanoCertificateType.STAKE_POOL_REGISTRATION
|
||||
and pool_owners_and_relays is not None
|
||||
):
|
||||
owners, _ = pool_owners_and_relays
|
||||
for pool_owner in owners:
|
||||
if pool_owner.staking_key_path:
|
||||
paths.add(tuple(pool_owner.staking_key_path))
|
||||
for withdrawal in withdrawals:
|
||||
if withdrawal.path:
|
||||
paths.add(tuple(withdrawal.path))
|
||||
|
||||
# add additional_witness_requests in all cases
|
||||
for additional_witness_request in additional_witness_requests:
|
||||
paths.add(tuple(additional_witness_request))
|
||||
|
||||
sorted_paths = sorted([list(path) for path in paths])
|
||||
return [messages.CardanoTxWitnessRequest(path=path) for path in sorted_paths]
|
||||
|
||||
|
||||
def _get_input_items(inputs: List[InputWithPath]) -> Iterator[messages.CardanoTxInput]:
|
||||
@ -508,6 +594,13 @@ def _get_certificate_items(
|
||||
yield from relays
|
||||
|
||||
|
||||
def _get_mint_items(mint: List[AssetGroupWithTokens]) -> Iterator[MintItem]:
|
||||
yield messages.CardanoTxMint(asset_groups_count=len(mint))
|
||||
for asset_group, tokens in mint:
|
||||
yield asset_group
|
||||
yield from tokens
|
||||
|
||||
|
||||
# ====== Client functions ====== #
|
||||
|
||||
|
||||
@ -561,10 +654,14 @@ def sign_tx(
|
||||
protocol_magic: int = PROTOCOL_MAGICS["mainnet"],
|
||||
network_id: int = NETWORK_IDS["mainnet"],
|
||||
auxiliary_data: messages.CardanoTxAuxiliaryData = None,
|
||||
mint: List[AssetGroupWithTokens] = (),
|
||||
additional_witness_requests: List[Path] = (),
|
||||
) -> SignTxResponse:
|
||||
UNEXPECTED_RESPONSE_ERROR = exceptions.TrezorException("Unexpected response")
|
||||
|
||||
witness_paths = _get_witness_paths(inputs, certificates, withdrawals)
|
||||
witness_requests = _get_witness_requests(
|
||||
inputs, certificates, withdrawals, additional_witness_requests, signing_mode
|
||||
)
|
||||
|
||||
response = client.call(
|
||||
messages.CardanoSignTxInit(
|
||||
@ -579,7 +676,8 @@ def sign_tx(
|
||||
protocol_magic=protocol_magic,
|
||||
network_id=network_id,
|
||||
has_auxiliary_data=auxiliary_data is not None,
|
||||
witness_requests_count=len(witness_paths),
|
||||
minting_asset_groups_count=len(mint),
|
||||
witness_requests_count=len(witness_requests),
|
||||
)
|
||||
)
|
||||
if not isinstance(response, messages.CardanoTxItemAck):
|
||||
@ -615,9 +713,15 @@ def sign_tx(
|
||||
if not isinstance(response, messages.CardanoTxItemAck):
|
||||
raise UNEXPECTED_RESPONSE_ERROR
|
||||
|
||||
if mint:
|
||||
for mint_item in _get_mint_items(mint):
|
||||
response = client.call(mint_item)
|
||||
if not isinstance(response, messages.CardanoTxItemAck):
|
||||
raise UNEXPECTED_RESPONSE_ERROR
|
||||
|
||||
sign_tx_response["witnesses"] = []
|
||||
for path in witness_paths:
|
||||
response = client.call(messages.CardanoTxWitnessRequest(path=path))
|
||||
for witness_request in witness_requests:
|
||||
response = client.call(witness_request)
|
||||
if not isinstance(response, messages.CardanoTxWitnessResponse):
|
||||
raise UNEXPECTED_RESPONSE_ERROR
|
||||
sign_tx_response["witnesses"].append(
|
||||
|
@ -66,6 +66,11 @@ def sign_tx(client, file, signing_mode, protocol_magic, network_id, testnet):
|
||||
for withdrawal in transaction.get("withdrawals", ())
|
||||
]
|
||||
auxiliary_data = cardano.parse_auxiliary_data(transaction.get("auxiliary_data"))
|
||||
mint = cardano.parse_mint(transaction.get("mint", ()))
|
||||
additional_witness_requests = [
|
||||
cardano.parse_additional_witness_request(p)
|
||||
for p in transaction["additional_witness_requests"]
|
||||
]
|
||||
|
||||
sign_tx_response = cardano.sign_tx(
|
||||
client,
|
||||
@ -80,6 +85,8 @@ def sign_tx(client, file, signing_mode, protocol_magic, network_id, testnet):
|
||||
protocol_magic,
|
||||
network_id,
|
||||
auxiliary_data,
|
||||
mint,
|
||||
additional_witness_requests,
|
||||
)
|
||||
|
||||
sign_tx_response["tx_hash"] = sign_tx_response["tx_hash"].hex()
|
||||
|
@ -178,6 +178,7 @@ class MessageType(IntEnum):
|
||||
CardanoPoolRelayParameters = 329
|
||||
CardanoGetNativeScriptHash = 330
|
||||
CardanoNativeScriptHash = 331
|
||||
CardanoTxMint = 332
|
||||
RippleGetAddress = 400
|
||||
RippleAddress = 401
|
||||
RippleSignTx = 402
|
||||
@ -380,6 +381,7 @@ class CardanoTxAuxiliaryDataSupplementType(IntEnum):
|
||||
class CardanoTxSigningMode(IntEnum):
|
||||
ORDINARY_TRANSACTION = 0
|
||||
POOL_REGISTRATION_AS_OWNER = 1
|
||||
MULTISIG_TRANSACTION = 2
|
||||
|
||||
|
||||
class CardanoTxWitnessType(IntEnum):
|
||||
@ -2072,6 +2074,7 @@ class CardanoSignTxInit(protobuf.MessageType):
|
||||
10: protobuf.Field("has_auxiliary_data", "bool", repeated=False, required=True),
|
||||
11: protobuf.Field("validity_interval_start", "uint64", repeated=False, required=False),
|
||||
12: protobuf.Field("witness_requests_count", "uint32", repeated=False, required=True),
|
||||
13: protobuf.Field("minting_asset_groups_count", "uint32", repeated=False, required=True),
|
||||
}
|
||||
|
||||
def __init__(
|
||||
@ -2087,6 +2090,7 @@ class CardanoSignTxInit(protobuf.MessageType):
|
||||
withdrawals_count: "int",
|
||||
has_auxiliary_data: "bool",
|
||||
witness_requests_count: "int",
|
||||
minting_asset_groups_count: "int",
|
||||
ttl: Optional["int"] = None,
|
||||
validity_interval_start: Optional["int"] = None,
|
||||
) -> None:
|
||||
@ -2100,6 +2104,7 @@ class CardanoSignTxInit(protobuf.MessageType):
|
||||
self.withdrawals_count = withdrawals_count
|
||||
self.has_auxiliary_data = has_auxiliary_data
|
||||
self.witness_requests_count = witness_requests_count
|
||||
self.minting_asset_groups_count = minting_asset_groups_count
|
||||
self.ttl = ttl
|
||||
self.validity_interval_start = validity_interval_start
|
||||
|
||||
@ -2165,17 +2170,20 @@ class CardanoToken(protobuf.MessageType):
|
||||
MESSAGE_WIRE_TYPE = 324
|
||||
FIELDS = {
|
||||
1: protobuf.Field("asset_name_bytes", "bytes", repeated=False, required=True),
|
||||
2: protobuf.Field("amount", "uint64", repeated=False, required=True),
|
||||
2: protobuf.Field("amount", "uint64", repeated=False, required=False),
|
||||
3: protobuf.Field("mint_amount", "sint64", repeated=False, required=False),
|
||||
}
|
||||
|
||||
def __init__(
|
||||
self,
|
||||
*,
|
||||
asset_name_bytes: "bytes",
|
||||
amount: "int",
|
||||
amount: Optional["int"] = None,
|
||||
mint_amount: Optional["int"] = None,
|
||||
) -> None:
|
||||
self.asset_name_bytes = asset_name_bytes
|
||||
self.amount = amount
|
||||
self.mint_amount = mint_amount
|
||||
|
||||
|
||||
class CardanoPoolOwner(protobuf.MessageType):
|
||||
@ -2292,6 +2300,7 @@ class CardanoTxCertificate(protobuf.MessageType):
|
||||
2: protobuf.Field("path", "uint32", repeated=True, required=False),
|
||||
3: protobuf.Field("pool", "bytes", repeated=False, required=False),
|
||||
4: protobuf.Field("pool_parameters", "CardanoPoolParametersType", repeated=False, required=False),
|
||||
5: protobuf.Field("script_hash", "bytes", repeated=False, required=False),
|
||||
}
|
||||
|
||||
def __init__(
|
||||
@ -2301,11 +2310,13 @@ class CardanoTxCertificate(protobuf.MessageType):
|
||||
path: Optional[List["int"]] = None,
|
||||
pool: Optional["bytes"] = None,
|
||||
pool_parameters: Optional["CardanoPoolParametersType"] = None,
|
||||
script_hash: Optional["bytes"] = None,
|
||||
) -> None:
|
||||
self.path = path if path is not None else []
|
||||
self.type = type
|
||||
self.pool = pool
|
||||
self.pool_parameters = pool_parameters
|
||||
self.script_hash = script_hash
|
||||
|
||||
|
||||
class CardanoTxWithdrawal(protobuf.MessageType):
|
||||
@ -2313,6 +2324,7 @@ class CardanoTxWithdrawal(protobuf.MessageType):
|
||||
FIELDS = {
|
||||
1: protobuf.Field("path", "uint32", repeated=True, required=False),
|
||||
2: protobuf.Field("amount", "uint64", repeated=False, required=True),
|
||||
3: protobuf.Field("script_hash", "bytes", repeated=False, required=False),
|
||||
}
|
||||
|
||||
def __init__(
|
||||
@ -2320,9 +2332,11 @@ class CardanoTxWithdrawal(protobuf.MessageType):
|
||||
*,
|
||||
amount: "int",
|
||||
path: Optional[List["int"]] = None,
|
||||
script_hash: Optional["bytes"] = None,
|
||||
) -> None:
|
||||
self.path = path if path is not None else []
|
||||
self.amount = amount
|
||||
self.script_hash = script_hash
|
||||
|
||||
|
||||
class CardanoCatalystRegistrationParametersType(protobuf.MessageType):
|
||||
@ -2365,6 +2379,20 @@ class CardanoTxAuxiliaryData(protobuf.MessageType):
|
||||
self.hash = hash
|
||||
|
||||
|
||||
class CardanoTxMint(protobuf.MessageType):
|
||||
MESSAGE_WIRE_TYPE = 332
|
||||
FIELDS = {
|
||||
1: protobuf.Field("asset_groups_count", "uint32", repeated=False, required=True),
|
||||
}
|
||||
|
||||
def __init__(
|
||||
self,
|
||||
*,
|
||||
asset_groups_count: "int",
|
||||
) -> None:
|
||||
self.asset_groups_count = asset_groups_count
|
||||
|
||||
|
||||
class CardanoTxItemAck(protobuf.MessageType):
|
||||
MESSAGE_WIRE_TYPE = 313
|
||||
|
||||
|
@ -31,6 +31,7 @@ pytestmark = [
|
||||
@parametrize_using_common_fixtures(
|
||||
"cardano/sign_tx_stake_pool_registration.json",
|
||||
"cardano/sign_tx.json",
|
||||
"cardano/sign_tx.multisig.json",
|
||||
"cardano/sign_tx.slip39.json",
|
||||
)
|
||||
def test_cardano_sign_tx(client, parameters, result):
|
||||
@ -40,6 +41,11 @@ def test_cardano_sign_tx(client, parameters, result):
|
||||
certificates = [cardano.parse_certificate(c) for c in parameters["certificates"]]
|
||||
withdrawals = [cardano.parse_withdrawal(w) for w in parameters["withdrawals"]]
|
||||
auxiliary_data = cardano.parse_auxiliary_data(parameters["auxiliary_data"])
|
||||
mint = cardano.parse_mint(parameters["mint"])
|
||||
additional_witness_requests = [
|
||||
cardano.parse_additional_witness_request(p)
|
||||
for p in parameters["additional_witness_requests"]
|
||||
]
|
||||
|
||||
if parameters.get("security_checks") == "prompt":
|
||||
device.apply_settings(
|
||||
@ -62,12 +68,16 @@ def test_cardano_sign_tx(client, parameters, result):
|
||||
protocol_magic=parameters["protocol_magic"],
|
||||
network_id=parameters["network_id"],
|
||||
auxiliary_data=auxiliary_data,
|
||||
mint=mint,
|
||||
additional_witness_requests=additional_witness_requests,
|
||||
)
|
||||
assert response == _transform_expected_result(result)
|
||||
|
||||
|
||||
@parametrize_using_common_fixtures(
|
||||
"cardano/sign_tx.failed.json", "cardano/sign_tx_stake_pool_registration.failed.json"
|
||||
"cardano/sign_tx.failed.json",
|
||||
"cardano/sign_tx.multisig.failed.json",
|
||||
"cardano/sign_tx_stake_pool_registration.failed.json",
|
||||
)
|
||||
def test_cardano_sign_tx_failed(client, parameters, result):
|
||||
signing_mode = messages.CardanoTxSigningMode.__members__[parameters["signing_mode"]]
|
||||
@ -76,6 +86,18 @@ def test_cardano_sign_tx_failed(client, parameters, result):
|
||||
certificates = [cardano.parse_certificate(c) for c in parameters["certificates"]]
|
||||
withdrawals = [cardano.parse_withdrawal(w) for w in parameters["withdrawals"]]
|
||||
auxiliary_data = cardano.parse_auxiliary_data(parameters["auxiliary_data"])
|
||||
mint = cardano.parse_mint(parameters["mint"])
|
||||
additional_witness_requests = [
|
||||
cardano.parse_additional_witness_request(p)
|
||||
for p in parameters["additional_witness_requests"]
|
||||
]
|
||||
|
||||
if parameters.get("security_checks") == "prompt":
|
||||
device.apply_settings(
|
||||
client, safety_checks=messages.SafetyCheckLevel.PromptTemporarily
|
||||
)
|
||||
else:
|
||||
device.apply_settings(client, safety_checks=messages.SafetyCheckLevel.Strict)
|
||||
|
||||
with client:
|
||||
with pytest.raises(TrezorFailure, match=result["error_message"]):
|
||||
@ -92,6 +114,8 @@ def test_cardano_sign_tx_failed(client, parameters, result):
|
||||
protocol_magic=parameters["protocol_magic"],
|
||||
network_id=parameters["network_id"],
|
||||
auxiliary_data=auxiliary_data,
|
||||
mint=mint,
|
||||
additional_witness_requests=additional_witness_requests,
|
||||
)
|
||||
|
||||
|
||||
|
Loading…
Reference in New Issue
Block a user