From 5d538122cb11288f04fb80b1f25c0e1e1bb1ce08 Mon Sep 17 00:00:00 2001 From: Nicolas Chamo Date: Tue, 10 Mar 2026 07:35:51 -0300 Subject: [PATCH 1/4] feat(pxe)!: pass BoundedVec sizes as oracle params (#21176) --- .../aztec/src/messages/processing/mod.nr | 2 ++ .../aztec/src/oracle/message_processing.nr | 6 ++++ .../event_validation_request.test.ts | 29 ++++++++++++++++++- .../noir-structs/event_validation_request.ts | 13 +++++---- .../noir-structs/log_retrieval_response.ts | 5 +--- .../note_validation_request.test.ts | 11 ++++--- .../noir-structs/note_validation_request.ts | 9 ++---- .../oracle/interfaces.ts | 2 ++ .../oracle/oracle.ts | 4 +++ .../oracle/utility_execution_oracle.ts | 6 ++-- yarn-project/pxe/src/oracle_version.ts | 2 +- yarn-project/txe/src/rpc_translator.ts | 6 ++++ 12 files changed, 70 insertions(+), 25 deletions(-) diff --git a/noir-projects/aztec-nr/aztec/src/messages/processing/mod.nr b/noir-projects/aztec-nr/aztec/src/messages/processing/mod.nr index 1dcf2c9e4257..e082b36aa262 100644 --- a/noir-projects/aztec-nr/aztec/src/messages/processing/mod.nr +++ b/noir-projects/aztec-nr/aztec/src/messages/processing/mod.nr @@ -145,6 +145,8 @@ pub unconstrained fn validate_and_store_enqueued_notes_and_events(contract_addre contract_address, NOTE_VALIDATION_REQUESTS_ARRAY_BASE_SLOT, EVENT_VALIDATION_REQUESTS_ARRAY_BASE_SLOT, + MAX_NOTE_PACKED_LEN as Field, + MAX_EVENT_SERIALIZED_LEN as Field, ); } diff --git a/noir-projects/aztec-nr/aztec/src/oracle/message_processing.nr b/noir-projects/aztec-nr/aztec/src/oracle/message_processing.nr index d0582872b23d..a176ce72a3c6 100644 --- a/noir-projects/aztec-nr/aztec/src/oracle/message_processing.nr +++ b/noir-projects/aztec-nr/aztec/src/oracle/message_processing.nr @@ -15,11 +15,15 @@ pub(crate) unconstrained fn validate_and_store_enqueued_notes_and_events( contract_address: AztecAddress, note_validation_requests_array_base_slot: Field, event_validation_requests_array_base_slot: Field, + max_note_packed_len: Field, + max_event_serialized_len: Field, ) { validate_and_store_enqueued_notes_and_events_oracle( contract_address, note_validation_requests_array_base_slot, event_validation_requests_array_base_slot, + max_note_packed_len, + max_event_serialized_len, ); } @@ -28,6 +32,8 @@ unconstrained fn validate_and_store_enqueued_notes_and_events_oracle( contract_address: AztecAddress, note_validation_requests_array_base_slot: Field, event_validation_requests_array_base_slot: Field, + max_note_packed_len: Field, + max_event_serialized_len: Field, ) {} pub(crate) unconstrained fn bulk_retrieve_logs( diff --git a/yarn-project/pxe/src/contract_function_simulator/noir-structs/event_validation_request.test.ts b/yarn-project/pxe/src/contract_function_simulator/noir-structs/event_validation_request.test.ts index 63816730790f..3b5d2ad06725 100644 --- a/yarn-project/pxe/src/contract_function_simulator/noir-structs/event_validation_request.test.ts +++ b/yarn-project/pxe/src/contract_function_simulator/noir-structs/event_validation_request.test.ts @@ -27,7 +27,7 @@ describe('EventValidationRequest', () => { 8, // recipient ].map(n => new Fr(n)); - const request = EventValidationRequest.fromFields(serialized); + const request = EventValidationRequest.fromFields(serialized, 10); expect(request.contractAddress).toEqual(AztecAddress.fromBigInt(1n)); expect(request.eventTypeId).toEqual(new EventSelector(2)); @@ -37,4 +37,31 @@ describe('EventValidationRequest', () => { expect(request.txHash).toEqual(TxHash.fromBigInt(7n)); expect(request.recipient).toEqual(AztecAddress.fromBigInt(8n)); }); + + it('throws if fed more fields than expected', () => { + const serialized = [ + 1, // contract_address + 2, // event_type_id + 3, // randomness + 4, // serialized_event[0] + 5, // serialized_event[1] + 0, // serialized_event padding (11 storage fields total, but maxEventSerializedLen=10) + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 2, // bounded_vec_len + 6, // event_commitment + 7, // tx_hash + 8, // recipient + ].map(n => new Fr(n)); + + expect(() => EventValidationRequest.fromFields(serialized, 10)).toThrow( + 'Error converting array of fields to EventValidationRequest: expected 17 fields but received 18 (maxEventSerializedLen=10).', + ); + }); }); diff --git a/yarn-project/pxe/src/contract_function_simulator/noir-structs/event_validation_request.ts b/yarn-project/pxe/src/contract_function_simulator/noir-structs/event_validation_request.ts index 8a33dd551923..ccf4b7a944ae 100644 --- a/yarn-project/pxe/src/contract_function_simulator/noir-structs/event_validation_request.ts +++ b/yarn-project/pxe/src/contract_function_simulator/noir-structs/event_validation_request.ts @@ -4,9 +4,6 @@ import { EventSelector } from '@aztec/stdlib/abi'; import { AztecAddress } from '@aztec/stdlib/aztec-address'; import { TxHash } from '@aztec/stdlib/tx'; -// TODO(#14617): should we compute this from constants? This value is aztec-nr specific. -const MAX_EVENT_SERIALIZED_LEN = 10; - /** * Intermediate struct used to perform batch event validation by PXE. The `utilityValidateAndStoreEnqueuedNotesAndEvents` oracle * expects for values of this type to be stored in a `CapsuleArray`. @@ -22,7 +19,7 @@ export class EventValidationRequest { public recipient: AztecAddress, ) {} - static fromFields(fields: Fr[] | FieldReader): EventValidationRequest { + static fromFields(fields: Fr[], maxEventSerializedLen: number): EventValidationRequest { const reader = FieldReader.asReader(fields); const contractAddress = AztecAddress.fromField(reader.readField()); @@ -30,7 +27,7 @@ export class EventValidationRequest { const randomness = reader.readField(); - const eventStorage = reader.readFieldArray(MAX_EVENT_SERIALIZED_LEN); + const eventStorage = reader.readFieldArray(maxEventSerializedLen); const eventLen = reader.readField().toNumber(); const serializedEvent = eventStorage.slice(0, eventLen); @@ -38,6 +35,12 @@ export class EventValidationRequest { const txHash = TxHash.fromField(reader.readField()); const recipient = AztecAddress.fromField(reader.readField()); + if (reader.remainingFields() !== 0) { + throw new Error( + `Error converting array of fields to EventValidationRequest: expected ${reader.cursor} fields but received ${fields.length} (maxEventSerializedLen=${maxEventSerializedLen}).`, + ); + } + return new EventValidationRequest( contractAddress, eventTypeId, diff --git a/yarn-project/pxe/src/contract_function_simulator/noir-structs/log_retrieval_response.ts b/yarn-project/pxe/src/contract_function_simulator/noir-structs/log_retrieval_response.ts index 020270e8821a..baa4b3c58e39 100644 --- a/yarn-project/pxe/src/contract_function_simulator/noir-structs/log_retrieval_response.ts +++ b/yarn-project/pxe/src/contract_function_simulator/noir-structs/log_retrieval_response.ts @@ -3,10 +3,7 @@ import { range } from '@aztec/foundation/array'; import { Fr } from '@aztec/foundation/curves/bn254'; import type { TxHash } from '@aztec/stdlib/tx'; -import { MAX_NOTE_PACKED_LEN } from './note_validation_request.js'; - -const MAX_PUBLIC_LOG_LEN_FOR_NOTE_COMPLETION = MAX_NOTE_PACKED_LEN; -const MAX_LOG_CONTENT_LEN = Math.max(MAX_PUBLIC_LOG_LEN_FOR_NOTE_COMPLETION, PRIVATE_LOG_CIPHERTEXT_LEN); +const MAX_LOG_CONTENT_LEN = PRIVATE_LOG_CIPHERTEXT_LEN; /** * Intermediate struct used to perform batch log retrieval by PXE. The `utilityBulkRetrieveLogs` oracle stores values of this diff --git a/yarn-project/pxe/src/contract_function_simulator/noir-structs/note_validation_request.test.ts b/yarn-project/pxe/src/contract_function_simulator/noir-structs/note_validation_request.test.ts index 4ac64de1d016..686d57c0e74a 100644 --- a/yarn-project/pxe/src/contract_function_simulator/noir-structs/note_validation_request.test.ts +++ b/yarn-project/pxe/src/contract_function_simulator/noir-structs/note_validation_request.test.ts @@ -19,7 +19,7 @@ describe('NoteValidationRequest', () => { '0x0000000000000000000000000000000000000000000000000000000000000000', '0x0000000000000000000000000000000000000000000000000000000000000000', '0x0000000000000000000000000000000000000000000000000000000000000000', - '0x0000000000000000000000000000000000000000000000000000000000000000', // content end (MAX_NOTE_PACKED_LEN = 8) + '0x0000000000000000000000000000000000000000000000000000000000000000', // content end (8 storage fields) '0x0000000000000000000000000000000000000000000000000000000000000002', // content length '0x0000000000000000000000000000000000000000000000000000000000000006', // note hash '0x0000000000000000000000000000000000000000000000000000000000000007', // nullifier @@ -27,7 +27,7 @@ describe('NoteValidationRequest', () => { '0x0000000000000000000000000000000000000000000000000000000000000009', // recipient ].map(Fr.fromHexString); - const request = NoteValidationRequest.fromFields(serialized); + const request = NoteValidationRequest.fromFields(serialized, 8); expect(request.contractAddress).toEqual(AztecAddress.fromBigInt(1n)); expect(request.owner).toEqual(AztecAddress.fromBigInt(50n)); @@ -56,8 +56,7 @@ describe('NoteValidationRequest', () => { '0x0000000000000000000000000000000000000000000000000000000000000000', '0x0000000000000000000000000000000000000000000000000000000000000000', '0x0000000000000000000000000000000000000000000000000000000000000000', - '0x0000000000000000000000000000000000000000000000000000000000000000', // content end (MAX_NOTE_PACKED_LEN = 8) - '0x0000000000000000000000000000000000000000000000000000000000000000', // extra field beyond MAX_NOTE_PACKED_LEN, this is a malformed serialization + '0x0000000000000000000000000000000000000000000000000000000000000000', // content end (9 storage fields, but maxNotePackedLen=8) '0x0000000000000000000000000000000000000000000000000000000000000002', // content length '0x0000000000000000000000000000000000000000000000000000000000000006', // note hash '0x0000000000000000000000000000000000000000000000000000000000000007', // nullifier @@ -65,8 +64,8 @@ describe('NoteValidationRequest', () => { '0x0000000000000000000000000000000000000000000000000000000000000009', // recipient ].map(Fr.fromHexString); - expect(() => NoteValidationRequest.fromFields(serialized)).toThrow( - /Error converting array of fields to NoteValidationRequest/, + expect(() => NoteValidationRequest.fromFields(serialized, 8)).toThrow( + 'Error converting array of fields to NoteValidationRequest: expected 18 fields but received 19 (maxNotePackedLen=8).', ); }); }); diff --git a/yarn-project/pxe/src/contract_function_simulator/noir-structs/note_validation_request.ts b/yarn-project/pxe/src/contract_function_simulator/noir-structs/note_validation_request.ts index 02ebba99e96e..286ad25ef377 100644 --- a/yarn-project/pxe/src/contract_function_simulator/noir-structs/note_validation_request.ts +++ b/yarn-project/pxe/src/contract_function_simulator/noir-structs/note_validation_request.ts @@ -3,9 +3,6 @@ import { FieldReader } from '@aztec/foundation/serialize'; import { AztecAddress } from '@aztec/stdlib/aztec-address'; import { TxHash } from '@aztec/stdlib/tx'; -// TODO(#14617): should we compute this from constants? This value is aztec-nr specific. -export const MAX_NOTE_PACKED_LEN = 8; - /** * Intermediate struct used to perform batch note validation by PXE. The `utilityValidateAndStoreEnqueuedNotesAndEvents` oracle * expects for values of this type to be stored in a `CapsuleArray`. @@ -24,7 +21,7 @@ export class NoteValidationRequest { public recipient: AztecAddress, ) {} - static fromFields(fields: Fr[] | FieldReader): NoteValidationRequest { + static fromFields(fields: Fr[], maxNotePackedLen: number): NoteValidationRequest { const reader = FieldReader.asReader(fields); const contractAddress = AztecAddress.fromField(reader.readField()); @@ -33,7 +30,7 @@ export class NoteValidationRequest { const randomness = reader.readField(); const noteNonce = reader.readField(); - const contentStorage = reader.readFieldArray(MAX_NOTE_PACKED_LEN); + const contentStorage = reader.readFieldArray(maxNotePackedLen); const contentLen = reader.readField().toNumber(); const content = contentStorage.slice(0, contentLen); @@ -44,7 +41,7 @@ export class NoteValidationRequest { if (reader.remainingFields() !== 0) { throw new Error( - `Error converting array of fields to NoteValidationRequest. Hint: check that MAX_NOTE_PACKED_LEN is consistent with private_notes::MAX_NOTE_PACKED_LEN in Aztec-nr.`, + `Error converting array of fields to NoteValidationRequest: expected ${reader.cursor} fields but received ${fields.length} (maxNotePackedLen=${maxNotePackedLen}).`, ); } diff --git a/yarn-project/pxe/src/contract_function_simulator/oracle/interfaces.ts b/yarn-project/pxe/src/contract_function_simulator/oracle/interfaces.ts index 9e9a14805f57..7c03e1eb8bd8 100644 --- a/yarn-project/pxe/src/contract_function_simulator/oracle/interfaces.ts +++ b/yarn-project/pxe/src/contract_function_simulator/oracle/interfaces.ts @@ -124,6 +124,8 @@ export interface IUtilityExecutionOracle { contractAddress: AztecAddress, noteValidationRequestsArrayBaseSlot: Fr, eventValidationRequestsArrayBaseSlot: Fr, + maxNotePackedLen: number, + maxEventSerializedLen: number, ): Promise; utilityBulkRetrieveLogs( contractAddress: AztecAddress, diff --git a/yarn-project/pxe/src/contract_function_simulator/oracle/oracle.ts b/yarn-project/pxe/src/contract_function_simulator/oracle/oracle.ts index ebfc888b4eab..217c4d9290c2 100644 --- a/yarn-project/pxe/src/contract_function_simulator/oracle/oracle.ts +++ b/yarn-project/pxe/src/contract_function_simulator/oracle/oracle.ts @@ -512,11 +512,15 @@ export class Oracle { [contractAddress]: ACVMField[], [noteValidationRequestsArrayBaseSlot]: ACVMField[], [eventValidationRequestsArrayBaseSlot]: ACVMField[], + [maxNotePackedLen]: ACVMField[], + [maxEventSerializedLen]: ACVMField[], ): Promise { await this.handlerAsUtility().utilityValidateAndStoreEnqueuedNotesAndEvents( AztecAddress.fromString(contractAddress), Fr.fromString(noteValidationRequestsArrayBaseSlot), Fr.fromString(eventValidationRequestsArrayBaseSlot), + Fr.fromString(maxNotePackedLen).toNumber(), + Fr.fromString(maxEventSerializedLen).toNumber(), ); return []; diff --git a/yarn-project/pxe/src/contract_function_simulator/oracle/utility_execution_oracle.ts b/yarn-project/pxe/src/contract_function_simulator/oracle/utility_execution_oracle.ts index 9e0d38befcba..085bd059366f 100644 --- a/yarn-project/pxe/src/contract_function_simulator/oracle/utility_execution_oracle.ts +++ b/yarn-project/pxe/src/contract_function_simulator/oracle/utility_execution_oracle.ts @@ -458,6 +458,8 @@ export class UtilityExecutionOracle implements IMiscOracle, IUtilityExecutionOra contractAddress: AztecAddress, noteValidationRequestsArrayBaseSlot: Fr, eventValidationRequestsArrayBaseSlot: Fr, + maxNotePackedLen: number, + maxEventSerializedLen: number, ) { // TODO(#10727): allow other contracts to store notes if (!this.contractAddress.equals(contractAddress)) { @@ -468,11 +470,11 @@ export class UtilityExecutionOracle implements IMiscOracle, IUtilityExecutionOra // faster as we don't need to wait for the network round-trip. const noteValidationRequests = ( await this.capsuleStore.readCapsuleArray(contractAddress, noteValidationRequestsArrayBaseSlot, this.jobId) - ).map(NoteValidationRequest.fromFields); + ).map(fields => NoteValidationRequest.fromFields(fields, maxNotePackedLen)); const eventValidationRequests = ( await this.capsuleStore.readCapsuleArray(contractAddress, eventValidationRequestsArrayBaseSlot, this.jobId) - ).map(EventValidationRequest.fromFields); + ).map(fields => EventValidationRequest.fromFields(fields, maxEventSerializedLen)); const noteService = new NoteService(this.noteStore, this.aztecNode, this.anchorBlockHeader, this.jobId); const noteStorePromises = noteValidationRequests.map(request => diff --git a/yarn-project/pxe/src/oracle_version.ts b/yarn-project/pxe/src/oracle_version.ts index 5f6dd5abc335..a4a23d74b1c2 100644 --- a/yarn-project/pxe/src/oracle_version.ts +++ b/yarn-project/pxe/src/oracle_version.ts @@ -9,4 +9,4 @@ export const ORACLE_VERSION = 12; /// This hash is computed as by hashing the Oracle interface and it is used to detect when the Oracle interface changes, /// which in turn implies that you need to update the ORACLE_VERSION constant in this file and in /// `noir-projects/aztec-nr/aztec/src/oracle/version.nr`. -export const ORACLE_INTERFACE_HASH = '666a8a7fc697f72b29dbf0ae7464db269cf5afa019acac8861f814543147dbb4'; +export const ORACLE_INTERFACE_HASH = '34238ab576c377b4ffc1ddbf557560f07a66baf879920191897bc784fa5a97ee'; diff --git a/yarn-project/txe/src/rpc_translator.ts b/yarn-project/txe/src/rpc_translator.ts index 55deeb05b91e..5b1e960e83cb 100644 --- a/yarn-project/txe/src/rpc_translator.ts +++ b/yarn-project/txe/src/rpc_translator.ts @@ -718,15 +718,21 @@ export class RPCTranslator { foreignContractAddress: ForeignCallSingle, foreignNoteValidationRequestsArrayBaseSlot: ForeignCallSingle, foreignEventValidationRequestsArrayBaseSlot: ForeignCallSingle, + foreignMaxNotePackedLen: ForeignCallSingle, + foreignMaxEventSerializedLen: ForeignCallSingle, ) { const contractAddress = AztecAddress.fromField(fromSingle(foreignContractAddress)); const noteValidationRequestsArrayBaseSlot = fromSingle(foreignNoteValidationRequestsArrayBaseSlot); const eventValidationRequestsArrayBaseSlot = fromSingle(foreignEventValidationRequestsArrayBaseSlot); + const maxNotePackedLen = fromSingle(foreignMaxNotePackedLen).toNumber(); + const maxEventSerializedLen = fromSingle(foreignMaxEventSerializedLen).toNumber(); await this.handlerAsUtility().utilityValidateAndStoreEnqueuedNotesAndEvents( contractAddress, noteValidationRequestsArrayBaseSlot, eventValidationRequestsArrayBaseSlot, + maxNotePackedLen, + maxEventSerializedLen, ); return toForeignCallResult([]); From 4b04033e244f15ccdc4fad14684f7433b1b8f986 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Jan=20Bene=C5=A1?= Date: Tue, 10 Mar 2026 16:50:55 +0700 Subject: [PATCH 2/4] refactor: deduplicate MembershipWitness struct (#21244) --- .../aztec-nr/aztec/src/history/note.nr | 2 +- .../aztec-nr/aztec/src/oracle/block_header.nr | 2 +- .../src/oracle/get_membership_witness.nr | 26 +++++-------------- .../get_nullifier_membership_witness.nr | 13 +++++++--- .../types/src/merkle_tree/membership.nr | 4 +-- 5 files changed, 20 insertions(+), 27 deletions(-) diff --git a/noir-projects/aztec-nr/aztec/src/history/note.nr b/noir-projects/aztec-nr/aztec/src/history/note.nr index de62753b9248..8239eb85c65d 100644 --- a/noir-projects/aztec-nr/aztec/src/history/note.nr +++ b/noir-projects/aztec-nr/aztec/src/history/note.nr @@ -36,7 +36,7 @@ where // don't even care _where_ in the tree it is stored. This is because entries in the note hash tree are unique. assert_eq( block_header.state.partial.note_hash_tree.root, - root_from_sibling_path(unique_note_hash, witness.index, witness.path), + root_from_sibling_path(unique_note_hash, witness.leaf_index, witness.sibling_path), "Proving note inclusion failed", ); 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 99fd5edcbc77..1bbb152fd7ee 100644 --- a/noir-projects/aztec-nr/aztec/src/oracle/block_header.nr +++ b/noir-projects/aztec-nr/aztec/src/oracle/block_header.nr @@ -61,7 +61,7 @@ fn constrain_get_block_header_at_internal( // 3) Check that the block is in the archive (i.e. the witness is valid) assert_eq( anchor_block_header.last_archive.root, - root_from_sibling_path(block_hash, witness.index, witness.path), + root_from_sibling_path(block_hash, witness.leaf_index, witness.sibling_path), "Proving membership of a block in archive failed", ); 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 156524b07d7a..337c75835ca7 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,33 +1,21 @@ use crate::protocol::{ abis::block_header::BlockHeader, constants::{ARCHIVE_HEIGHT, NOTE_HASH_TREE_HEIGHT}, - traits::{Deserialize, Hash, Serialize}, + merkle_tree::MembershipWitness, + traits::Hash, }; -// Note: We have M here because we need to somehow set it when calling get_membership_witness function and one way to -// do it is to set M here and then set type of the return param, e.g.: -// -// `let witness: MembershipWitness = get_membership_witness(...);` -// -// Another way to do it would be to add "type_hint: [Field; T]" as argument to `get_membership_witness` but that's a -// bit too boilerplatey for my taste. -#[derive(Deserialize, Eq, Serialize)] -pub struct MembershipWitness { - pub index: Field, - pub path: [Field; N], -} - -#[oracle(utilityGetNoteHashMembershipWitness)] +#[oracle(aztec_utl_getNoteHashMembershipWitness)] unconstrained fn get_note_hash_membership_witness_oracle( anchor_block_hash: Field, note_hash: Field, -) -> MembershipWitness {} +) -> MembershipWitness {} #[oracle(utilityGetBlockHashMembershipWitness)] unconstrained fn get_block_hash_membership_witness_oracle( anchor_block_hash: Field, block_hash: Field, -) -> MembershipWitness {} +) -> MembershipWitness {} // Note: get_nullifier_membership_witness function is implemented in get_nullifier_membership_witness.nr @@ -36,7 +24,7 @@ unconstrained fn get_block_hash_membership_witness_oracle( pub unconstrained fn get_note_hash_membership_witness( anchor_block_header: BlockHeader, note_hash: Field, -) -> MembershipWitness { +) -> MembershipWitness { let anchor_block_hash = anchor_block_header.hash(); get_note_hash_membership_witness_oracle(anchor_block_hash, note_hash) } @@ -48,7 +36,7 @@ pub unconstrained fn get_note_hash_membership_witness( pub unconstrained fn get_block_hash_membership_witness( anchor_block_header: BlockHeader, block_hash: Field, -) -> MembershipWitness { +) -> MembershipWitness { let anchor_block_hash = anchor_block_header.hash(); get_block_hash_membership_witness_oracle(anchor_block_hash, block_hash) } 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 71a2bb2b98b4..c9dc95850707 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 @@ -17,8 +17,12 @@ unconstrained fn get_low_nullifier_membership_witness_oracle( _nullifier: Field, ) -> 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) +/// Returns a membership witness for the low nullifier of `nullifier` in the nullifier tree whose root is defined in +/// `block_header`. +/// +/// The low nullifier is the leaf with the largest value that is still smaller than `nullifier`. This is used to prove +/// non-inclusion: if the low nullifier's `next_value` is greater than `nullifier`, then `nullifier` is not in the +/// tree. pub unconstrained fn get_low_nullifier_membership_witness( block_header: BlockHeader, nullifier: Field, @@ -33,8 +37,9 @@ unconstrained fn get_nullifier_membership_witness_oracle( _nullifier: Field, ) -> 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) +/// Returns a membership witness for `nullifier` in the nullifier tree whose root is defined in `block_header`. +/// +/// This is used to prove that a nullifier exists in the tree (inclusion proof). pub unconstrained fn get_nullifier_membership_witness( block_header: BlockHeader, nullifier: Field, diff --git a/noir-projects/noir-protocol-circuits/crates/types/src/merkle_tree/membership.nr b/noir-projects/noir-protocol-circuits/crates/types/src/merkle_tree/membership.nr index 22f45f274ada..effc0aa23b6f 100644 --- a/noir-projects/noir-protocol-circuits/crates/types/src/merkle_tree/membership.nr +++ b/noir-projects/noir-protocol-circuits/crates/types/src/merkle_tree/membership.nr @@ -4,10 +4,10 @@ use crate::{ leaf_preimage::IndexedTreeLeafPreimage, root::{root_from_sibling_path, root_from_sibling_path_with_hasher}, }, - traits::Empty, + traits::{Deserialize, Empty, Serialize}, }; -#[derive(Eq)] +#[derive(Deserialize, Eq, Serialize)] pub struct MembershipWitness { pub leaf_index: Field, pub sibling_path: [Field; N], From dc86fc3381fd30ab21b0bcf10610789843c93f93 Mon Sep 17 00:00:00 2001 From: AztecBot Date: Wed, 11 Mar 2026 03:48:21 +0000 Subject: [PATCH 3/4] fix: complete oracle name rename missed by cherry-pick of #21244 The cherry-pick of #21244 only resolved the conflict region (first oracle name), but missed renaming utilityGetBlockHashMembershipWitness to aztec_utl_getBlockHashMembershipWitness. --- .../aztec-nr/aztec/src/oracle/get_membership_witness.nr | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) 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 337c75835ca7..8c1783f085b3 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 @@ -11,7 +11,7 @@ unconstrained fn get_note_hash_membership_witness_oracle( note_hash: Field, ) -> MembershipWitness {} -#[oracle(utilityGetBlockHashMembershipWitness)] +#[oracle(aztec_utl_getBlockHashMembershipWitness)] unconstrained fn get_block_hash_membership_witness_oracle( anchor_block_hash: Field, block_hash: Field, From 8c888fd67e862e0fabfef2ad66c889bb33778d57 Mon Sep 17 00:00:00 2001 From: AztecBot Date: Wed, 11 Mar 2026 03:48:59 +0000 Subject: [PATCH 4/4] fix: update ORACLE_INTERFACE_HASH for v4-next The hash from next (34238ab5...) doesn't match v4-next's oracle interface. Updated to the correct hash (c4c91e3c...) computed by CI. --- yarn-project/pxe/src/oracle_version.ts | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/yarn-project/pxe/src/oracle_version.ts b/yarn-project/pxe/src/oracle_version.ts index a4a23d74b1c2..5fe1675eaabc 100644 --- a/yarn-project/pxe/src/oracle_version.ts +++ b/yarn-project/pxe/src/oracle_version.ts @@ -9,4 +9,4 @@ export const ORACLE_VERSION = 12; /// This hash is computed as by hashing the Oracle interface and it is used to detect when the Oracle interface changes, /// which in turn implies that you need to update the ORACLE_VERSION constant in this file and in /// `noir-projects/aztec-nr/aztec/src/oracle/version.nr`. -export const ORACLE_INTERFACE_HASH = '34238ab576c377b4ffc1ddbf557560f07a66baf879920191897bc784fa5a97ee'; +export const ORACLE_INTERFACE_HASH = 'c4c91e3c3141574eb6dd5a5dbd961b3663d28b80f97b60777cef253c3985995c';