diff --git a/packages/sdk/CHANGELOG.md b/packages/sdk/CHANGELOG.md index 621c3778..e130c98d 100644 --- a/packages/sdk/CHANGELOG.md +++ b/packages/sdk/CHANGELOG.md @@ -1,5 +1,14 @@ # Changelog +## Unreleased + +## 8.1.1 + +### Fixed + +- `getEnergyCost` returning energy amounts that were off by one due to not including the transaction type in the + transaction payload serialization. + ## 8.1.0 ### Added diff --git a/packages/sdk/package.json b/packages/sdk/package.json index f4892b4b..0203c653 100644 --- a/packages/sdk/package.json +++ b/packages/sdk/package.json @@ -1,6 +1,6 @@ { "name": "@concordium/web-sdk", - "version": "8.1.0", + "version": "8.1.1", "license": "Apache-2.0", "engines": { "node": ">=16" diff --git a/packages/sdk/src/accountTransactions.ts b/packages/sdk/src/accountTransactions.ts index 931b5565..becedab5 100644 --- a/packages/sdk/src/accountTransactions.ts +++ b/packages/sdk/src/accountTransactions.ts @@ -49,6 +49,8 @@ export interface AccountTransactionHandler< > { /** * Serializes the payload to a buffer. + * This does NOT include the serialized transaction type. To have this included, use {@linkcode serializeAccountTransactionPayload} instead. + * * @param payload - The payload to serialize. * @returns The serialized payload. */ diff --git a/packages/sdk/src/energyCost.ts b/packages/sdk/src/energyCost.ts index 24190dfb..71d72eb1 100644 --- a/packages/sdk/src/energyCost.ts +++ b/packages/sdk/src/energyCost.ts @@ -1,5 +1,6 @@ import { getAccountTransactionHandler } from './accountTransactions.js'; import { collapseRatio, multiplyRatio } from './ratioHelpers.js'; +import { serializeAccountTransactionPayload } from './serialization.js'; import { AccountTransactionPayload, AccountTransactionType, ChainParameters, Ratio } from './types.js'; import * as CcdAmount from './types/CcdAmount.js'; import * as Energy from './types/Energy.js'; @@ -12,7 +13,7 @@ export const constantA = 100n; export const constantB = 1n; // Account address (32 bytes), nonce (8 bytes), energy (8 bytes), payload size (4 bytes), expiry (8 bytes); -const accountTransactionHeaderSize = BigInt(32 + 8 + 8 + 4 + 8); +const ACCOUNT_TRANSACTION_HEADER_SIZE = BigInt(32 + 8 + 8 + 4 + 8); /** * The energy cost is assigned according to the formula: @@ -30,7 +31,9 @@ export function calculateEnergyCost( transactionSpecificCost: bigint ): Energy.Type { return Energy.create( - constantA * signatureCount + constantB * (accountTransactionHeaderSize + payloadSize) + transactionSpecificCost + constantA * signatureCount + + constantB * (ACCOUNT_TRANSACTION_HEADER_SIZE + payloadSize) + + transactionSpecificCost ); } @@ -44,8 +47,8 @@ export function getEnergyCost( payload: AccountTransactionPayload, signatureCount = 1n ): Energy.Type { + const size = serializeAccountTransactionPayload({ payload, type: transactionType }).length; const handler = getAccountTransactionHandler(transactionType); - const size = handler.serialize(payload).length; return calculateEnergyCost(signatureCount, BigInt(size), handler.getBaseEnergyCost(payload)); } diff --git a/packages/sdk/src/serialization.ts b/packages/sdk/src/serialization.ts index 56cfc3be..2b305190 100644 --- a/packages/sdk/src/serialization.ts +++ b/packages/sdk/src/serialization.ts @@ -98,20 +98,18 @@ export function serializeAccountTransaction( const serializedBlockItemKind = encodeWord8(BlockItemKind.AccountTransactionKind); const serializedAccountTransactionSignatures = serializeAccountTransactionSignature(signatures); - const serializedType = serializeAccountTransactionType(accountTransaction.type); - const accountTransactionHandler = getAccountTransactionHandler(accountTransaction.type); - const serializedPayload = accountTransactionHandler.serialize(accountTransaction.payload); + const serializedPayload = serializeAccountTransactionPayload(accountTransaction); const baseEnergyCost = accountTransactionHandler.getBaseEnergyCost(accountTransaction.payload); const energyCost = calculateEnergyCost( countSignatures(signatures), - BigInt(serializedPayload.length + 1), + BigInt(serializedPayload.length), baseEnergyCost ); const serializedHeader = serializeAccountTransactionHeader( accountTransaction.header, - serializedPayload.length + 1, + serializedPayload.length, energyCost ); @@ -119,7 +117,6 @@ export function serializeAccountTransaction( serializedBlockItemKind, serializedAccountTransactionSignatures, serializedHeader, - serializedType, serializedPayload, ]); } @@ -129,7 +126,7 @@ export function serializeAccountTransaction( * @param accountTransaction the transaction which payload is to be serialized * @returns the account transaction payload serialized as a buffer. */ -export function serializeAccountTransactionPayload(accountTransaction: AccountTransaction): Buffer { +export function serializeAccountTransactionPayload(accountTransaction: Omit): Buffer { const serializedType = serializeAccountTransactionType(accountTransaction.type); const accountTransactionHandler = getAccountTransactionHandler(accountTransaction.type); @@ -160,17 +157,17 @@ export function getAccountTransactionHash( */ export function getAccountTransactionSignDigest(accountTransaction: AccountTransaction, signatureCount = 1n): Buffer { const accountTransactionHandler = getAccountTransactionHandler(accountTransaction.type); - const serializedPayload = accountTransactionHandler.serialize(accountTransaction.payload); + const serializedPayload = serializeAccountTransactionPayload(accountTransaction); const baseEnergyCost = accountTransactionHandler.getBaseEnergyCost(accountTransaction.payload); - const energyCost = calculateEnergyCost(signatureCount, BigInt(serializedPayload.length + 1), baseEnergyCost); + const energyCost = calculateEnergyCost(signatureCount, BigInt(serializedPayload.length), baseEnergyCost); const serializedHeader = serializeAccountTransactionHeader( accountTransaction.header, - serializedPayload.length + 1, + serializedPayload.length, energyCost ); - return sha256([serializedHeader, serializeAccountTransactionType(accountTransaction.type), serializedPayload]); + return sha256([serializedHeader, serializedPayload]); } /**