Skip to content

Commit 61f26e3

Browse files
nchamoaztec-bot
authored andcommitted
fix(aztec-nr): tolerate malformed partial-note completion logs (#24668)
## Problem Partial-note discovery has four crash points on the completion path, each reachable by a malicious sender and each firing before the pending note advances — so every subsequent sync re-hits it and permanently freezes note sync for that contract: - a matched completion log yields no note (`panic`), - a pending note resolves to more than one completion log (`assert`), - the delivered private half plus the log's public content exceed the packed-note capacity (`BoundedVec` overflow in the append), or - the completion log payload is empty, so reading the storage slot is out of bounds. The first three are reachable on the canonical token (mismatched content over the unconstrained delivery channel, completing the same partial note twice which the token does not prevent, and an over-length delivered private half); the last needs an attacker-controlled contract emitting a tag-only log. ## Fix Make each non-fatal: warn and advance the FSM rather than panicking, so one bad message cannot break sync. A completion log that cannot yield a note (empty, over-length, or matching none) is skipped; more than one completion log completes with the first. Fixes F-798 (cherry picked from commit 6489102)
1 parent 99632a7 commit 61f26e3

5 files changed

Lines changed: 322 additions & 43 deletions

File tree

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

Lines changed: 5 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,8 @@
11
use crate::messages::logs::note::MAX_NOTE_PACKED_LEN;
2-
use crate::protocol::{constants::{MAX_NOTE_HASHES_PER_TX, PRIVATE_LOG_CIPHERTEXT_LEN}, traits::Deserialize};
2+
use crate::protocol::{
3+
constants::{MAX_NOTE_HASHES_PER_TX, PRIVATE_LOG_CIPHERTEXT_LEN},
4+
traits::{Deserialize, Serialize},
5+
};
36

47
pub global MAX_PUBLIC_LOG_LEN_FOR_NOTE_COMPLETION: u32 = MAX_NOTE_PACKED_LEN;
58

@@ -11,7 +14,7 @@ pub(crate) global MAX_LOG_CONTENT_LEN: u32 = std::cmp::max(
1114
/// A response to a `LogRetrievalRequest`, containing the payload of a log (i.e. the content minus the tag, called
1215
/// plaintext for public logs and ciphertext for private), plus contextual information about the transaction in which
1316
/// the log was emitted. This is the data required in order to discover notes that are being delivered in a log.
14-
#[derive(Deserialize, Eq)]
17+
#[derive(Deserialize, Eq, Serialize)]
1518
pub struct LogRetrievalResponse {
1619
pub log_payload: BoundedVec<Field, MAX_LOG_CONTENT_LEN>,
1720
pub tx_hash: Field,

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

Lines changed: 7 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -95,6 +95,13 @@ pub unconstrained fn enqueue_note_for_validation(
9595
))
9696
}
9797

98+
/// The note validation requests enqueued so far in the current context via [`enqueue_note_for_validation`], before
99+
/// [`validate_and_store_enqueued_notes_and_events`] drains them. Exists so tests can inspect the pending queue;
100+
/// production code should not read requests back once enqueued.
101+
pub(crate) unconstrained fn get_enqueued_note_validation_requests() -> EphemeralArray<NoteValidationRequest> {
102+
EphemeralArray::at(NOTE_VALIDATION_REQUESTS_ARRAY_BASE_SLOT)
103+
}
104+
98105
/// Enqueues an event for validation and storage by PXE.
99106
///
100107
/// This is the primary way for custom message handlers (registered via

0 commit comments

Comments
 (0)