Skip to content

Commit a42bff4

Browse files
authored
feat(aztec-nr)!: embed BoundedVec max length in validation requests (#23622)
## Problem `NoteValidationRequest` and `EventValidationRequest` contain a `BoundedVec` whose `maxLen` is needed for deserialization, but it was passed as a separate oracle parameter (`maxNotePackedLen` / `maxEventSerializedLen`). This meant that we can't build a self-contained `TypeMapping` for it, and we wouldn't be able to build auto generated mappings in the future ## Fix Each struct now includes its own max length field (`max_note_packed_len` / `max_event_serialized_len`) that is populated automatically via a `new` constructor from the compile-time constant. The TypeScript `fromFields` methods read the length from the field stream instead of taking it as a parameter, making them self-contained.
1 parent 7332e70 commit a42bff4

19 files changed

Lines changed: 128 additions & 93 deletions

File tree

noir-projects/aztec-nr/aztec/src/messages/processing/event_validation_request.nr

Lines changed: 39 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -6,16 +6,39 @@ use crate::protocol::{address::AztecAddress, traits::Serialize};
66
/// `EphemeralArray` at the given `base_slot`.
77
#[derive(Serialize)]
88
pub(crate) struct EventValidationRequest {
9-
pub contract_address: AztecAddress,
10-
pub event_type_id: EventSelector,
11-
pub randomness: Field,
12-
pub serialized_event: BoundedVec<Field, MAX_EVENT_SERIALIZED_LEN>,
13-
pub event_commitment: Field,
14-
pub tx_hash: Field,
9+
contract_address: AztecAddress,
10+
event_type_id: EventSelector,
11+
randomness: Field,
12+
max_event_serialized_len: Field,
13+
serialized_event: BoundedVec<Field, MAX_EVENT_SERIALIZED_LEN>,
14+
event_commitment: Field,
15+
tx_hash: Field,
16+
}
17+
18+
impl EventValidationRequest {
19+
pub(crate) fn new(
20+
contract_address: AztecAddress,
21+
event_type_id: EventSelector,
22+
randomness: Field,
23+
serialized_event: BoundedVec<Field, MAX_EVENT_SERIALIZED_LEN>,
24+
event_commitment: Field,
25+
tx_hash: Field,
26+
) -> Self {
27+
Self {
28+
contract_address,
29+
event_type_id,
30+
randomness,
31+
max_event_serialized_len: MAX_EVENT_SERIALIZED_LEN as Field,
32+
serialized_event,
33+
event_commitment,
34+
tx_hash,
35+
}
36+
}
1537
}
1638

1739
mod test {
1840
use crate::event::EventSelector;
41+
use crate::messages::logs::event::MAX_EVENT_SERIALIZED_LEN;
1942
use crate::protocol::{address::AztecAddress, traits::{FromField, Serialize}};
2043
use super::EventValidationRequest;
2144

@@ -25,6 +48,7 @@ mod test {
2548
contract_address: AztecAddress::from_field(1),
2649
event_type_id: EventSelector::from_field(2),
2750
randomness: 3,
51+
max_event_serialized_len: MAX_EVENT_SERIALIZED_LEN as Field,
2852
serialized_event: BoundedVec::from_array([4, 5]),
2953
event_commitment: 6,
3054
tx_hash: 7,
@@ -38,9 +62,17 @@ mod test {
3862
1, // contract_address
3963
2, // event_type_id
4064
3, // randomness
65+
MAX_EVENT_SERIALIZED_LEN as Field,
4166
4, // serialized_event[0]
4267
5, // serialized_event[1]
43-
0, 0, 0, 0, 0, 0, 0, 0, // serialized_event padding
68+
0,
69+
0,
70+
0,
71+
0,
72+
0,
73+
0,
74+
0,
75+
0, // serialized_event padding
4476
2, // bounded_vec_len
4577
6, // event_commitment
4678
7, // tx_hash

noir-projects/aztec-nr/aztec/src/messages/processing/mod.nr

Lines changed: 19 additions & 25 deletions
Original file line numberDiff line numberDiff line change
@@ -83,19 +83,17 @@ pub unconstrained fn enqueue_note_for_validation(
8383
nullifier: Field,
8484
tx_hash: Field,
8585
) {
86-
EphemeralArray::at(NOTE_VALIDATION_REQUESTS_ARRAY_BASE_SLOT).push(
87-
NoteValidationRequest {
88-
contract_address,
89-
owner,
90-
storage_slot,
91-
randomness,
92-
note_nonce,
93-
packed_note,
94-
note_hash,
95-
nullifier,
96-
tx_hash,
97-
},
98-
)
86+
EphemeralArray::at(NOTE_VALIDATION_REQUESTS_ARRAY_BASE_SLOT).push(NoteValidationRequest::new(
87+
contract_address,
88+
owner,
89+
storage_slot,
90+
randomness,
91+
note_nonce,
92+
packed_note,
93+
note_hash,
94+
nullifier,
95+
tx_hash,
96+
))
9997
}
10098

10199
/// Enqueues an event for validation and storage by PXE.
@@ -118,16 +116,14 @@ pub unconstrained fn enqueue_event_for_validation(
118116
event_commitment: Field,
119117
tx_hash: Field,
120118
) {
121-
EphemeralArray::at(EVENT_VALIDATION_REQUESTS_ARRAY_BASE_SLOT).push(
122-
EventValidationRequest {
123-
contract_address,
124-
event_type_id,
125-
randomness,
126-
serialized_event,
127-
event_commitment,
128-
tx_hash,
129-
},
130-
)
119+
EphemeralArray::at(EVENT_VALIDATION_REQUESTS_ARRAY_BASE_SLOT).push(EventValidationRequest::new(
120+
contract_address,
121+
event_type_id,
122+
randomness,
123+
serialized_event,
124+
event_commitment,
125+
tx_hash,
126+
))
131127
}
132128

133129
/// Validates and stores all enqueued notes and events.
@@ -139,8 +135,6 @@ pub unconstrained fn validate_and_store_enqueued_notes_and_events(scope: AztecAd
139135
message_processing::validate_and_store_enqueued_notes_and_events(
140136
EphemeralArray::at(NOTE_VALIDATION_REQUESTS_ARRAY_BASE_SLOT),
141137
EphemeralArray::at(EVENT_VALIDATION_REQUESTS_ARRAY_BASE_SLOT),
142-
MAX_NOTE_PACKED_LEN as Field,
143-
MAX_EVENT_SERIALIZED_LEN as Field,
144138
scope,
145139
);
146140

noir-projects/aztec-nr/aztec/src/messages/processing/note_validation_request.nr

Lines changed: 40 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -6,18 +6,47 @@ use crate::protocol::{address::AztecAddress, traits::{Deserialize, Serialize}};
66
/// `EphemeralArray`.
77
#[derive(Serialize, Deserialize)]
88
pub struct NoteValidationRequest {
9-
pub contract_address: AztecAddress,
10-
pub owner: AztecAddress,
11-
pub storage_slot: Field,
12-
pub randomness: Field,
13-
pub note_nonce: Field,
14-
pub packed_note: BoundedVec<Field, MAX_NOTE_PACKED_LEN>,
15-
pub note_hash: Field,
16-
pub nullifier: Field,
17-
pub tx_hash: Field,
9+
contract_address: AztecAddress,
10+
owner: AztecAddress,
11+
storage_slot: Field,
12+
randomness: Field,
13+
note_nonce: Field,
14+
max_note_packed_len: Field,
15+
packed_note: BoundedVec<Field, MAX_NOTE_PACKED_LEN>,
16+
note_hash: Field,
17+
nullifier: Field,
18+
tx_hash: Field,
19+
}
20+
21+
impl NoteValidationRequest {
22+
pub fn new(
23+
contract_address: AztecAddress,
24+
owner: AztecAddress,
25+
storage_slot: Field,
26+
randomness: Field,
27+
note_nonce: Field,
28+
packed_note: BoundedVec<Field, MAX_NOTE_PACKED_LEN>,
29+
note_hash: Field,
30+
nullifier: Field,
31+
tx_hash: Field,
32+
) -> Self {
33+
Self {
34+
contract_address,
35+
owner,
36+
storage_slot,
37+
randomness,
38+
note_nonce,
39+
max_note_packed_len: MAX_NOTE_PACKED_LEN as Field,
40+
packed_note,
41+
note_hash,
42+
nullifier,
43+
tx_hash,
44+
}
45+
}
1846
}
1947

2048
mod test {
49+
use crate::messages::logs::note::MAX_NOTE_PACKED_LEN;
2150
use crate::protocol::{address::AztecAddress, traits::{FromField, Serialize}};
2251
use super::NoteValidationRequest;
2352

@@ -29,6 +58,7 @@ mod test {
2958
storage_slot: 2,
3059
randomness: 42,
3160
note_nonce: 3,
61+
max_note_packed_len: MAX_NOTE_PACKED_LEN as Field,
3262
packed_note: BoundedVec::from_array([4, 5]),
3363
note_hash: 6,
3464
nullifier: 7,
@@ -45,6 +75,7 @@ mod test {
4575
0x0000000000000000000000000000000000000000000000000000000000000002,
4676
0x000000000000000000000000000000000000000000000000000000000000002a,
4777
0x0000000000000000000000000000000000000000000000000000000000000003,
78+
MAX_NOTE_PACKED_LEN as Field,
4879
0x0000000000000000000000000000000000000000000000000000000000000004,
4980
0x0000000000000000000000000000000000000000000000000000000000000005,
5081
0x0000000000000000000000000000000000000000000000000000000000000000,

noir-projects/aztec-nr/aztec/src/oracle/message_processing.nr

Lines changed: 1 addition & 11 deletions
Original file line numberDiff line numberDiff line change
@@ -20,25 +20,15 @@ unconstrained fn get_pending_tagged_logs_oracle(scope: AztecAddress) -> Ephemera
2020
pub(crate) unconstrained fn validate_and_store_enqueued_notes_and_events(
2121
note_validation_requests: EphemeralArray<NoteValidationRequest>,
2222
event_validation_requests: EphemeralArray<EventValidationRequest>,
23-
max_note_packed_len: Field,
24-
max_event_serialized_len: Field,
2523
scope: AztecAddress,
2624
) {
27-
validate_and_store_enqueued_notes_and_events_oracle(
28-
note_validation_requests,
29-
event_validation_requests,
30-
max_note_packed_len,
31-
max_event_serialized_len,
32-
scope,
33-
);
25+
validate_and_store_enqueued_notes_and_events_oracle(note_validation_requests, event_validation_requests, scope);
3426
}
3527

3628
#[oracle(aztec_utl_validateAndStoreEnqueuedNotesAndEvents)]
3729
unconstrained fn validate_and_store_enqueued_notes_and_events_oracle(
3830
note_validation_requests: EphemeralArray<NoteValidationRequest>,
3931
event_validation_requests: EphemeralArray<EventValidationRequest>,
40-
max_note_packed_len: Field,
41-
max_event_serialized_len: Field,
4232
scope: AztecAddress,
4333
) {}
4434

noir-projects/aztec-nr/aztec/src/oracle/version.nr

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -10,7 +10,7 @@
1010
/// the PXE and used to provide helpful error messages if a contract calls an oracle that doesn't exist. We don't throw
1111
/// immediately if AZTEC_NR_MINOR > PXE_MINOR because if a contract is updated to use a newer Aztec.nr dependency
1212
/// without actually using any of the new oracles then there is no reason to throw.
13-
pub global ORACLE_VERSION_MAJOR: Field = 25;
13+
pub global ORACLE_VERSION_MAJOR: Field = 26;
1414
pub global ORACLE_VERSION_MINOR: Field = 1;
1515

1616
/// Asserts that the version of the oracle is compatible with the version expected by the contract.

noir-projects/noir-contracts/contracts/app/private_token_contract/src/main.nr

Lines changed: 3 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -33,7 +33,9 @@ pub contract PrivateToken {
3333
// Admin itself is the owner of the underlying note because we want admin to be able to transfer the admin
3434
// privileges to someone else which requires being able to nullify the note. We use constrained onchain message
3535
// delivery because we don't know if the party deploying this contract is incentivized to deliver the note.
36-
self.storage.admin.initialize(AddressNote { address: admin }, admin).deliver(MessageDelivery::onchain_constrained());
36+
self.storage.admin.initialize(AddressNote { address: admin }, admin).deliver(
37+
MessageDelivery::onchain_constrained(),
38+
);
3739

3840
// Mint the initial admin balance to the admin.
3941
self.storage.balances.at(admin).add(initial_admin_balance).deliver(MessageDelivery::onchain_constrained());

noir-projects/noir-contracts/contracts/protocol/aztec_sublib/src/oracle/version.nr

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -10,7 +10,7 @@
1010
/// the PXE and used to provide helpful error messages if a contract calls an oracle that doesn't exist. We don't throw
1111
/// immediately if AZTEC_NR_MINOR > PXE_MINOR because if a contract is updated to use a newer Aztec.nr dependency
1212
/// without actually using any of the new oracles then there is no reason to throw.
13-
pub global ORACLE_VERSION_MAJOR: Field = 25;
13+
pub global ORACLE_VERSION_MAJOR: Field = 26;
1414
pub global ORACLE_VERSION_MINOR: Field = 0;
1515

1616
/// Asserts that the version of the oracle is compatible with the version expected by the contract.

noir-projects/noir-contracts/contracts/test/custom_sync_state_contract/src/main.nr

Lines changed: 1 addition & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -31,9 +31,7 @@ contract CustomSyncState {
3131
#[initializer]
3232
fn constructor(owner: AztecAddress, value: Field) {
3333
let note = FieldNote { value };
34-
self.storage.value.at(owner).initialize(note).deliver(
35-
MessageDelivery::onchain_unconstrained(),
36-
);
34+
self.storage.value.at(owner).initialize(note).deliver(MessageDelivery::onchain_unconstrained());
3735
}
3836

3937
#[external("utility")]

noir-projects/noir-contracts/contracts/test/state_vars_contract/src/main.nr

Lines changed: 3 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -106,7 +106,9 @@ pub contract StateVars {
106106
let owner = self.msg_sender();
107107
let private_mutable = FieldNote { value };
108108

109-
self.storage.private_mutable.at(owner).initialize(private_mutable).deliver(MessageDelivery::onchain_constrained());
109+
self.storage.private_mutable.at(owner).initialize(private_mutable).deliver(
110+
MessageDelivery::onchain_constrained(),
111+
);
110112
}
111113

112114
#[external("private")]

yarn-project/pxe/src/contract_function_simulator/noir-structs/event_validation_request.test.ts

Lines changed: 6 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -11,6 +11,7 @@ describe('EventValidationRequest', () => {
1111
1, // contract_address
1212
2, // event_type_id
1313
3, // randomness
14+
10, // max_event_serialized_len
1415
4, // serialized_event[0]
1516
5, // serialized_event[1]
1617
0, // serialized_event padding start
@@ -26,7 +27,7 @@ describe('EventValidationRequest', () => {
2627
7, // tx_hash
2728
].map(n => new Fr(n));
2829

29-
const request = EventValidationRequest.fromFields(serialized, 10);
30+
const request = EventValidationRequest.fromFields(serialized);
3031

3132
expect(request.contractAddress).toEqual(AztecAddress.fromBigInt(1n));
3233
expect(request.eventTypeId).toEqual(new EventSelector(2));
@@ -41,9 +42,10 @@ describe('EventValidationRequest', () => {
4142
1, // contract_address
4243
2, // event_type_id
4344
3, // randomness
45+
10, // max_event_serialized_len (10)
4446
4, // serialized_event[0]
4547
5, // serialized_event[1]
46-
0, // serialized_event padding (11 storage fields total, but maxEventSerializedLen=10)
48+
0, // serialized_event padding (11 storage fields total, but max_event_serialized_len=10)
4749
0,
4850
0,
4951
0,
@@ -57,8 +59,8 @@ describe('EventValidationRequest', () => {
5759
7, // tx_hash
5860
].map(n => new Fr(n));
5961

60-
expect(() => EventValidationRequest.fromFields(serialized, 10)).toThrow(
61-
'Error converting array of fields to EventValidationRequest: expected 16 fields but received 17 (maxEventSerializedLen=10).',
62+
expect(() => EventValidationRequest.fromFields(serialized)).toThrow(
63+
'Error converting array of fields to EventValidationRequest: expected 17 fields but received 18 (maxEventSerializedLen=10).',
6264
);
6365
});
6466
});

0 commit comments

Comments
 (0)