feat: merge-train/fairies-v5#24223
Merged
Merged
Conversation
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>
Fixes [F-664](https://linear.app/aztec-labs/issue/F-664/e2e-test-constrained-delivery-via-non-interactive-handshake) Add e2e tests for discovering events and notes sent with constrained delivery. --------- Co-authored-by: Nicolas Chamo <nicolas@chamo.com.ar>
Collaborator
Author
|
🤖 Auto-merge enabled after 4 hours of inactivity. This PR will be merged automatically once all checks pass. |
## 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>
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>
## 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
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).
Requested by @benesjan. This is fairly trivial, all of the machinery was already setup.
This was referenced Jun 26, 2026
Closed
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.
## 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
Collaborator
Author
|
🤖 Auto-merge enabled after 4 hours of inactivity. This PR will be merged automatically once all checks pass. |
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>
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.
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