Skip to content

Commit

Permalink
feat!: transaction body core type now includes the auxiliaryDataHash …
Browse files Browse the repository at this point in the history
…and networkId fields

BREAKING CHANGE:
 - auxiliaryDataHash is now included in the TxBody core type.
 - networkId is now included in the TxBody core type.
 - auxiliaryData no longer contains the optional hash field.
 - auxiliaryData no longer contains the optional body field.
  • Loading branch information
AngelCastilloB committed Apr 28, 2023
1 parent 694e04b commit 8b92b01
Show file tree
Hide file tree
Showing 23 changed files with 327 additions and 281 deletions.
Original file line number Diff line number Diff line change
Expand Up @@ -175,9 +175,7 @@ export const mapTxAlonzo = (
auxiliaryData:
metadata && metadata.size > 0
? {
body: {
blob: metadata
}
blob: metadata
}
: undefined,
blockHeader: {
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -364,7 +364,7 @@ describe('chain history mappers', () => {
});
expect(result).toEqual<Cardano.HydratedTx>({
...expected,
auxiliaryData: { body: { blob: metadata } },
auxiliaryData: { blob: metadata },
body: { ...expected.body, certificates, collaterals: inputs, mint: assets, withdrawals },
witness: { ...expected.witness, redeemers }
});
Expand Down
4 changes: 1 addition & 3 deletions packages/cardano-services/test/data-mocks/tx.ts
Original file line number Diff line number Diff line change
Expand Up @@ -35,9 +35,7 @@ export const txIn: Cardano.HydratedTxIn = {

export const base = {
auxiliaryData: {
body: {
blob: new Map()
}
blob: new Map()
},
blockHeader: {
blockNo: Cardano.BlockNo(3_157_934),
Expand Down
9 changes: 5 additions & 4 deletions packages/core/src/CML/cmlToCore/cmlToCore.ts
Original file line number Diff line number Diff line change
Expand Up @@ -275,14 +275,18 @@ export const txBody = (body: CML.TransactionBody): Cardano.TxBody =>
const cslReferenceInputs = scope.manage(body.reference_inputs());
const cslCollateralReturn = scope.manage(body.collateral_return());
const cslTotalCollateral = scope.manage(body.total_collateral());
const cslAuxiliaryDataHash = scope.manage(body.auxiliary_data_hash());
const cslNetworkId = scope.manage(body.network_id());

return {
auxiliaryDataHash: cslAuxiliaryDataHash ? Crypto.Hash32ByteBase16(cslAuxiliaryDataHash.to_hex()) : undefined,
certificates: txCertificates(scope.manage(body.certs())),
collateralReturn: cslCollateralReturn ? txOut(cslCollateralReturn) : undefined,
collaterals: cslCollaterals && txInputs(cslCollaterals),
fee: BigInt(scope.manage(body.fee()).to_str()),
inputs: txInputs(scope.manage(body.inputs())),
mint: txMint(scope.manage(body.multiassets())),
networkId: cslNetworkId ? cslNetworkId.kind() : undefined,
outputs: txOutputs(scope.manage(body.outputs())),
referenceInputs: cslReferenceInputs ? txInputs(cslReferenceInputs) : undefined,
requiredExtraSignatures: txRequiredExtraSignatures(scope.manage(body.required_signers())),
Expand Down Expand Up @@ -468,12 +472,9 @@ export const txMetadata = (auxiliaryMetadata?: CML.GeneralTransactionMetadata):
export const txAuxiliaryData = (auxiliaryData?: CML.AuxiliaryData): Cardano.AuxiliaryData | undefined =>
usingAutoFree((scope) => {
if (!auxiliaryData) return;
// TODO: create hash
const auxiliaryMetadata = scope.manage(auxiliaryData.metadata());
return {
body: {
blob: txMetadata(auxiliaryMetadata)
}
blob: txMetadata(auxiliaryMetadata)
};
});

Expand Down
33 changes: 21 additions & 12 deletions packages/core/src/CML/coreToCml/coreToCml.ts
Original file line number Diff line number Diff line change
Expand Up @@ -6,6 +6,7 @@ import {
AssetName,
Assets,
AuxiliaryData,
AuxiliaryDataHash,
BigNum,
BootstrapWitness,
BootstrapWitnesses,
Expand Down Expand Up @@ -59,12 +60,11 @@ import {
Vkey,
Vkeywitness,
Vkeywitnesses,
Withdrawals,
hash_auxiliary_data
Withdrawals
} from '@dcspark/cardano-multiplatform-lib-nodejs';
import { AssetId, NetworkId, RedeemerPurpose } from '../../Cardano';

import * as certificate from './certificate';
import { AssetId, RedeemerPurpose } from '../../Cardano';
import { CML } from '../CML';
import { ManagedFreeableScope } from '@cardano-sdk/util';
import { SerializationError, SerializationFailure } from '../../errors';
Expand Down Expand Up @@ -368,7 +368,7 @@ export const txAuxiliaryData = (
if (!auxiliaryData) return;
const result = scope.manage(AuxiliaryData.new());

const { blob, scripts } = auxiliaryData.body;
const { blob, scripts } = auxiliaryData;
if (blob) {
result.set_metadata(txMetadata(scope, blob));
}
Expand Down Expand Up @@ -422,16 +422,18 @@ export const txBody = (
validityInterval,
certificates,
withdrawals,
auxiliaryDataHash,
mint,
collaterals,
requiredExtraSignatures,
scriptIntegrityHash,
totalCollateral,
collateralReturn,
referenceInputs
}: Cardano.TxBody,
auxiliaryData?: Cardano.AuxiliaryData
): TransactionBody => {
referenceInputs,
networkId
}: Cardano.TxBody
): // eslint-disable-next-line sonarjs/cognitive-complexity
TransactionBody => {
const cslOutputs = scope.manage(TransactionOutputs.new());
for (const output of outputs) {
cslOutputs.add(txOut(scope, output));
Expand Down Expand Up @@ -473,6 +475,17 @@ export const txBody = (
if (scriptIntegrityHash) {
cslBody.set_script_data_hash(scope.manage(ScriptDataHash.from_bytes(Buffer.from(scriptIntegrityHash, 'hex'))));
}

if (auxiliaryDataHash) {
cslBody.set_auxiliary_data_hash(scope.manage(AuxiliaryDataHash.from_hex(auxiliaryDataHash)));
}

if (networkId) {
const id =
networkId === NetworkId.Mainnet ? scope.manage(CML.NetworkId.mainnet()) : scope.manage(CML.NetworkId.testnet());
cslBody.set_network_id(id);
}

if (certificates?.length) {
const certs = scope.manage(Certificates.new());
for (const cert of certificates) {
Expand All @@ -483,10 +496,6 @@ export const txBody = (
if (withdrawals?.length) {
cslBody.set_withdrawals(txWithdrawals(scope, withdrawals));
}
const cslAuxiliaryData = txAuxiliaryData(scope, auxiliaryData);
if (cslAuxiliaryData) {
cslBody.set_auxiliary_data_hash(scope.manage(hash_auxiliary_data(cslAuxiliaryData)));
}

return cslBody;
};
Expand Down
15 changes: 10 additions & 5 deletions packages/core/src/Cardano/types/AuxiliaryData.ts
Original file line number Diff line number Diff line change
@@ -1,5 +1,8 @@
import * as Crypto from '@cardano-sdk/crypto';
import { Hash32ByteBase16 } from '@cardano-sdk/crypto';
import { Script } from './Script';
import { coreToCml } from '../../CML';
import { usingAutoFree } from '@cardano-sdk/util';

// eslint-disable-next-line no-use-before-define
export type MetadatumMap = Map<Metadatum, Metadatum>;
Expand All @@ -8,12 +11,14 @@ export type Metadatum = bigint | MetadatumMap | string | Uint8Array | Metadatum[

export type TxMetadata = Map<bigint, Metadatum>;

export interface AuxiliaryDataBody {
export interface AuxiliaryData {
blob?: TxMetadata;
scripts?: Script[];
}

export interface AuxiliaryData {
hash?: Hash32ByteBase16;
body: AuxiliaryDataBody;
}
export const computeAuxiliaryDataHash = (data: AuxiliaryData | undefined): Hash32ByteBase16 | undefined =>
usingAutoFree((scope) => {
if (!data) return;
const cmlData = coreToCml.txAuxiliaryData(scope, data);
return Hash32ByteBase16(Crypto.blake2b(Crypto.blake2b.BYTES).update(cmlData!.to_bytes()).digest('hex'));
});
3 changes: 3 additions & 0 deletions packages/core/src/Cardano/types/Transaction.ts
Original file line number Diff line number Diff line change
Expand Up @@ -7,6 +7,7 @@ import { Datum, Script } from './Script';
import { ExUnits, ValidityInterval } from './ProtocolParameters';
import { HydratedTxIn, TxIn, TxOut } from './Utxo';
import { Lovelace, TokenMap } from './Value';
import { NetworkId } from '../ChainId';
import { PartialBlockHeader } from './Block';
import { RewardAccount } from '../Address';
import { TxBodyCBOR } from '../../CBOR/TxBodyCBOR';
Expand Down Expand Up @@ -49,6 +50,8 @@ export interface HydratedTxBody {
mint?: TokenMap;
scriptIntegrityHash?: Crypto.Hash32ByteBase16;
requiredExtraSignatures?: Crypto.Ed25519KeyHashHex[];
networkId?: NetworkId;
auxiliaryDataHash?: Crypto.Hash32ByteBase16;

/**
* The total collateral field lets users write transactions whose collateral is evident by just looking at the
Expand Down
2 changes: 1 addition & 1 deletion packages/core/src/Serialization/Transaction.ts
Original file line number Diff line number Diff line change
Expand Up @@ -153,7 +153,7 @@ export class Transaction {

const transaction = scope.manage(
new Transaction(
CoreToCml.txBody(scope, tx.body, tx.auxiliaryData),
CoreToCml.txBody(scope, tx.body),
txWitnessSet,
CoreToCml.txAuxiliaryData(scope, tx.auxiliaryData)
)
Expand Down
4 changes: 2 additions & 2 deletions packages/core/src/util/txInspector.ts
Original file line number Diff line number Diff line change
Expand Up @@ -290,7 +290,7 @@ export const mintInspector =
// was built by this client the script will be present in the witness set, however, if this transaction was
// queried from a remote repository that doesn't fetch the witness data of the transaction we can still check
// if the script is present in the auxiliary data.
const scripts = [...(tx.auxiliaryData?.body?.scripts || []), ...(tx.witness?.scripts || [])];
const scripts = [...(tx.auxiliaryData?.scripts || []), ...(tx.witness?.scripts || [])];

for (const script of scripts) {
switch (script.__type) {
Expand Down Expand Up @@ -338,7 +338,7 @@ export const assetsBurnedInspector: AssetsMintedInspector = mintInspector((quant
*
* @param {HydratedTx} tx transaction to inspect.
*/
export const metadataInspector: MetadataInspector = (tx) => tx.auxiliaryData?.body?.blob ?? new Map();
export const metadataInspector: MetadataInspector = (tx) => tx.auxiliaryData?.blob ?? new Map();

/**
* Returns a function to convert lower level transaction data to a higher level object, using the provided inspectors.
Expand Down
2 changes: 1 addition & 1 deletion packages/core/test/CML/coreToCml.test.ts
Original file line number Diff line number Diff line change
Expand Up @@ -256,7 +256,7 @@ describe('coreToCml', () => {
// eslint-disable-next-line unicorn/consistent-function-scoping, @typescript-eslint/no-explicit-any
const convertMetadatum = (metadatum: any) => {
const label = 123n;
const auxiliaryData = coreToCml.txAuxiliaryData(scope, { body: { blob: new Map([[label, metadatum]]) } });
const auxiliaryData = coreToCml.txAuxiliaryData(scope, { blob: new Map([[label, metadatum]]) });
const metadata = scope.manage(auxiliaryData?.metadata());
return scope.manage(metadata?.get(scope.manage(BigNum.from_str(label.toString()))));
};
Expand Down
31 changes: 15 additions & 16 deletions packages/core/test/CML/testData.ts
Original file line number Diff line number Diff line change
Expand Up @@ -143,6 +143,7 @@ export const txOutWithDatum: Cardano.TxOut = {
};

export const txBody: Cardano.TxBody = {
auxiliaryDataHash: Crypto.Hash32ByteBase16('2ceb364d93225b4a0f004a0975a13eb50c3cc6348474b4fe9121f8dc72ca0cfa'),
certificates: [
{
__typename: Cardano.CertificateType.PoolRetirement,
Expand Down Expand Up @@ -188,22 +189,20 @@ export const signature =
'bdea87fca1b4b4df8a9b8fb4183c0fab2f8261eb6c5e4bc42c800bb9c8918755bdea87fca1b4b4df8a9b8fb4183c0fab2f8261eb6c5e4bc42c800bb9c8918755';
export const tx: Cardano.Tx = {
auxiliaryData: {
body: {
blob: new Map<bigint, Cardano.Metadatum>([
[1n, 1234n],
[2n, 'str'],
[3n, [1234n, 'str']],
[4n, new Uint8Array(Buffer.from('bytes'))],
[
5n,
new Map<Cardano.Metadatum, Cardano.Metadatum>([
['strkey', 123n],
[['listkey'], 'strvalue']
])
],
[6n, -7n]
])
}
blob: new Map<bigint, Cardano.Metadatum>([
[1n, 1234n],
[2n, 'str'],
[3n, [1234n, 'str']],
[4n, new Uint8Array(Buffer.from('bytes'))],
[
5n,
new Map<Cardano.Metadatum, Cardano.Metadatum>([
['strkey', 123n],
[['listkey'], 'strvalue']
])
],
[6n, -7n]
])
},
body: txBody,
id: Cardano.TransactionId('8d2feeab1087e0aa4ad06e878c5269eaa2edcef5264bcc97542a28c189b2cbc5'),
Expand Down
35 changes: 35 additions & 0 deletions packages/core/test/Cardano/types/AuxiliaryData.test.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,35 @@
import { Metadatum, computeAuxiliaryDataHash } from '../../../src/Cardano';

describe('Cardano/types/AuxiliaryData', () => {
describe('computeAuxiliaryDataHash', () => {
it('can compute the correct auxiliary data hash', () => {
const auxiliaryData = {
blob: new Map<bigint, Metadatum>([
[1n, 1234n],
[2n, 'str'],
[3n, [1234n, 'str']],
[4n, new Uint8Array(Buffer.from('bytes'))],
[
5n,
new Map<Metadatum, Metadatum>([
['strkey', 123n],
[['listkey'], 'strvalue']
])
],
[6n, -7n]
])
};

expect(computeAuxiliaryDataHash(auxiliaryData)).toEqual(
'2ceb364d93225b4a0f004a0975a13eb50c3cc6348474b4fe9121f8dc72ca0cfa'
);
});

it('returns undefined when given an undefined auxiliary data', () => {
const auxiliaryData = undefined;

expect(() => computeAuxiliaryDataHash(auxiliaryData)).not.toThrow();
expect(computeAuxiliaryDataHash(auxiliaryData)).toEqual(undefined);
});
});
});
3 changes: 1 addition & 2 deletions packages/core/test/Serialization/Transaction.test.ts
Original file line number Diff line number Diff line change
Expand Up @@ -40,9 +40,9 @@ describe('Transaction', () => {
it('correctly converts from a Babbage Core transaction', () => {
const scope = new ManagedFreeableScope();
const tx = Transaction.fromCore(scope, babbageTx);

expect(tx.toCore()).toEqual(babbageTx);
});

it('calling free several times doesnt throw an error', () => {
const tx = Transaction.fromCbor(HexBlob(TX));
expect(() => tx.free()).not.toThrow();
Expand All @@ -59,7 +59,6 @@ describe('Transaction', () => {

// Perform a round trip serialization.
const tx2 = Transaction.fromCbor(tx.toCbor());

expect(tx2.isValid()).toEqual(false);
});

Expand Down
6 changes: 2 additions & 4 deletions packages/core/test/util/txInspector.test.ts
Original file line number Diff line number Diff line change
Expand Up @@ -190,10 +190,8 @@ describe('txInspector', () => {
};

const auxiliaryData = {
body: {
blob: txMetadatum,
scripts: [mockScript2]
}
blob: txMetadatum,
scripts: [mockScript2]
};

const buildMockTx = (
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -48,6 +48,6 @@ describe('SingleAddressWallet/metadata', () => {
filter(isNotNil)
)
);
expect(loadedTx.auxiliaryData?.body.blob).toEqual(metadata);
expect(loadedTx.auxiliaryData?.blob).toEqual(metadata);
});
});
6 changes: 2 additions & 4 deletions packages/e2e/test/wallet/SingleAddressWallet/nft.test.ts
Original file line number Diff line number Diff line change
Expand Up @@ -135,9 +135,7 @@ describe('SingleAddressWallet.assets/nft', () => {
});

const auxiliaryData = {
body: {
blob: new Map([[721n, txMetadatum]])
}
blob: new Map([[721n, txMetadatum]])
};

const txProps: InitializeTxProps = {
Expand Down Expand Up @@ -317,7 +315,7 @@ describe('SingleAddressWallet.assets/nft', () => {
]
]);

const auxiliaryData = { body: { blob: new Map([[721n, txDataMetadatum]]) } };
const auxiliaryData = { blob: new Map([[721n, txDataMetadatum]]) };

const txProps: InitializeTxProps = {
auxiliaryData,
Expand Down
Loading

0 comments on commit 8b92b01

Please sign in to comment.