From bebc0fbd241b6370b31b91e5a60b1d5d30cec403 Mon Sep 17 00:00:00 2001 From: Dominik Toton <166132265+dtscalac@users.noreply.github.com> Date: Wed, 10 Jul 2024 15:28:26 +0200 Subject: [PATCH] feat: add required signers (#605) --- .../catalyst_cardano_serialization/README.md | 2 +- .../lib/src/builders/transaction_builder.dart | 8 +++ .../lib/src/transaction.dart | 22 +++++++- .../test/fees_test.dart | 4 +- .../test/test_utils/test_data.dart | 16 ++++++ .../test/transaction_test.dart | 56 ++++++++++--------- 6 files changed, 76 insertions(+), 32 deletions(-) diff --git a/catalyst_voices_packages/catalyst_cardano_serialization/README.md b/catalyst_voices_packages/catalyst_cardano_serialization/README.md index 4e82f26cb64..4e016e087ac 100644 --- a/catalyst_voices_packages/catalyst_cardano_serialization/README.md +++ b/catalyst_voices_packages/catalyst_cardano_serialization/README.md @@ -198,7 +198,7 @@ Byron era addresses are not supported. | 9 = mint | ❌️ | | 11 = script_data_hash | ❌️ | | 13 = collateral inputs | ❌️ | -| 14 = required signers | ❌️ | +| 14 = required signers | ✔️ | | 15 = network_id | ✔️ | | 16 = collateral return | ❌️ | | 17 = total collateral | ❌️ | diff --git a/catalyst_voices_packages/catalyst_cardano_serialization/lib/src/builders/transaction_builder.dart b/catalyst_voices_packages/catalyst_cardano_serialization/lib/src/builders/transaction_builder.dart index e4ebabfa757..8a55cda0ec7 100644 --- a/catalyst_voices_packages/catalyst_cardano_serialization/lib/src/builders/transaction_builder.dart +++ b/catalyst_voices_packages/catalyst_cardano_serialization/lib/src/builders/transaction_builder.dart @@ -38,6 +38,10 @@ final class TransactionBuilder extends Equatable { /// The transaction metadata as a list of key-value pairs (a map). final AuxiliaryData? auxiliaryData; + /// The list of public key hashes of addresses + /// that are required to sign the transaction. + final Set? requiredSigners; + /// Specifies on which network the code will run. final NetworkId? networkId; @@ -56,6 +60,7 @@ final class TransactionBuilder extends Equatable { this.fee, this.ttl, this.auxiliaryData, + this.requiredSigners, this.networkId, this.witnessBuilder = const TransactionWitnessSetBuilder( vkeys: {}, @@ -224,6 +229,7 @@ final class TransactionBuilder extends Equatable { fee, ttl, auxiliaryData, + requiredSigners, networkId, witnessBuilder, ]; @@ -467,6 +473,7 @@ final class TransactionBuilder extends Equatable { auxiliaryDataHash: auxiliaryData != null ? AuxiliaryDataHash.fromAuxiliaryData(auxiliaryData!) : null, + requiredSigners: requiredSigners, networkId: networkId, ); } @@ -483,6 +490,7 @@ final class TransactionBuilder extends Equatable { fee: fee ?? this.fee, ttl: ttl, auxiliaryData: auxiliaryData, + requiredSigners: requiredSigners, networkId: networkId, witnessBuilder: witnessBuilder ?? this.witnessBuilder, ); diff --git a/catalyst_voices_packages/catalyst_cardano_serialization/lib/src/transaction.dart b/catalyst_voices_packages/catalyst_cardano_serialization/lib/src/transaction.dart index c9d9b5a5f01..86f21b82ef8 100644 --- a/catalyst_voices_packages/catalyst_cardano_serialization/lib/src/transaction.dart +++ b/catalyst_voices_packages/catalyst_cardano_serialization/lib/src/transaction.dart @@ -81,6 +81,10 @@ final class TransactionBody extends Equatable { /// which is the metadata of the transaction. final AuxiliaryDataHash? auxiliaryDataHash; + /// The list of public key hashes of addresses + /// that are required to sign the transaction. + final Set? requiredSigners; + /// Specifies on which network the code will run. final NetworkId? networkId; @@ -91,6 +95,7 @@ final class TransactionBody extends Equatable { required this.fee, this.ttl, this.auxiliaryDataHash, + this.requiredSigners, this.networkId, }); @@ -102,6 +107,7 @@ final class TransactionBody extends Equatable { final fee = map[const CborSmallInt(2)]!; final ttl = map[const CborSmallInt(3)]; final auxiliaryDataHash = map[const CborSmallInt(7)]; + final requiredSigners = map[const CborSmallInt(14)] as CborList?; final networkId = map[const CborSmallInt(15)] as CborSmallInt?; return TransactionBody( @@ -112,6 +118,7 @@ final class TransactionBody extends Equatable { auxiliaryDataHash: auxiliaryDataHash != null ? AuxiliaryDataHash.fromCbor(auxiliaryDataHash) : null, + requiredSigners: requiredSigners?.map(Vkey.fromCbor).toSet(), networkId: networkId != null ? NetworkId.fromId(networkId.value) : null, ); } @@ -129,14 +136,25 @@ final class TransactionBody extends Equatable { if (ttl != null) const CborSmallInt(3): ttl!.toCbor(), if (auxiliaryDataHash != null) const CborSmallInt(7): auxiliaryDataHash!.toCbor(), + if (requiredSigners != null && requiredSigners!.isNotEmpty) + const CborSmallInt(14): CborList([ + for (final signer in requiredSigners!) signer.toCbor(), + ]), if (networkId != null) const CborSmallInt(15): CborSmallInt(networkId!.id), }); } @override - List get props => - [inputs, outputs, fee, ttl, auxiliaryDataHash, networkId]; + List get props => [ + inputs, + outputs, + fee, + ttl, + auxiliaryDataHash, + requiredSigners, + networkId, + ]; } /// The transaction output of a previous transaction, diff --git a/catalyst_voices_packages/catalyst_cardano_serialization/test/fees_test.dart b/catalyst_voices_packages/catalyst_cardano_serialization/test/fees_test.dart index aa5e40c7695..da84355c50a 100644 --- a/catalyst_voices_packages/catalyst_cardano_serialization/test/fees_test.dart +++ b/catalyst_voices_packages/catalyst_cardano_serialization/test/fees_test.dart @@ -13,7 +13,7 @@ void main() { ); final tx = fullSignedTestTransaction(); - expect(linearFee.minNoScriptFee(tx), equals(176369)); + expect(linearFee.minNoScriptFee(tx), equals(177953)); }); test('minFeeNoScript with constant fee only', () { @@ -33,7 +33,7 @@ void main() { ); final tx = fullSignedTestTransaction(); - expect(linearFee.minNoScriptFee(tx), equals(20988)); + expect(linearFee.minNoScriptFee(tx), equals(22572)); }); }); } diff --git a/catalyst_voices_packages/catalyst_cardano_serialization/test/test_utils/test_data.dart b/catalyst_voices_packages/catalyst_cardano_serialization/test/test_utils/test_data.dart index 7072258a28a..2bc1af8a920 100644 --- a/catalyst_voices_packages/catalyst_cardano_serialization/test/test_utils/test_data.dart +++ b/catalyst_voices_packages/catalyst_cardano_serialization/test/test_utils/test_data.dart @@ -127,6 +127,14 @@ Transaction fullUnsignedTestTransaction() { fee: const Coin(167173), ttl: const SlotBigNum(41193), auxiliaryDataHash: AuxiliaryDataHash.fromAuxiliaryData(auxiliaryData), + requiredSigners: { + Vkey.fromBytes( + hex.decode( + '3311ca404fcf22c91d607ace285d70e2' + '263a1b81745c39673080329bd1a3f56e', + ), + ), + }, networkId: NetworkId.testnet, ), isValid: true, @@ -157,6 +165,14 @@ Transaction fullSignedTestTransaction() { fee: const Coin(167173), ttl: const SlotBigNum(41193), auxiliaryDataHash: AuxiliaryDataHash.fromAuxiliaryData(auxiliaryData), + requiredSigners: { + Vkey.fromBytes( + hex.decode( + '3311ca404fcf22c91d607ace285d70e2' + '263a1b81745c39673080329bd1a3f56e', + ), + ), + }, networkId: NetworkId.testnet, ), isValid: true, diff --git a/catalyst_voices_packages/catalyst_cardano_serialization/test/transaction_test.dart b/catalyst_voices_packages/catalyst_cardano_serialization/test/transaction_test.dart index 979e7aec900..b6776a96fb4 100644 --- a/catalyst_voices_packages/catalyst_cardano_serialization/test/transaction_test.dart +++ b/catalyst_voices_packages/catalyst_cardano_serialization/test/transaction_test.dart @@ -10,21 +10,22 @@ void main() { test('full signed transaction serialized to cbor', () { _testTransactionSerialization( fullSignedTestTransaction(), - '84a600818258204c1fbc5433ec764164945d736a09dc087d59ff30e64d26d462ff' - '8570cd4be9a700018282581d6082e016828989cd9d809b50d6976d9efa9bc5b2c1' - 'a78d4b3bfa1bb83b1a000f424082583900c035332d2dcba35744e880729198459e' - '32c50eb3e179b1fa2247348c80b846ad416f120db94c1a401992950b11b9bc7d65' - 'dbb3424c0f8de41b0000000253fa14bb021a00028d050319a0e907582057b9d497' - '6bc8017e5b95c6996bac1749765e188c990b5c705a65c78f8349227d0f00a10081' - '8258203311ca404fcf22c91d607ace285d70e2263a1b81745c39673080329bd1a3' - 'f56e5840f5eb006f048fdfa9b81b0fe3abee1ce1f1a75789dc21088b23ebf95c76' - 'b050ad157a497999e083e1957c2a3d730a07a5b2aef4a755783c9ce778c02c4a08' - '970ff5a40164546573740246aabbccddeeff031903e50482a50081825820afcf84' - '97561065afe1ca623823508753cc580eb575ac8f1d6cfaa18c3ceeac0100018182' - '58390080f9e2c88e6c817008f3a812ed889b4a4da8e0bd103f86e7335422aa122a' - '946b9ad3d2ddf029d3a828f0468aece76895f15c9efbd69b42771a00df1560021a' - '0002e63003182f075820bdc2b27e6869aa9a5fa23a1f1fd3a87025d8703df4fd7b' - '120d058c839dc0415c82a10141aa80', + '84a700818258204c1fbc5433ec764164945d736a09dc087d59ff30e64d26d462ff85' + '70cd4be9a700018282581d6082e016828989cd9d809b50d6976d9efa9bc5b2c1a78d' + '4b3bfa1bb83b1a000f424082583900c035332d2dcba35744e880729198459e32c50e' + 'b3e179b1fa2247348c80b846ad416f120db94c1a401992950b11b9bc7d65dbb3424c' + '0f8de41b0000000253fa14bb021a00028d050319a0e907582057b9d4976bc8017e5b' + '95c6996bac1749765e188c990b5c705a65c78f8349227d0e8158203311ca404fcf22' + 'c91d607ace285d70e2263a1b81745c39673080329bd1a3f56e0f00a1008182582033' + '11ca404fcf22c91d607ace285d70e2263a1b81745c39673080329bd1a3f56e5840f5' + 'eb006f048fdfa9b81b0fe3abee1ce1f1a75789dc21088b23ebf95c76b050ad157a49' + '7999e083e1957c2a3d730a07a5b2aef4a755783c9ce778c02c4a08970ff5a4016454' + '6573740246aabbccddeeff031903e50482a50081825820afcf8497561065afe1ca62' + '3823508753cc580eb575ac8f1d6cfaa18c3ceeac010001818258390080f9e2c88e6c' + '817008f3a812ed889b4a4da8e0bd103f86e7335422aa122a946b9ad3d2ddf029d3a8' + '28f0468aece76895f15c9efbd69b42771a00df1560021a0002e63003182f075820bd' + 'c2b27e6869aa9a5fa23a1f1fd3a87025d8703df4fd7b120d058c839dc0415c82a101' + '41aa80', ); }); @@ -35,18 +36,19 @@ void main() { test('full unsigned transaction serialized to cbor', () { _testTransactionSerialization( fullUnsignedTestTransaction(), - '84a600818258204c1fbc5433ec764164945d736a09dc087d59ff30e64d26d462ff' - '8570cd4be9a700018282581d6082e016828989cd9d809b50d6976d9efa9bc5b2c1' - 'a78d4b3bfa1bb83b1a000f424082583900c035332d2dcba35744e880729198459e' - '32c50eb3e179b1fa2247348c80b846ad416f120db94c1a401992950b11b9bc7d65' - 'dbb3424c0f8de41b0000000253fa14bb021a00028d050319a0e907582057b9d497' - '6bc8017e5b95c6996bac1749765e188c990b5c705a65c78f8349227d0f00a0f5a4' - '0164546573740246aabbccddeeff031903e50482a50081825820afcf8497561065' - 'afe1ca623823508753cc580eb575ac8f1d6cfaa18c3ceeac010001818258390080' - 'f9e2c88e6c817008f3a812ed889b4a4da8e0bd103f86e7335422aa122a946b9ad3' - 'd2ddf029d3a828f0468aece76895f15c9efbd69b42771a00df1560021a0002e630' - '03182f075820bdc2b27e6869aa9a5fa23a1f1fd3a87025d8703df4fd7b120d058c' - '839dc0415c82a10141aa80', + '84a700818258204c1fbc5433ec764164945d736a09dc087d59ff30e64d26d462ff85' + '70cd4be9a700018282581d6082e016828989cd9d809b50d6976d9efa9bc5b2c1a78d' + '4b3bfa1bb83b1a000f424082583900c035332d2dcba35744e880729198459e32c50e' + 'b3e179b1fa2247348c80b846ad416f120db94c1a401992950b11b9bc7d65dbb3424c' + '0f8de41b0000000253fa14bb021a00028d050319a0e907582057b9d4976bc8017e5b' + '95c6996bac1749765e188c990b5c705a65c78f8349227d0e8158203311ca404fcf22' + 'c91d607ace285d70e2263a1b81745c39673080329bd1a3f56e0f00a0f5a401645465' + '73740246aabbccddeeff031903e50482a50081825820afcf8497561065afe1ca6238' + '23508753cc580eb575ac8f1d6cfaa18c3ceeac010001818258390080f9e2c88e6c81' + '7008f3a812ed889b4a4da8e0bd103f86e7335422aa122a946b9ad3d2ddf029d3a828' + 'f0468aece76895f15c9efbd69b42771a00df1560021a0002e63003182f075820bdc2' + 'b27e6869aa9a5fa23a1f1fd3a87025d8703df4fd7b120d058c839dc0415c82a10141' + 'aa80', ); });