Skip to content

Commit

Permalink
use validation lib to enforce sorting and ordering
Browse files Browse the repository at this point in the history
  • Loading branch information
sklppy88 committed Nov 13, 2024
1 parent 0faa106 commit 4c8b87e
Show file tree
Hide file tree
Showing 4 changed files with 30 additions and 10 deletions.
21 changes: 18 additions & 3 deletions yarn-project/circuits.js/src/contract/artifact_hash.test.ts
Original file line number Diff line number Diff line change
@@ -1,7 +1,10 @@
import { type ContractArtifact } from '@aztec/foundation/abi';

import { getTestContractArtifact } from '../tests/fixtures.js';
import { computeArtifactHash } from './artifact_hash.js';
import { getPathToFixture, getTestContractArtifact } from '../tests/fixtures.js';
import { loadContractArtifact } from '@aztec/types/abi';
import type { NoirCompiledContract } from '@aztec/types/noir';
import { readFileSync } from 'fs';

describe('ArtifactHash', () => {
it('calculates the artifact hash', () => {
Expand All @@ -17,7 +20,7 @@ describe('ArtifactHash', () => {
notes: {},
};
expect(computeArtifactHash(emptyArtifact).toString()).toMatchInlineSnapshot(
`"0x0c6fd9b48570721c5d36f978d084d77cacbfd2814f1344985f40e62bea6e61be"`,
`"0x0dea64e7fa0688017f77bcb7075485485afb4a5f1f8508483398869439f82fdf"`,
);
});

Expand All @@ -26,8 +29,20 @@ describe('ArtifactHash', () => {

for (let i = 0; i < 1000; i++) {
expect(computeArtifactHash(testArtifact).toString()).toMatchInlineSnapshot(
`"0x16b7b028aaaa06d648cc521c385644d7786d2f1ae49157b27a424b172b298162"`,
`"0x0daa596e37c780de679311a601bd8b371c40d5a6898f452a06180bfef69e7df8"`,
);
}
});

it('calculates the test contract artifact hash', () => {
const path = getPathToFixture('Test.test.json');
const content = JSON.parse(readFileSync(path).toString()) as NoirCompiledContract;
content.outputs.structs.functions.reverse();

const testArtifact = loadContractArtifact(content);

expect(computeArtifactHash(testArtifact).toString()).toMatchInlineSnapshot(
`"0x0daa596e37c780de679311a601bd8b371c40d5a6898f452a06180bfef69e7df8"`,
);
});
});
6 changes: 1 addition & 5 deletions yarn-project/circuits.js/src/contract/artifact_hash.ts
Original file line number Diff line number Diff line change
Expand Up @@ -59,11 +59,7 @@ export function computeArtifactHashPreimage(artifact: ContractArtifact) {
}

export function computeArtifactMetadataHash(artifact: ContractArtifact) {
// TODO: #6021 We need to make sure the artifact is deterministic from any specific compiler run. This relates to selectors not being sorted and being
// apparently random in the order they appear after compiled w/ nargo. We can try to sort this upon loading an artifact.
// TODO: #6021: Should we use the sorted event selectors instead? They'd need to be unique for that.
// Response - The output selectors need to be sorted, because if not noir makes no guarantees on the order of outputs for some reason
return sha256Fr(Buffer.from(JSON.stringify({ name: artifact.name }), 'utf-8'));
return sha256Fr(Buffer.from(JSON.stringify({ name: artifact.name, outputs: artifact.outputs }), 'utf-8'));
}

export function computeArtifactFunctionTreeRoot(artifact: ContractArtifact, fnType: FunctionType) {
Expand Down
2 changes: 1 addition & 1 deletion yarn-project/circuits.js/src/tests/fixtures.ts
Original file line number Diff line number Diff line change
Expand Up @@ -48,6 +48,6 @@ export function getSampleUnconstrainedFunctionBroadcastedEventPayload(): Buffer
return Buffer.from(readFileSync(path).toString(), 'hex');
}

function getPathToFixture(name: string) {
export function getPathToFixture(name: string) {
return resolve(dirname(fileURLToPath(import.meta.url)), `../../fixtures/${name}`);
}
11 changes: 10 additions & 1 deletion yarn-project/foundation/src/abi/abi.ts
Original file line number Diff line number Diff line change
Expand Up @@ -358,7 +358,16 @@ export const ContractArtifactSchema: ZodFor<ContractArtifact> = z.object({
aztecNrVersion: z.string().optional(),
functions: z.array(FunctionArtifactSchema),
outputs: z.object({
structs: z.record(z.array(AbiTypeSchema)),
structs: z.record(z.array(AbiTypeSchema)).transform(structs => {
for (const [key, value] of Object.entries(structs)) {
// We are manually ordering events and functions in the abi by path.
// The path ordering is arbitrary, and only needed to ensure deterministic order.
if (key === 'events' || key === 'functions') {
structs[key] = (value as StructType[]).sort((a, b) => a.path > b.path ? -1 : 1);
}
}
return structs;
}),
globals: z.record(z.array(AbiValueSchema)),
}),
storageLayout: z.record(z.object({ slot: schemas.Fr })),
Expand Down

0 comments on commit 4c8b87e

Please sign in to comment.