Skip to content

chore(port): forward-port v5-next aztec-nr/contracts backlog to next - #24931

Merged
nchamo merged 16 commits into
nextfrom
port-v5-aztec-nr
Jul 23, 2026
Merged

chore(port): forward-port v5-next aztec-nr/contracts backlog to next#24931
nchamo merged 16 commits into
nextfrom
port-v5-aztec-nr

Conversation

@PhilWindle

Copy link
Copy Markdown
Contributor

Forward-ports the noir / aztec-nr / contracts slice of the v5-next → next backlog (work merged to v5-next after the ~2026-07-08 cut that reshaped next).

Applied (clean cherry-picks, chronological)

⚠️ Needs owner conflict-resolution (conflict against reshaped next; not included here)

Cherry-pick onto this branch and resolve:

Part of the manual v5-next → next backlog sweep. Draft until conflicts are resolved and CI is green.

nventuro and others added 7 commits July 23, 2026 11:01
I added a sanity check to avoid having messages implausibly far into the
future, which would lead to them not getting evicted etc., but more
importantly which would signal some inconsistency somewhere.

(cherry picked from commit fdc2ac5)
…24665)

## Problem

When encrypting a message, the ephemeral secret key comes from an
unconstrained routine, so a malicious sender can substitute any value
while proving. Substituting `eph_sk = 0` yields the point at infinity as
the ephemeral public key, which passed the y-sign check: its
y-coordinate is 0, which counts as positive. Its x-coordinate (0) is
then broadcast, but 0 is not a valid x-coordinate on the curve, so the
recipient can never reconstruct the key and the message is permanently
undecryptable. This breaks the constrained-delivery guarantee that a
note delivered by an untrusted sender remains decryptable by the
recipient.

## Fix

`generate_positive_ephemeral_key_pair` now asserts the ephemeral public
key is not the point at infinity, alongside the existing sign check. A
test emulates the substitution by mocking the randomness oracle to
return 0.

Fixes F-799

(cherry picked from commit 47c30a1)
## 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)
## Summary

- Documents the trust model of partial note completion on
`PartialUintNote` and `PartialNFTNote`:
- The validity commitment only proves that the contract created the
partial note designating `completer`.
- The storage slot and value/token id are trusted arguments, not bound
by the commitment.
- The completer is not authenticated by the check itself, so contracts
must pass `msg_sender()` as `completer`.
- Adds a WARNING that completion is not single-use: the designated
completer can complete the same partial note any number of times, so
contracts must make every completion independently paid for or
authorized in the completing function (as the token and NFT contracts
already do).
- Fixes doc overclaims that said the validity commitment verifies the
storage slot / state variable.

(cherry picked from commit 1879ac1)
…#24844)

## Summary

- AuthRegistry, MultiCallEntrypoint and PublicChecks hold no private
state, but used the default `sync_state`, which performs pointless
discovery RPC calls and embeds the HandshakeRegistry address in their
bytecode.
- Adds a shared `do_sync_state_no_op` handler to aztec-nr and wires it
into those three contracts, plus SchnorrInitializerlessAccount, which
previously carried its own local copy of the same no-op.
- The pinned standard-contract artifacts are untouched, so shipped
artifacts and addresses only change at the next intentional re-pin.

(cherry picked from commit 3b4ba4a)
A contract with no notes might otherwise panic if e.g. it processed an
offchain message related to one. I also made PXE skip the standard
contracts that have no notes and events, both to avoid such a situation
and because there's no need to do it.

(cherry picked from commit dfcdea6)
@PhilWindle PhilWindle added ci-draft Run CI on draft PRs. ci-no-squash labels Jul 23, 2026
@nchamo
nchamo marked this pull request as ready for review July 23, 2026 13:33
@nchamo
nchamo requested a review from nventuro as a code owner July 23, 2026 13:33
@nchamo nchamo self-assigned this Jul 23, 2026
nventuro and others added 8 commits July 23, 2026 10:42
With this, an L1->L2 message's `secret` need no longer be a single field
but instead an array of fields. I moved the message nullifier
computation from PXE into nr so that contracts can have different
nullification schemes (e.g. those that don't depend exclusively on the
contents of `secret`).

