Skip to content

feat: merge-train/fairies-v5#24223

Merged
mverzilli merged 30 commits into
v5-nextfrom
merge-train/fairies-v5
Jun 29, 2026
Merged

feat: merge-train/fairies-v5#24223
mverzilli merged 30 commits into
v5-nextfrom
merge-train/fairies-v5

Conversation

@AztecBot

@AztecBot AztecBot commented Jun 22, 2026

Copy link
Copy Markdown
Collaborator

BEGIN_COMMIT_OVERRIDE
feat: make node.getContract take an optional reference block (#24207)
feat(aztec-nr): wire constrained message delivery (#23866)
fix(pxe): respect slot boundaries in oracle (de)serialization (#24211)
feat: allow registration of raw shared secrets (#23708)
feat(e2e): constrained delivery and discovery with two PXEs (#24228)
refactor(stdlib)!: rename unsafe AztecAddress constructors to *Unsafe (#24230)
fix(txe): correct AVM oracle registry types for call and success_copy (#24203)
feat(aztec-nr): make handshake tagging secrets mode agnostic (#24241)
refactor(pxe): derive oracle wire mappings from plain structs (#24244)
chore: merge v5-next into merge-train/fairies-v5 (#24296)
chore: merge v5-next into merge-train/fairies-v5 (#24299)
refactor(aztec_sublib): drop unused standard addresses and authwit (#24273)
chore(sqlite3mc-wasm): bump SQLite3MultipleCiphers to 2.3.5 (#24293)
refactor(aztec-nr)!: return structs from call & keys oracles (#24284)
feat(pxe)!: unify sender/secret registration into TaggingSecretSource (#24280)
feat(pxe): resolve tagging secret strategy via wallet hook (#24040)
feat: FactStore (#23989)
fix(pxe): use v5 AztecAddress factories in FactStore (#24322)
refactor: message context service -> tx resolver service (#24131)
fix(aztec-node): import inspectBlockParameter in server.ts (#24323)
feat: add TestEnvironment::send_l1_to_l2_message (#24314)
feat: aztec.nr side of fact store (#24139)
refactor(noir-contracts): drop unneeded constrained delivery (#24336)
refactor: offchain reception on entity store (#24142)
fix: support pagination in getPublicEvents (#24324)
test(noir-contracts): TestToken with unconstrained delivery and repoint e2e tests (#24337)
END_COMMIT_OVERRIDE

PXE needs the class id at the anchor block, but the node only exposed
the latest one. This forced PXE to reimplement the class id detection by
raw reads of the trees combined with delayed public mutable
interpretation of said data, which unnecessarily coupled PXE and the
registry contracts. With this PR we simply query the data from the node,
which will always be available if there's an upgrade, making the
original class a safe fallback.

The new `referenceBlock` argument is optional and defaults to
`'latest'`, with `address` kept as the first argument, so the change is
backwards compatible: existing single-argument `getContract(address)`
callers keep working unchanged, and only PXE's class-id resolution
passes an explicit anchor block.

Supersedes #24205, addressing the review feedback to make the new
argument optional.

Fixes #15170

---------

Co-authored-by: Nicolás Venturo <nicolas.venturo@gmail.com>
Fixes
[F-669](https://linear.app/aztec-labs/issue/F-669/aztec-nr-calculate-secret-and-index-helper-for-constrained-delivery)
Fixes
[F-670](https://linear.app/aztec-labs/issue/F-670/aztec-nr-send-constrained-msg-helper-that-emits-a-constrained)

## The change

- Adds constrained-delivery helpers that resolve or bootstrap the
app-siloed handshake secret, seed same-tx index reuse, validate index
`0` against the standard HandshakeRegistry, and constrain `index > 0`
through the previous chain nullifier.
- Wires constrained private message delivery to derive constrained log
tags from the resolved `(secret, index)` pair and emit the current
constrained-message nullifier.
- Keeps constrained logs from being squashed with note hashes so
recipient discovery can advance the per-secret index chain.
- Authorizes the standard HandshakeRegistry utility reads needed by the
flow.
- Adds TXE, snapshot, and e2e coverage for bootstrap, reuse, index
advancement, missing prior-nullifier failure, invalid API combinations,
and standard-registry constrained delivery.

Large portion of the diff is tests. 


[F-741](https://linear.app/aztec-labs/issue/F-741/getsharedsecrets-throws-no-public-key-during-recipient-discovery-for-a)
follow-up for the test skipped in
[fd07996](fd07996).

## Concurrency / batching constraint (worth a look)

Pinning the e2e tests surfaced a sequencing constraint in constrained
delivery that reviewers should sanity-check:

- **Parallel sends on one `(sender, recipient, secret)` chain collide.**
Each send is keyed on an incrementing index, so two sends fired as
separate parallel txs read the same index and one tx is rejected.
Distinct recipients are distinct chains and parallelize fine. Pinned as
`it.failing` (documents the limit; flips green if parallel sends ever
become supported).
- **Same-chain sends _can_ be batched into one tx**, but only onto an
already-committed handshake. A later send discharges its predecessor
check against a same-tx pending nullifier. Works both via a single
contract call (`emit_two_events`) and client-side `BatchCall`.
- **Batching onto a brand-new chain does not reuse, it re-handshakes.**
The reuse-vs-bootstrap decision in
`get_or_create_app_siloed_handshake_secret` is a utility call reading
_committed_ state, so a bootstrap earlier in the same tx is invisible
and the later send mints a fresh secret on a separate chain (next index
lands at 1, not 2). A new recipient therefore needs one landed tx to
establish the chain before sends can be batched onto it. This is why the
batched tests seed the handshake first.

All four behaviors are pinned in `e2e_constrained_delivery.test.ts`; the
rationale lives in the module doc and on
`get_or_create_app_siloed_handshake_secret`. Follow-up: allowing utility
functions to execute against combined committed + pending transaction
state is tracked in
[F-238](https://linear.app/aztec-labs/issue/F-238/allow-execution-of-utility-functions-touched-by-pending-transactions).

---------

Co-authored-by: AztecBot <tech@aztec-labs.com>
Co-authored-by: Nicolas Chamo <nicolas@chamo.com.ar>

@ludamad ludamad left a comment

Copy link
Copy Markdown
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

🤖 Auto-approved

@AztecBot AztecBot added this pull request to the merge queue Jun 23, 2026
@AztecBot

Copy link
Copy Markdown
Collaborator Author

🤖 Auto-merge enabled after 4 hours of inactivity. This PR will be merged automatically once all checks pass.

@github-merge-queue github-merge-queue Bot removed this pull request from the merge queue due to failed status checks Jun 23, 2026
@benesjan benesjan added this pull request to the merge queue Jun 23, 2026
@github-merge-queue github-merge-queue Bot removed this pull request from the merge queue due to a conflict with the base branch Jun 23, 2026
nchamo and others added 2 commits June 23, 2026 14:59
## Summary

Switches handshake-derived tagging secrets to be mode agnostic across
constrained and unconstrained delivery.

- Removes delivery mode specialization from handshake secrets and
registry handling
- Updates provided secret processing so PXE scans handshake secrets
across both on-chain tag domains
- Adds/updates Noir, PXE, and e2e coverage for mode-agnostic handshake
behavior. The meaningful tests of multiple mode scanning functionality
is contained in the TS.

---------

Co-authored-by: Nicolas Chamo <nicolas@chamo.com.ar>
@AztecBot AztecBot enabled auto-merge June 24, 2026 09:02
@AztecBot

Copy link
Copy Markdown
Collaborator Author

🤖 Auto-merge enabled after 4 hours of inactivity. This PR will be merged automatically once all checks pass.

Brings `v5-next` up to date into `merge-train/fairies-v5`, which had
stopped merging (PR #24223 was in `mergeable_state: dirty`). Merge this
into the train branch to clear that.

The work is split into two commits so the conflict resolution is
reviewable on its own:

1. **`chore: merge v5-next into merge-train/fairies-v5 (raw merge,
conflicts as markers)`** — the bare `git merge origin/v5-next` with the
single conflict committed verbatim (conflict markers in the tree), so
reviewers can see exactly what git could not auto-merge.
2. **`fix: resolve v5-next merge conflict in e2e_2_pxes.test.ts`** — the
only human decision; review this commit in isolation to check the
resolution.

### Conflict
One file: `yarn-project/end-to-end/src/e2e_2_pxes.test.ts` (the `private
state is "zero" when PXE does not have the account secret key` test).

- The fairies train deliberately `it.skip`s this test with a
`TODO(F-741)`: under the train's in-progress handshake-discovery work,
`expectTokenBalance(walletB, token, accountAAddress, 0n)` throws `No
public key registered` because discovery (`get_shared_secrets`) needs
the scope's keys, which this PXE lacks for a foreign account.
- `v5-next` only reworded the surrounding comment and kept the test
enabled (the test body auto-merged identically).

Resolution keeps the train's `it.skip` + `TODO(F-741)` (preserving the
train's deliberate divergence) while retaining `v5-next`'s accurate
description of what the test does.

Refs #24223.

---
*Created by
[claudebox](https://claudebox.work/v2/sessions/110d3b4223158cd4) ·
group: `slackbot`*

---------

Co-authored-by: Santiago Palladino <santiago@aztec-labs.com>
Co-authored-by: PhilWindle <60546371+PhilWindle@users.noreply.github.com>
Co-authored-by: Santiago Palladino <santiago@aztecprotocol.com>
Co-authored-by: Phil Windle <philip.windle@gmail.com>
Co-authored-by: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
Co-authored-by: Mitchell Tracy <mitchellftracy@gmail.com>
Co-authored-by: Nicolas Chamo <nicolas@chamo.com.ar>
Co-authored-by: just-mitch <68168980+just-mitch@users.noreply.github.com>
Co-authored-by: Nicolás Venturo <nicolas.venturo@gmail.com>
Co-authored-by: AztecBot <tech@aztecprotocol.com>
Co-authored-by: josh crites <jc@joshcrites.com>
Co-authored-by: Alex <alexghr@users.noreply.github.com>
@mverzilli mverzilli requested a review from charlielye as a code owner June 25, 2026 13:26
Re-integrates v5-next so it is a recorded ancestor of the train (the
prior catch-up PR #24296 was squash-merged, which dropped the v5-next
merge parent and re-surfaced the e2e_2_pxes.test.ts conflict on #24223).
Keeps the fairies train's it.skip on the 'private state is zero' test
(TODO(F-741)).
AztecBot and others added 2 commits June 26, 2026 09:48
## Summary

Fixes the merge-train/fairies-v5 CI failure from
http://ci.aztec-labs.com/1782463944315763 by replacing FactStore uses of
`AztecAddress.fromBigInt` and `AztecAddress.fromString` with the v5
branch's available `fromBigIntUnsafe` and `fromStringUnsafe` factories.

## Verification

- `yarn workspace @aztec/pxe test
src/storage/fact_store/fact_store_keys.test.ts
src/storage/fact_store/stored_fact.test.ts` passed: 2 suites, 9 tests.
- `yarn format pxe --check` passed.
- `./bootstrap.sh ci` attempted from repo root, but this branch does not
define a `ci` bootstrap command.
- `./bootstrap.sh ci-fast` attempted from repo root, matching the failed
CI command, but local execution stopped before yarn-project at
`./.claude/tests/agents_symlink_test`.
- `CI=1 ./bootstrap.sh` and `yarn tsgo -b --emitDeclarationOnly`
attempted in `yarn-project`; local execution is blocked by missing
generated Noir/L1 artifacts after the Noir build dependency failed
fetching `just` from `index.crates.io`. The original FactStore `TS2339`
diagnostics are absent after this fix.

---
*Created by
[claudebox](https://claudebox.work/v2/sessions/aef0d54ad3b2a0c3) ·
group: `slackbot`*
Back for the first version of offchain delivery, we introduced a
`getMessageContextsByTxHash` , needed to determine when a message was
ready to process.

This is too ad-hoc: the actual help that Aztec.nr needs from PXE here is
to query status of a collection of TXs, it's only the offchain reception
that cares about constructing a MessageContext from that info.

This PR decouples both notions, but it also adds block number and hash
of the block a TX is included in.

Closes F-738
@mverzilli mverzilli added this pull request to the merge queue Jun 26, 2026
@github-merge-queue github-merge-queue Bot removed this pull request from the merge queue due to failed status checks Jun 26, 2026
@PhilWindle PhilWindle added this pull request to the merge queue Jun 26, 2026
@github-merge-queue github-merge-queue Bot removed this pull request from the merge queue due to failed status checks Jun 26, 2026
AztecBot and others added 2 commits June 26, 2026 12:05
merge-train/spartan-v5 has landed in v5-next and auto-pulled into this train.
Its server.ts refactor (#24283) rewrote the imports and dropped
inspectBlockParameter, but this train's getContract change (#24207) still
calls it in the reference-block-not-found error, so the merged server.ts
references an unimported symbol and the yarn-project build fails. Re-add
inspectBlockParameter to the existing @aztec/stdlib/block import.
## Why

`merge-train/spartan-v5`
([#24272](#24272))
has landed in `v5-next` and been auto-pulled into this train (merge
commit `34209c32`), so the cross-train build break is now live on the
`merge-train/fairies-v5` tip itself — `yarn-project` no longer compiles
(`make: *** [Makefile:359: yarn-project] Error 1`, in `compile_all`).

## Root cause

In `aztec-node/src/aztec-node/server.ts`:

- spartan-v5's
[#24283](#24283)
(`split server.ts into factory + focused modules`) rewrote the imports
and dropped `inspectBlockParameter` — its own uses moved into
`modules/node_world_state_queries.ts`, which imports it correctly.
- This train's
[#24207](#24207)
(`make node.getContract take an optional reference block`) still calls
`inspectBlockParameter(referenceBlock)` in `getContract`'s
reference-block-not-found error.

The auto-merge took spartan-v5's import block, leaving `getContract`
referencing an unimported symbol → `Cannot find name
'inspectBlockParameter'`.

## Fix

Re-add `inspectBlockParameter` to the existing `@aztec/stdlib/block`
import in `server.ts` (it is the only remaining consumer there, and the
symbol is still exported from that module). One-line change; the error
message is unchanged.

Since the train tip already contains spartan-v5's refactor, this PR's
own CI now builds the actual merged tree, so it verifies the fix
directly.

Refs
[#24223](#24223),
[#24207](#24207),
[#24283](#24283).
@mverzilli mverzilli added this pull request to the merge queue Jun 26, 2026
@github-merge-queue github-merge-queue Bot removed this pull request from the merge queue due to failed status checks Jun 26, 2026
Requested by @benesjan. This is fairly trivial, all of the machinery was
already setup.
Adds oracles to consume FactStore services from Aztec.nr, as well as
some abstractions

Closes F-739
AztecBot added a commit that referenced this pull request Jun 26, 2026
…eployment contracts

These account, token and benchmarking contracts delivered their notes with
MessageDelivery::onchain_constrained(). That mode was effectively a no-op on
v5-next, but #23866 (wire constrained message delivery) made it issue a real
validate_handshake private call on the first send (index 0) of each
(sender, recipient, secret) sequence. That extra app circuit broke the full
(merge-queue-only) client_flows step-count benches once v5-next merged into
merge-train/fairies-v5, dequeuing #24223:
  - account_deployments: 10 -> 11 execution steps
  - amm add_liquidity:   14 -> 17 execution steps
and it advanced the per-secret tagging index until bench_build_block exceeded
UNFINALIZED_TAGGING_INDEXES_WINDOW_LEN (20), failing every tx commit until the
600s timeout.

These flows test app/deployment logic and don't need constrained delivery
(constrained delivery has dedicated coverage in constrained_delivery_test_contract),
so deliver via onchain_unconstrained instead -- the behavior these benches were
written against. No benchmark expectations change: they already encode the
unconstrained (no-bootstrap) step counts.

The warm-send benches (transfers, bridging) were unaffected either way, and the
dedicated constrained_delivery_test_contract is intentionally left as-is.
nchamo and others added 2 commits June 26, 2026 13:03
## Summary

Follow-up to #24312: audits where
`MessageDelivery::onchain_constrained()` is used and drops it where it
buys nothing. Constrained delivery only matters when the message sender
isn't incentivized to deliver correctly and differs from the recipient;
it also costs an extra nullifier, a handshake bootstrap, and serializes
sends per `(sender, recipient, secret)` chain.

- **Account constructors** (`schnorr`, `ecdsa_k`, `ecdsa_r`)
self-deliver the signing-key note — with `.with_sender(self.address)`,
sender and recipient are both the account, so the guarantee is vacuous.
Note integrity is already constrained in-circuit by `create_note` before
delivery, and discoverability is preserved by the sender override plus
the self-note sender scan. Now
`onchain_unconstrained().with_sender(self.address)`.
- **Simulated account stubs** (`SimulatedSchnorrAccount` /
`SimulatedEcdsaAccount`) reverted to their pre-#23866 shape — #23866
both wired constrained delivery into the real accounts and added the
matching handshake dummies to these kernelless gas-estimation stubs.
- **Test / example contracts** that deliver notes to `self.msg_sender()`
(counter, child, static_child, scope_test, no_constructor,
nested_utility, test, updated, updatable, private_init_test, and the
counter scaffold) downgraded to `onchain_unconstrained()`.
Re-implementation of offchain reception workflows using the new
EntityStore machinery

Note this exposed a problem in the EntityStore idempotency semantics:
throwing on an attempt at creating an already existing entity is
problematic, because Noir doesn't provide error handling mechanisms. In
the end, I decided to make entity creation idempotent, with the first
attempt at creating a given entity "winning" to avoid inadvertent
overwrites. It is then user responsibility to model their workflows
properly (there's plenty of alternatives: change how entity id's are
derived, check for existence before attempting creation, using facts,
etc).

Closes F-682
@AztecBot

Copy link
Copy Markdown
Collaborator Author

🤖 Auto-merge enabled after 4 hours of inactivity. This PR will be merged automatically once all checks pass.

@AztecBot AztecBot added this pull request to the merge queue Jun 26, 2026
@github-merge-queue github-merge-queue Bot removed this pull request from the merge queue due to failed status checks Jun 27, 2026
mverzilli and others added 2 commits June 29, 2026 10:48
Make `getPublicEvents` in Aztec.js support pagination by including a
`nextCursor` handle in its result.

Closes F-764
…nt e2e tests (#24337)

## What

Splits the token used in e2e tests into two contracts:

- **canonical `TokenContract`** (`app/token_contract`) is unchanged and
remains the production / public-docs source of truth. Several of its
paths (`transfer_to_public`, `transfer_in_private`, `burn_private`,
`finalize_transfer_to_private_from_private`, ...) use **constrained**
message delivery; plain `transfer` already uses unconstrained delivery.
- **`TestTokenContract`** (`contracts/test/test_token_contract`) is its
all-**unconstrained-delivery** sibling, generated from canonical Token
at build time by `scripts/gen_test_token.sh`.

e2e suites where a token is just a unit-of-account vehicle now deploy
`TestToken`. The benchmarks hand-enumerate the exact private calls a
flow makes (`expectedExecutionSteps`); a constrained-delivery path's
first send injects an extra handshake bootstrap that the hand-count
doesn't include, which inflated the `client_flows/amm` step count (14 ->
17) once #23866 wired constrained delivery in. With `TestToken` the
bench counts model the app flow again, with no `expectedExecutionSteps`
changes.

Constrained delivery's own cost/behavior stays covered by the dedicated
`constrained_delivery_test_contract` +
`e2e_constrained_delivery.test.ts`.

## How

- `scripts/gen_test_token.sh` copies `app/token_contract`, drops the
Noir TXE test module, flips all delivery sites to
`onchain_unconstrained`, and renames the contract/package to `TestToken`
/ `test_token_contract`. The generated source is committed and marked
generated.

`TestToken` is regenerated from canonical Token automatically, so the
two can't drift:

| When | Action | Why |
|---|---|---|
| Local build | regenerate in place (bootstrap build) | an edited
canonical Token shows up in `TestToken`-based e2e tests before any
commit |
| Commit (precommit hook) | regenerate + re-stage | keeps the committed
source matching canonical Token (accurate diffs / IDE) |
| CI | `--check` only | a stale `TestToken` fails with a clear message |

Regeneration is idempotent (an unchanged Token stays a cache hit), which
keeps `TestToken` a faithful "canonical Token minus the handshake" --
the premise that makes it a valid bench vehicle.
- `token_utils.ts` gains `deployTestToken`; its mint/balance helpers
accept either token. `getTokenAllowedSetupFunctions` now keys the FPC
allowlist on the deployed token's class (defaulting to canonical Token),
so the benches' `TestToken` fee vehicle is allowlisted on the right
class.

### Repointed to TestToken (token is a vehicle)

`bench/client_flows/*` (the amm bench + its shared base), `e2e_amm`,
`forward-compatibility/e2e_amm`, `e2e_orderbook`, `e2e_partial_notes`,
`e2e_multiple_accounts_1_enc_key`. In the bridging bench only the FPC
fee token is repointed; the bridged L2 asset (deployed by
`CrossChainTestHarness`) stays canonical Token, which is harmless
because its claim / `mint_to_private` path doesn't use constrained
delivery.

### Kept on canonical Token

- Subject / discovery: `e2e_token`, the `e2e_2_pxes` cross-PXE section,
`e2e_constrained_delivery`.
- Gas / step sensitive (pass on constrained today): `e2e_fees/*`,
`e2e_kernelless_simulation`.
- Docs / deploy-mechanism: `e2e_deploy_contract/*` (the `deploy_token`
docs snippet must show canonical Token).

Context / rationale:
https://gist.github.com/AztecBot/ee4c54b9100e4925cde9b2d17e53cdca and
the constrained-delivery wiring in #23866.

Follow-ups at the bottom of
https://gist.github.com/AztecBot/d3537fa9e1aba8c2e0fe3a9d74698d5f.

---------

Co-authored-by: AztecBot <tech@aztec-labs.com>
@mverzilli mverzilli enabled auto-merge June 29, 2026 09:08
@mverzilli mverzilli added this pull request to the merge queue Jun 29, 2026
Merged via the queue into v5-next with commit c81bb25 Jun 29, 2026
17 checks passed
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Projects

None yet

Development

Successfully merging this pull request may close these issues.

7 participants