From 7b804afd5d711d4952a6723300413c6ce5004a3c Mon Sep 17 00:00:00 2001 From: sklppy88 Date: Tue, 12 Nov 2024 15:47:21 +0000 Subject: [PATCH] init --- .../src/contract/artifact_hash.test.ts | 11 ++++++ .../foundation/src/abi/note_selector.ts | 2 +- .../types/src/abi/contract_artifact.ts | 35 +++++++------------ 3 files changed, 25 insertions(+), 23 deletions(-) diff --git a/yarn-project/circuits.js/src/contract/artifact_hash.test.ts b/yarn-project/circuits.js/src/contract/artifact_hash.test.ts index c6261e83bd1..fcbacad077f 100644 --- a/yarn-project/circuits.js/src/contract/artifact_hash.test.ts +++ b/yarn-project/circuits.js/src/contract/artifact_hash.test.ts @@ -1,5 +1,6 @@ import { type ContractArtifact } from '@aztec/foundation/abi'; +import { getTestContractArtifact } from '../tests/fixtures.js'; import { computeArtifactHash } from './artifact_hash.js'; describe('ArtifactHash', () => { @@ -19,4 +20,14 @@ describe('ArtifactHash', () => { `"0x0c6fd9b48570721c5d36f978d084d77cacbfd2814f1344985f40e62bea6e61be"`, ); }); + + it('calculates the test contract artifact hash multiple times to ensure deterministic hashing', () => { + const testArtifact = getTestContractArtifact(); + + for (let i = 0; i < 1000; i++) { + expect(computeArtifactHash(testArtifact).toString()).toMatchInlineSnapshot( + `"0x16b7b028aaaa06d648cc521c385644d7786d2f1ae49157b27a424b172b298162"`, + ); + } + }); }); diff --git a/yarn-project/foundation/src/abi/note_selector.ts b/yarn-project/foundation/src/abi/note_selector.ts index 392399f7ee1..8fdcaa945c3 100644 --- a/yarn-project/foundation/src/abi/note_selector.ts +++ b/yarn-project/foundation/src/abi/note_selector.ts @@ -27,7 +27,7 @@ export class NoteSelector extends Selector { } static fromString(buf: string) { - const withoutPrefix = buf.replace(/^0x/i, ''); + const withoutPrefix = buf.replace(/^0x/i, '').slice(-8); const buffer = Buffer.from(withoutPrefix, 'hex'); return NoteSelector.fromBuffer(buffer); } diff --git a/yarn-project/types/src/abi/contract_artifact.ts b/yarn-project/types/src/abi/contract_artifact.ts index 4fc0616e78c..0141145e7b3 100644 --- a/yarn-project/types/src/abi/contract_artifact.ts +++ b/yarn-project/types/src/abi/contract_artifact.ts @@ -4,16 +4,15 @@ import { type AbiType, type BasicValue, type ContractArtifact, + ContractArtifactSchema, type ContractNote, type FieldLayout, type FunctionArtifact, FunctionType, type IntegerValue, - NoteSelector, type StructValue, type TypedStructFieldValue, } from '@aztec/foundation/abi'; -import { Fr } from '@aztec/foundation/fields'; import { AZTEC_INITIALIZER_ATTRIBUTE, @@ -53,18 +52,7 @@ export function contractArtifactToBuffer(artifact: ContractArtifact): Buffer { * @returns Deserialized artifact. */ export function contractArtifactFromBuffer(buffer: Buffer): ContractArtifact { - return JSON.parse(buffer.toString('utf-8'), (key, value) => { - if (key === 'bytecode' && typeof value === 'string') { - return Buffer.from(value, 'base64'); - } - if (typeof value === 'object' && value !== null && value.type === 'NoteSelector') { - return new NoteSelector(Number(value.value)); - } - if (typeof value === 'object' && value !== null && value.type === 'Fr') { - return new Fr(BigInt(value.value)); - } - return value; - }); + return ContractArtifactSchema.parse(JSON.parse(buffer.toString('utf-8'))); } /** @@ -133,7 +121,10 @@ type NoirCompiledContractFunction = NoirCompiledContract['functions'][number]; * @param contract - Parent contract. * @returns Function artifact. */ -function generateFunctionArtifact(fn: NoirCompiledContractFunction, contract: NoirCompiledContract): FunctionArtifact { +function generateFunctionArtifact( + fn: NoirCompiledContractFunction, + contract: NoirCompiledContract, +): Omit & { bytecode: string } { if (fn.custom_attributes === undefined) { throw new Error( `No custom attributes found for contract function ${fn.name}. Try rebuilding the contract with the latest nargo version.`, @@ -178,7 +169,7 @@ function generateFunctionArtifact(fn: NoirCompiledContractFunction, contract: No isInitializer: fn.custom_attributes.includes(AZTEC_INITIALIZER_ATTRIBUTE), parameters, returnTypes, - bytecode: Buffer.from(fn.bytecode, 'base64'), + bytecode: fn.bytecode, debugSymbols: fn.debug_symbols, errorTypes: fn.abi.error_types, ...(fn.assert_messages ? { assertMessages: fn.assert_messages } : undefined), @@ -238,11 +229,11 @@ function getStorageLayout(input: NoirCompiledContract) { return {}; } - return storageFields.reduce((acc: Record, field) => { + return storageFields.reduce((acc: Record & { slot: string }>, field) => { const name = field.name; const slot = field.value.fields[0].value as IntegerValue; acc[name] = { - slot: Fr.fromString(slot.value), + slot: slot.value, }; return acc; }, {}); @@ -262,7 +253,7 @@ function getNoteTypes(input: NoirCompiledContract) { return {}; } - return notes.reduce((acc: Record, note) => { + return notes.reduce((acc: Record & { id: string }>, note) => { const noteFields = note.fields; // We find note type id by looking for respective kinds as each of them is unique @@ -274,7 +265,7 @@ function getNoteTypes(input: NoirCompiledContract) { throw new Error(`Could not find note type id, name or fields for note ${note}`); } - const noteTypeId = NoteSelector.fromField(Fr.fromString(rawNoteTypeId.value)); + const noteTypeId = rawNoteTypeId.value as string; const name = rawName.value as string; // Note type id is encoded as a hex string @@ -301,7 +292,7 @@ function getNoteTypes(input: NoirCompiledContract) { */ function generateContractArtifact(contract: NoirCompiledContract, aztecNrVersion?: string): ContractArtifact { try { - return { + return ContractArtifactSchema.parse({ name: contract.name, functions: contract.functions.map(f => generateFunctionArtifact(f, contract)), outputs: contract.outputs, @@ -309,7 +300,7 @@ function generateContractArtifact(contract: NoirCompiledContract, aztecNrVersion notes: getNoteTypes(contract), fileMap: contract.file_map, ...(aztecNrVersion ? { aztecNrVersion } : {}), - }; + }); } catch (err) { throw new Error(`Could not generate contract artifact for ${contract.name}: ${err}`); }