Because the fee juice contract uses this oracle, I introduced an adaptor
for it.

(cherry picked from commit 9f1167e)
This fixes an issue in which the note validation checks were not using
the note's contract address to do the nhsk app siloing, but instead the
_executing_ contract's address. This is because app siloing kernel
requests can only be done for the current contract, but the helpers did
not prevent usage on external contracts.

They now contain an assertion preventing this, and have been renamed to
reflect it.

(cherry picked from commit 8b1903c)
#24689)

## Motivation

The `#[note]` macro generated each `PropertySelector` from the field's
position in the struct declaration, but selectors are applied to the
note's packed representation. The two only agree when every field packs
to one `Field`. For a note with a multi-slot field (a `Point`, an array,
a nested struct), every filter on a later field silently constrained an
unrelated packed slot — on the constrained read path, where these checks
are what bind oracle-returned notes to the contract's criteria. A
malicious PXE could satisfy a filter with a note that does not match it.
No shipped contract is affected (all first-party filters target
single-slot fields with single-slot predecessors); the bug was latent in
the library.

## The change

- Selector indices are the field's packed offset: the accumulated sum of
preceding fields' `Packable::N`, mirroring `derive(Packable)`'s layout.
- `PropertySelector<T>` carries the selected field's type.
`select`/`sort` reject fields that pack to more than one `Field` at
compile time (a one-slot criterion cannot express them), and `select`'s
value is typed as the field's type.
- Criterion values are compared as `value.pack()[0]` instead of
`value.to_field()`, matching what the packed note slot actually
contains.
- `properties()` statically asserts the note's packed length equals the
sum of its field packed lengths, so custom `Packable` layouts get a
compile error directing to hand-written selectors instead of wrong ones.
A same-length field reorder is not detectable; that residual gap is
documented.
- Breaking: hand-written `PropertySelector` literals need a type
annotation, and every note field type must implement `Packable`.
Migration notes included. All existing contracts compile to identical
circuits; the PXE already applied indices to the packed layout, so no TS
changes.

## Future changes

The root cause is that two independent authorities describe the same
layout: the note's `Packable` impl owns it, and the macro assumes it.
Every assertion in this PR is a consistency check between the two, and
one divergence (a custom pack that reorders fields at the same total
length) cannot be checked at all and still fails silently. A potential
fix (maybe there is a better one) is for the note macro to own the
layout: `#[note]` derives `Packable` itself and generates the selectors
from the same field list, making divergence impossible by construction,
with an explicit custom-packing opt-out that generates neither and
leaves both to the author. That is a larger breaking change to the macro
surface and is left for a follow-up.

Fixes F-800

(cherry picked from commit 10e339a)
Just a comment.

(cherry picked from commit 15c7a1e)
…esting utilities (#24892)

Reimplementation of
#24837 - same
nullifier fix, this time extending `TestEnvironment` so that we can test
the fix works as intended.

(cherry picked from commit f66808c)
The v5-next pinned artifacts embed verification keys in a format this
line's barretenberg no longer accepts, so the pin cannot be carried over
verbatim. Regenerate it from the ported sources (forgery-protected
handshake secrets, owner-bound initialization nullifiers) with this
line's compiler and prover, moving all standard contracts to new
canonical addresses.
@nchamo
nchamo requested review from a team and LeilaWang as code owners July 23, 2026 14:43
@nchamo

nchamo commented Jul 23, 2026

Copy link
Copy Markdown
Contributor

Cherry-picked the six outstanding commits onto this branch, plus two follow-ups their resolution required:

make yarn-project (bb, noir, noir-projects, l1-contracts, yarn-project) builds green locally on the branch tip.

@nchamo
nchamo enabled auto-merge July 23, 2026 16:54
@nchamo
nchamo added this pull request to the merge queue Jul 23, 2026
Merged via the queue into next with commit 11552a0 Jul 23, 2026
20 checks passed
@nchamo
nchamo deleted the port-v5-aztec-nr branch July 23, 2026 17:30
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

ci-draft Run CI on draft PRs. ci-no-squash

Projects

None yet

Development

Successfully merging this pull request may close these issues.

3 participants