From 9d8150da638f0a4d09a6d8449cd5af6c6cab15b1 Mon Sep 17 00:00:00 2001 From: Jan Mazak Date: Fri, 3 Nov 2023 00:45:14 +0100 Subject: [PATCH] Conway: proposal procedures --- src/errors/parseError.ts | 3 + src/errors/validationError.ts | 2 + src/txParsers.ts | 29 ++++++ src/txSerializers.ts | 12 +++ src/txTransformers.ts | 3 + src/txValidators.ts | 7 ++ src/types.ts | 8 ++ src/utils.ts | 1 + test/integration/__fixtures__/transactions.ts | 93 +++++++++++++++++++ 9 files changed, 158 insertions(+) diff --git a/src/errors/parseError.ts b/src/errors/parseError.ts index df99f25..aace8b0 100644 --- a/src/errors/parseError.ts +++ b/src/errors/parseError.ts @@ -84,8 +84,11 @@ export enum ParseErrorReason { INVALID_GOV_ACTION_ID = 'Invalid governance action id', INVALID_VOTING_PROCEDURE = 'Invalid voting procedure', INVALID_VOTE_OPTION = 'Invalid vote', + INVALID_PROPOSAL_PROCEDURES = 'Invalid proposal procedures', + INVALID_PROPOSAL_PROCEDURE = 'Invalid proposal procedure', INVALID_TREASURY = 'Invalid treasury', INVALID_DONATION = 'Invalid donation', + // TODO the order of the items in this enum is messed up? INVALID_TX_CBOR = 'Invalid transaction CBOR', } diff --git a/src/errors/validationError.ts b/src/errors/validationError.ts index 16d820e..bc78a59 100644 --- a/src/errors/validationError.ts +++ b/src/errors/validationError.ts @@ -1,6 +1,7 @@ export enum ValidationErrorReason { // Unfixable validation errors UNSUPPORTED_TX_UPDATE = 'The transaction body entry update must not be included', + UNSUPPORTED_TX_PROPOSAL_PROCEDURES = 'The transaction body entry proposal_procedures must not be included', UNSUPPORTED_CERTIFICATE_GENESIS_KEY_DELEGATION = 'Certificate of type genesis_key_delegation is not supported and must not be included', UNSUPPORTED_CERTIFICATE_MOVE_INSTANTANEOUS_REWARDS_CERT = 'Certificate of type move_instantaneous_rewards_cert is not supported and must not be included', UNSUPPORTED_CERTIFICATE_STAKE_VOTE_DELEG = 'Certificate of type stake_vote_deleg_cert is not supported and must not be included', @@ -32,6 +33,7 @@ const UNFIXABLE = false const validationErrorFixability: Record = { [ValidationErrorReason.UNSUPPORTED_TX_UPDATE]: UNFIXABLE, + [ValidationErrorReason.UNSUPPORTED_TX_PROPOSAL_PROCEDURES]: UNFIXABLE, [ValidationErrorReason.UNSUPPORTED_CERTIFICATE_GENESIS_KEY_DELEGATION]: UNFIXABLE, [ValidationErrorReason.UNSUPPORTED_CERTIFICATE_MOVE_INSTANTANEOUS_REWARDS_CERT]: diff --git a/src/txParsers.ts b/src/txParsers.ts index f4e0ccb..299ae42 100644 --- a/src/txParsers.ts +++ b/src/txParsers.ts @@ -103,6 +103,7 @@ import { VotingProcedure, VoteOption, Coin, + ProposalProcedure, } from './types' import { BabbageTransactionOutputKeys, @@ -960,6 +961,30 @@ const parseVotingProcedures = (unparsed: unknown): Ballot[] => { })) } +const parseProposalProcedure = ( + unparsedProcedure: unknown, +): ProposalProcedure => { + const [deposit, rewardAccount, govAction, anchor] = parseTuple( + unparsedProcedure, + ParseErrorReason.INVALID_PROPOSAL_PROCEDURE, + parseCoin, + parseRewardAccount, + doNotParse, + parseAnchor, // TODO not nullable, should we check for that? + ) + return { + deposit, + rewardAccount, + govAction, + anchor, + } +} +const parseProposalProcedures = createParser( + parseArray, + parseProposalProcedure, + ParseErrorReason.INVALID_PROPOSAL_PROCEDURES, +) + const parseTreasury = createParser(parseUint, ParseErrorReason.INVALID_TREASURY) const parseDonation = (unparsed: unknown): Coin => { const coin = parseUint(unparsed, ParseErrorReason.INVALID_DONATION) @@ -1037,6 +1062,10 @@ export const parseTxBody = (unparsedTxBody: unknown): TransactionBody => { unparsedTxBody.get(TransactionBodyKeys.VOTING_PROCEDURES), parseVotingProcedures, ), + proposalProcedures: parseOptional( + unparsedTxBody.get(TransactionBodyKeys.PROPOSAL_PROCEDURES), + parseProposalProcedures, + ), treasury: parseOptional( unparsedTxBody.get(TransactionBodyKeys.TREASURY), parseTreasury, diff --git a/src/txSerializers.ts b/src/txSerializers.ts index db20023..f974478 100644 --- a/src/txSerializers.ts +++ b/src/txSerializers.ts @@ -33,6 +33,7 @@ import { Voter, GovActionId, VotingProcedure, + ProposalProcedure, } from './types' import { BabbageTransactionOutputKeys, @@ -305,6 +306,13 @@ const serializeVotingProcedures = (ballots: Ballot[]) => ]), ) +const serializeProposalProcedure = (procedure: ProposalProcedure) => [ + procedure.deposit, + procedure.rewardAccount, + procedure.govAction, + serializeAnchor(procedure.anchor), +] + export const serializeTxBody = (txBody: TransactionBody) => filteredMap([ [TransactionBodyKeys.INPUTS, txBody.inputs.map(serializeTxInput)], @@ -351,6 +359,10 @@ export const serializeTxBody = (txBody: TransactionBody) => txBody.votingProcedures && serializeVotingProcedures(txBody.votingProcedures), ], + [ + TransactionBodyKeys.PROPOSAL_PROCEDURES, + txBody.proposalProcedures?.map(serializeProposalProcedure), + ], [TransactionBodyKeys.TREASURY, identity(txBody.treasury)], [TransactionBodyKeys.DONATION, identity(txBody.donation)], ]) diff --git a/src/txTransformers.ts b/src/txTransformers.ts index 360d0e7..09a106d 100644 --- a/src/txTransformers.ts +++ b/src/txTransformers.ts @@ -132,6 +132,9 @@ export const transformTxBody = ( txBody.collateralReturnOutput && transformTxOutput(txBody.collateralReturnOutput), referenceInputs: transformOptionalList(txBody.referenceInputs), + // TODO voting procedures? there might be empty map + // TODO proposal procedures? empty list, and + // check with CDDL which lists are nonempty there, maybe we should check it at parsing immediately auxiliaryDataHash: transformAuxiliaryDataHash( txBody.auxiliaryDataHash, auxiliaryData, diff --git a/src/txValidators.ts b/src/txValidators.ts index 833b384..6eee251 100644 --- a/src/txValidators.ts +++ b/src/txValidators.ts @@ -541,6 +541,13 @@ function* validateTxBody(txBody: TransactionBody): ValidatorReturnType { bind(validateUint64, 'transaction_body.total_collateral'), ) yield* validateOptional(txBody.referenceInputs, validateReferenceInputs) + yield* validate( + txBody.proposalProcedures === undefined, + err( + ValidationErrorReason.UNSUPPORTED_TX_PROPOSAL_PROCEDURES, + 'transaction_body.proposal_procedures', + ), + ) yield* validateOptional( txBody.treasury, bind(validateUint64, 'transaction_body.treasury'), diff --git a/src/types.ts b/src/types.ts index 4efc359..13fbf4d 100644 --- a/src/types.ts +++ b/src/types.ts @@ -462,6 +462,13 @@ export type Ballot = { votes: Vote[] } +export type ProposalProcedure = { + deposit: Coin + rewardAccount: RewardAccount + govAction: Unparsed + anchor: Anchor +} + // Transaction body export type TransactionBody = { inputs: TransactionInput[] @@ -482,6 +489,7 @@ export type TransactionBody = { totalCollateral?: Coin referenceInputs?: TransactionInput[] votingProcedures?: Ballot[] + proposalProcedures?: ProposalProcedure[] treasury?: Coin donation?: Coin } diff --git a/src/utils.ts b/src/utils.ts index e0332bd..631b1c5 100644 --- a/src/utils.ts +++ b/src/utils.ts @@ -99,6 +99,7 @@ export enum TransactionBodyKeys { TOTAL_COLLATERAL = 17, REFERENCE_INPUTS = 18, VOTING_PROCEDURES = 19, + PROPOSAL_PROCEDURES = 20, TREASURY = 21, DONATION = 22, } diff --git a/test/integration/__fixtures__/transactions.ts b/test/integration/__fixtures__/transactions.ts index 8d33cc9..d78f980 100644 --- a/test/integration/__fixtures__/transactions.ts +++ b/test/integration/__fixtures__/transactions.ts @@ -75,6 +75,7 @@ export const ValidTransactionBodyTestCases: ValidTransactionBodyTestCase[] = [ totalCollateral: undefined, referenceInputs: undefined, votingProcedures: undefined, + proposalProcedures: undefined, treasury: undefined, donation: undefined, }, @@ -134,6 +135,7 @@ export const ValidTransactionBodyTestCases: ValidTransactionBodyTestCase[] = [ totalCollateral: undefined, referenceInputs: undefined, votingProcedures: undefined, + proposalProcedures: undefined, treasury: undefined, donation: undefined, }, @@ -240,6 +242,7 @@ export const ValidTransactionBodyTestCases: ValidTransactionBodyTestCase[] = [ totalCollateral: undefined, referenceInputs: undefined, votingProcedures: undefined, + proposalProcedures: undefined, treasury: undefined, donation: undefined, }, @@ -388,6 +391,7 @@ export const ValidTransactionBodyTestCases: ValidTransactionBodyTestCase[] = [ totalCollateral: undefined, referenceInputs: undefined, votingProcedures: undefined, + proposalProcedures: undefined, treasury: undefined, donation: undefined, }, @@ -492,6 +496,7 @@ export const ValidTransactionBodyTestCases: ValidTransactionBodyTestCase[] = [ totalCollateral: undefined, referenceInputs: undefined, votingProcedures: undefined, + proposalProcedures: undefined, treasury: undefined, donation: undefined, }, @@ -576,6 +581,7 @@ export const ValidTransactionBodyTestCases: ValidTransactionBodyTestCase[] = [ }, ], votingProcedures: undefined, + proposalProcedures: undefined, treasury: undefined, donation: undefined, }, @@ -650,6 +656,87 @@ export const ValidTransactionBodyTestCases: ValidTransactionBodyTestCase[] = [ ], }, ], + proposalProcedures: undefined, + treasury: undefined, + donation: undefined, + }, + }, + { + // https://auspicious-fuchsia-2e9.notion.site/Transactions-in-SanchoNet-fbcf91c799404fe4b30a78e8e091df79#a5ef58aa46e84d2f96d0b14f906e0417 + testName: 'Conway tx body: proposal procedures', + cbor: 'a40081825820017b91576a79a3602a02a65b600665ab71037ad14aa162538a26e64b3f5069fc000181a2005839002d745f050a8f7e263f4d0749a82284ed9cc065018c1f4f6a7c1b764882293a49e3ef29a4f9c32e4c18f202f5324182db7790f48dccf7a6dd011b0000000253d1efbc021a0002b3b11481841a000f4240581de082293a49e3ef29a4f9c32e4c18f202f5324182db7790f48dccf7a6dd8305f68282781968747470733a2f2f73686f727475726c2e61742f6173494a365820ee90ece16c47bf812b88edb89a01539e6683d6549a80b15383a4fb218ab9412df682781968747470733a2f2f73686f727475726c2e61742f784d53313558206f890de0c6e418e6526e2b1aa821850cb87aee94a6d77dc2a2e440116abc8e09', + txBody: { + inputs: [ + { + transactionId: toFixLenBuffer( + '017b91576a79a3602a02a65b600665ab71037ad14aa162538a26e64b3f5069fc', + 32, + ), + index: toUint(0), + }, + ], + outputs: [ + { + format: TxOutputFormat.MAP_BABBAGE, + address: toFixLenBuffer( + '002d745f050a8f7e263f4d0749a82284ed9cc065018c1f4f6a7c1b764882293a49e3ef29a4f9c32e4c18f202f5324182db7790f48dccf7a6dd', + 57, + ), + amount: { + type: AmountType.WITHOUT_MULTIASSET, + coin: toUint(9996201916), + }, + datum: undefined, + referenceScript: undefined, + }, + ], + fee: toUint(177073), + ttl: undefined, + certificates: undefined, + withdrawals: undefined, + update: undefined, + auxiliaryDataHash: undefined, + validityIntervalStart: undefined, + mint: undefined, + scriptDataHash: undefined, + collateralInputs: undefined, + requiredSigners: undefined, + networkId: undefined, + collateralReturnOutput: undefined, + totalCollateral: undefined, + referenceInputs: undefined, + votingProcedures: undefined, + proposalProcedures: [ + { + deposit: toUint(1000000), + rewardAccount: toFixLenBuffer( + 'e082293a49e3ef29a4f9c32e4c18f202f5324182db7790f48dccf7a6dd', + 29, + ), + govAction: [ + 5, + null, + [ + // constitution + [ + 'https://shorturl.at/asIJ6', + toFixLenBuffer( + 'ee90ece16c47bf812b88edb89a01539e6683d6549a80b15383a4fb218ab9412d', + 32, + ), + ], + null, + ], + ], + anchor: { + url: toMaxLenString('https://shorturl.at/xMS15', 64), + dataHash: toFixLenBuffer( + '6f890de0c6e418e6526e2b1aa821850cb87aee94a6d77dc2a2e440116abc8e09', + 32, + ), + }, + }, + ], treasury: undefined, donation: undefined, }, @@ -708,6 +795,7 @@ export const TransformTransactionTestCases: TransformTransactionBodyTestCase[] = totalCollateral: undefined, referenceInputs: undefined, votingProcedures: undefined, + proposalProcedures: undefined, treasury: undefined, donation: undefined, }, @@ -755,6 +843,7 @@ export const TransformTransactionTestCases: TransformTransactionBodyTestCase[] = totalCollateral: undefined, referenceInputs: undefined, votingProcedures: undefined, + proposalProcedures: undefined, treasury: undefined, donation: undefined, }, @@ -805,6 +894,7 @@ export const TransformTransactionTestCases: TransformTransactionBodyTestCase[] = totalCollateral: undefined, referenceInputs: undefined, votingProcedures: undefined, + proposalProcedures: undefined, treasury: undefined, donation: undefined, }, @@ -861,6 +951,7 @@ export const ValidTransactionTestCases: ValidTransactionTestCase[] = [ totalCollateral: undefined, referenceInputs: undefined, votingProcedures: undefined, + proposalProcedures: undefined, treasury: undefined, donation: undefined, }, @@ -934,6 +1025,7 @@ export const ValidTransactionTestCases: ValidTransactionTestCase[] = [ totalCollateral: undefined, referenceInputs: undefined, votingProcedures: undefined, + proposalProcedures: undefined, treasury: undefined, donation: undefined, }, @@ -1075,6 +1167,7 @@ export const ValidTransactionTestCases: ValidTransactionTestCase[] = [ totalCollateral: undefined, referenceInputs: undefined, votingProcedures: undefined, + proposalProcedures: undefined, treasury: undefined, donation: undefined, },