From 2226e97dff13b2ea71093a83f815a77ff88f2eb4 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Peter=20Jas=CC=8Cko?= Date: Sun, 3 Dec 2023 16:52:45 +0100 Subject: [PATCH 1/3] feat(connect): Conway certificates --- .../__fixtures__/cardanoSignTransaction.ts | 260 ++++++++++++++++++ .../api/cardano/api/cardanoSignTransaction.ts | 15 +- .../src/api/cardano/cardanoCertificate.ts | 55 ++++ .../connect/src/api/cardano/cardanoUtils.ts | 1 + .../src/api/cardano/cardanoWitnesses.ts | 5 +- .../connect/src/types/api/cardano/index.ts | 9 + .../scripts/protobuf-patches/index.js | 1 + packages/protobuf/src/messages-schema.ts | 2 +- packages/protobuf/src/messages.ts | 2 +- 9 files changed, 345 insertions(+), 5 deletions(-) diff --git a/packages/connect/e2e/__fixtures__/cardanoSignTransaction.ts b/packages/connect/e2e/__fixtures__/cardanoSignTransaction.ts index 7262daec028..61df527bf4d 100644 --- a/packages/connect/e2e/__fixtures__/cardanoSignTransaction.ts +++ b/packages/connect/e2e/__fixtures__/cardanoSignTransaction.ts @@ -6,6 +6,7 @@ const { CardanoAddressType, CardanoCVoteRegistrationFormat, CardanoCertificateType, + CardanoDRepType, CardanoTxOutputSerializationFormat, CardanoTxSigningMode, } = MessagesSchema; @@ -225,6 +226,11 @@ const SAMPLE_CERTIFICATES = { type: CardanoCertificateType.STAKE_REGISTRATION, path: "m/1852'/1815'/0'/2/0", }, + stake_registration_conway: { + type: CardanoCertificateType.STAKE_REGISTRATION_CONWAY, + path: "m/1852'/1815'/0'/2/0", + deposit: '2000000', + }, stake_registration_script: { type: CardanoCertificateType.STAKE_REGISTRATION, scriptHash: '29fb5fd4aa8cadd6705acc8263cee0fc62edca5ac38db593fec2f9fd', @@ -233,6 +239,11 @@ const SAMPLE_CERTIFICATES = { type: CardanoCertificateType.STAKE_DEREGISTRATION, path: "m/1852'/1815'/0'/2/0", }, + stake_deregistration_conway: { + type: CardanoCertificateType.STAKE_DEREGISTRATION_CONWAY, + path: "m/1852'/1815'/0'/2/0", + deposit: '2000000', + }, stake_deregistration_script: { type: CardanoCertificateType.STAKE_DEREGISTRATION, scriptHash: '29fb5fd4aa8cadd6705acc8263cee0fc62edca5ac38db593fec2f9fd', @@ -327,6 +338,36 @@ const SAMPLE_CERTIFICATES = { metadata: null, }, }, + vote_delegation_key_hash: { + type: CardanoCertificateType.VOTE_DELEGATION, + path: "m/1852'/1815'/0'/2/0", + dRep: { + type: CardanoDRepType.KEY_HASH, + keyHash: '3a7f09d3df4cf66a7399c2b05bfa234d5a29560c311fc5db4c490711', + }, + }, + vote_delegation_script: { + type: CardanoCertificateType.VOTE_DELEGATION, + path: "m/1852'/1815'/0'/2/0", + dRep: { + type: CardanoDRepType.SCRIPT_HASH, + scriptHash: '29fb5fd4aa8cadd6705acc8263cee0fc62edca5ac38db593fec2f9fd', + }, + }, + vote_delegation_abstain: { + type: CardanoCertificateType.VOTE_DELEGATION, + path: "m/1852'/1815'/0'/2/0", + dRep: { + type: CardanoDRepType.ABSTAIN, + }, + }, + vote_delegation_no_confidence: { + type: CardanoCertificateType.VOTE_DELEGATION, + path: "m/1852'/1815'/0'/2/0", + dRep: { + type: CardanoDRepType.NO_CONFIDENCE, + }, + }, }; const SAMPLE_WITHDRAWALS = { @@ -396,6 +437,15 @@ const VALIDITY_INTERVAL_START = '47'; const SCRIPT_DATA_HASH = 'd593fd793c377ac50a3169bb8378ffc257c944da31aa8f355dfa5a4f6ff89e02'; const TOTAL_COLLATERAL = '1000'; +const legacyResults = { + // FW <2.6.0 is not supported by Connect at all + beforeConway: { + // older FW doesn't support Conway certificates + rules: ['<2.6.5', '1'], + payload: false, + }, +}; + export default { method: 'cardanoSignTransaction', setup: { @@ -599,6 +649,41 @@ export default { }, }, + { + description: 'signStakeRegistrationConway', + params: { + inputs: [SAMPLE_INPUTS.shelley_input], + outputs: [SAMPLE_OUTPUTS.simple_shelley_output], + fee: FEE, + ttl: TTL, + certificates: [SAMPLE_CERTIFICATES.stake_registration_conway], + protocolMagic: PROTOCOL_MAGICS.mainnet, + networkId: NETWORK_IDS.mainnet, + signingMode: CardanoTxSigningMode.ORDINARY_TRANSACTION, + }, + result: { + hash: 'e200b2c91f3493a1f3b9cfc8b6c141f70181741025e53941e9d57d22b1470c5c', + witnesses: [ + { + type: 1, + pubKey: '5d010cf16fdeff40955633d6c565f3844a288a24967cf6b76acbeb271b4f13c1', + signature: + '79a357517a08c7256b0fab1e93a92a477386f4c2d72cea7bc68527c0133c32472305f010350665d72e8017bb6c2080b5742680ce7700bbddda561c917f294a07', + chainCode: null, + }, + { + type: 1, + pubKey: 'bc65be1b0b9d7531778a1317c2aa6de936963c3f9ac7d5ee9e9eda25e0c97c5e', + signature: + 'dca542910d0362fc22744e7a24732343db4e013495a7d9b47562886f09af8eb56ecaa105e20a9df3e4248fdab61dd91b6fb2a3bfc15d0d9a0442671c07e1ba02', + chainCode: null, + }, + ], + auxiliaryDataSupplement: undefined, + }, + legacyResults: [legacyResults.beforeConway], + }, + { description: 'signStakeRegistrationNoOutputs', params: { @@ -697,6 +782,41 @@ export default { }, }, + { + description: 'signStakeDeregistrationConway', + params: { + inputs: [SAMPLE_INPUTS.shelley_input], + outputs: [SAMPLE_OUTPUTS.simple_shelley_output], + fee: FEE, + ttl: TTL, + certificates: [SAMPLE_CERTIFICATES.stake_deregistration_conway], + protocolMagic: PROTOCOL_MAGICS.mainnet, + networkId: NETWORK_IDS.mainnet, + signingMode: CardanoTxSigningMode.ORDINARY_TRANSACTION, + }, + result: { + hash: '564ad55097101e1ca85629cffe839f43a19bf33aa1940c99a62eb8f14392eebb', + witnesses: [ + { + type: 1, + pubKey: '5d010cf16fdeff40955633d6c565f3844a288a24967cf6b76acbeb271b4f13c1', + signature: + 'a0fa6630498f57249b305824ad4d32157653820e7d651332a58af70a80364df882ee8b0471e76dd7a335eea84a18c52b12c02508779d46b193bc418c22e8a00f', + chainCode: null, + }, + { + type: 1, + pubKey: 'bc65be1b0b9d7531778a1317c2aa6de936963c3f9ac7d5ee9e9eda25e0c97c5e', + signature: + '5d282fcd2685ee47f3770f84b2badf4046e8e76bfdaa26f74e292ecd16bcf89fb330b99edff13bc9c81e8c6523864f69a3ac7cde29d5a648707724c5cb48730e', + chainCode: null, + }, + ], + auxiliaryDataSupplement: undefined, + }, + legacyResults: [legacyResults.beforeConway], + }, + { description: 'signStakeDeregistrationAndWithdrawal', params: { @@ -1177,6 +1297,146 @@ export default { }, }, + { + description: 'signVoteDelegationKeyHash', + params: { + inputs: [SAMPLE_INPUTS.shelley_input], + outputs: [SAMPLE_OUTPUTS.simple_shelley_output], + fee: FEE, + ttl: TTL, + certificates: [SAMPLE_CERTIFICATES.vote_delegation_key_hash], + protocolMagic: PROTOCOL_MAGICS.mainnet, + networkId: NETWORK_IDS.mainnet, + signingMode: CardanoTxSigningMode.ORDINARY_TRANSACTION, + }, + result: { + hash: '154e0164e1d06e11a569054309b02a2926c5af1de7832473120a96465713bdc5', + witnesses: [ + { + type: 1, + pubKey: '5d010cf16fdeff40955633d6c565f3844a288a24967cf6b76acbeb271b4f13c1', + signature: + '2bd248ab6172b1757bd28573a36839a08e189d032a34f0ecaafa421b31c76af2f1f48ecb9c12c4a225d52873f7390938ab442842c55f1196f6213e4e971e6903', + chainCode: null, + }, + { + type: 1, + pubKey: 'bc65be1b0b9d7531778a1317c2aa6de936963c3f9ac7d5ee9e9eda25e0c97c5e', + signature: + '4b4f43f599eb55b2a9489c6696d6d0812fd02bba1d0d4b2d68b2db8f1641e6cfdcfc1bc602428543a37abd981e0e3ba28516c2617396ec7675b361e3eb0bde0e', + chainCode: null, + }, + ], + auxiliaryDataSupplement: undefined, + }, + legacyResults: [legacyResults.beforeConway], + }, + + { + description: 'signVoteDelegationScript', + params: { + inputs: [SAMPLE_INPUTS.shelley_input], + outputs: [SAMPLE_OUTPUTS.simple_shelley_output], + fee: FEE, + ttl: TTL, + certificates: [SAMPLE_CERTIFICATES.vote_delegation_script], + protocolMagic: PROTOCOL_MAGICS.mainnet, + networkId: NETWORK_IDS.mainnet, + signingMode: CardanoTxSigningMode.ORDINARY_TRANSACTION, + }, + result: { + hash: 'fccf753e4f96e20c880e5ea933041ed33509ec6c0dc1aee8b25a1fe3d562b7aa', + witnesses: [ + { + type: 1, + pubKey: '5d010cf16fdeff40955633d6c565f3844a288a24967cf6b76acbeb271b4f13c1', + signature: + 'bde0242fee0de5b862d2f02847d789ebe10e8f82bf15837370f115c89c1b413f1b0fa5a470210127af92059c4d3ebff297d39e93143667d3823476f12f0f6f07', + chainCode: null, + }, + { + type: 1, + pubKey: 'bc65be1b0b9d7531778a1317c2aa6de936963c3f9ac7d5ee9e9eda25e0c97c5e', + signature: + 'cd8a2fca634c1aa2c88609042de7e4fce232bf233b1271612b5edc7b806e11ff44e6b6b15feb5b6e76b7e16a8d703e7653d860c00981edf6fe3b1e4cbeaba406', + chainCode: null, + }, + ], + auxiliaryDataSupplement: undefined, + }, + legacyResults: [legacyResults.beforeConway], + }, + + { + description: 'signVoteDelegationAbstain', + params: { + inputs: [SAMPLE_INPUTS.shelley_input], + outputs: [SAMPLE_OUTPUTS.simple_shelley_output], + fee: FEE, + ttl: TTL, + certificates: [SAMPLE_CERTIFICATES.vote_delegation_abstain], + protocolMagic: PROTOCOL_MAGICS.mainnet, + networkId: NETWORK_IDS.mainnet, + signingMode: CardanoTxSigningMode.ORDINARY_TRANSACTION, + }, + result: { + hash: '01d0f76fadc899087c5352befac56cbfdc2e868ac715fbfe00230bab3f7fa751', + witnesses: [ + { + type: 1, + pubKey: '5d010cf16fdeff40955633d6c565f3844a288a24967cf6b76acbeb271b4f13c1', + signature: + '52c57d9c0e06fc9883285db4eec1a1504e27726dc5afce943d6f54df22188f05c3eeee06d052375eceb55df83c314237b3718f07fccef6198bda8c20d794b102', + chainCode: null, + }, + { + type: 1, + pubKey: 'bc65be1b0b9d7531778a1317c2aa6de936963c3f9ac7d5ee9e9eda25e0c97c5e', + signature: + '6de4940ff99738aaf3659ffeb8e4f6f01ff88ddb65c24028d75a847ca684d07af000e32eaa4c915c8031f6d928b2bcbe8c6f57e389299d3eafe213bd0ab1190c', + chainCode: null, + }, + ], + auxiliaryDataSupplement: undefined, + }, + legacyResults: [legacyResults.beforeConway], + }, + + { + description: 'signVoteDelegationNoConfidence', + params: { + inputs: [SAMPLE_INPUTS.shelley_input], + outputs: [SAMPLE_OUTPUTS.simple_shelley_output], + fee: FEE, + ttl: TTL, + certificates: [SAMPLE_CERTIFICATES.vote_delegation_no_confidence], + protocolMagic: PROTOCOL_MAGICS.mainnet, + networkId: NETWORK_IDS.mainnet, + signingMode: CardanoTxSigningMode.ORDINARY_TRANSACTION, + }, + result: { + hash: '567e9bd00787190f1ab51879dcf834002b76007130c526b2e4d1bf9a996f5ad0', + witnesses: [ + { + type: 1, + pubKey: '5d010cf16fdeff40955633d6c565f3844a288a24967cf6b76acbeb271b4f13c1', + signature: + '20e3f9ecc3a1b97cbda08cf610b2e72b45d0e0916af2be2ad472d4c8d2be4b13818497818961c8d27379754f0057b00fa286bce0d59f177f24eeee4e2b24940f', + chainCode: null, + }, + { + type: 1, + pubKey: 'bc65be1b0b9d7531778a1317c2aa6de936963c3f9ac7d5ee9e9eda25e0c97c5e', + signature: + '898fb2cef0c4b954f22c4218fc9a188a5da340ddb5c6d5bba01c67520bbf537f5743814b6d40dd7f299ece7e39d7efb16a1cb597e8d421649a9483f631371703', + chainCode: null, + }, + ], + auxiliaryDataSupplement: undefined, + }, + legacyResults: [legacyResults.beforeConway], + }, + { description: 'signMaryWithValidityIntervalStart', params: { diff --git a/packages/connect/src/api/cardano/api/cardanoSignTransaction.ts b/packages/connect/src/api/cardano/api/cardanoSignTransaction.ts index 5f8c9b2477c..fbd1b63801f 100644 --- a/packages/connect/src/api/cardano/api/cardanoSignTransaction.ts +++ b/packages/connect/src/api/cardano/api/cardanoSignTransaction.ts @@ -38,7 +38,8 @@ import { tokenBundleToProto } from '../cardanoTokenBundle'; import { AssertWeak, Type } from '@trezor/schema-utils'; const CardanoSignTransactionFeatures = Object.freeze({ - // Minimum firmware (2.6.0) currently supports all features + // FW <2.6.0 is not supported by Connect at all + Conway: ['0', '2.6.5'], }); export type CardanoSignTransactionParams = { @@ -246,7 +247,17 @@ export default class CardanoSignTransaction extends AbstractMethod< } _ensureFirmwareSupportsParams() { - // Currently, there are no additional features to check for + const { params } = this; + + params.certificatesWithPoolOwnersAndRelays.forEach(({ certificate }) => { + if ( + certificate.type === PROTO.CardanoCertificateType.STAKE_REGISTRATION_CONWAY || + certificate.type === PROTO.CardanoCertificateType.STAKE_DEREGISTRATION_CONWAY || + certificate.type === PROTO.CardanoCertificateType.VOTE_DELEGATION + ) { + this._ensureFeatureIsSupported('Conway'); + } + }); } async _sign_tx(): Promise { diff --git a/packages/connect/src/api/cardano/cardanoCertificate.ts b/packages/connect/src/api/cardano/cardanoCertificate.ts index db7df8467c5..92998d7545f 100644 --- a/packages/connect/src/api/cardano/cardanoCertificate.ts +++ b/packages/connect/src/api/cardano/cardanoCertificate.ts @@ -7,6 +7,7 @@ import { CardanoPoolParameters, CardanoPoolOwner, CardanoPoolRelay, + CardanoDRep, } from '../../types/api/cardano'; import { Assert } from '@trezor/schema-utils'; @@ -68,6 +69,21 @@ const validatePoolParameters = (poolParameters: CardanoPoolParameters) => { poolParameters.relays.forEach(validatePoolRelay); }; +const validateDRep = (dRep: CardanoDRep) => { + Assert(CardanoDRep, dRep); + if (dRep.type === PROTO.CardanoDRepType.KEY_HASH && !dRep.keyHash) { + throw ERRORS.TypedError( + 'Method_InvalidParameter', + 'keyHash must be supplied for KEY_HASH dRep type', + ); + } else if (dRep.type === PROTO.CardanoDRepType.SCRIPT_HASH && !dRep.scriptHash) { + throw ERRORS.TypedError( + 'Method_InvalidParameter', + 'scriptHash must be supplied for SCRIPT_HASH dRep type', + ); + } +}; + export type CertificateWithPoolOwnersAndRelays = { certificate: PROTO.CardanoTxCertificate; poolOwners: PROTO.CardanoPoolOwner[]; @@ -118,6 +134,20 @@ const transformPoolParameters = ( }; }; +const transformDRep = (dRep: CardanoDRep | undefined): PROTO.CardanoDRep | undefined => { + if (!dRep) { + return undefined; + } + + validateDRep(dRep); + + return { + type: dRep.type, + key_hash: dRep.keyHash, + script_hash: dRep.scriptHash, + }; +}; + // transform incoming certificate object to protobuf messages format export const transformCertificate = ( certificate: CardanoCertificate, @@ -142,10 +172,33 @@ export const transformCertificate = ( } } + if ( + certificate.type === PROTO.CardanoCertificateType.STAKE_REGISTRATION_CONWAY || + certificate.type === PROTO.CardanoCertificateType.STAKE_DEREGISTRATION_CONWAY + ) { + if (!certificate.deposit) { + throw ERRORS.TypedError( + 'Method_InvalidParameter', + 'deposit must be supplied for STAKE_REGISTRATION_CONWAY or STAKE_DEREGISTRATION_CONWAY', + ); + } + } + + if (certificate.type === PROTO.CardanoCertificateType.VOTE_DELEGATION) { + if (!certificate.dRep) { + throw ERRORS.TypedError( + 'Method_InvalidParameter', + 'dRep must be supplied for VOTE_DELEGATION', + ); + } + } + const { poolParameters, poolOwners, poolRelays } = transformPoolParameters( certificate.poolParameters, ); + const dRep = transformDRep(certificate.dRep); + return { certificate: { type: certificate.type, @@ -154,6 +207,8 @@ export const transformCertificate = ( key_hash: certificate.keyHash, pool: certificate.pool, pool_parameters: poolParameters, + deposit: certificate.deposit, + drep: dRep, }, poolOwners, poolRelays, diff --git a/packages/connect/src/api/cardano/cardanoUtils.ts b/packages/connect/src/api/cardano/cardanoUtils.ts index 9ddf9457bbb..60b62331c0d 100644 --- a/packages/connect/src/api/cardano/cardanoUtils.ts +++ b/packages/connect/src/api/cardano/cardanoUtils.ts @@ -47,6 +47,7 @@ export const prepareCertificates = (certs: CardanoCertificate[]) => { convertedCerts.push({ type: cert.type, }); + // TODO conway certificates not supported by coin-selection lib yet break; // no default } diff --git a/packages/connect/src/api/cardano/cardanoWitnesses.ts b/packages/connect/src/api/cardano/cardanoWitnesses.ts index a1aaf41cdda..a57f6556398 100644 --- a/packages/connect/src/api/cardano/cardanoWitnesses.ts +++ b/packages/connect/src/api/cardano/cardanoWitnesses.ts @@ -29,7 +29,10 @@ export const gatherWitnessPaths = ( if ( certificate.path && (certificate.type === PROTO.CardanoCertificateType.STAKE_DELEGATION || - certificate.type === PROTO.CardanoCertificateType.STAKE_DEREGISTRATION) + certificate.type === PROTO.CardanoCertificateType.STAKE_DEREGISTRATION || + certificate.type === PROTO.CardanoCertificateType.STAKE_REGISTRATION_CONWAY || + certificate.type === PROTO.CardanoCertificateType.STAKE_DEREGISTRATION_CONWAY || + certificate.type === PROTO.CardanoCertificateType.VOTE_DELEGATION) ) { _insert(certificate.path); } diff --git a/packages/connect/src/types/api/cardano/index.ts b/packages/connect/src/types/api/cardano/index.ts index 0af73a327ab..908644a0dc9 100644 --- a/packages/connect/src/types/api/cardano/index.ts +++ b/packages/connect/src/types/api/cardano/index.ts @@ -165,6 +165,13 @@ export const CardanoPoolParameters = Type.Object({ metadata: Type.Optional(CardanoPoolMetadata), }); +export type CardanoDRep = Static; +export const CardanoDRep = Type.Object({ + type: PROTO.EnumCardanoDRepType, + keyHash: Type.Optional(Type.String()), + scriptHash: Type.Optional(Type.String()), +}); + export type CardanoCertificate = Static; export const CardanoCertificate = Type.Object({ type: PROTO.EnumCardanoCertificateType, @@ -173,6 +180,8 @@ export const CardanoCertificate = Type.Object({ poolParameters: Type.Optional(CardanoPoolParameters), scriptHash: Type.Optional(Type.String()), keyHash: Type.Optional(Type.String()), + deposit: Type.Optional(Type.String()), + dRep: Type.Optional(CardanoDRep), }); export type CardanoWithdrawal = Static; diff --git a/packages/protobuf/scripts/protobuf-patches/index.js b/packages/protobuf/scripts/protobuf-patches/index.js index 9e246a65b9d..d08457a47c5 100644 --- a/packages/protobuf/scripts/protobuf-patches/index.js +++ b/packages/protobuf/scripts/protobuf-patches/index.js @@ -129,6 +129,7 @@ const TYPE_PATCH = { 'CardanoPoolParametersType.cost': UINT_TYPE, 'CardanoPoolParametersType.margin_numerator': UINT_TYPE, 'CardanoPoolParametersType.margin_denominator': UINT_TYPE, + 'CardanoTxCertificate.deposit': UINT_TYPE, 'CardanoSignTxInit.ttl': UINT_TYPE, 'CardanoSignTxInit.validity_interval_start': UINT_TYPE, 'CardanoSignTxInit.total_collateral': UINT_TYPE, diff --git a/packages/protobuf/src/messages-schema.ts b/packages/protobuf/src/messages-schema.ts index 23a78ff2294..0079a85185c 100644 --- a/packages/protobuf/src/messages-schema.ts +++ b/packages/protobuf/src/messages-schema.ts @@ -1208,7 +1208,7 @@ export const CardanoTxCertificate = Type.Object( pool_parameters: Type.Optional(CardanoPoolParametersType), script_hash: Type.Optional(Type.String()), key_hash: Type.Optional(Type.String()), - deposit: Type.Optional(Type.Number()), + deposit: Type.Optional(Type.Uint()), drep: Type.Optional(CardanoDRep), }, { $id: 'CardanoTxCertificate' }, diff --git a/packages/protobuf/src/messages.ts b/packages/protobuf/src/messages.ts index 68487359711..4d55fdaa839 100644 --- a/packages/protobuf/src/messages.ts +++ b/packages/protobuf/src/messages.ts @@ -874,7 +874,7 @@ export type CardanoTxCertificate = { pool_parameters?: CardanoPoolParametersType; script_hash?: string; key_hash?: string; - deposit?: number; + deposit?: UintType; drep?: CardanoDRep; }; From 8aacc85a7a6c9480f63b0c5f76ad656cd4c94705 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Peter=20Jas=CC=8Cko?= Date: Tue, 12 Dec 2023 10:58:12 +0100 Subject: [PATCH 2/3] feat(connect): Add tag 258 support --- .../connect/methods/cardanoSignTransaction.md | 1 + .../cardano/cardanoSignTransaction.mdx | 2 + .../__fixtures__/cardanoSignTransaction.ts | 87 +++++++++++++++++++ .../api/cardano/api/cardanoSignTransaction.ts | 7 ++ .../src/types/api/__tests__/cardano.ts | 1 + .../connect/src/types/api/cardano/index.ts | 1 + 6 files changed, 99 insertions(+) diff --git a/docs/packages/connect/methods/cardanoSignTransaction.md b/docs/packages/connect/methods/cardanoSignTransaction.md index ed129ad5f2b..323bd040bef 100644 --- a/docs/packages/connect/methods/cardanoSignTransaction.md +++ b/docs/packages/connect/methods/cardanoSignTransaction.md @@ -36,6 +36,7 @@ const result = await TrezorConnect.cardanoSignTransaction(params); - `derivationType` — _optional_ `CardanoDerivationType` enum. Determines used derivation type. Default is set to ICARUS_TREZOR=2. - `includeNetworkId` — _optional_ `Boolean`. Determines whether `networkId` should be explicitly serialized into the transaction body. Default is `false`. - `chunkify` — _optional_ `boolean` determines if recipient address will be displayed in chunks of 4 characters. Default is set to `false` +- `tagCborSets` - _optional_ `boolean` determines if CBOR arrays intended to be sets will be encoded with tag 258. Default is set to `false` ### CardanoTxSigningMode diff --git a/packages/connect-explorer/src/pages/methods/cardano/cardanoSignTransaction.mdx b/packages/connect-explorer/src/pages/methods/cardano/cardanoSignTransaction.mdx index 5dedb855569..3a1e2d0951f 100644 --- a/packages/connect-explorer/src/pages/methods/cardano/cardanoSignTransaction.mdx +++ b/packages/connect-explorer/src/pages/methods/cardano/cardanoSignTransaction.mdx @@ -53,6 +53,8 @@ export const paramDescriptions = { 'Determines whether `networkId` should be explicitly serialized into the transaction body. Default is `false`.', chunkify: 'determines if recipient address will be displayed in chunks of 4 characters. Default is set to `false`', + tagCborSets: + 'determines if CBOR arrays intended to be sets will be encoded with tag 258. Default is set to `false`', }; ## Cardano: Sign transaction diff --git a/packages/connect/e2e/__fixtures__/cardanoSignTransaction.ts b/packages/connect/e2e/__fixtures__/cardanoSignTransaction.ts index 61df527bf4d..b9e9cb2e2c9 100644 --- a/packages/connect/e2e/__fixtures__/cardanoSignTransaction.ts +++ b/packages/connect/e2e/__fixtures__/cardanoSignTransaction.ts @@ -660,6 +660,7 @@ export default { protocolMagic: PROTOCOL_MAGICS.mainnet, networkId: NETWORK_IDS.mainnet, signingMode: CardanoTxSigningMode.ORDINARY_TRANSACTION, + tagCborSets: false, }, result: { hash: 'e200b2c91f3493a1f3b9cfc8b6c141f70181741025e53941e9d57d22b1470c5c', @@ -684,6 +685,42 @@ export default { legacyResults: [legacyResults.beforeConway], }, + { + description: 'signStakeRegistrationConwayWith258TaggedSets', + params: { + inputs: [SAMPLE_INPUTS.shelley_input], + outputs: [SAMPLE_OUTPUTS.simple_shelley_output], + fee: FEE, + ttl: TTL, + certificates: [SAMPLE_CERTIFICATES.stake_registration_conway], + protocolMagic: PROTOCOL_MAGICS.mainnet, + networkId: NETWORK_IDS.mainnet, + signingMode: CardanoTxSigningMode.ORDINARY_TRANSACTION, + tagCborSets: true, + }, + result: { + hash: '5e27f8fba938603411452a8cb373462fb64305539573b7a9edc9155be5cd6473', + witnesses: [ + { + type: 1, + pubKey: '5d010cf16fdeff40955633d6c565f3844a288a24967cf6b76acbeb271b4f13c1', + signature: + '13c136487d8048ab7bbb081a324aa6b999e0b3237f956503b5446a4c409ec1062091b82e9e5459dee7ab0ba67ed874692d788872c8bbdb5ad4a3975c465fea09', + chainCode: null, + }, + { + type: 1, + pubKey: 'bc65be1b0b9d7531778a1317c2aa6de936963c3f9ac7d5ee9e9eda25e0c97c5e', + signature: + 'f0674db7194d8e04d7df416af8ad9dcf1b1203ca4b78f14c1e394d47418c8f7e95fd41a8f01c43eeeb39df6264359c865a41621fc1e6b540819b25c7c4df5803', + chainCode: null, + }, + ], + auxiliaryDataSupplement: undefined, + }, + legacyResults: [legacyResults.beforeConway], + }, + { description: 'signStakeRegistrationNoOutputs', params: { @@ -2424,6 +2461,56 @@ export default { }, }, + { + description: 'plutusWithRequiredSignersAndReferenceInputAnd258TaggedSets', + params: { + inputs: [SAMPLE_INPUTS.shelley_input], + outputs: [SAMPLE_OUTPUTS.simple_shelley_output], + fee: FEE, + ttl: TTL, + protocolMagic: PROTOCOL_MAGICS.mainnet, + networkId: NETWORK_IDS.mainnet, + signingMode: CardanoTxSigningMode.PLUTUS_TRANSACTION, + scriptDataHash: SCRIPT_DATA_HASH, + collateralInputs: [SAMPLE_INPUTS.shelley_input_2], + requiredSigners: [ + { keyPath: "m/1852'/1815'/0'/0/0" }, + { keyPath: "m/1854'/1815'/0'/0/0" }, + { keyHash: '3a7f09d3df4cf66a7399c2b05bfa234d5a29560c311fc5db4c490711' }, + ], + referenceInput: [SAMPLE_INPUTS.plutus_input], + tagCborSets: true, + }, + result: { + hash: 'eee852948723773f059bbbc9f4378473e339a62ec518ac3aeb8ecdf27abf8581', + witnesses: [ + { + type: 1, + pubKey: '5d010cf16fdeff40955633d6c565f3844a288a24967cf6b76acbeb271b4f13c1', + signature: + 'ccf25b4926d4ea953f9330196f881ec6974b3979a05fd679e846eb0fd90f5e5d64cdba51fad9354a50343a29c09dfda8177fd1717ca8d105c9d923a31071b909', + chainCode: null, + }, + { + type: 1, + pubKey: '36a8ef21d5b98fdf23a27325cf643deaac35e912c835e35037f23d1061ae5b16', + signature: + '39231ff0df125987c5a7583f307d74d3bdcb9702baafc8588aa16002d19d595725da64518603bb0617bfba851fe96f0cf75c19d75b0749443e09fdc8aebb4603', + chainCode: null, + }, + { + type: 1, + pubKey: 'b10be5c0d11ad8292bbe69e220ca0cfbe154610b3041a8e72f9d515c226ab3b1', + signature: + 'e78e5a21c07ed5f613d01d20f9684a3b807b30ca211f69a2a0391ab3137d3b1260c51bdf08079e213e2487f3b8c36d6b42d7d15733113cf725ca3f162f030001', + chainCode: null, + }, + ], + auxiliaryDataSupplement: undefined, + }, + legacyResults: [legacyResults.beforeConway], + }, + { description: 'plutusWithManyWitnesses', params: { diff --git a/packages/connect/src/api/cardano/api/cardanoSignTransaction.ts b/packages/connect/src/api/cardano/api/cardanoSignTransaction.ts index fbd1b63801f..eb44714aeb6 100644 --- a/packages/connect/src/api/cardano/api/cardanoSignTransaction.ts +++ b/packages/connect/src/api/cardano/api/cardanoSignTransaction.ts @@ -65,6 +65,7 @@ export type CardanoSignTransactionParams = { additionalWitnessRequests: Path[]; derivationType: PROTO.CardanoDerivationType; includeNetworkId?: boolean; + tagCborSets?: boolean; unsignedTx?: { body: string; hash: string }; testnet?: boolean; chunkify?: boolean; @@ -223,6 +224,7 @@ export default class CardanoSignTransaction extends AbstractMethod< ? payload.derivationType : PROTO.CardanoDerivationType.ICARUS_TREZOR, includeNetworkId: payload.includeNetworkId, + tagCborSets: payload.tagCborSets, unsignedTx: 'unsignedTx' in payload ? payload.unsignedTx : undefined, testnet: 'testnet' in payload ? payload.testnet : undefined, chunkify: typeof payload.chunkify === 'boolean' ? payload.chunkify : false, @@ -258,6 +260,10 @@ export default class CardanoSignTransaction extends AbstractMethod< this._ensureFeatureIsSupported('Conway'); } }); + + if (params.tagCborSets) { + this._ensureFeatureIsSupported('Conway'); + } } async _sign_tx(): Promise { @@ -288,6 +294,7 @@ export default class CardanoSignTransaction extends AbstractMethod< derivation_type: this.params.derivationType, include_network_id: this.params.includeNetworkId, chunkify: this.params.chunkify, + tag_cbor_sets: this.params.tagCborSets, }; // init diff --git a/packages/connect/src/types/api/__tests__/cardano.ts b/packages/connect/src/types/api/__tests__/cardano.ts index caf38add058..ab59c6d05be 100644 --- a/packages/connect/src/types/api/__tests__/cardano.ts +++ b/packages/connect/src/types/api/__tests__/cardano.ts @@ -401,6 +401,7 @@ export const cardanoSignTransaction = async (api: TrezorConnect) => { networkId: 0, signingMode: CardanoTxSigningMode.ORDINARY_TRANSACTION, includeNetworkId: false, + tagCborSets: false, }); if (sign.success) { diff --git a/packages/connect/src/types/api/cardano/index.ts b/packages/connect/src/types/api/cardano/index.ts index 908644a0dc9..7170a522713 100644 --- a/packages/connect/src/types/api/cardano/index.ts +++ b/packages/connect/src/types/api/cardano/index.ts @@ -262,6 +262,7 @@ export const CardanoSignTransaction = Type.Object({ derivationType: Type.Optional(PROTO.EnumCardanoDerivationType), includeNetworkId: Type.Optional(Type.Boolean()), chunkify: Type.Optional(Type.Boolean()), + tagCborSets: Type.Optional(Type.Boolean()), }); export type CardanoSignTransactionExtended = Static; From fd92a5cf6bfcc4a12812cf18bbee6d25dc8c7339 Mon Sep 17 00:00:00 2001 From: David Misiak Date: Fri, 24 May 2024 20:00:14 +0200 Subject: [PATCH 3/3] chore(connect): update fw version number for cardano --- packages/connect/e2e/__fixtures__/cardanoSignTransaction.ts | 2 +- packages/connect/src/api/cardano/api/cardanoSignTransaction.ts | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/packages/connect/e2e/__fixtures__/cardanoSignTransaction.ts b/packages/connect/e2e/__fixtures__/cardanoSignTransaction.ts index b9e9cb2e2c9..b1841193bd8 100644 --- a/packages/connect/e2e/__fixtures__/cardanoSignTransaction.ts +++ b/packages/connect/e2e/__fixtures__/cardanoSignTransaction.ts @@ -441,7 +441,7 @@ const legacyResults = { // FW <2.6.0 is not supported by Connect at all beforeConway: { // older FW doesn't support Conway certificates - rules: ['<2.6.5', '1'], + rules: ['<2.7.1', '1'], payload: false, }, }; diff --git a/packages/connect/src/api/cardano/api/cardanoSignTransaction.ts b/packages/connect/src/api/cardano/api/cardanoSignTransaction.ts index eb44714aeb6..ef748f83971 100644 --- a/packages/connect/src/api/cardano/api/cardanoSignTransaction.ts +++ b/packages/connect/src/api/cardano/api/cardanoSignTransaction.ts @@ -39,7 +39,7 @@ import { AssertWeak, Type } from '@trezor/schema-utils'; const CardanoSignTransactionFeatures = Object.freeze({ // FW <2.6.0 is not supported by Connect at all - Conway: ['0', '2.6.5'], + Conway: ['0', '2.7.1'], }); export type CardanoSignTransactionParams = {