From 397d6e1ce6cad1a38f37512a157cbeb32c022ec9 Mon Sep 17 00:00:00 2001 From: benesjan Date: Tue, 18 Mar 2025 23:06:00 +0000 Subject: [PATCH 01/10] fix: oracles handlers --- .../src/oracle/get_public_data_witness.nr | 20 +- .../src/oracle/key_validation_request.nr | 19 +- .../aztec-nr/aztec/src/oracle/notes.nr | 14 +- .../aztec/src/oracle/shared_secret.nr | 14 +- .../aztec-node/src/aztec-node/server.ts | 2 +- .../src/utils/client/foreign_call_handler.ts | 8 +- .../src/utils/server/foreign_call_handler.ts | 22 +- .../private_kernel_oracle_impl.ts | 2 +- .../pxe_oracle_interface.ts | 4 +- .../simulator/src/private/acvm/acvm.ts | 27 +- .../simulator/src/private/acvm/deserialize.ts | 15 +- .../src/private/acvm/oracle/oracle.ts | 278 +++++++++--------- .../src/private/acvm/oracle/typed_oracle.ts | 4 +- .../src/private/execution_data_provider.ts | 2 +- .../src/private/private_execution.ts | 4 +- .../private/unconstrained_execution_oracle.ts | 4 +- .../stdlib/src/interfaces/aztec-node.test.ts | 6 +- .../stdlib/src/interfaces/aztec-node.ts | 7 +- .../stdlib/src/trees/public_data_witness.ts | 15 + yarn-project/txe/src/node/txe_node.ts | 4 +- yarn-project/txe/src/oracle/txe_oracle.ts | 2 +- .../txe/src/txe_service/txe_service.ts | 4 +- 22 files changed, 209 insertions(+), 268 deletions(-) diff --git a/noir-projects/aztec-nr/aztec/src/oracle/get_public_data_witness.nr b/noir-projects/aztec-nr/aztec/src/oracle/get_public_data_witness.nr index 07879b4fd3e1..9954e4f570da 100644 --- a/noir-projects/aztec-nr/aztec/src/oracle/get_public_data_witness.nr +++ b/noir-projects/aztec-nr/aztec/src/oracle/get_public_data_witness.nr @@ -1,34 +1,20 @@ -use crate::utils::array; use dep::protocol_types::{constants::PUBLIC_DATA_TREE_HEIGHT, data::PublicDataTreeLeafPreimage}; -global LEAF_PREIMAGE_LENGTH: u32 = 4; -global PUBLIC_DATA_WITNESS: u32 = 45; - pub struct PublicDataWitness { pub index: Field, pub leaf_preimage: PublicDataTreeLeafPreimage, pub path: [Field; PUBLIC_DATA_TREE_HEIGHT], } -#[oracle(getPublicDataTreeWitness)] +#[oracle(getPublicDataWitness)] unconstrained fn get_public_data_witness_oracle( _block_number: u32, _public_data_tree_index: Field, -) -> [Field; PUBLIC_DATA_WITNESS] {} +) -> PublicDataWitness {} pub unconstrained fn get_public_data_witness( block_number: u32, public_data_tree_index: Field, ) -> PublicDataWitness { - let fields = get_public_data_witness_oracle(block_number, public_data_tree_index); - PublicDataWitness { - index: fields[0], - leaf_preimage: PublicDataTreeLeafPreimage { - slot: fields[1], - value: fields[2], - next_index: fields[3] as u32, - next_slot: fields[4], - }, - path: array::subarray(fields, 1 + LEAF_PREIMAGE_LENGTH), - } + get_public_data_witness_oracle(block_number, public_data_tree_index) } diff --git a/noir-projects/aztec-nr/aztec/src/oracle/key_validation_request.nr b/noir-projects/aztec-nr/aztec/src/oracle/key_validation_request.nr index a6754e5458aa..117c0c01b370 100644 --- a/noir-projects/aztec-nr/aztec/src/oracle/key_validation_request.nr +++ b/noir-projects/aztec-nr/aztec/src/oracle/key_validation_request.nr @@ -1,27 +1,14 @@ -use dep::protocol_types::{ - abis::validation_requests::{ - key_validation_request::KEY_VALIDATION_REQUEST_LENGTH, KeyValidationRequest, - }, - traits::Deserialize, -}; +use protocol_types::abis::validation_requests::KeyValidationRequest; #[oracle(getKeyValidationRequest)] unconstrained fn get_key_validation_request_oracle( _pk_m_hash: Field, _key_index: Field, -) -> [Field; KEY_VALIDATION_REQUEST_LENGTH] {} - -unconstrained fn get_key_validation_request_internal( - npk_m_hash: Field, - key_index: Field, -) -> KeyValidationRequest { - let result = get_key_validation_request_oracle(npk_m_hash, key_index); - KeyValidationRequest::deserialize(result) -} +) -> KeyValidationRequest {} pub unconstrained fn get_key_validation_request( pk_m_hash: Field, key_index: Field, ) -> KeyValidationRequest { - get_key_validation_request_internal(pk_m_hash, key_index) + get_key_validation_request_oracle(pk_m_hash, key_index) } diff --git a/noir-projects/aztec-nr/aztec/src/oracle/notes.nr b/noir-projects/aztec-nr/aztec/src/oracle/notes.nr index db2b8f6413cb..b5326cfd4ffe 100644 --- a/noir-projects/aztec-nr/aztec/src/oracle/notes.nr +++ b/noir-projects/aztec-nr/aztec/src/oracle/notes.nr @@ -64,29 +64,25 @@ unconstrained fn notify_created_note_oracle( _packed_note: [Field; N], _note_hash: Field, _counter: u32, -) -> Field {} +) {} unconstrained fn notify_nullified_note_oracle_wrapper( nullifier: Field, note_hash: Field, counter: u32, ) { - let _ = notify_nullified_note_oracle(nullifier, note_hash, counter); + notify_nullified_note_oracle(nullifier, note_hash, counter); } #[oracle(notifyNullifiedNote)] -unconstrained fn notify_nullified_note_oracle( - _nullifier: Field, - _note_hash: Field, - _counter: u32, -) -> Field {} +unconstrained fn notify_nullified_note_oracle(_nullifier: Field, _note_hash: Field, _counter: u32) {} unconstrained fn notify_created_nullifier_oracle_wrapper(nullifier: Field) { - let _ = notify_created_nullifier_oracle(nullifier); + notify_created_nullifier_oracle(nullifier); } #[oracle(notifyCreatedNullifier)] -unconstrained fn notify_created_nullifier_oracle(_nullifier: Field) -> Field {} +unconstrained fn notify_created_nullifier_oracle(_nullifier: Field) {} #[oracle(getNotes)] unconstrained fn get_notes_oracle( diff --git a/noir-projects/aztec-nr/aztec/src/oracle/shared_secret.nr b/noir-projects/aztec-nr/aztec/src/oracle/shared_secret.nr index 4462f4b04e2d..ba1bb41c7567 100644 --- a/noir-projects/aztec-nr/aztec/src/oracle/shared_secret.nr +++ b/noir-projects/aztec-nr/aztec/src/oracle/shared_secret.nr @@ -1,15 +1,8 @@ -use dep::protocol_types::{ - address::aztec_address::AztecAddress, - point::{Point, POINT_LENGTH}, - traits::Deserialize, -}; +use dep::protocol_types::{address::aztec_address::AztecAddress, point::Point}; // TODO(#12656): return an app-siloed secret + document this #[oracle(getSharedSecret)] -unconstrained fn get_shared_secret_oracle( - address: AztecAddress, - ephPk: Point, -) -> [Field; POINT_LENGTH] {} +unconstrained fn get_shared_secret_oracle(address: AztecAddress, ephPk: Point) -> Point {} /// Returns an app-siloed shared secret between `address` and someone who knows the secret key behind an /// ephemeral public key `ephPk`. The app-siloing means that contracts cannot retrieve secrets that belong to @@ -21,6 +14,5 @@ unconstrained fn get_shared_secret_oracle( /// where `ivsk + h` is the 'preaddress' i.e. the preimage of the address, also called the address secret. /// TODO(#12656): app-silo this secret pub unconstrained fn get_shared_secret(address: AztecAddress, ephPk: Point) -> Point { - let fields = get_shared_secret_oracle(address, ephPk); - Point::deserialize(fields) + get_shared_secret_oracle(address, ephPk) } diff --git a/yarn-project/aztec-node/src/aztec-node/server.ts b/yarn-project/aztec-node/src/aztec-node/server.ts index 82463cb700b1..a79abb677d51 100644 --- a/yarn-project/aztec-node/src/aztec-node/server.ts +++ b/yarn-project/aztec-node/src/aztec-node/server.ts @@ -784,7 +784,7 @@ export class AztecNodeService implements AztecNode, AztecNodeAdmin, Traceable { return new NullifierMembershipWitness(BigInt(index), preimageData as NullifierLeafPreimage, siblingPath); } - async getPublicDataTreeWitness(blockNumber: L2BlockNumber, leafSlot: Fr): Promise { + async getPublicDataWitness(blockNumber: L2BlockNumber, leafSlot: Fr): Promise { const committedDb = await this.#getWorldState(blockNumber); const lowLeafResult = await committedDb.getPreviousValueIndex(MerkleTreeId.PUBLIC_DATA_TREE, leafSlot.toBigInt()); if (!lowLeafResult) { diff --git a/yarn-project/noir-protocol-circuits-types/src/utils/client/foreign_call_handler.ts b/yarn-project/noir-protocol-circuits-types/src/utils/client/foreign_call_handler.ts index 22a1874029f3..d66f915cca88 100644 --- a/yarn-project/noir-protocol-circuits-types/src/utils/client/foreign_call_handler.ts +++ b/yarn-project/noir-protocol-circuits-types/src/utils/client/foreign_call_handler.ts @@ -4,10 +4,6 @@ import type { ForeignCallInput, ForeignCallOutput } from '@aztec/noir-acvm_js'; import { strict as assert } from 'assert'; -function fromACVMField(field: string): Fr { - return Fr.fromBuffer(Buffer.from(field.slice(2), 'hex')); -} - export function foreignCallHandler(name: string, args: ForeignCallInput[]): Promise { // ForeignCallInput is actually a string[], so the args are string[][]. const log = createLogger('noir-protocol-circuits:oracle'); @@ -15,8 +11,8 @@ export function foreignCallHandler(name: string, args: ForeignCallInput[]): Prom if (name === 'debugLog') { assert(args.length === 3, 'expected 3 arguments for debugLog: msg, fields_length, fields'); const [msgRaw, _ignoredFieldsSize, fields] = args; - const msg: string = msgRaw.map(acvmField => String.fromCharCode(fromACVMField(acvmField).toNumber())).join(''); - const fieldsFr: Fr[] = fields.map((field: string) => fromACVMField(field)); + const msg: string = msgRaw.map(acvmField => String.fromCharCode(Fr.fromString(acvmField).toNumber())).join(''); + const fieldsFr: Fr[] = fields.map((field: string) => Fr.fromString(field)); log.verbose('debug_log ' + applyStringFormatting(msg, fieldsFr)); } else if (name === 'noOp') { // Workaround for compiler issues where data is deleted because it's "unused" diff --git a/yarn-project/noir-protocol-circuits-types/src/utils/server/foreign_call_handler.ts b/yarn-project/noir-protocol-circuits-types/src/utils/server/foreign_call_handler.ts index a436fd0a31ba..eefd55037115 100644 --- a/yarn-project/noir-protocol-circuits-types/src/utils/server/foreign_call_handler.ts +++ b/yarn-project/noir-protocol-circuits-types/src/utils/server/foreign_call_handler.ts @@ -5,14 +5,6 @@ import type { ForeignCallInput, ForeignCallOutput } from '@aztec/noir-acvm_js'; import { strict as assert } from 'assert'; -function fromACVMField(field: string): Fr { - return Fr.fromBuffer(Buffer.from(field.slice(2), 'hex')); -} - -function toACVMField(field: Fr): string { - return `0x${field.toBuffer().toString('hex')}`; -} - export async function foreignCallHandler(name: string, args: ForeignCallInput[]): Promise { // ForeignCallInput is actually a string[], so the args are string[][]. const log = createLogger('noir-protocol-circuits:oracle'); @@ -20,25 +12,25 @@ export async function foreignCallHandler(name: string, args: ForeignCallInput[]) if (name === 'debugLog') { assert(args.length === 3, 'expected 3 arguments for debugLog: msg, fields_length, fields'); const [msgRaw, _ignoredFieldsSize, fields] = args; - const msg: string = msgRaw.map(acvmField => String.fromCharCode(fromACVMField(acvmField).toNumber())).join(''); - const fieldsFr: Fr[] = fields.map((field: string) => fromACVMField(field)); + const msg: string = msgRaw.map(acvmField => String.fromCharCode(Fr.fromString(acvmField).toNumber())).join(''); + const fieldsFr: Fr[] = fields.map((field: string) => Fr.fromString(field)); log.verbose('debug_log ' + applyStringFormatting(msg, fieldsFr)); } else if (name === 'evaluateBlobs') { // TODO(#10323): this was added to save simulation time (~1min in ACVM, ~3mins in wasm -> 500ms). // The use of bignum adds a lot of unconstrained code which overloads limits when simulating. // If/when simulation times of unconstrained are improved, remove this. // Create and evaulate our blobs: - const paddedBlobsAsFr: Fr[] = args[0].map((field: string) => fromACVMField(field)); - const kzgCommitments = args[1].map((field: string) => fromACVMField(field)); + const paddedBlobsAsFr: Fr[] = args[0].map((field: string) => Fr.fromString(field)); + const kzgCommitments = args[1].map((field: string) => Fr.fromString(field)); const spongeBlob = SpongeBlob.fromFields( args .slice(2) .flat() - .map((field: string) => fromACVMField(field)), + .map((field: string) => Fr.fromString(field)), ); const blobsAsFr = paddedBlobsAsFr.slice(0, spongeBlob.expectedFields); // NB: the above used to be: - // const blobsAsFr: Fr[] = args[0].map((field: string) => fromACVMField(field)).filter(field => !field.isZero()); + // const blobsAsFr: Fr[] = args[0].map((field: string) => Fr.fromString(field)).filter(field => !field.isZero()); // ...but we now have private logs which have a fixed number of fields and may have 0 values. // TODO(Miranda): trim 0 fields from private logs const blobs = await Blob.getBlobs(blobsAsFr); @@ -57,7 +49,7 @@ export async function foreignCallHandler(name: string, args: ForeignCallInput[]) ); } }); - return Promise.resolve([blobPublicInputs.toFields().map(toACVMField)]); + return Promise.resolve([blobPublicInputs.toFields().map(field => field.toString())]); } else if (name === 'noOp') { // Workaround for compiler issues where data is deleted because it's "unused" } else { diff --git a/yarn-project/pxe/src/private_kernel/private_kernel_oracle_impl.ts b/yarn-project/pxe/src/private_kernel/private_kernel_oracle_impl.ts index 3a0da8a20d66..f68faee33dc0 100644 --- a/yarn-project/pxe/src/private_kernel/private_kernel_oracle_impl.ts +++ b/yarn-project/pxe/src/private_kernel/private_kernel_oracle_impl.ts @@ -95,7 +95,7 @@ export class PrivateKernelOracleImpl implements PrivateKernelOracle { ProtocolContractAddress.ContractInstanceDeployer, sharedMutableHashSlot, ); - const updatedClassIdWitness = await this.node.getPublicDataTreeWitness(this.blockNumber, hashLeafSlot); + const updatedClassIdWitness = await this.node.getPublicDataWitness(this.blockNumber, hashLeafSlot); if (!updatedClassIdWitness) { throw new Error(`No public data tree witness found for ${hashLeafSlot}`); diff --git a/yarn-project/pxe/src/pxe_oracle_interface/pxe_oracle_interface.ts b/yarn-project/pxe/src/pxe_oracle_interface/pxe_oracle_interface.ts index 0c2950395ed7..1cff4c39112c 100644 --- a/yarn-project/pxe/src/pxe_oracle_interface/pxe_oracle_interface.ts +++ b/yarn-project/pxe/src/pxe_oracle_interface/pxe_oracle_interface.ts @@ -209,8 +209,8 @@ export class PXEOracleInterface implements ExecutionDataProvider { return await this.aztecNode.getBlock(blockNumber); } - public async getPublicDataTreeWitness(blockNumber: number, leafSlot: Fr): Promise { - return await this.aztecNode.getPublicDataTreeWitness(blockNumber, leafSlot); + public async getPublicDataWitness(blockNumber: number, leafSlot: Fr): Promise { + return await this.aztecNode.getPublicDataWitness(blockNumber, leafSlot); } public async getPublicStorageAt(blockNumber: number, contract: AztecAddress, slot: Fr): Promise { diff --git a/yarn-project/simulator/src/private/acvm/acvm.ts b/yarn-project/simulator/src/private/acvm/acvm.ts index d85ff1fbf4b9..f06bb5e42cfc 100644 --- a/yarn-project/simulator/src/private/acvm/acvm.ts +++ b/yarn-project/simulator/src/private/acvm/acvm.ts @@ -15,18 +15,7 @@ import type { ORACLE_NAMES } from './oracle/index.js'; /** * The callback interface for the ACIR. */ -export type ACIRCallback = Record< - ORACLE_NAMES, - ( - ...args: ForeignCallInput[] - ) => - | void - | Promise - | ForeignCallOutput - | ForeignCallOutput[] - | Promise - | Promise ->; +export type ACIRCallback = Record Promise>; /** * The result of executing an ACIR. @@ -54,7 +43,7 @@ export async function acvm( const solvedAndReturnWitness = await executeCircuitWithReturnWitness( acir, initialWitness, - async (name: string, args: ForeignCallInput[]) => { + (name: string, args: ForeignCallInput[]) => { try { logger.debug(`Oracle callback ${name}`); const oracleFunction = callback[name as ORACLE_NAMES]; @@ -62,17 +51,7 @@ export async function acvm( throw new Error(`Oracle callback ${name} not found`); } - const result = await oracleFunction.call(callback, ...args); - - if (typeof result === 'undefined') { - return []; - } else if (result instanceof Array && !result.every(item => typeof item === 'string')) { - // We are dealing with a nested array which means that we do not need it wrap it in another array as to have - // the nested array structure it is already "wrapped". - return result; - } else { - return [result] as ForeignCallOutput[]; - } + return oracleFunction.call(callback, ...args); } catch (err) { let typedError: Error; if (err instanceof Error) { diff --git a/yarn-project/simulator/src/private/acvm/deserialize.ts b/yarn-project/simulator/src/private/acvm/deserialize.ts index fb970e304b9d..f562d6a6ca8b 100644 --- a/yarn-project/simulator/src/private/acvm/deserialize.ts +++ b/yarn-project/simulator/src/private/acvm/deserialize.ts @@ -3,15 +3,6 @@ import { hexToBuffer } from '@aztec/foundation/string'; import type { ACVMField, ACVMWitness } from './acvm_types.js'; -/** - * Converts an ACVM field to a Fr. - * @param field - The ACVM field to convert. - * @returns The Fr. - */ -export function fromACVMField(field: ACVMField): Fr { - return Fr.fromBuffer(Buffer.from(field.slice(2), 'hex')); -} - /** * Converts a field to a number. * @param fr - The field to convert. @@ -39,7 +30,7 @@ export function frToBoolean(fr: Fr): boolean { * @returns An array with the same content as the Noir version. Elements past the length are discarded. */ export function fromBoundedVec(storage: ACVMField[], length: ACVMField): Fr[] { - return storage.slice(0, frToNumber(fromACVMField(length))).map(fromACVMField); + return storage.slice(0, frToNumber(Fr.fromString(length))).map(Fr.fromString); } /** @@ -56,7 +47,7 @@ export function fromUintBoundedVec(storage: ACVMField[], length: ACVMField, uint throw new Error(`u${uintBitSize} is not a supported type in Noir`); } const uintByteSize = uintBitSize / 8; - const boundedStorage = storage.slice(0, frToNumber(fromACVMField(length))); + const boundedStorage = storage.slice(0, frToNumber(Fr.fromString(length))); return Buffer.concat(boundedStorage.map(str => hexToBuffer(str).subarray(-uintByteSize))); } @@ -67,7 +58,7 @@ export function fromUintBoundedVec(storage: ACVMField[], length: ACVMField, uint */ export function witnessMapToFields(witness: ACVMWitness): Fr[] { const sortedKeys = [...witness.keys()].sort((a, b) => a - b); - return sortedKeys.map(key => witness.get(key)!).map(fromACVMField); + return sortedKeys.map(key => witness.get(key)!).map(Fr.fromString); } /** diff --git a/yarn-project/simulator/src/private/acvm/oracle/oracle.ts b/yarn-project/simulator/src/private/acvm/oracle/oracle.ts index ba1cdb767ea3..31de71b65fa9 100644 --- a/yarn-project/simulator/src/private/acvm/oracle/oracle.ts +++ b/yarn-project/simulator/src/private/acvm/oracle/oracle.ts @@ -5,14 +5,7 @@ import { ContractClassLog, LogWithTxData } from '@aztec/stdlib/logs'; import { MerkleTreeId } from '@aztec/stdlib/trees'; import type { ACVMField } from '../acvm_types.js'; -import { - frToBoolean, - frToNumber, - fromACVMField, - fromBoundedVec, - fromUintArray, - fromUintBoundedVec, -} from '../deserialize.js'; +import { frToBoolean, frToNumber, fromBoundedVec, fromUintArray, fromUintBoundedVec } from '../deserialize.js'; import { bufferToBoundedVec, toACVMField, toACVMFieldSingleOrArray } from '../serialize.js'; import type { TypedOracle } from './typed_oracle.js'; @@ -22,54 +15,56 @@ import type { TypedOracle } from './typed_oracle.js'; export class Oracle { constructor(private typedOracle: TypedOracle) {} - getRandomField(): ACVMField { + getRandomField(): Promise { const val = this.typedOracle.getRandomField(); - return toACVMField(val); + return Promise.resolve([toACVMField(val)]); } // Since the argument is a slice, noir automatically adds a length field to oracle call. - async storeInExecutionCache(_length: ACVMField[], values: ACVMField[]): Promise { - const hash = await this.typedOracle.storeInExecutionCache(values.map(fromACVMField)); - return toACVMField(hash); + async storeInExecutionCache(_length: ACVMField[], values: ACVMField[]): Promise { + const hash = await this.typedOracle.storeInExecutionCache(values.map(Fr.fromString)); + return [toACVMField(hash)]; } - async loadFromExecutionCache([returnsHash]: ACVMField[]): Promise { - const values = await this.typedOracle.loadFromExecutionCache(fromACVMField(returnsHash)); - return values.map(toACVMField); + async loadFromExecutionCache([returnsHash]: ACVMField[]): Promise { + const values = await this.typedOracle.loadFromExecutionCache(Fr.fromString(returnsHash)); + return [values.map(toACVMField)]; } - async getBlockNumber(): Promise { - return toACVMField(await this.typedOracle.getBlockNumber()); + async getBlockNumber(): Promise { + return [toACVMField(await this.typedOracle.getBlockNumber())]; } - async getContractAddress(): Promise { - return toACVMField(await this.typedOracle.getContractAddress()); + async getContractAddress(): Promise { + return [toACVMField(await this.typedOracle.getContractAddress())]; } - async getVersion(): Promise { - return toACVMField(await this.typedOracle.getVersion()); + async getVersion(): Promise { + return [toACVMField(await this.typedOracle.getVersion())]; } - async getChainId(): Promise { - return toACVMField(await this.typedOracle.getChainId()); + async getChainId(): Promise { + return [toACVMField(await this.typedOracle.getChainId())]; } async getKeyValidationRequest([pkMHash]: ACVMField[]): Promise { - const { pkM, skApp } = await this.typedOracle.getKeyValidationRequest(fromACVMField(pkMHash)); + const keyValidationRequest = await this.typedOracle.getKeyValidationRequest(Fr.fromString(pkMHash)); - return [toACVMField(pkM.x), toACVMField(pkM.y), toACVMField(pkM.isInfinite), toACVMField(skApp)]; + return keyValidationRequest.toFields().map(toACVMField); } - async getContractInstance([address]: ACVMField[]) { - const instance = await this.typedOracle.getContractInstance(AztecAddress.fromField(fromACVMField(address))); + async getContractInstance([address]: ACVMField[]): Promise { + const instance = await this.typedOracle.getContractInstance(AztecAddress.fromField(Fr.fromString(address))); return [ - instance.salt, - instance.deployer, - instance.currentContractClassId, - instance.initializationHash, - ...instance.publicKeys.toFields(), - ].map(toACVMField); + [ + instance.salt, + instance.deployer, + instance.currentContractClassId, + instance.initializationHash, + ...instance.publicKeys.toFields(), + ].map(toACVMField), + ]; } async getMembershipWitness( @@ -77,9 +72,9 @@ export class Oracle { [treeId]: ACVMField[], [leafValue]: ACVMField[], ): Promise { - const parsedBlockNumber = frToNumber(fromACVMField(blockNumber)); - const parsedTreeId = frToNumber(fromACVMField(treeId)); - const parsedLeafValue = fromACVMField(leafValue); + const parsedBlockNumber = frToNumber(Fr.fromString(blockNumber)); + const parsedTreeId = frToNumber(Fr.fromString(treeId)); + const parsedLeafValue = Fr.fromString(leafValue); const witness = await this.typedOracle.getMembershipWitness(parsedBlockNumber, parsedTreeId, parsedLeafValue); if (!witness) { @@ -94,8 +89,8 @@ export class Oracle { [blockNumber]: ACVMField[], [nullifier]: ACVMField[], // nullifier, we try to find the witness for (to prove inclusion) ): Promise { - const parsedBlockNumber = frToNumber(fromACVMField(blockNumber)); - const parsedNullifier = fromACVMField(nullifier); + const parsedBlockNumber = frToNumber(Fr.fromString(blockNumber)); + const parsedNullifier = Fr.fromString(nullifier); const witness = await this.typedOracle.getNullifierMembershipWitness(parsedBlockNumber, parsedNullifier); if (!witness) { @@ -108,8 +103,8 @@ export class Oracle { [blockNumber]: ACVMField[], [nullifier]: ACVMField[], // nullifier, we try to find the low nullifier witness for (to prove non-inclusion) ): Promise { - const parsedBlockNumber = frToNumber(fromACVMField(blockNumber)); - const parsedNullifier = fromACVMField(nullifier); + const parsedBlockNumber = frToNumber(Fr.fromString(blockNumber)); + const parsedNullifier = Fr.fromString(nullifier); const witness = await this.typedOracle.getLowNullifierMembershipWitness(parsedBlockNumber, parsedNullifier); if (!witness) { @@ -120,19 +115,22 @@ export class Oracle { return witness.toFields().map(toACVMField); } - async getPublicDataTreeWitness([blockNumber]: ACVMField[], [leafSlot]: ACVMField[]): Promise { - const parsedBlockNumber = frToNumber(fromACVMField(blockNumber)); - const parsedLeafSlot = fromACVMField(leafSlot); + async getPublicDataWitness( + [blockNumber]: ACVMField[], + [leafSlot]: ACVMField[], + ): Promise<(ACVMField | ACVMField[])[]> { + const parsedBlockNumber = frToNumber(Fr.fromString(blockNumber)); + const parsedLeafSlot = Fr.fromString(leafSlot); - const witness = await this.typedOracle.getPublicDataTreeWitness(parsedBlockNumber, parsedLeafSlot); + const witness = await this.typedOracle.getPublicDataWitness(parsedBlockNumber, parsedLeafSlot); if (!witness) { throw new Error(`Public data witness not found for slot ${parsedLeafSlot} at block ${parsedBlockNumber}.`); } - return witness.toFields().map(toACVMField); + return witness.toNoirRepresentation(); } async getBlockHeader([blockNumber]: ACVMField[]): Promise { - const parsedBlockNumber = frToNumber(fromACVMField(blockNumber)); + const parsedBlockNumber = frToNumber(Fr.fromString(blockNumber)); const header = await this.typedOracle.getBlockHeader(parsedBlockNumber); if (!header) { @@ -141,20 +139,20 @@ export class Oracle { return header.toFields().map(toACVMField); } - async getAuthWitness([messageHash]: ACVMField[]): Promise { - const messageHashField = fromACVMField(messageHash); + async getAuthWitness([messageHash]: ACVMField[]): Promise { + const messageHashField = Fr.fromString(messageHash); const witness = await this.typedOracle.getAuthWitness(messageHashField); if (!witness) { throw new Error(`Unknown auth witness for message hash ${messageHashField}`); } - return witness.map(toACVMField); + return [witness.map(toACVMField)]; } - async getPublicKeysAndPartialAddress([address]: ACVMField[]): Promise { - const parsedAddress = AztecAddress.fromField(fromACVMField(address)); + async getPublicKeysAndPartialAddress([address]: ACVMField[]): Promise { + const parsedAddress = AztecAddress.fromField(Fr.fromString(address)); const { publicKeys, partialAddress } = await this.typedOracle.getCompleteAddress(parsedAddress); - return [...publicKeys.toFields(), partialAddress].map(toACVMField); + return [[...publicKeys.toFields(), partialAddress].map(toACVMField)]; } async getNotes( @@ -173,14 +171,14 @@ export class Oracle { [offset]: ACVMField[], [status]: ACVMField[], [returnSize]: ACVMField[], - ): Promise { + ): Promise { const noteDatas = await this.typedOracle.getNotes( - fromACVMField(storageSlot), + Fr.fromString(storageSlot), +numSelects, selectByIndexes.map(s => +s), selectByOffsets.map(s => +s), selectByLengths.map(s => +s), - selectValues.map(fromACVMField), + selectValues.map(Fr.fromString), selectComparators.map(s => +s), sortByIndexes.map(s => +s), sortByOffsets.map(s => +s), @@ -216,7 +214,7 @@ export class Oracle { } const paddedZeros = Array(returnFieldSize - returnData.length).fill(toACVMField(0)); - return returnData.concat(paddedZeros); + return [returnData.concat(paddedZeros)]; } notifyCreatedNote( @@ -225,34 +223,34 @@ export class Oracle { note: ACVMField[], [noteHash]: ACVMField[], [counter]: ACVMField[], - ): ACVMField { + ): Promise { this.typedOracle.notifyCreatedNote( - fromACVMField(storageSlot), - NoteSelector.fromField(fromACVMField(noteTypeId)), - note.map(fromACVMField), - fromACVMField(noteHash), + Fr.fromString(storageSlot), + NoteSelector.fromField(Fr.fromString(noteTypeId)), + note.map(Fr.fromString), + Fr.fromString(noteHash), +counter, ); - return toACVMField(0); + return Promise.resolve([]); } async notifyNullifiedNote( [innerNullifier]: ACVMField[], [noteHash]: ACVMField[], [counter]: ACVMField[], - ): Promise { - await this.typedOracle.notifyNullifiedNote(fromACVMField(innerNullifier), fromACVMField(noteHash), +counter); - return toACVMField(0); + ): Promise { + await this.typedOracle.notifyNullifiedNote(Fr.fromString(innerNullifier), Fr.fromString(noteHash), +counter); + return []; } - async notifyCreatedNullifier([innerNullifier]: ACVMField[]): Promise { - await this.typedOracle.notifyCreatedNullifier(fromACVMField(innerNullifier)); - return toACVMField(0); + async notifyCreatedNullifier([innerNullifier]: ACVMField[]): Promise { + await this.typedOracle.notifyCreatedNullifier(Fr.fromString(innerNullifier)); + return []; } - async checkNullifierExists([innerNullifier]: ACVMField[]): Promise { - const exists = await this.typedOracle.checkNullifierExists(fromACVMField(innerNullifier)); - return toACVMField(exists); + async checkNullifierExists([innerNullifier]: ACVMField[]): Promise { + const exists = await this.typedOracle.checkNullifierExists(Fr.fromString(innerNullifier)); + return [toACVMField(exists)]; } async getL1ToL2MembershipWitness( @@ -262,8 +260,8 @@ export class Oracle { ): Promise { const message = await this.typedOracle.getL1ToL2MembershipWitness( AztecAddress.fromString(contractAddress), - fromACVMField(messageHash), - fromACVMField(secret), + Fr.fromString(messageHash), + Fr.fromString(secret), ); return message.toFields().map(toACVMField); } @@ -273,32 +271,38 @@ export class Oracle { [startStorageSlot]: ACVMField[], [blockNumber]: ACVMField[], [numberOfElements]: ACVMField[], - ): Promise { + ): Promise { const values = await this.typedOracle.storageRead( - new AztecAddress(fromACVMField(contractAddress)), - fromACVMField(startStorageSlot), + new AztecAddress(Fr.fromString(contractAddress)), + Fr.fromString(startStorageSlot), +blockNumber, +numberOfElements, ); - return values.map(toACVMField); + return [values.map(toACVMField)]; } async storageWrite([startStorageSlot]: ACVMField[], values: ACVMField[]): Promise { - const newValues = await this.typedOracle.storageWrite(fromACVMField(startStorageSlot), values.map(fromACVMField)); + const newValues = await this.typedOracle.storageWrite(Fr.fromString(startStorageSlot), values.map(Fr.fromString)); return newValues.map(toACVMField); } - notifyCreatedContractClassLog([contractAddress]: ACVMField[], message: ACVMField[], [counter]: ACVMField[]): void { - const logPayload = message.map(fromACVMField); - const log = new ContractClassLog(new AztecAddress(fromACVMField(contractAddress)), logPayload); + notifyCreatedContractClassLog( + [contractAddress]: ACVMField[], + message: ACVMField[], + [counter]: ACVMField[], + ): Promise { + const logPayload = message.map(Fr.fromString); + const log = new ContractClassLog(new AztecAddress(Fr.fromString(contractAddress)), logPayload); this.typedOracle.notifyCreatedContractClassLog(log, +counter); + return Promise.resolve([]); } - debugLog(message: ACVMField[], _ignoredFieldsSize: ACVMField[], fields: ACVMField[]): void { - const messageStr = message.map(acvmField => String.fromCharCode(fromACVMField(acvmField).toNumber())).join(''); - const fieldsFr = fields.map(fromACVMField); + debugLog(message: ACVMField[], _ignoredFieldsSize: ACVMField[], fields: ACVMField[]): Promise { + const messageStr = message.map(acvmField => String.fromCharCode(Fr.fromString(acvmField).toNumber())).join(''); + const fieldsFr = fields.map(Fr.fromString); this.typedOracle.debugLog(messageStr, fieldsFr); + return Promise.resolve([]); } async callPrivateFunction( @@ -307,15 +311,15 @@ export class Oracle { [argsHash]: ACVMField[], [sideEffectCounter]: ACVMField[], [isStaticCall]: ACVMField[], - ): Promise { + ): Promise { const { endSideEffectCounter, returnsHash } = await this.typedOracle.callPrivateFunction( - AztecAddress.fromField(fromACVMField(contractAddress)), - FunctionSelector.fromField(fromACVMField(functionSelector)), - fromACVMField(argsHash), - frToNumber(fromACVMField(sideEffectCounter)), - frToBoolean(fromACVMField(isStaticCall)), + AztecAddress.fromField(Fr.fromString(contractAddress)), + FunctionSelector.fromField(Fr.fromString(functionSelector)), + Fr.fromString(argsHash), + frToNumber(Fr.fromString(sideEffectCounter)), + frToBoolean(Fr.fromString(isStaticCall)), ); - return [endSideEffectCounter, returnsHash].map(toACVMField); + return [[endSideEffectCounter, returnsHash].map(toACVMField)]; } async enqueuePublicFunctionCall( @@ -324,15 +328,15 @@ export class Oracle { [argsHash]: ACVMField[], [sideEffectCounter]: ACVMField[], [isStaticCall]: ACVMField[], - ): Promise { + ): Promise { const newArgsHash = await this.typedOracle.enqueuePublicFunctionCall( AztecAddress.fromString(contractAddress), - FunctionSelector.fromField(fromACVMField(functionSelector)), - fromACVMField(argsHash), - frToNumber(fromACVMField(sideEffectCounter)), - frToBoolean(fromACVMField(isStaticCall)), + FunctionSelector.fromField(Fr.fromString(functionSelector)), + Fr.fromString(argsHash), + frToNumber(Fr.fromString(sideEffectCounter)), + frToBoolean(Fr.fromString(isStaticCall)), ); - return toACVMField(newArgsHash); + return [toACVMField(newArgsHash)]; } async setPublicTeardownFunctionCall( @@ -341,38 +345,41 @@ export class Oracle { [argsHash]: ACVMField[], [sideEffectCounter]: ACVMField[], [isStaticCall]: ACVMField[], - ): Promise { + ): Promise { const newArgsHash = await this.typedOracle.setPublicTeardownFunctionCall( AztecAddress.fromString(contractAddress), - FunctionSelector.fromField(fromACVMField(functionSelector)), - fromACVMField(argsHash), - frToNumber(fromACVMField(sideEffectCounter)), - frToBoolean(fromACVMField(isStaticCall)), + FunctionSelector.fromField(Fr.fromString(functionSelector)), + Fr.fromString(argsHash), + frToNumber(Fr.fromString(sideEffectCounter)), + frToBoolean(Fr.fromString(isStaticCall)), ); - return toACVMField(newArgsHash); + return [toACVMField(newArgsHash)]; } - notifySetMinRevertibleSideEffectCounter([minRevertibleSideEffectCounter]: ACVMField[]) { - this.typedOracle.notifySetMinRevertibleSideEffectCounter(frToNumber(fromACVMField(minRevertibleSideEffectCounter))); + notifySetMinRevertibleSideEffectCounter([minRevertibleSideEffectCounter]: ACVMField[]): Promise { + this.typedOracle.notifySetMinRevertibleSideEffectCounter(frToNumber(Fr.fromString(minRevertibleSideEffectCounter))); + return Promise.resolve([]); } - async getIndexedTaggingSecretAsSender([sender]: ACVMField[], [recipient]: ACVMField[]): Promise { + async getIndexedTaggingSecretAsSender([sender]: ACVMField[], [recipient]: ACVMField[]): Promise { const taggingSecret = await this.typedOracle.getIndexedTaggingSecretAsSender( AztecAddress.fromString(sender), AztecAddress.fromString(recipient), ); - return taggingSecret.toFields().map(toACVMField); + return [taggingSecret.toFields().map(toACVMField)]; } - async incrementAppTaggingSecretIndexAsSender([sender]: ACVMField[], [recipient]: ACVMField[]) { + async incrementAppTaggingSecretIndexAsSender([sender]: ACVMField[], [recipient]: ACVMField[]): Promise { await this.typedOracle.incrementAppTaggingSecretIndexAsSender( AztecAddress.fromString(sender), AztecAddress.fromString(recipient), ); + return []; } - async syncNotes() { + async syncNotes(): Promise { await this.typedOracle.syncNotes(); + return []; } async deliverNote( @@ -385,26 +392,26 @@ export class Oracle { [nullifier]: ACVMField[], [txHash]: ACVMField[], [recipient]: ACVMField[], - ): Promise { + ): Promise { // TODO(#10728): try-catch this block and return false if we get an exception so that the contract can decide what // to do if a note fails delivery (e.g. not increment the tagging index, or add it to some pending work list). // Delivery might fail due to temporary issues, such as poor node connectivity. await this.typedOracle.deliverNote( AztecAddress.fromString(contractAddress), - fromACVMField(storageSlot), - fromACVMField(nonce), + Fr.fromString(storageSlot), + Fr.fromString(nonce), fromBoundedVec(content, contentLength), - fromACVMField(noteHash), - fromACVMField(nullifier), - fromACVMField(txHash), + Fr.fromString(noteHash), + Fr.fromString(nullifier), + Fr.fromString(txHash), AztecAddress.fromString(recipient), ); - return toACVMField(true); + return [toACVMField(true)]; } async getLogByTag([tag]: ACVMField[]): Promise<(ACVMField | ACVMField[])[]> { - const log = await this.typedOracle.getLogByTag(fromACVMField(tag)); + const log = await this.typedOracle.getLogByTag(Fr.fromString(tag)); if (log == null) { return [toACVMField(0), ...LogWithTxData.noirSerializationOfEmpty().map(toACVMFieldSingleOrArray)]; @@ -413,12 +420,13 @@ export class Oracle { } } - async storeCapsule([contractAddress]: ACVMField[], [slot]: ACVMField[], capsule: ACVMField[]) { + async storeCapsule([contractAddress]: ACVMField[], [slot]: ACVMField[], capsule: ACVMField[]): Promise { await this.typedOracle.storeCapsule( - AztecAddress.fromField(fromACVMField(contractAddress)), - fromACVMField(slot), - capsule.map(fromACVMField), + AztecAddress.fromField(Fr.fromString(contractAddress)), + Fr.fromString(slot), + capsule.map(Fr.fromString), ); + return []; } async loadCapsule( @@ -427,23 +435,24 @@ export class Oracle { [tSize]: ACVMField[], ): Promise<(ACVMField | ACVMField[])[]> { const values = await this.typedOracle.loadCapsule( - AztecAddress.fromField(fromACVMField(contractAddress)), - fromACVMField(slot), + AztecAddress.fromField(Fr.fromString(contractAddress)), + Fr.fromString(slot), ); // We are going to return a Noir Option struct to represent the possibility of null values. Options are a struct // with two fields: `some` (a boolean) and `value` (a field array in this case). if (values === null) { // No data was found so we set `some` to 0 and pad `value` with zeros get the correct return size. - return [toACVMField(0), Array(frToNumber(fromACVMField(tSize))).fill(toACVMField(0))]; + return [toACVMField(0), Array(frToNumber(Fr.fromString(tSize))).fill(toACVMField(0))]; } else { // Data was found so we set `some` to 1 and return it along with `value`. return [toACVMField(1), values.map(toACVMField)]; } } - async deleteCapsule([contractAddress]: ACVMField[], [slot]: ACVMField[]) { - await this.typedOracle.deleteCapsule(AztecAddress.fromField(fromACVMField(contractAddress)), fromACVMField(slot)); + async deleteCapsule([contractAddress]: ACVMField[], [slot]: ACVMField[]): Promise { + await this.typedOracle.deleteCapsule(AztecAddress.fromField(Fr.fromString(contractAddress)), Fr.fromString(slot)); + return []; } async copyCapsule( @@ -451,13 +460,14 @@ export class Oracle { [srcSlot]: ACVMField[], [dstSlot]: ACVMField[], [numEntries]: ACVMField[], - ) { + ): Promise { await this.typedOracle.copyCapsule( - AztecAddress.fromField(fromACVMField(contractAddress)), - fromACVMField(srcSlot), - fromACVMField(dstSlot), - frToNumber(fromACVMField(numEntries)), + AztecAddress.fromField(Fr.fromString(contractAddress)), + Fr.fromString(srcSlot), + Fr.fromString(dstSlot), + frToNumber(Fr.fromString(numEntries)), ); + return []; } async aes128Decrypt( @@ -481,8 +491,8 @@ export class Oracle { [ephPKField2]: ACVMField[], ): Promise { const secret = await this.typedOracle.getSharedSecret( - AztecAddress.fromField(fromACVMField(address)), - Point.fromFields([ephPKField0, ephPKField1, ephPKField2].map(fromACVMField)), + AztecAddress.fromField(Fr.fromString(address)), + Point.fromFields([ephPKField0, ephPKField1, ephPKField2].map(Fr.fromString)), ); return secret.toFields().map(toACVMField); } diff --git a/yarn-project/simulator/src/private/acvm/oracle/typed_oracle.ts b/yarn-project/simulator/src/private/acvm/oracle/typed_oracle.ts index a94d9af06970..4fd3c5580653 100644 --- a/yarn-project/simulator/src/private/acvm/oracle/typed_oracle.ts +++ b/yarn-project/simulator/src/private/acvm/oracle/typed_oracle.ts @@ -87,8 +87,8 @@ export abstract class TypedOracle { return Promise.reject(new OracleMethodNotAvailableError('getNullifierMembershipWitness')); } - getPublicDataTreeWitness(_blockNumber: number, _leafSlot: Fr): Promise { - return Promise.reject(new OracleMethodNotAvailableError('getPublicDataTreeWitness')); + getPublicDataWitness(_blockNumber: number, _leafSlot: Fr): Promise { + return Promise.reject(new OracleMethodNotAvailableError('getPublicDataWitness')); } getLowNullifierMembershipWitness( diff --git a/yarn-project/simulator/src/private/execution_data_provider.ts b/yarn-project/simulator/src/private/execution_data_provider.ts index 0b13338d40a1..21ba493c4b41 100644 --- a/yarn-project/simulator/src/private/execution_data_provider.ts +++ b/yarn-project/simulator/src/private/execution_data_provider.ts @@ -150,7 +150,7 @@ export interface ExecutionDataProvider extends CommitmentsDBInterface { * @param blockNumber - The block number at which to get the witness. * @param leafSlot - The slot of the public data in the public data tree. */ - getPublicDataTreeWitness(blockNumber: number, leafSlot: Fr): Promise; + getPublicDataWitness(blockNumber: number, leafSlot: Fr): Promise; /** * Gets the storage value at the given contract storage slot. diff --git a/yarn-project/simulator/src/private/private_execution.ts b/yarn-project/simulator/src/private/private_execution.ts index 006733051924..e15f2cf84803 100644 --- a/yarn-project/simulator/src/private/private_execution.ts +++ b/yarn-project/simulator/src/private/private_execution.ts @@ -13,7 +13,7 @@ import type { CircuitWitnessGenerationStats } from '@aztec/stdlib/stats'; import { PrivateCallExecutionResult } from '@aztec/stdlib/tx'; import { ExecutionError, resolveAssertionMessageFromError } from '../common/errors.js'; -import { fromACVMField, witnessMapToFields } from './acvm/deserialize.js'; +import { witnessMapToFields } from './acvm/deserialize.js'; import { type ACVMWitness, Oracle, extractCallStack } from './acvm/index.js'; import type { ExecutionDataProvider } from './execution_data_provider.js'; import type { PrivateExecutionOracle } from './private_execution_oracle.js'; @@ -113,7 +113,7 @@ export function extractPrivateCircuitPublicInputs( if (returnedField === undefined) { throw new Error(`Missing return value for index ${i}`); } - returnData.push(fromACVMField(returnedField)); + returnData.push(Fr.fromString(returnedField)); } return PrivateCircuitPublicInputs.fromFields(returnData); } diff --git a/yarn-project/simulator/src/private/unconstrained_execution_oracle.ts b/yarn-project/simulator/src/private/unconstrained_execution_oracle.ts index 2480da38825b..5a00e623b534 100644 --- a/yarn-project/simulator/src/private/unconstrained_execution_oracle.ts +++ b/yarn-project/simulator/src/private/unconstrained_execution_oracle.ts @@ -103,11 +103,11 @@ export class UnconstrainedExecutionOracle extends TypedOracle { * @param leafSlot - The slot of the public data tree to get the witness for. * @returns - The witness */ - public override async getPublicDataTreeWitness( + public override async getPublicDataWitness( blockNumber: number, leafSlot: Fr, ): Promise { - return await this.executionDataProvider.getPublicDataTreeWitness(blockNumber, leafSlot); + return await this.executionDataProvider.getPublicDataWitness(blockNumber, leafSlot); } /** diff --git a/yarn-project/stdlib/src/interfaces/aztec-node.test.ts b/yarn-project/stdlib/src/interfaces/aztec-node.test.ts index 7ff5871d7ec1..1add6f7cb609 100644 --- a/yarn-project/stdlib/src/interfaces/aztec-node.test.ts +++ b/yarn-project/stdlib/src/interfaces/aztec-node.test.ts @@ -152,8 +152,8 @@ describe('AztecNodeApiSchema', () => { expect(response).toBeInstanceOf(NullifierMembershipWitness); }); - it('getPublicDataTreeWitness', async () => { - const response = await context.client.getPublicDataTreeWitness(1, Fr.random()); + it('getPublicDataWitness', async () => { + const response = await context.client.getPublicDataWitness(1, Fr.random()); expect(response).toBeInstanceOf(PublicDataWitness); }); @@ -460,7 +460,7 @@ class MockAztecNode implements AztecNode { expect(nullifier).toBeInstanceOf(Fr); return Promise.resolve(NullifierMembershipWitness.random()); } - getPublicDataTreeWitness(blockNumber: number | 'latest', leafSlot: Fr): Promise { + getPublicDataWitness(blockNumber: number | 'latest', leafSlot: Fr): Promise { expect(leafSlot).toBeInstanceOf(Fr); return Promise.resolve(PublicDataWitness.random()); } diff --git a/yarn-project/stdlib/src/interfaces/aztec-node.ts b/yarn-project/stdlib/src/interfaces/aztec-node.ts index 913425c8c5c6..7b931fe7a1a5 100644 --- a/yarn-project/stdlib/src/interfaces/aztec-node.ts +++ b/yarn-project/stdlib/src/interfaces/aztec-node.ts @@ -219,7 +219,7 @@ export interface AztecNode * "in range" slot, means that the slot doesn't exist and the value is 0. If the low leaf preimage corresponds to the exact slot, the current value * is contained in the leaf preimage. */ - getPublicDataTreeWitness(blockNumber: L2BlockNumber, leafSlot: Fr): Promise; + getPublicDataWitness(blockNumber: L2BlockNumber, leafSlot: Fr): Promise; /** * Get a block specified by its number. @@ -500,10 +500,7 @@ export const AztecNodeApiSchema: ApiSchemaFor = { .args(L2BlockNumberSchema, schemas.Fr) .returns(NullifierMembershipWitness.schema.optional()), - getPublicDataTreeWitness: z - .function() - .args(L2BlockNumberSchema, schemas.Fr) - .returns(PublicDataWitness.schema.optional()), + getPublicDataWitness: z.function().args(L2BlockNumberSchema, schemas.Fr).returns(PublicDataWitness.schema.optional()), getBlock: z.function().args(z.number()).returns(L2Block.schema.optional()), diff --git a/yarn-project/stdlib/src/trees/public_data_witness.ts b/yarn-project/stdlib/src/trees/public_data_witness.ts index 35c913eacfca..5f8b409dda90 100644 --- a/yarn-project/stdlib/src/trees/public_data_witness.ts +++ b/yarn-project/stdlib/src/trees/public_data_witness.ts @@ -58,6 +58,21 @@ export class PublicDataWitness { ]; } + /** + * Returns a field array representation of a public data witness. + */ + public toNoirRepresentation(): (string | string[])[] { + // TODO(benesjan): remove the stupid as string conversion by modifying ForeignCallOutput type in acvm.js + return [ + new Fr(this.index).toString() as string, + new Fr(this.leafPreimage.slot).toString() as string, + new Fr(this.leafPreimage.value).toString() as string, + new Fr(this.leafPreimage.nextSlot).toString() as string, + new Fr(this.leafPreimage.nextIndex).toString() as string, + this.siblingPath.toFields().map(fr => fr.toString()) as string[], + ]; + } + toBuffer(): Buffer { return serializeToBuffer([this.index, this.leafPreimage, this.siblingPath]); } diff --git a/yarn-project/txe/src/node/txe_node.ts b/yarn-project/txe/src/node/txe_node.ts index c44f0f48ca2a..8dcbcd4868a4 100644 --- a/yarn-project/txe/src/node/txe_node.ts +++ b/yarn-project/txe/src/node/txe_node.ts @@ -383,8 +383,8 @@ export class TXENode implements AztecNode { * "in range" slot, means that the slot doesn't exist and the value is 0. If the low leaf preimage corresponds to the exact slot, the current value * is contained in the leaf preimage. */ - getPublicDataTreeWitness(_blockNumber: L2BlockNumber, _leafSlot: Fr): Promise { - throw new Error('TXE Node method getPublicDataTreeWitness not implemented'); + getPublicDataWitness(_blockNumber: L2BlockNumber, _leafSlot: Fr): Promise { + throw new Error('TXE Node method getPublicDataWitness not implemented'); } /** diff --git a/yarn-project/txe/src/oracle/txe_oracle.ts b/yarn-project/txe/src/oracle/txe_oracle.ts index 26d7aadf3fcd..b569a0675119 100644 --- a/yarn-project/txe/src/oracle/txe_oracle.ts +++ b/yarn-project/txe/src/oracle/txe_oracle.ts @@ -468,7 +468,7 @@ export class TXE implements TypedOracle { return new NullifierMembershipWitness(BigInt(index), leafPreimage as NullifierLeafPreimage, siblingPath); } - async getPublicDataTreeWitness(blockNumber: number, leafSlot: Fr): Promise { + async getPublicDataWitness(blockNumber: number, leafSlot: Fr): Promise { const snap = this.nativeWorldStateService.getSnapshot(blockNumber); const lowLeafResult = await snap.getPreviousValueIndex(MerkleTreeId.PUBLIC_DATA_TREE, leafSlot.toBigInt()); diff --git a/yarn-project/txe/src/txe_service/txe_service.ts b/yarn-project/txe/src/txe_service/txe_service.ts index e14568425c29..c714bba435db 100644 --- a/yarn-project/txe/src/txe_service/txe_service.ts +++ b/yarn-project/txe/src/txe_service/txe_service.ts @@ -263,11 +263,11 @@ export class TXEService { return toForeignCallResult([toArray(newValues)]); } - async getPublicDataTreeWitness(blockNumber: ForeignCallSingle, leafSlot: ForeignCallSingle) { + async getPublicDataWitness(blockNumber: ForeignCallSingle, leafSlot: ForeignCallSingle) { const parsedBlockNumber = fromSingle(blockNumber).toNumber(); const parsedLeafSlot = fromSingle(leafSlot); - const witness = await this.typedOracle.getPublicDataTreeWitness(parsedBlockNumber, parsedLeafSlot); + const witness = await this.typedOracle.getPublicDataWitness(parsedBlockNumber, parsedLeafSlot); if (!witness) { throw new Error(`Public data witness not found for slot ${parsedLeafSlot} at block ${parsedBlockNumber}.`); } From db696a8bd9c05aef23bef9c0f2e35d323e1728a8 Mon Sep 17 00:00:00 2001 From: benesjan Date: Tue, 18 Mar 2025 23:26:00 +0000 Subject: [PATCH 02/10] more fixes --- .../src/oracle/get_l1_to_l2_membership_witness.nr | 10 ++-------- .../simulator/src/common/message_load_oracle_inputs.ts | 8 ++++++++ .../simulator/src/private/acvm/oracle/oracle.ts | 4 ++-- yarn-project/stdlib/src/trees/public_data_witness.ts | 2 +- 4 files changed, 13 insertions(+), 11 deletions(-) diff --git a/noir-projects/aztec-nr/aztec/src/oracle/get_l1_to_l2_membership_witness.nr b/noir-projects/aztec-nr/aztec/src/oracle/get_l1_to_l2_membership_witness.nr index d648f7f2b12e..f1e1c8cb6352 100644 --- a/noir-projects/aztec-nr/aztec/src/oracle/get_l1_to_l2_membership_witness.nr +++ b/noir-projects/aztec-nr/aztec/src/oracle/get_l1_to_l2_membership_witness.nr @@ -1,4 +1,3 @@ -use crate::utils::array; use dep::protocol_types::{address::AztecAddress, constants::L1_TO_L2_MSG_TREE_HEIGHT}; /// Returns the leaf index and sibling path of an entry in the L1 to L2 messaging tree, which can then be used to prove @@ -8,12 +7,7 @@ pub unconstrained fn get_l1_to_l2_membership_witness( message_hash: Field, secret: Field, ) -> (Field, [Field; L1_TO_L2_MSG_TREE_HEIGHT]) { - let returned_message = - get_l1_to_l2_membership_witness_oracle(contract_address, message_hash, secret); - let leaf_index = returned_message[0]; - let sibling_path = array::subarray(returned_message, 1); - - (leaf_index, sibling_path) + get_l1_to_l2_membership_witness_oracle(contract_address, message_hash, secret) } // Obtains membership witness (index and sibling path) for a message in the L1 to L2 message tree. @@ -22,4 +16,4 @@ unconstrained fn get_l1_to_l2_membership_witness_oracle( _contract_address: AztecAddress, _message_hash: Field, _secret: Field, -) -> [Field; L1_TO_L2_MSG_TREE_HEIGHT + 1] {} +) -> (Field, [Field; L1_TO_L2_MSG_TREE_HEIGHT]) {} diff --git a/yarn-project/simulator/src/common/message_load_oracle_inputs.ts b/yarn-project/simulator/src/common/message_load_oracle_inputs.ts index 47b29ec4571e..2a8e324c73e2 100644 --- a/yarn-project/simulator/src/common/message_load_oracle_inputs.ts +++ b/yarn-project/simulator/src/common/message_load_oracle_inputs.ts @@ -12,4 +12,12 @@ export class MessageLoadOracleInputs { toFields(): Fr[] { return [new Fr(this.index), ...this.siblingPath.toFields()]; } + + /** + * Returns a representation of the public data witness as expected by intrinsic Noir deserialization. + */ + public toNoirRepresentation(): (string | string[])[] { + // TODO(benesjan): remove the stupid as string conversion by modifying ForeignCallOutput type in acvm.js + return [new Fr(this.index).toString() as string, this.siblingPath.toFields().map(fr => fr.toString()) as string[]]; + } } diff --git a/yarn-project/simulator/src/private/acvm/oracle/oracle.ts b/yarn-project/simulator/src/private/acvm/oracle/oracle.ts index 31de71b65fa9..972f08b238cb 100644 --- a/yarn-project/simulator/src/private/acvm/oracle/oracle.ts +++ b/yarn-project/simulator/src/private/acvm/oracle/oracle.ts @@ -257,13 +257,13 @@ export class Oracle { [contractAddress]: ACVMField[], [messageHash]: ACVMField[], [secret]: ACVMField[], - ): Promise { + ): Promise<(ACVMField | ACVMField[])[]> { const message = await this.typedOracle.getL1ToL2MembershipWitness( AztecAddress.fromString(contractAddress), Fr.fromString(messageHash), Fr.fromString(secret), ); - return message.toFields().map(toACVMField); + return message.toNoirRepresentation(); } async storageRead( diff --git a/yarn-project/stdlib/src/trees/public_data_witness.ts b/yarn-project/stdlib/src/trees/public_data_witness.ts index 5f8b409dda90..ac76613a43f2 100644 --- a/yarn-project/stdlib/src/trees/public_data_witness.ts +++ b/yarn-project/stdlib/src/trees/public_data_witness.ts @@ -59,7 +59,7 @@ export class PublicDataWitness { } /** - * Returns a field array representation of a public data witness. + * Returns a representation of the public data witness as expected by intrinsic Noir deserialization. */ public toNoirRepresentation(): (string | string[])[] { // TODO(benesjan): remove the stupid as string conversion by modifying ForeignCallOutput type in acvm.js From ab503ab4d0a0ea7b3d389c1f385001046024f963 Mon Sep 17 00:00:00 2001 From: benesjan Date: Wed, 19 Mar 2025 03:02:23 +0000 Subject: [PATCH 03/10] fixes --- .../default_aes128/note/encryption.nr | 4 ++-- .../src/oracle/get_nullifier_membership_witness.nr | 10 ++++------ noir-projects/aztec-nr/aztec/src/oracle/notes.nr | 6 +++--- .../simulator/src/private/acvm/oracle/oracle.ts | 8 ++++---- .../stdlib/src/trees/nullifier_membership_witness.ts | 12 ++++++++++++ yarn-project/txe/src/txe_service/txe_service.ts | 12 ++++++------ 6 files changed, 31 insertions(+), 21 deletions(-) diff --git a/noir-projects/aztec-nr/aztec/src/encrypted_logs/log_assembly_strategies/default_aes128/note/encryption.nr b/noir-projects/aztec-nr/aztec/src/encrypted_logs/log_assembly_strategies/default_aes128/note/encryption.nr index 22cd2f8c43d6..d9016f1cc9aa 100644 --- a/noir-projects/aztec-nr/aztec/src/encrypted_logs/log_assembly_strategies/default_aes128/note/encryption.nr +++ b/noir-projects/aztec-nr/aztec/src/encrypted_logs/log_assembly_strategies/default_aes128/note/encryption.nr @@ -306,7 +306,7 @@ mod test { use std::{embedded_curve_ops::EmbeddedCurveScalar, test::OracleMock}; #[test] - unconstrained fn test_encrypt_decrypt_log() { + unconstrained fn encrypt_decrypt_log() { let mut env = TestEnvironment::new(); // Advance 1 block so we can read historic state from private env.advance_block_by(1); @@ -344,7 +344,7 @@ mod test { EmbeddedCurveScalar::from_field(eph_sk), recipient, ); - let _ = OracleMock::mock("getSharedSecret").returns(shared_secret.serialize()); + let _ = OracleMock::mock("getSharedSecret").returns(shared_secret); // Decrypt the log let decrypted = decrypt_log(encrypted_log, recipient); diff --git a/noir-projects/aztec-nr/aztec/src/oracle/get_nullifier_membership_witness.nr b/noir-projects/aztec-nr/aztec/src/oracle/get_nullifier_membership_witness.nr index d41ac58cf148..668f51df5862 100644 --- a/noir-projects/aztec-nr/aztec/src/oracle/get_nullifier_membership_witness.nr +++ b/noir-projects/aztec-nr/aztec/src/oracle/get_nullifier_membership_witness.nr @@ -28,7 +28,7 @@ impl NullifierMembershipWitness { unconstrained fn get_low_nullifier_membership_witness_oracle( _block_number: u32, _nullifier: Field, -) -> [Field; NULLIFIER_MEMBERSHIP_WITNESS] {} +) -> NullifierMembershipWitness {} // Nullifier here refers to the nullifier we are looking to get non-inclusion proof for (by proving that a lower // nullifier's next_value is bigger than the nullifier) @@ -36,15 +36,14 @@ pub unconstrained fn get_low_nullifier_membership_witness( block_number: u32, nullifier: Field, ) -> NullifierMembershipWitness { - let fields = get_low_nullifier_membership_witness_oracle(block_number, nullifier); - NullifierMembershipWitness::deserialize(fields) + get_low_nullifier_membership_witness_oracle(block_number, nullifier) } #[oracle(getNullifierMembershipWitness)] unconstrained fn get_nullifier_membership_witness_oracle( _block_number: u32, _nullifier: Field, -) -> [Field; NULLIFIER_MEMBERSHIP_WITNESS] {} +) -> NullifierMembershipWitness {} // Nullifier here refers to the nullifier we are looking to get non-inclusion proof for (by proving that a lower // nullifier's next_value is bigger than the nullifier) @@ -52,6 +51,5 @@ pub unconstrained fn get_nullifier_membership_witness( block_number: u32, nullifier: Field, ) -> NullifierMembershipWitness { - let fields = get_nullifier_membership_witness_oracle(block_number, nullifier); - NullifierMembershipWitness::deserialize(fields) + get_nullifier_membership_witness_oracle(block_number, nullifier) } diff --git a/noir-projects/aztec-nr/aztec/src/oracle/notes.nr b/noir-projects/aztec-nr/aztec/src/oracle/notes.nr index b5326cfd4ffe..766ad74032da 100644 --- a/noir-projects/aztec-nr/aztec/src/oracle/notes.nr +++ b/noir-projects/aztec-nr/aztec/src/oracle/notes.nr @@ -54,7 +54,7 @@ unconstrained fn notify_created_note_oracle_wrapper( note_hash: Field, counter: u32, ) { - let _ = notify_created_note_oracle(storage_slot, note_type_id, packed_note, note_hash, counter); + notify_created_note_oracle(storage_slot, note_type_id, packed_note, note_hash, counter); } #[oracle(notifyCreatedNote)] @@ -209,11 +209,11 @@ where /// current transaction is included in a block. While this might seem of little use at first, certain design patterns /// benefit from this abstraction (see e.g. `PrivateMutable`). pub unconstrained fn check_nullifier_exists(inner_nullifier: Field) -> bool { - check_nullifier_exists_oracle(inner_nullifier) == 1 + check_nullifier_exists_oracle(inner_nullifier) } #[oracle(checkNullifierExists)] -unconstrained fn check_nullifier_exists_oracle(_inner_nullifier: Field) -> Field {} +unconstrained fn check_nullifier_exists_oracle(_inner_nullifier: Field) -> bool {} /// Same as `get_indexed_tagging_secret_as_sender`, except it returns the derived tag, ready to be included in a log. pub unconstrained fn get_app_tag_as_sender(sender: AztecAddress, recipient: AztecAddress) -> Field { diff --git a/yarn-project/simulator/src/private/acvm/oracle/oracle.ts b/yarn-project/simulator/src/private/acvm/oracle/oracle.ts index 972f08b238cb..0bafb96e7ff5 100644 --- a/yarn-project/simulator/src/private/acvm/oracle/oracle.ts +++ b/yarn-project/simulator/src/private/acvm/oracle/oracle.ts @@ -88,7 +88,7 @@ export class Oracle { async getNullifierMembershipWitness( [blockNumber]: ACVMField[], [nullifier]: ACVMField[], // nullifier, we try to find the witness for (to prove inclusion) - ): Promise { + ): Promise<(ACVMField | ACVMField[])[]> { const parsedBlockNumber = frToNumber(Fr.fromString(blockNumber)); const parsedNullifier = Fr.fromString(nullifier); @@ -96,13 +96,13 @@ export class Oracle { if (!witness) { throw new Error(`Nullifier witness not found for nullifier ${parsedNullifier} at block ${parsedBlockNumber}.`); } - return witness.toFields().map(toACVMField); + return witness.toNoirRepresentation(); } async getLowNullifierMembershipWitness( [blockNumber]: ACVMField[], [nullifier]: ACVMField[], // nullifier, we try to find the low nullifier witness for (to prove non-inclusion) - ): Promise { + ): Promise<(ACVMField | ACVMField[])[]> { const parsedBlockNumber = frToNumber(Fr.fromString(blockNumber)); const parsedNullifier = Fr.fromString(nullifier); @@ -112,7 +112,7 @@ export class Oracle { `Low nullifier witness not found for nullifier ${parsedNullifier} at block ${parsedBlockNumber}.`, ); } - return witness.toFields().map(toACVMField); + return witness.toNoirRepresentation(); } async getPublicDataWitness( diff --git a/yarn-project/stdlib/src/trees/nullifier_membership_witness.ts b/yarn-project/stdlib/src/trees/nullifier_membership_witness.ts index 128874a6690f..0aba380940a4 100644 --- a/yarn-project/stdlib/src/trees/nullifier_membership_witness.ts +++ b/yarn-project/stdlib/src/trees/nullifier_membership_witness.ts @@ -56,4 +56,16 @@ export class NullifierMembershipWitness { public toFields(): Fr[] { return [new Fr(this.index), ...this.leafPreimage.toFields(), ...this.siblingPath.toFields()]; } + + /** + * Returns a representation of the nullifier membership witness as expected by intrinsic Noir deserialization. + */ + public toNoirRepresentation(): (string | string[])[] { + // TODO(benesjan): remove the stupid as string conversion by modifying ForeignCallOutput type in acvm.js + return [ + new Fr(this.index).toString() as string, + ...(this.leafPreimage.toFields().map(fr => fr.toString()) as string[]), + this.siblingPath.toFields().map(fr => fr.toString()) as string[], + ]; + } } diff --git a/yarn-project/txe/src/txe_service/txe_service.ts b/yarn-project/txe/src/txe_service/txe_service.ts index c714bba435db..0f82d4288c5d 100644 --- a/yarn-project/txe/src/txe_service/txe_service.ts +++ b/yarn-project/txe/src/txe_service/txe_service.ts @@ -271,7 +271,7 @@ export class TXEService { if (!witness) { throw new Error(`Public data witness not found for slot ${parsedLeafSlot} at block ${parsedBlockNumber}.`); } - return toForeignCallResult([toArray(witness.toFields())]); + return toForeignCallResult(witness.toNoirRepresentation()); } async getNotes( @@ -349,7 +349,7 @@ export class TXEService { fromSingle(noteHash), fromSingle(counter).toNumber(), ); - return toForeignCallResult([toSingle(new Fr(0))]); + return toForeignCallResult([]); } async notifyNullifiedNote( @@ -362,12 +362,12 @@ export class TXEService { fromSingle(noteHash), fromSingle(counter).toNumber(), ); - return toForeignCallResult([toSingle(new Fr(0))]); + return toForeignCallResult([]); } async notifyCreatedNullifier(innerNullifier: ForeignCallSingle) { await this.typedOracle.notifyCreatedNullifier(fromSingle(innerNullifier)); - return toForeignCallResult([toSingle(new Fr(0))]); + return toForeignCallResult([]); } async checkNullifierExists(innerNullifier: ForeignCallSingle) { @@ -396,7 +396,7 @@ export class TXEService { async getKeyValidationRequest(pkMHash: ForeignCallSingle) { const keyValidationRequest = await this.typedOracle.getKeyValidationRequest(fromSingle(pkMHash)); - return toForeignCallResult([toArray(keyValidationRequest.toFields())]); + return toForeignCallResult(keyValidationRequest.toFields().map(toSingle)); } async callPrivateFunction( @@ -630,7 +630,7 @@ export class TXEService { AztecAddress.fromField(fromSingle(address)), Point.fromFields(fromArray(ephPk)), ); - return toForeignCallResult([toArray(secret.toFields())]); + return toForeignCallResult(secret.toFields().map(toSingle)); } // AVM opcodes From 519163b38ba44d454ee051fe7b4942c6a8d69ba1 Mon Sep 17 00:00:00 2001 From: benesjan Date: Wed, 19 Mar 2025 12:02:21 +0000 Subject: [PATCH 04/10] fix --- .../log_assembly_strategies/default_aes128/note/encryption.nr | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/noir-projects/aztec-nr/aztec/src/encrypted_logs/log_assembly_strategies/default_aes128/note/encryption.nr b/noir-projects/aztec-nr/aztec/src/encrypted_logs/log_assembly_strategies/default_aes128/note/encryption.nr index d9016f1cc9aa..c22047499739 100644 --- a/noir-projects/aztec-nr/aztec/src/encrypted_logs/log_assembly_strategies/default_aes128/note/encryption.nr +++ b/noir-projects/aztec-nr/aztec/src/encrypted_logs/log_assembly_strategies/default_aes128/note/encryption.nr @@ -302,7 +302,7 @@ mod test { test::helpers::test_environment::TestEnvironment, }; use super::{decrypt_log, encrypt_log, PRIVATE_LOG_PLAINTEXT_SIZE_IN_FIELDS}; - use protocol_types::{address::AztecAddress, traits::{FromField, Serialize}}; + use protocol_types::{address::AztecAddress, traits::FromField}; use std::{embedded_curve_ops::EmbeddedCurveScalar, test::OracleMock}; #[test] From cd51e9dcf4cfae2319043fd4f09fc2f035a0cc74 Mon Sep 17 00:00:00 2001 From: benesjan Date: Wed, 19 Mar 2025 12:44:49 +0000 Subject: [PATCH 05/10] WIP --- .../aztec-nr/aztec/src/oracle/block_header.nr | 12 ++++------- .../aztec/src/oracle/get_contract_instance.nr | 20 ++++++------------- .../src/oracle/get_membership_witness.nr | 16 +++------------ .../src/private/acvm/oracle/oracle.ts | 20 +++++++++---------- .../txe/src/txe_service/txe_service.ts | 16 +++++++-------- 5 files changed, 30 insertions(+), 54 deletions(-) diff --git a/noir-projects/aztec-nr/aztec/src/oracle/block_header.nr b/noir-projects/aztec-nr/aztec/src/oracle/block_header.nr index 270319405741..65a8e60a4300 100644 --- a/noir-projects/aztec-nr/aztec/src/oracle/block_header.nr +++ b/noir-projects/aztec-nr/aztec/src/oracle/block_header.nr @@ -1,20 +1,16 @@ -use dep::protocol_types::{ - block_header::BlockHeader, - constants::BLOCK_HEADER_LENGTH, - traits::{Deserialize, Hash}, +use protocol_types::{ + block_header::BlockHeader, merkle_tree::root::root_from_sibling_path, traits::Hash, }; -use dep::protocol_types::merkle_tree::root::root_from_sibling_path; use crate::{ context::PrivateContext, oracle::get_membership_witness::get_archive_membership_witness, }; #[oracle(getBlockHeader)] -unconstrained fn get_block_header_at_oracle(_block_number: u32) -> [Field; BLOCK_HEADER_LENGTH] {} +unconstrained fn get_block_header_at_oracle(_block_number: u32) -> BlockHeader {} unconstrained fn get_block_header_at_internal(block_number: u32) -> BlockHeader { - let header = get_block_header_at_oracle(block_number); - BlockHeader::deserialize(header) + get_block_header_at_oracle(block_number) } pub fn get_block_header_at(block_number: u32, context: PrivateContext) -> BlockHeader { diff --git a/noir-projects/aztec-nr/aztec/src/oracle/get_contract_instance.nr b/noir-projects/aztec-nr/aztec/src/oracle/get_contract_instance.nr index 70ce38c43595..543b5c955611 100644 --- a/noir-projects/aztec-nr/aztec/src/oracle/get_contract_instance.nr +++ b/noir-projects/aztec-nr/aztec/src/oracle/get_contract_instance.nr @@ -1,21 +1,14 @@ -use dep::protocol_types::{ - address::AztecAddress, - constants::CONTRACT_INSTANCE_LENGTH, - contract_class_id::ContractClassId, - contract_instance::ContractInstance, - traits::{Deserialize, FromField}, +use protocol_types::{ + address::AztecAddress, contract_class_id::ContractClassId, contract_instance::ContractInstance, + traits::FromField, }; // NOTE: this is for use in private only #[oracle(getContractInstance)] -unconstrained fn get_contract_instance_oracle( - _address: AztecAddress, -) -> [Field; CONTRACT_INSTANCE_LENGTH] {} +unconstrained fn get_contract_instance_oracle(_address: AztecAddress) -> ContractInstance {} // NOTE: this is for use in private only -unconstrained fn get_contract_instance_internal( - address: AztecAddress, -) -> [Field; CONTRACT_INSTANCE_LENGTH] { +unconstrained fn get_contract_instance_internal(address: AztecAddress) -> ContractInstance { get_contract_instance_oracle(address) } @@ -23,8 +16,7 @@ unconstrained fn get_contract_instance_internal( pub fn get_contract_instance(address: AztecAddress) -> ContractInstance { // Safety: The to_address function combines all values in the instance object to produce an address, // so by checking that we get the expected address we validate the entire struct. - let instance = - unsafe { ContractInstance::deserialize(get_contract_instance_internal(address)) }; + let instance = unsafe { get_contract_instance_internal(address) }; assert_eq(instance.to_address(), address); instance diff --git a/noir-projects/aztec-nr/aztec/src/oracle/get_membership_witness.nr b/noir-projects/aztec-nr/aztec/src/oracle/get_membership_witness.nr index 7a6a28b385be..5588a8d31dae 100644 --- a/noir-projects/aztec-nr/aztec/src/oracle/get_membership_witness.nr +++ b/noir-projects/aztec-nr/aztec/src/oracle/get_membership_witness.nr @@ -1,5 +1,4 @@ -use crate::utils::array; -use dep::protocol_types::constants::{ARCHIVE_HEIGHT, NOTE_HASH_TREE_HEIGHT}; +use protocol_types::constants::{ARCHIVE_HEIGHT, NOTE_HASH_TREE_HEIGHT}; global NOTE_HASH_TREE_ID: Field = 1; global ARCHIVE_TREE_ID: Field = 4; @@ -17,20 +16,11 @@ pub struct MembershipWitness { } #[oracle(getMembershipWitness)] -unconstrained fn get_membership_witness_oracle( +unconstrained fn get_membership_witness( _block_number: u32, _tree_id: Field, _leaf_value: Field, -) -> [Field; M] {} - -pub unconstrained fn get_membership_witness( - block_number: u32, - tree_id: Field, - leaf_value: Field, -) -> MembershipWitness { - let fields: [Field; M] = get_membership_witness_oracle(block_number, tree_id, leaf_value); - MembershipWitness { index: fields[0], path: array::subarray(fields, 1) } -} +) -> MembershipWitness {} // Note: get_nullifier_membership_witness function is implemented in get_nullifier_membership_witness.nr diff --git a/yarn-project/simulator/src/private/acvm/oracle/oracle.ts b/yarn-project/simulator/src/private/acvm/oracle/oracle.ts index 0bafb96e7ff5..f34d29130b5f 100644 --- a/yarn-project/simulator/src/private/acvm/oracle/oracle.ts +++ b/yarn-project/simulator/src/private/acvm/oracle/oracle.ts @@ -53,25 +53,23 @@ export class Oracle { return keyValidationRequest.toFields().map(toACVMField); } - async getContractInstance([address]: ACVMField[]): Promise { + async getContractInstance([address]: ACVMField[]): Promise { const instance = await this.typedOracle.getContractInstance(AztecAddress.fromField(Fr.fromString(address))); return [ - [ - instance.salt, - instance.deployer, - instance.currentContractClassId, - instance.initializationHash, - ...instance.publicKeys.toFields(), - ].map(toACVMField), - ]; + instance.salt, + instance.deployer, + instance.currentContractClassId, + instance.initializationHash, + ...instance.publicKeys.toFields(), + ].map(toACVMField); } async getMembershipWitness( [blockNumber]: ACVMField[], [treeId]: ACVMField[], [leafValue]: ACVMField[], - ): Promise { + ): Promise<(ACVMField | ACVMField[])[]> { const parsedBlockNumber = frToNumber(Fr.fromString(blockNumber)); const parsedTreeId = frToNumber(Fr.fromString(treeId)); const parsedLeafValue = Fr.fromString(leafValue); @@ -82,7 +80,7 @@ export class Oracle { `Leaf ${leafValue} not found in the tree ${MerkleTreeId[parsedTreeId]} at block ${parsedBlockNumber}.`, ); } - return witness.map(toACVMField); + return [toACVMField(witness[0]), witness.slice(1).map(toACVMField)]; } async getNullifierMembershipWitness( diff --git a/yarn-project/txe/src/txe_service/txe_service.ts b/yarn-project/txe/src/txe_service/txe_service.ts index 0f82d4288c5d..69d6c539cd0e 100644 --- a/yarn-project/txe/src/txe_service/txe_service.ts +++ b/yarn-project/txe/src/txe_service/txe_service.ts @@ -377,15 +377,15 @@ export class TXEService { async getContractInstance(address: ForeignCallSingle) { const instance = await this.typedOracle.getContractInstance(addressFromSingle(address)); - return toForeignCallResult([ - toArray([ + return toForeignCallResult( + [ instance.salt, instance.deployer.toField(), instance.currentContractClassId, instance.initializationHash, ...instance.publicKeys.toFields(), - ]), - ]); + ].map(toSingle), + ); } async getPublicKeysAndPartialAddress(address: ForeignCallSingle) { @@ -422,7 +422,7 @@ export class TXEService { if (!witness) { throw new Error(`Nullifier membership witness not found at block ${parsedBlockNumber}.`); } - return toForeignCallResult([toArray(witness.toFields())]); + return toForeignCallResult(witness.toNoirRepresentation()); } async getAuthWitness(messageHash: ForeignCallSingle) { @@ -485,7 +485,7 @@ export class TXEService { if (!header) { throw new Error(`Block header not found for block ${blockNumber}.`); } - return toForeignCallResult([toArray(header.toFields())]); + return toForeignCallResult(header.toFields().map(toSingle)); } async getMembershipWitness(blockNumber: ForeignCallSingle, treeId: ForeignCallSingle, leafValue: ForeignCallSingle) { @@ -498,7 +498,7 @@ export class TXEService { `Membership witness in tree ${MerkleTreeId[parsedTreeId]} not found for value ${parsedLeafValue} at block ${parsedBlockNumber}.`, ); } - return toForeignCallResult([toArray(witness)]); + return toForeignCallResult([toSingle(witness[0]), toArray(witness.slice(1))]); } async getLowNullifierMembershipWitness(blockNumber: ForeignCallSingle, nullifier: ForeignCallSingle) { @@ -508,7 +508,7 @@ export class TXEService { if (!witness) { throw new Error(`Low nullifier witness not found for nullifier ${nullifier} at block ${parsedBlockNumber}.`); } - return toForeignCallResult([toArray(witness.toFields())]); + return toForeignCallResult(witness.toNoirRepresentation()); } async getIndexedTaggingSecretAsSender(sender: ForeignCallSingle, recipient: ForeignCallSingle) { From a4e29a77aea8c8d5465bef3cd2eb34304867c80c Mon Sep 17 00:00:00 2001 From: benesjan Date: Wed, 19 Mar 2025 13:00:27 +0000 Subject: [PATCH 06/10] wip --- noir-projects/aztec-nr/aztec/src/oracle/shared_secret.nr | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/noir-projects/aztec-nr/aztec/src/oracle/shared_secret.nr b/noir-projects/aztec-nr/aztec/src/oracle/shared_secret.nr index ba1bb41c7567..646ffe9e378e 100644 --- a/noir-projects/aztec-nr/aztec/src/oracle/shared_secret.nr +++ b/noir-projects/aztec-nr/aztec/src/oracle/shared_secret.nr @@ -1,4 +1,4 @@ -use dep::protocol_types::{address::aztec_address::AztecAddress, point::Point}; +use protocol_types::{address::aztec_address::AztecAddress, point::Point}; // TODO(#12656): return an app-siloed secret + document this #[oracle(getSharedSecret)] From c67557cba11edbc226514b411389fd7441d53c44 Mon Sep 17 00:00:00 2001 From: benesjan Date: Wed, 19 Mar 2025 13:12:41 +0000 Subject: [PATCH 07/10] fix --- .../aztec-nr/aztec/src/state_vars/private_mutable/test.nr | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/noir-projects/aztec-nr/aztec/src/state_vars/private_mutable/test.nr b/noir-projects/aztec-nr/aztec/src/state_vars/private_mutable/test.nr index 0d7a7f8da2f9..09e54751cde4 100644 --- a/noir-projects/aztec-nr/aztec/src/state_vars/private_mutable/test.nr +++ b/noir-projects/aztec-nr/aztec/src/state_vars/private_mutable/test.nr @@ -19,8 +19,8 @@ unconstrained fn in_private( ) -> PrivateMutable { let state_var = PrivateMutable::new(&mut env.private(), storage_slot); - // This oracle is called for its side effects alone - it's always expected to return 0. - let _ = OracleMock::mock("notifyCreatedNote").returns(0); + // This oracle is called for its side effects alone - it does not return anything. + let _ = OracleMock::mock("notifyCreatedNote").returns(()); state_var } From d38602a6543d4eb4983508c036fa11ab22d76a05 Mon Sep 17 00:00:00 2001 From: benesjan Date: Wed, 19 Mar 2025 13:38:22 +0000 Subject: [PATCH 08/10] linking issues --- yarn-project/simulator/src/common/message_load_oracle_inputs.ts | 2 +- yarn-project/stdlib/src/trees/nullifier_membership_witness.ts | 2 +- yarn-project/stdlib/src/trees/public_data_witness.ts | 2 +- 3 files changed, 3 insertions(+), 3 deletions(-) diff --git a/yarn-project/simulator/src/common/message_load_oracle_inputs.ts b/yarn-project/simulator/src/common/message_load_oracle_inputs.ts index 2a8e324c73e2..e5f65d15cffb 100644 --- a/yarn-project/simulator/src/common/message_load_oracle_inputs.ts +++ b/yarn-project/simulator/src/common/message_load_oracle_inputs.ts @@ -17,7 +17,7 @@ export class MessageLoadOracleInputs { * Returns a representation of the public data witness as expected by intrinsic Noir deserialization. */ public toNoirRepresentation(): (string | string[])[] { - // TODO(benesjan): remove the stupid as string conversion by modifying ForeignCallOutput type in acvm.js + // TODO(#12874): remove the stupid as string conversion by modifying ForeignCallOutput type in acvm.js return [new Fr(this.index).toString() as string, this.siblingPath.toFields().map(fr => fr.toString()) as string[]]; } } diff --git a/yarn-project/stdlib/src/trees/nullifier_membership_witness.ts b/yarn-project/stdlib/src/trees/nullifier_membership_witness.ts index 0aba380940a4..521f715b549e 100644 --- a/yarn-project/stdlib/src/trees/nullifier_membership_witness.ts +++ b/yarn-project/stdlib/src/trees/nullifier_membership_witness.ts @@ -61,7 +61,7 @@ export class NullifierMembershipWitness { * Returns a representation of the nullifier membership witness as expected by intrinsic Noir deserialization. */ public toNoirRepresentation(): (string | string[])[] { - // TODO(benesjan): remove the stupid as string conversion by modifying ForeignCallOutput type in acvm.js + // TODO(#12874): remove the stupid as string conversion by modifying ForeignCallOutput type in acvm.js return [ new Fr(this.index).toString() as string, ...(this.leafPreimage.toFields().map(fr => fr.toString()) as string[]), diff --git a/yarn-project/stdlib/src/trees/public_data_witness.ts b/yarn-project/stdlib/src/trees/public_data_witness.ts index ac76613a43f2..3ae48769057b 100644 --- a/yarn-project/stdlib/src/trees/public_data_witness.ts +++ b/yarn-project/stdlib/src/trees/public_data_witness.ts @@ -62,7 +62,7 @@ export class PublicDataWitness { * Returns a representation of the public data witness as expected by intrinsic Noir deserialization. */ public toNoirRepresentation(): (string | string[])[] { - // TODO(benesjan): remove the stupid as string conversion by modifying ForeignCallOutput type in acvm.js + // TODO(#12874): remove the stupid as string conversion by modifying ForeignCallOutput type in acvm.js return [ new Fr(this.index).toString() as string, new Fr(this.leafPreimage.slot).toString() as string, From 593c1d8d425953157a78c1d474b7f436e7b0ec46 Mon Sep 17 00:00:00 2001 From: benesjan Date: Wed, 19 Mar 2025 13:45:08 +0000 Subject: [PATCH 09/10] nuking more stupid utils --- .../simulator/src/private/acvm/deserialize.ts | 22 ++----------- .../src/private/acvm/oracle/oracle.ts | 32 +++++++++---------- 2 files changed, 18 insertions(+), 36 deletions(-) diff --git a/yarn-project/simulator/src/private/acvm/deserialize.ts b/yarn-project/simulator/src/private/acvm/deserialize.ts index f562d6a6ca8b..77423ca5d6ad 100644 --- a/yarn-project/simulator/src/private/acvm/deserialize.ts +++ b/yarn-project/simulator/src/private/acvm/deserialize.ts @@ -3,24 +3,6 @@ import { hexToBuffer } from '@aztec/foundation/string'; import type { ACVMField, ACVMWitness } from './acvm_types.js'; -/** - * Converts a field to a number. - * @param fr - The field to convert. - * @returns The number. - * TODO(#4102): Nuke this once block number is big int. - */ -export function frToNumber(fr: Fr): number { - return Number(fr.value); -} - -/** - * Converts a field to a boolean. - * @param fr - The field to convert. - */ -export function frToBoolean(fr: Fr): boolean { - return fr.toBigInt() === BigInt(1); -} - /** * Converts a Noir BoundedVec of Fields into an Fr array. Note that BoundedVecs are structs, and therefore translated as * two separate ACVMField values (an array and a single field). @@ -30,7 +12,7 @@ export function frToBoolean(fr: Fr): boolean { * @returns An array with the same content as the Noir version. Elements past the length are discarded. */ export function fromBoundedVec(storage: ACVMField[], length: ACVMField): Fr[] { - return storage.slice(0, frToNumber(Fr.fromString(length))).map(Fr.fromString); + return storage.slice(0, Fr.fromString(length).toNumber()).map(Fr.fromString); } /** @@ -47,7 +29,7 @@ export function fromUintBoundedVec(storage: ACVMField[], length: ACVMField, uint throw new Error(`u${uintBitSize} is not a supported type in Noir`); } const uintByteSize = uintBitSize / 8; - const boundedStorage = storage.slice(0, frToNumber(Fr.fromString(length))); + const boundedStorage = storage.slice(0, Fr.fromString(length).toNumber()); return Buffer.concat(boundedStorage.map(str => hexToBuffer(str).subarray(-uintByteSize))); } diff --git a/yarn-project/simulator/src/private/acvm/oracle/oracle.ts b/yarn-project/simulator/src/private/acvm/oracle/oracle.ts index f34d29130b5f..d791679c5ae0 100644 --- a/yarn-project/simulator/src/private/acvm/oracle/oracle.ts +++ b/yarn-project/simulator/src/private/acvm/oracle/oracle.ts @@ -5,7 +5,7 @@ import { ContractClassLog, LogWithTxData } from '@aztec/stdlib/logs'; import { MerkleTreeId } from '@aztec/stdlib/trees'; import type { ACVMField } from '../acvm_types.js'; -import { frToBoolean, frToNumber, fromBoundedVec, fromUintArray, fromUintBoundedVec } from '../deserialize.js'; +import { fromBoundedVec, fromUintArray, fromUintBoundedVec } from '../deserialize.js'; import { bufferToBoundedVec, toACVMField, toACVMFieldSingleOrArray } from '../serialize.js'; import type { TypedOracle } from './typed_oracle.js'; @@ -70,8 +70,8 @@ export class Oracle { [treeId]: ACVMField[], [leafValue]: ACVMField[], ): Promise<(ACVMField | ACVMField[])[]> { - const parsedBlockNumber = frToNumber(Fr.fromString(blockNumber)); - const parsedTreeId = frToNumber(Fr.fromString(treeId)); + const parsedBlockNumber = Fr.fromString(blockNumber).toNumber(); + const parsedTreeId = Fr.fromString(treeId).toNumber(); const parsedLeafValue = Fr.fromString(leafValue); const witness = await this.typedOracle.getMembershipWitness(parsedBlockNumber, parsedTreeId, parsedLeafValue); @@ -87,7 +87,7 @@ export class Oracle { [blockNumber]: ACVMField[], [nullifier]: ACVMField[], // nullifier, we try to find the witness for (to prove inclusion) ): Promise<(ACVMField | ACVMField[])[]> { - const parsedBlockNumber = frToNumber(Fr.fromString(blockNumber)); + const parsedBlockNumber = Fr.fromString(blockNumber).toNumber(); const parsedNullifier = Fr.fromString(nullifier); const witness = await this.typedOracle.getNullifierMembershipWitness(parsedBlockNumber, parsedNullifier); @@ -101,7 +101,7 @@ export class Oracle { [blockNumber]: ACVMField[], [nullifier]: ACVMField[], // nullifier, we try to find the low nullifier witness for (to prove non-inclusion) ): Promise<(ACVMField | ACVMField[])[]> { - const parsedBlockNumber = frToNumber(Fr.fromString(blockNumber)); + const parsedBlockNumber = Fr.fromString(blockNumber).toNumber(); const parsedNullifier = Fr.fromString(nullifier); const witness = await this.typedOracle.getLowNullifierMembershipWitness(parsedBlockNumber, parsedNullifier); @@ -117,7 +117,7 @@ export class Oracle { [blockNumber]: ACVMField[], [leafSlot]: ACVMField[], ): Promise<(ACVMField | ACVMField[])[]> { - const parsedBlockNumber = frToNumber(Fr.fromString(blockNumber)); + const parsedBlockNumber = Fr.fromString(blockNumber).toNumber(); const parsedLeafSlot = Fr.fromString(leafSlot); const witness = await this.typedOracle.getPublicDataWitness(parsedBlockNumber, parsedLeafSlot); @@ -128,7 +128,7 @@ export class Oracle { } async getBlockHeader([blockNumber]: ACVMField[]): Promise { - const parsedBlockNumber = frToNumber(Fr.fromString(blockNumber)); + const parsedBlockNumber = Fr.fromString(blockNumber).toNumber(); const header = await this.typedOracle.getBlockHeader(parsedBlockNumber); if (!header) { @@ -314,8 +314,8 @@ export class Oracle { AztecAddress.fromField(Fr.fromString(contractAddress)), FunctionSelector.fromField(Fr.fromString(functionSelector)), Fr.fromString(argsHash), - frToNumber(Fr.fromString(sideEffectCounter)), - frToBoolean(Fr.fromString(isStaticCall)), + Fr.fromString(sideEffectCounter).toNumber(), + Fr.fromString(isStaticCall).toBool(), ); return [[endSideEffectCounter, returnsHash].map(toACVMField)]; } @@ -331,8 +331,8 @@ export class Oracle { AztecAddress.fromString(contractAddress), FunctionSelector.fromField(Fr.fromString(functionSelector)), Fr.fromString(argsHash), - frToNumber(Fr.fromString(sideEffectCounter)), - frToBoolean(Fr.fromString(isStaticCall)), + Fr.fromString(sideEffectCounter).toNumber(), + Fr.fromString(isStaticCall).toBool(), ); return [toACVMField(newArgsHash)]; } @@ -348,14 +348,14 @@ export class Oracle { AztecAddress.fromString(contractAddress), FunctionSelector.fromField(Fr.fromString(functionSelector)), Fr.fromString(argsHash), - frToNumber(Fr.fromString(sideEffectCounter)), - frToBoolean(Fr.fromString(isStaticCall)), + Fr.fromString(sideEffectCounter).toNumber(), + Fr.fromString(isStaticCall).toBool(), ); return [toACVMField(newArgsHash)]; } notifySetMinRevertibleSideEffectCounter([minRevertibleSideEffectCounter]: ACVMField[]): Promise { - this.typedOracle.notifySetMinRevertibleSideEffectCounter(frToNumber(Fr.fromString(minRevertibleSideEffectCounter))); + this.typedOracle.notifySetMinRevertibleSideEffectCounter(Fr.fromString(minRevertibleSideEffectCounter).toNumber()); return Promise.resolve([]); } @@ -441,7 +441,7 @@ export class Oracle { // with two fields: `some` (a boolean) and `value` (a field array in this case). if (values === null) { // No data was found so we set `some` to 0 and pad `value` with zeros get the correct return size. - return [toACVMField(0), Array(frToNumber(Fr.fromString(tSize))).fill(toACVMField(0))]; + return [toACVMField(0), Array(Fr.fromString(tSize).toNumber()).fill(toACVMField(0))]; } else { // Data was found so we set `some` to 1 and return it along with `value`. return [toACVMField(1), values.map(toACVMField)]; @@ -463,7 +463,7 @@ export class Oracle { AztecAddress.fromField(Fr.fromString(contractAddress)), Fr.fromString(srcSlot), Fr.fromString(dstSlot), - frToNumber(Fr.fromString(numEntries)), + Fr.fromString(numEntries).toNumber(), ); return []; } From 2673a8ca94295da6ec742de2946dea460468a3af Mon Sep 17 00:00:00 2001 From: benesjan Date: Wed, 19 Mar 2025 13:48:50 +0000 Subject: [PATCH 10/10] migration notes --- docs/docs/migration_notes.md | 4 ++++ 1 file changed, 4 insertions(+) diff --git a/docs/docs/migration_notes.md b/docs/docs/migration_notes.md index f71ec322758b..a73799aaf364 100644 --- a/docs/docs/migration_notes.md +++ b/docs/docs/migration_notes.md @@ -8,6 +8,10 @@ Aztec is in full-speed development. Literally every version breaks compatibility ## TBD +## [aztec.js] AztecNode.getPublicDataTreeWitness renamed as AztecNode.getPublicDataWitness + +This change was done to have consistent naming across codebase. + ## [aztec.js] Wallet interface and Authwit management The `Wallet` interface in `aztec.js` is undergoing transformations, trying to be friendlier to wallet builders and reducing the surface of its API. This means `Wallet` no longer extends `PXE`, and instead just implements a subset of the methods of the former. This is NOT going to be its final form, but paves the way towards better interfaces and starts to clarify what the responsibilities of the wallet are: