mirror of
https://github.com/trezor/trezor-firmware.git
synced 2024-12-18 04:18:10 +00:00
fix(cardano): add map key canonical order validation
This commit is contained in:
parent
143af80aea
commit
1388912762
367
common/tests/fixtures/cardano/sign_tx.failed.json
vendored
367
common/tests/fixtures/cardano/sign_tx.failed.json
vendored
@ -923,48 +923,6 @@
|
||||
"error_message": "Invalid withdrawal"
|
||||
}
|
||||
},
|
||||
{
|
||||
"description": "Duplicate withdrawal",
|
||||
"parameters": {
|
||||
"protocol_magic": 764824073,
|
||||
"network_id": 1,
|
||||
"fee": 42,
|
||||
"ttl": 10,
|
||||
"certificates": [],
|
||||
"withdrawals": [
|
||||
{
|
||||
"path": "m/1852'/1815'/0'/2/0",
|
||||
"amount": "1000"
|
||||
},
|
||||
{
|
||||
"path": "m/1852'/1815'/0'/2/0",
|
||||
"amount": "2000"
|
||||
}
|
||||
],
|
||||
"auxiliary_data": null,
|
||||
"inputs": [
|
||||
{
|
||||
"path": "m/1852'/1815'/0'/0/0",
|
||||
"prev_hash": "3b40265111d8bb3c3c608d95b3a0bf83461ace32d79336579a1939b3aad1c0b7",
|
||||
"prev_index": 0
|
||||
}
|
||||
],
|
||||
"outputs": [
|
||||
{
|
||||
"address": "Ae2tdPwUPEZCanmBz5g2GEwFqKTKpNJcGYPKfDxoNeKZ8bRHr8366kseiK2",
|
||||
"amount": "3003112"
|
||||
}
|
||||
],
|
||||
"mint": [],
|
||||
"script_data_hash": null,
|
||||
"signing_mode": "ORDINARY_TRANSACTION",
|
||||
"additional_witness_requests": [],
|
||||
"include_network_id": false
|
||||
},
|
||||
"result": {
|
||||
"error_message": "Duplicate withdrawals"
|
||||
}
|
||||
},
|
||||
{
|
||||
"description": "Auxiliary data hash has incorrect length",
|
||||
"parameters": {
|
||||
@ -1514,6 +1472,331 @@
|
||||
"error_message": "Invalid token bundle in output"
|
||||
}
|
||||
},
|
||||
{
|
||||
"description": "Repeated asset name in mint token group",
|
||||
"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": [
|
||||
{
|
||||
"policy_id": "95a292ffee938be03e9bae5657982a74e9014eb4960108c9e23a5b39",
|
||||
"tokens": [
|
||||
{
|
||||
"asset_name_bytes": "74652474436f696e",
|
||||
"mint_amount": "7878754"
|
||||
},
|
||||
{
|
||||
"asset_name_bytes": "74652474436f696e",
|
||||
"mint_amount": "1234"
|
||||
}
|
||||
]
|
||||
}
|
||||
],
|
||||
"script_data_hash": null,
|
||||
"signing_mode": "ORDINARY_TRANSACTION",
|
||||
"additional_witness_requests": [],
|
||||
"include_network_id": false
|
||||
},
|
||||
"result": {
|
||||
"error_message": "Invalid mint token bundle"
|
||||
}
|
||||
},
|
||||
{
|
||||
"description": "Repeated policyId in mint",
|
||||
"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": [
|
||||
{
|
||||
"policy_id": "95a292ffee938be03e9bae5657982a74e9014eb4960108c9e23a5b39",
|
||||
"tokens": [
|
||||
{
|
||||
"asset_name_bytes": "74652474436f696e",
|
||||
"mint_amount": "7878754"
|
||||
}
|
||||
]
|
||||
},
|
||||
{
|
||||
"policy_id": "95a292ffee938be03e9bae5657982a74e9014eb4960108c9e23a5b39",
|
||||
"tokens": [
|
||||
{
|
||||
"asset_name_bytes": "74652474436f696f",
|
||||
"mint_amount": "7878754"
|
||||
}
|
||||
]
|
||||
}
|
||||
],
|
||||
"script_data_hash": null,
|
||||
"signing_mode": "ORDINARY_TRANSACTION",
|
||||
"additional_witness_requests": [],
|
||||
"include_network_id": false
|
||||
},
|
||||
"result": {
|
||||
"error_message": "Invalid mint token bundle"
|
||||
}
|
||||
},
|
||||
{
|
||||
"description": "Asset names in multiasset token group in wrong order",
|
||||
"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",
|
||||
"token_bundle": [
|
||||
{
|
||||
"policy_id": "95a292ffee938be03e9bae5657982a74e9014eb4960108c9e23a5b39",
|
||||
"tokens": [
|
||||
{
|
||||
"asset_name_bytes": "74652474436f696e",
|
||||
"amount": "7878754"
|
||||
},
|
||||
{
|
||||
"asset_name_bytes": "76652474436f696e",
|
||||
"amount": "1234"
|
||||
},
|
||||
{
|
||||
"asset_name_bytes": "75652474436f696e",
|
||||
"amount": "1234"
|
||||
}
|
||||
]
|
||||
}
|
||||
]
|
||||
}
|
||||
],
|
||||
"mint": [],
|
||||
"script_data_hash": null,
|
||||
"signing_mode": "ORDINARY_TRANSACTION",
|
||||
"additional_witness_requests": [],
|
||||
"include_network_id": false
|
||||
},
|
||||
"result": {
|
||||
"error_message": "Invalid token bundle in output"
|
||||
}
|
||||
},
|
||||
{
|
||||
"description": "PolicyIds in multiasset output in wrong order",
|
||||
"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",
|
||||
"token_bundle": [
|
||||
{
|
||||
"policy_id": "95a292ffee938be03e9bae5657982a74e9014eb4960108c9e23a5b39",
|
||||
"tokens": [
|
||||
{
|
||||
"asset_name_bytes": "74652474436f696d",
|
||||
"amount": "7878754"
|
||||
}
|
||||
]
|
||||
},
|
||||
{
|
||||
"policy_id": "9aa292ffee938be03e9bae5657982a74e9014eb4960108c9e23a5b39",
|
||||
"tokens": [
|
||||
{
|
||||
"asset_name_bytes": "74652474436f696e",
|
||||
"amount": "7878754"
|
||||
}
|
||||
]
|
||||
},
|
||||
{
|
||||
"policy_id": "96a292ffee938be03e9bae5657982a74e9014eb4960108c9e23a5b39",
|
||||
"tokens": [
|
||||
{
|
||||
"asset_name_bytes": "74652474436f696f",
|
||||
"amount": "7878754"
|
||||
}
|
||||
]
|
||||
}
|
||||
]
|
||||
}
|
||||
],
|
||||
"mint": [],
|
||||
"script_data_hash": null,
|
||||
"signing_mode": "ORDINARY_TRANSACTION",
|
||||
"additional_witness_requests": [],
|
||||
"include_network_id": false
|
||||
},
|
||||
"result": {
|
||||
"error_message": "Invalid token bundle in output"
|
||||
}
|
||||
},
|
||||
{
|
||||
"description": "Asset names in mint token group in wrong order",
|
||||
"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": [
|
||||
{
|
||||
"policy_id": "95a292ffee938be03e9bae5657982a74e9014eb4960108c9e23a5b39",
|
||||
"tokens": [
|
||||
{
|
||||
"asset_name_bytes": "74652474436f696e",
|
||||
"mint_amount": "7878754"
|
||||
},
|
||||
{
|
||||
"asset_name_bytes": "76652474436f696e",
|
||||
"mint_amount": "1234"
|
||||
},
|
||||
{
|
||||
"asset_name_bytes": "75652474436f696e",
|
||||
"mint_amount": "1234"
|
||||
}
|
||||
]
|
||||
}
|
||||
],
|
||||
"script_data_hash": null,
|
||||
"signing_mode": "ORDINARY_TRANSACTION",
|
||||
"additional_witness_requests": [],
|
||||
"include_network_id": false
|
||||
},
|
||||
"result": {
|
||||
"error_message": "Invalid mint token bundle"
|
||||
}
|
||||
},
|
||||
{
|
||||
"description": "PolicyIds in mint in wrong order",
|
||||
"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": [
|
||||
{
|
||||
"policy_id": "95a292ffee938be03e9bae5657982a74e9014eb4960108c9e23a5b39",
|
||||
"tokens": [
|
||||
{
|
||||
"asset_name_bytes": "14652474436f696d",
|
||||
"mint_amount": "7878754"
|
||||
}
|
||||
]
|
||||
},
|
||||
{
|
||||
"policy_id": "9aa292ffee938be03e9bae5657982a74e9014eb4960108c9e23a5b39",
|
||||
"tokens": [
|
||||
{
|
||||
"asset_name_bytes": "24652474436f696e",
|
||||
"mint_amount": "7878754"
|
||||
}
|
||||
]
|
||||
},
|
||||
{
|
||||
"policy_id": "96a292ffee938be03e9bae5657982a74e9014eb4960108c9e23a5b39",
|
||||
"tokens": [
|
||||
{
|
||||
"asset_name_bytes": "34652474436f696f",
|
||||
"mint_amount": "7878754"
|
||||
}
|
||||
]
|
||||
}
|
||||
],
|
||||
"script_data_hash": null,
|
||||
"signing_mode": "ORDINARY_TRANSACTION",
|
||||
"additional_witness_requests": [],
|
||||
"include_network_id": false
|
||||
},
|
||||
"result": {
|
||||
"error_message": "Invalid mint token bundle"
|
||||
}
|
||||
},
|
||||
{
|
||||
"description": "Additional witness requests in ORDINARY_TRANSACTION",
|
||||
"parameters": {
|
||||
|
138
common/tests/fixtures/cardano/sign_tx.json
vendored
138
common/tests/fixtures/cardano/sign_tx.json
vendored
@ -1707,6 +1707,144 @@
|
||||
}
|
||||
]
|
||||
}
|
||||
},
|
||||
{
|
||||
"description": "Ordinary transaction with multiple correctly ordered tokens",
|
||||
"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": "f565",
|
||||
"amount": "9878754"
|
||||
},
|
||||
{
|
||||
"asset_name_bytes": "f5652474436f69",
|
||||
"amount": "7878754"
|
||||
},
|
||||
{
|
||||
"asset_name_bytes": "74652474436f696e",
|
||||
"amount": "7878754"
|
||||
},
|
||||
{
|
||||
"asset_name_bytes": "75652474436f696e",
|
||||
"amount": "1234"
|
||||
}
|
||||
]
|
||||
},
|
||||
{
|
||||
"policy_id": "96a292ffee938be03e9bae5657982a74e9014eb4960108c9e23a5b39",
|
||||
"tokens": [
|
||||
{
|
||||
"asset_name_bytes": "74652474436f696e",
|
||||
"amount": "7878754"
|
||||
}
|
||||
]
|
||||
},
|
||||
{
|
||||
"policy_id": "d6a292ffee938be03e9bae5657982a74e9014eb4960108c9e23a5b39",
|
||||
"tokens": [
|
||||
{
|
||||
"asset_name_bytes": "74652474436f696e",
|
||||
"amount": "7878754"
|
||||
}
|
||||
]
|
||||
}
|
||||
]
|
||||
},
|
||||
{
|
||||
"address": "addr1q84sh2j72ux0l03fxndjnhctdg7hcppsaejafsa84vh7lwgmcs5wgus8qt4atk45lvt4xfxpjtwfhdmvchdf2m3u3hlsd5tq5r",
|
||||
"amount": "2000000",
|
||||
"token_bundle": [
|
||||
{
|
||||
"policy_id": "a6a292ffee938be03e9bae5657982a74e9014eb4960108c9e23a5b39",
|
||||
"tokens": [
|
||||
{
|
||||
"asset_name_bytes": "74652474436f696e",
|
||||
"amount": "7878754"
|
||||
}
|
||||
]
|
||||
}
|
||||
]
|
||||
}
|
||||
],
|
||||
"mint": [
|
||||
{
|
||||
"policy_id": "95a292ffee938be03e9bae5657982a74e9014eb4960108c9e23a5b39",
|
||||
"tokens": [
|
||||
{
|
||||
"asset_name_bytes": "f565",
|
||||
"mint_amount": "9878754"
|
||||
},
|
||||
{
|
||||
"asset_name_bytes": "f5652474436f69",
|
||||
"mint_amount": "7878754"
|
||||
},
|
||||
{
|
||||
"asset_name_bytes": "74652474436f696e",
|
||||
"mint_amount": "-7878754"
|
||||
},
|
||||
{
|
||||
"asset_name_bytes": "75652474436f696e",
|
||||
"mint_amount": "-1234"
|
||||
}
|
||||
]
|
||||
},
|
||||
{
|
||||
"policy_id": "96a292ffee938be03e9bae5657982a74e9014eb4960108c9e23a5b39",
|
||||
"tokens": [
|
||||
{
|
||||
"asset_name_bytes": "74652474436f696e",
|
||||
"mint_amount": "7878754"
|
||||
}
|
||||
]
|
||||
},
|
||||
{
|
||||
"policy_id": "d6a292ffee938be03e9bae5657982a74e9014eb4960108c9e23a5b39",
|
||||
"tokens": [
|
||||
{
|
||||
"asset_name_bytes": "74652474436f696e",
|
||||
"mint_amount": "7878754"
|
||||
}
|
||||
]
|
||||
}
|
||||
],
|
||||
"script_data_hash": null,
|
||||
"signing_mode": "ORDINARY_TRANSACTION",
|
||||
"additional_witness_requests": [],
|
||||
"include_network_id": false
|
||||
},
|
||||
"result": {
|
||||
"tx_hash": "f1bda77315626ce61c784f3e60a74128f29b7d00a0c8baca030464293da2d7c4",
|
||||
"witnesses": [
|
||||
{
|
||||
"type": 1,
|
||||
"pub_key": "5d010cf16fdeff40955633d6c565f3844a288a24967cf6b76acbeb271b4f13c1",
|
||||
"signature": "4254a6cae8156771ac8e1e75ceb8003f8370a7f6b08013fda32174b56025fcb01bc9d7f4e1eed10bc2c0ff1020eda47475f728cc824ef98a109fd9fe6a1c4105",
|
||||
"chain_code": null
|
||||
}
|
||||
]
|
||||
}
|
||||
}
|
||||
]
|
||||
}
|
||||
|
@ -131,6 +131,92 @@
|
||||
"error_message": "Invalid certificate"
|
||||
}
|
||||
},
|
||||
{
|
||||
"description": "Multisig transaction with repeated withdrawal",
|
||||
"parameters": {
|
||||
"protocol_magic": 764824073,
|
||||
"network_id": 1,
|
||||
"fee": 42,
|
||||
"ttl": 10,
|
||||
"certificates": [],
|
||||
"withdrawals": [
|
||||
{
|
||||
"script_hash": "19fb5fd4aa8cadd6705acc8263cee0fc62edca5ac38db593fec2f9fd",
|
||||
"amount": "1000"
|
||||
},
|
||||
{
|
||||
"script_hash": "29fb5fd4aa8cadd6705acc8263cee0fc62edca5ac38db593fec2f9fd",
|
||||
"amount": "3000"
|
||||
},
|
||||
{
|
||||
"script_hash": "29fb5fd4aa8cadd6705acc8263cee0fc62edca5ac38db593fec2f9fd",
|
||||
"amount": "1000"
|
||||
}
|
||||
],
|
||||
"auxiliary_data": null,
|
||||
"inputs": [
|
||||
{
|
||||
"prev_hash": "3b40265111d8bb3c3c608d95b3a0bf83461ace32d79336579a1939b3aad1c0b7",
|
||||
"prev_index": 0
|
||||
}
|
||||
],
|
||||
"outputs": [
|
||||
{
|
||||
"address": "addr1w9rhu54nz94k9l5v6d9rzfs47h7dv7xffcwkekuxcx3evnqpvuxu0",
|
||||
"amount": "1"
|
||||
}
|
||||
],
|
||||
"mint": [],
|
||||
"script_data_hash": null,
|
||||
"signing_mode": "MULTISIG_TRANSACTION",
|
||||
"additional_witness_requests": [],
|
||||
"include_network_id": false
|
||||
},
|
||||
"result": {
|
||||
"error_message": "Invalid withdrawal"
|
||||
}
|
||||
},
|
||||
{
|
||||
"description": "Multisig transaction with wthdrawal addresses in wrong order",
|
||||
"parameters": {
|
||||
"protocol_magic": 764824073,
|
||||
"network_id": 1,
|
||||
"fee": 42,
|
||||
"ttl": 10,
|
||||
"certificates": [],
|
||||
"withdrawals": [
|
||||
{
|
||||
"script_hash": "39fb5fd4aa8cadd6705acc8263cee0fc62edca5ac38db593fec2f9fd",
|
||||
"amount": "3000"
|
||||
},
|
||||
{
|
||||
"script_hash": "29fb5fd4aa8cadd6705acc8263cee0fc62edca5ac38db593fec2f9fd",
|
||||
"amount": "1000"
|
||||
}
|
||||
],
|
||||
"auxiliary_data": null,
|
||||
"inputs": [
|
||||
{
|
||||
"prev_hash": "3b40265111d8bb3c3c608d95b3a0bf83461ace32d79336579a1939b3aad1c0b7",
|
||||
"prev_index": 0
|
||||
}
|
||||
],
|
||||
"outputs": [
|
||||
{
|
||||
"address": "addr1w9rhu54nz94k9l5v6d9rzfs47h7dv7xffcwkekuxcx3evnqpvuxu0",
|
||||
"amount": "1"
|
||||
}
|
||||
],
|
||||
"mint": [],
|
||||
"script_data_hash": null,
|
||||
"signing_mode": "MULTISIG_TRANSACTION",
|
||||
"additional_witness_requests": [],
|
||||
"include_network_id": false
|
||||
},
|
||||
"result": {
|
||||
"error_message": "Invalid withdrawal"
|
||||
}
|
||||
},
|
||||
{
|
||||
"description": "Multisig transaction with 1852 multisig witness request",
|
||||
"parameters": {
|
||||
|
@ -421,15 +421,13 @@ async def _process_asset_groups(
|
||||
should_show_tokens: bool,
|
||||
) -> None:
|
||||
"""Read, validate and serialize the asset groups of an output."""
|
||||
# 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()
|
||||
previous_policy_id: bytes = b""
|
||||
for _ in range(asset_groups_count):
|
||||
asset_group: CardanoAssetGroup = await ctx.call(
|
||||
CardanoTxItemAck(), CardanoAssetGroup
|
||||
)
|
||||
_validate_asset_group(asset_group, seen_policy_ids)
|
||||
seen_policy_ids.add(asset_group.policy_id)
|
||||
_validate_asset_group(asset_group, previous_policy_id)
|
||||
previous_policy_id = asset_group.policy_id
|
||||
|
||||
tokens: HashBuilderDict[bytes, int] = HashBuilderDict(asset_group.tokens_count)
|
||||
with asset_groups_dict.add(asset_group.policy_id, tokens):
|
||||
@ -450,13 +448,11 @@ async def _process_tokens(
|
||||
should_show_tokens: bool,
|
||||
) -> 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()
|
||||
previous_asset_name_bytes: bytes = b""
|
||||
for _ in range(tokens_count):
|
||||
token: CardanoToken = await ctx.call(CardanoTxItemAck(), CardanoToken)
|
||||
_validate_token(token, seen_asset_name_bytes)
|
||||
seen_asset_name_bytes.add(token.asset_name_bytes)
|
||||
_validate_token(token, previous_asset_name_bytes)
|
||||
previous_asset_name_bytes = token.asset_name_bytes
|
||||
if should_show_tokens:
|
||||
await confirm_sending_token(ctx, policy_id, token)
|
||||
|
||||
@ -577,32 +573,26 @@ async def _process_withdrawals(
|
||||
if withdrawals_count == 0:
|
||||
return
|
||||
|
||||
# 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, ...] | bytes] = set()
|
||||
previous_reward_address: bytes = b""
|
||||
for _ in range(withdrawals_count):
|
||||
withdrawal: CardanoTxWithdrawal = await ctx.call(
|
||||
CardanoTxItemAck(), CardanoTxWithdrawal
|
||||
)
|
||||
_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=reward_address_type,
|
||||
address_n_staking=withdrawal.path,
|
||||
script_staking_hash=withdrawal.script_hash,
|
||||
),
|
||||
withdrawal,
|
||||
signing_mode,
|
||||
protocol_magic,
|
||||
network_id,
|
||||
account_path_checker,
|
||||
previous_reward_address,
|
||||
)
|
||||
reward_address = _derive_withdrawal_reward_address_bytes(
|
||||
keychain, withdrawal, protocol_magic, network_id
|
||||
)
|
||||
previous_reward_address = reward_address
|
||||
|
||||
await confirm_withdrawal(ctx, withdrawal)
|
||||
|
||||
withdrawals_dict.add(reward_address, withdrawal.amount)
|
||||
|
||||
@ -649,15 +639,13 @@ async def _process_minting(
|
||||
|
||||
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()
|
||||
previous_policy_id: bytes = b""
|
||||
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)
|
||||
_validate_asset_group(asset_group, previous_policy_id, is_mint=True)
|
||||
previous_policy_id = asset_group.policy_id
|
||||
|
||||
tokens: HashBuilderDict[bytes, int] = HashBuilderDict(asset_group.tokens_count)
|
||||
with minting_dict.add(asset_group.policy_id, tokens):
|
||||
@ -676,13 +664,11 @@ async def _process_minting_tokens(
|
||||
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()
|
||||
previous_asset_name_bytes: bytes = b""
|
||||
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)
|
||||
_validate_token(token, previous_asset_name_bytes, is_mint=True)
|
||||
previous_asset_name_bytes = token.asset_name_bytes
|
||||
await confirm_token_minting(ctx, policy_id, token)
|
||||
|
||||
assert token.mint_amount is not None # _validate_token
|
||||
@ -890,7 +876,7 @@ async def _show_output(
|
||||
|
||||
|
||||
def _validate_asset_group(
|
||||
asset_group: CardanoAssetGroup, seen_policy_ids: set[bytes], is_mint: bool = False
|
||||
asset_group: CardanoAssetGroup, previous_policy_id: bytes, is_mint: bool = False
|
||||
) -> None:
|
||||
INVALID_TOKEN_BUNDLE = (
|
||||
INVALID_TOKEN_BUNDLE_MINT if is_mint else INVALID_TOKEN_BUNDLE_OUTPUT
|
||||
@ -900,12 +886,12 @@ def _validate_asset_group(
|
||||
raise INVALID_TOKEN_BUNDLE
|
||||
if asset_group.tokens_count == 0:
|
||||
raise INVALID_TOKEN_BUNDLE
|
||||
if asset_group.policy_id in seen_policy_ids:
|
||||
if not cbor.are_canonically_ordered(previous_policy_id, asset_group.policy_id):
|
||||
raise INVALID_TOKEN_BUNDLE
|
||||
|
||||
|
||||
def _validate_token(
|
||||
token: CardanoToken, seen_asset_name_bytes: set[bytes], is_mint: bool = False
|
||||
token: CardanoToken, previous_asset_name_bytes: bytes, is_mint: bool = False
|
||||
) -> None:
|
||||
INVALID_TOKEN_BUNDLE = (
|
||||
INVALID_TOKEN_BUNDLE_MINT if is_mint else INVALID_TOKEN_BUNDLE_OUTPUT
|
||||
@ -920,7 +906,9 @@ def _validate_token(
|
||||
|
||||
if len(token.asset_name_bytes) > MAX_ASSET_NAME_LENGTH:
|
||||
raise INVALID_TOKEN_BUNDLE
|
||||
if token.asset_name_bytes in seen_asset_name_bytes:
|
||||
if not cbor.are_canonically_ordered(
|
||||
previous_asset_name_bytes, token.asset_name_bytes
|
||||
):
|
||||
raise INVALID_TOKEN_BUNDLE
|
||||
|
||||
|
||||
@ -943,10 +931,13 @@ async def _show_certificate(
|
||||
|
||||
|
||||
def _validate_withdrawal(
|
||||
keychain: seed.Keychain,
|
||||
withdrawal: CardanoTxWithdrawal,
|
||||
seen_withdrawals: set[tuple[int, ...] | bytes],
|
||||
signing_mode: CardanoTxSigningMode,
|
||||
protocol_magic: int,
|
||||
network_id: int,
|
||||
account_path_checker: AccountPathChecker,
|
||||
previous_reward_address: bytes,
|
||||
) -> None:
|
||||
validate_stake_credential(
|
||||
withdrawal.path, withdrawal.script_hash, signing_mode, INVALID_WITHDRAWAL
|
||||
@ -958,10 +949,11 @@ def _validate_withdrawal(
|
||||
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(credential)
|
||||
reward_address = _derive_withdrawal_reward_address_bytes(
|
||||
keychain, withdrawal, protocol_magic, network_id
|
||||
)
|
||||
if not cbor.are_canonically_ordered(previous_reward_address, reward_address):
|
||||
raise INVALID_WITHDRAWAL
|
||||
|
||||
account_path_checker.add_withdrawal(withdrawal)
|
||||
|
||||
@ -971,6 +963,29 @@ def _validate_script_data_hash(script_data_hash: bytes) -> None:
|
||||
raise INVALID_SCRIPT_DATA_HASH
|
||||
|
||||
|
||||
def _derive_withdrawal_reward_address_bytes(
|
||||
keychain: seed.Keychain,
|
||||
withdrawal: CardanoTxWithdrawal,
|
||||
protocol_magic: int,
|
||||
network_id: int,
|
||||
) -> bytes:
|
||||
reward_address_type = (
|
||||
CardanoAddressType.REWARD
|
||||
if withdrawal.path
|
||||
else CardanoAddressType.REWARD_SCRIPT
|
||||
)
|
||||
return derive_address_bytes(
|
||||
keychain,
|
||||
CardanoAddressParametersType(
|
||||
address_type=reward_address_type,
|
||||
address_n_staking=withdrawal.path,
|
||||
script_staking_hash=withdrawal.script_hash,
|
||||
),
|
||||
protocol_magic,
|
||||
network_id,
|
||||
)
|
||||
|
||||
|
||||
def _get_output_address(
|
||||
keychain: seed.Keychain,
|
||||
protocol_magic: int,
|
||||
|
@ -318,3 +318,13 @@ def create_array_header(size: int) -> bytes:
|
||||
|
||||
def create_map_header(size: int) -> bytes:
|
||||
return _header(_CBOR_MAP, size)
|
||||
|
||||
|
||||
def are_canonically_ordered(previous: Value, current: Value) -> bool:
|
||||
"""
|
||||
Returns True if `previous` is smaller than `current` with regards to
|
||||
the cbor map key ordering as defined in
|
||||
https://datatracker.ietf.org/doc/html/rfc7049#section-3.9
|
||||
"""
|
||||
u, v = encode(previous), encode(current)
|
||||
return len(u) < len(v) or (len(u) == len(v) and u < v)
|
||||
|
Loading…
Reference in New Issue
Block a user