Skip to content

chore: merge next into monorepo-split/labs - #25091

Merged
fcarreiro merged 54 commits into
monorepo-split/labsfrom
fc/labs-next-merge
Aug 4, 2026
Merged

fcarreiro merged 54 commits into
monorepo-split/labsfrom
fc/labs-next-merge

Conversation

@fcarreiro

@fcarreiro fcarreiro commented Aug 4, 2026 •

Copy link
Copy Markdown
Contributor

Merges next (b00c780) into monorepo-split/labs.

Important

This is a branch-sync merge — it should be merged with a merge commit, not squashed, so the shared history with next is preserved.

Conflict resolutions

Four files conflicted, all in territory where next just received the port of #25047/#25057 (via #25078) while labs had already evolved past it:

  • labs-aztec-toolchain/bootstrap.sh + README.md (add/add): took the labs side. next's version is byte-identical to labs at feat: abstract labs noir/bb toolchain #25047; labs has since moved to the download-based toolchain (feat: labs repo downloads aztec toolchain #25049), which supersedes it.
  • noir-projects/labs/bootstrap.sh: took the labs side. Both sides carried the same feat: abstract labs noir/bb toolchain #25047 changes (toolchain nargo path, protocol-fuzzer removal); labs additionally has the targeted partial-clone cache eviction, which is labs-specific (protocol_types resolves from a large aztec-packages git clone).
  • Makefile:
    • kept labs' commented-out # labs-aztec-toolchain: noir bb-cpp-native (labs already fulfilled next's "comment this out when pinning binaries" TODO) and labs' TODO wording on the format-check dependency;
    • took next's new fnd-release / fnd-release-tests targets;
    • took next's split of yarn-project: deps into noir-projects-labs labs-aztec-toolchain plus the monorepo-extras line (total dependency set unchanged).

Toolchain fix (semantic conflict caught by CI)

The first CI run failed compiling account/schnorr_initializerless_account_contract: two Return variable contains a constant value errors pointing at the aztec-nr macro's self.context.finish().

Root cause: next switched the noir-contracts compile to --deny-warnings, relying on the macro-generated #[allow(constant_return)] to silence that one lint (replacing the old grep-allowlist in bootstrap.sh). Support for #[allow(constant_return)] only exists in Noir v1.0.0-beta.26 — earlier compilers silently ignore the attribute and the warning becomes an error. The labs toolchain provisions the pinned noir release, and the pin was still 1.0.0-beta.25, so CI compiled with a nargo that can't honor the allow. (Both parents were green: labs still had the grep-allowlist, and next builds nargo from its beta.26 submodule.)

Fix, folded into the merge commit:

  • bumped NOIR_VERSION to 1.0.0-beta.26 in labs-aztec-toolchain/bootstrap.sh — reproduced the failure locally with the pinned beta.25 toolchain (identical toolchain hash 0d18d107bf07e280 to the CI run) and verified the same compile passes after the bump;
  • added bootstrap.sh itself to the toolchain hash function, so pin bumps and provisioning-logic changes move the cache key even before binaries are refreshed.

Note: BB_VERSION stays at 6.0.0-nightly.20260729, which was built against noir 75061fab — two commits shy of the beta.26 tag (release stamp + an unrelated frontend fix), so the pairing skew is negligible. A future pin refresh can realign both to a newer nightly.

Notes

  • Adopts next's noir submodule bump to 40d6574f85 (v1.0.0-beta.26) — verified the pointer matches origin/next exactly.
  • Verified no conflict markers remain (git diff --check + full grep) and make -n passes for fast full bench release yarn-project fnd-release-tests noir-projects.
  • Supersedes the older sync attempt on nchamo/labs-next-merge (f0b50f9), which predates next's current tip.

charlielye and others added 30 commits July 20, 2026 12:08
The 'Upload benchmarks' steps used github-action-benchmark, which does a
full clone of AztecProtocol/benchmark-page-data per upload. That repo
has grown to 3.9GB of append-only gh-pages history, making each upload
take ~8 minutes and every upload slower than the last.

Replace the action with ci3/upload_benchmarks, which writes the same
window.BENCHMARK_DATA format but:

- appends via a shallow, blob-filtered, sparse clone of just the target
  data dir (~4s / 89MB today vs ~8min / 3.9GB)
- in --maintain mode (bench/next uploads only) prunes data dirs with no
  update in 6 months and squashes history older than 6 months into a
  single root, so the repo can no longer grow without bound. Squashing
  uses a blob-less clone and rewrites only commit objects (trees and
  blobs are content-addressed and reused), rate-limited to monthly via
  a stamp file and guarded by force-with-lease against concurrent
  uploads.

ci3/upload_benchmarks_test covers append, squash+prune, idempotence,
new-dir initialization, and MAX_ITEMS trimming against a local fixture
repo.
Add the self-hosted monitoring installer as the primary monitoring path, and
resync operator contract addresses to the V5 rollup.

Monitoring:
- host aztec-monitoring.sh as a static asset (self-contained: Grafana
  dashboard, Prometheus alert rules, and the Alertmanager template are embedded)
- add the installer walkthrough to the monitoring page as the primary path,
  keep the manual Prometheus/Grafana route as an alternative
- list it under Foundation tools; keep the community script as an alternative,
  and add the aztec-butler provider CLI under provider/key management
- drop the superseded community-monitoring section and the day-2 pointer to a
  community script, now that a first-party stack ships with alerting
- lead the slashing-risk proxies with the missed-attestation and
  missed-proposal alerts the stack ships

Addresses:
- refresh the central operator config with the current canonical rollup and
  slasher for both networks (verified on-chain via the Registry), so pages that
  render addresses from it stop showing the pre-upgrade rollup
- correct the hardcoded rollup addresses in the prover claiming-rewards table
  and the start-node sample node-info output
…paths

The merge-queue run exposed three failures:
- pushing rewritten history from a partial clone lazy-fetches promisor
  objects one at a time (93 minutes, then the connection dropped) -> the
  squash is removed from the job entirely; run it out-of-band from a full
  clone when needed
- the datapoint entry exceeded Linux's 128KB per-argv-element cap
  (jq: Argument list too long) -> large inputs now reach jq as files
- append_and_push runs inside an if, which suppresses errexit, so the jq
  failure was swallowed and a truncated data.js was pushed as a success
  -> every critical step now aborts the attempt explicitly
…25028)

## Context

`SiblingPath.deserialize` read a 32-bit length prefix and then both
pre-allocated an array of that
size and looped that many times, with nothing tying the declared length
to the bytes actually
present. Its element reader was built on `Buffer.slice`, which clamps
past the end of a buffer
instead of throwing — so the loop never ran out of input and ran the
full declared count regardless
of how much data arrived.

A 4-byte field was therefore enough to build a million-element path, or
to walk a client's V8 heap
into a fatal out-of-memory abort. That abort is not catchable, so a
`try`/`catch` around RPC decoding
does not contain it. This matters because sibling paths reach clients as
RPC *outputs* (witness
lookups, which the PXE fetches automatically during private execution),
so it is the node that can
crash the client, not the other way round.

## Approach

Sibling paths now deserialize through `BufferReader.readVector`, which
bounds the declared length
three ways: an explicit `maxSize` (`MAX_SIBLING_PATH_LENGTH`, 128 — the
deepest protocol tree is 42
levels and the stacked path for L2-to-L1 message inclusion spans four
unbalanced trees, so real paths
are well under it), a new check that the size does not exceed the bytes
left after the prefix, and
`readBytes`' own per-element range check. The last of those also closes
the truncation half of the
problem, where a path declaring more elements than its payload holds
used to deserialize into
undersized buffers instead of failing.

The cap has to live in `foundation`, which cannot import
`@aztec/constants` since `constants` depends
on it, so a test in `stdlib` asserts the cap stays above every generated
`*_HEIGHT` constant.
Enumerating them rather than listing the deep ones means a future deeper
tree fails that test instead
of silently failing to deserialize.

`deserializeArrayFromVector`, the primitive behind the old code, had
exactly one caller and
duplicated `readVector` minus all of those checks, so it is deleted
rather than fixed. The
remaining-bytes bound lands in `readVector` itself, which covers its
other callers too: every element
consumes at least one byte, so any size beyond the bytes remaining is
unsatisfiable and can be
rejected before allocating or looping. It was not exploitable there in
the same way (its item
deserializers all range-check as they read), but the guard makes the
failure explicit and cheap
rather than dependent on every element reader.

That bound assumes a minimum of one byte per element, so I checked for
anything that deserializes a
count of sub-byte items: `BitVector` is the only bit-packed reader, and
it converts its bit count to
`ceil(length / 8)` bytes itself and reads through the range-checked
`readBytes`, so it never reaches
the bound with a bit-denominated length. Every other `readVector`
element reader in the tree advances
by whole bytes.

One existing `readVector` test changed: it asserted that a 32-byte
buffer declaring 65537 elements
yields 65537 elements, using a deserializer that consumed no bytes. That
amplification is what the
bound removes, so the happy path is now exercised against a well-formed
vector and the oversized case
asserts the throw.

Fixes A-1522
Two public node RPC inputs reached expensive work with no length cap.

`simulatePublicCalls` accepted an unbounded `overrides.publicStorage`
array (and an unbounded
`overrides.contracts` record). Each storage override becomes a leaf
inserted into a forked public
data tree before the simulated transaction runs, so a small request
could force a large amount of
Merkle work and memory that the transaction's gas limit does not meter.

`getCheckpointsData` range queries validated `limit` with only `min(1)`,
while the sibling
`getCheckpoints` capped it. The effective upper bound was the node's
contiguous checkpoint history
rather than a page size, so one request could ask the archiver to read
and serialize the whole chain.

## Approach

Both caps live in `stdlib/src/interfaces/api_limit.ts` next to the
existing `MAX_RPC_*` limits and are
enforced in the zod schemas, so they reject at the RPC boundary before
any handler runs:

- `MAX_RPC_PUBLIC_STORAGE_OVERRIDES_LEN` (200) and
`MAX_RPC_CONTRACT_OVERRIDES_LEN` (50) on
`SimulationOverrides.schema`. Internal callers of the override path use
a handful of entries at
most (`fastforwardContractUpdate` writes one delayed-public-mutable
value), so there is ample
  headroom.
- `MAX_RPC_CHECKPOINTS_DATA_LEN` (200) on both range variants of
`CheckpointsQuerySchema`
(`{ from, limit }` and `{ fromSlot, limit }`). Checkpoint data carries
no attestations or block
bodies, hence a larger page than a full checkpoint response. The widest
internal caller is the
prover node's catch-up fetch, bounded by `(proofSubmissionEpochs + 1) *
epochDuration`.

The existing `MAX_RPC_TXS_LEN`, `MAX_RPC_BLOCKS_LEN` and
`MAX_RPC_CHECKPOINTS_LEN` page caps stay at
50 and are unchanged. Two ideas from earlier revisions were dropped:
raising those caps to 100 while
adding a tighter `MAX_RPC_HEAVY_LEN` for reads whose `include*` options
attach a tx body or proof to
every entry, which needed a refine on four schemas plus a divergent
default for `getPendingTxs`; and
capping the per-slot attestation arrays at the committee size, which is
not actually an upper bound
since equivocation can produce more than one attestation per validator
per slot.

Tests cover each cap at the schema level (`SimulationOverrides`,
`CheckpointsQuerySchema`) and as
round-trips through the JSON-RPC client and server in
`aztec-node.test.ts`.

Fixes A-1524
Fixes A-1523
…25029)

## Context

`Tx.schema` accepted `contractClassLogFields` and
`publicFunctionCalldata` arrays of any length, and
the `HashedValues.schema` those calldata entries are built from accepted
any number of values. Three
unauthenticated node RPC methods take a full tx — `sendTx`, `isValidTx`
and `simulatePublicCalls` —
so until now the only thing bounding those arrays at the RPC boundary
was `RPC_MAX_BODY_SIZE`. A
caller could post a tx whose calldata array is orders of magnitude
larger than any real tx, and the
node would deserialize all of it and compute the tx hash before
protocol-level validation rejected
it.

Follow-up to #25026, which capped simulation overrides and
checkpoint-data range queries.

## Approach

Each array is capped at what the protocol can actually produce:

- `publicFunctionCalldata` → `MAX_ENQUEUED_CALLS_PER_TX + 1` (33). One
entry per enqueued call, plus
the teardown call. `MAX_ENQUEUED_CALLS_PER_TX` is a whole-tx bound
rather than a per-phase one: the
revertible and non-revertible call request arrays are each sized
`MAX_ENQUEUED_CALLS_PER_TX` in the
circuit ABI, but `split_to_public` in the private tail fills them by
*partitioning* a single
`ClaimedLengthArray<_, MAX_ENQUEUED_CALLS_PER_TX>`, so their lengths sum
to 32 rather than reaching
it each. The teardown request is a separate field that "can only be set
once", hence the `+ 1`.
  `mockTx` with its defaults and a teardown call produces exactly 33.
- `contractClassLogFields` → `MAX_CONTRACT_CLASS_LOGS_PER_TX` (1). Same
partitioning argument:
`getNonEmptyContractClassLogsHashes` concatenates both accumulated data
sets, but they are filled
  from one array of that size.
- The fields within a calldata entry →
`MAX_FR_CALLDATA_TO_ALL_ENQUEUED_CALLS` (16000). A tx cannot
spend more than its whole calldata budget on a single call. That also
clears every producer by a
wide margin: the largest payload the client builds is packed bytecode
for a contract class
publication, bounded by `MAX_PACKED_PUBLIC_BYTECODE_SIZE_IN_FIELDS`
(3000).

The last of those is applied through a new
`HashedValues.schemaFor(maxValues)` rather than baked into
`HashedValues.schema`, because that schema is shared with
`TxExecutionRequest.argsOfCalls`,
`PrivateExecutionResult` and the wallet's `extraHashedArgs` — a public
calldata budget is not the
right bound for private call arguments or authwit arguments. `Tx.schema`
is the only caller that opts
in.

## Note for reviewers

`Tx.schema` is also used to deserialize txs from the tx file store, so
an over-tight bound would
reject previously-valid stored data rather than just bad RPC input. The
values above are protocol
ceilings, so stored and gossiped txs stay parseable; the only behavior
change is that a tx exceeding
them is now rejected while parsing instead of later, by
`DataTxValidator`. Note that gossip and the
reqresp protocols go through `Tx.fromBuffer`, not the schema, so
validator coverage there is
unchanged.

Fixes A-1527
…ization (#25035)

This just catches a misconstructred oracle call.
These should serve to clarify the purpose of these contracts.
This deletes some old unused constants, moves some from the protocol
into aztec-nr, and creates the aztec-nr infra required for testing that
we're not colliding with the protocol's (e.g. not colliding with any
domain separator). This is not complete - some aztecnr constants (and
app constants) remain in protocol, specifically those that are also used
in TS, as that'd require also changing transpilation.
BEGIN_COMMIT_OVERRIDE
fix(foundation): bound deserialized sibling path and vector lengths
(#25028)
fix(rpc): cap simulation overrides and checkpoint queries (#25026)
fix(stdlib): cap the unbounded arrays in Tx and HashedValues schemas
(#25029)
END_COMMIT_OVERRIDE
## Summary

Two operator-docs updates in one PR:

1. **Monitoring installer** — host the self-hosted sequencer monitoring
stack in the docs (a single self-contained script) and feature it as the
primary monitoring path.
2. **V5 L1 addresses** — the operator docs still pointed at the pre-V5
rollup; resync the central config and the few pages that hardcode an
address.

## Monitoring

- **`static/scripts/aztec-monitoring.sh`**: one self-contained installer
(the Grafana dashboard, Prometheus alert rules, and
Alertmanager→Telegram template are embedded). Targets `v5.0.0`, for
nodes run via Docker Compose. Runs entirely on operator infrastructure;
optional and replaceable.
- **`concepts/monitoring.md`**: add the installer walkthrough as the
primary "Set up monitoring with the installer" section (curl + run,
node/HA/monitoring-machine steps, day-2, security); keep the manual
Prometheus/Grafana route as "Set up monitoring manually". Drop the
now-superseded community-monitoring section. Lead the slashing-risk
proxies with the missed-attestation/missed-proposal alerts the stack
ships.
- **`tooling/index.md`**: list the installer under Foundation tools as
the recommended monitoring starting point; reframe the community
monitoring script as an alternative; add the `aztec-butler` provider CLI
under a new provider/key-management heading.
- **`{solo-sequencer,provider}/day-2-essentials.mdx`**: replace the
pointer to a community monitoring script with a pointer to the
installer.
- **`docs-words.txt`**: add `Alertmanager`.

## Addresses

- **`src/components/OperatorConfig/context.js`**: refresh the canonical
rollup and slasher for both networks. Pages that render
`{{ROLLUP_ADDR}}` / `{{SLASHER_ADDR}}` (register-sequencer, etc.) now
show current values from this single source.
- Mainnet rollup `0xae20…4962` →
`0x91fF8bbD8Ebb07893010D50A48A1609e5EBd8E34`; slasher →
`0xCD6855470A01aBcd989126A1183Fb50673952548`
- Testnet rollup `0xf6D0…32c1` →
`0xD73A91bdcF6891C7642F3e460036e1ef2CC23178`; slasher →
`0xBFa3625CfC7cdDAbF29961e12C4399c5bd8D8763`
- Registry, GSE, staking-registry unchanged (stable anchors, confirmed
on-chain).
- **`prover/claiming-rewards.mdx`**,
**`{solo-sequencer,provider}/start-node.mdx`**: correct hardcoded rollup
addresses (claiming-rewards table + sample node-info output).

All addresses verified on-chain via the Registry
(`getCanonicalRollup()`) and each rollup's `getSlasher()`. The hosted
script is byte-identical to source (sha256 verified). Docs build passes
with `onBrokenLinks: throw`; spellcheck clean.
Scripted installs need bb placed in a chosen directory (BB_PATH) without
editing the invoking user's shell config; --no-modify-path skips
update_shell_config for them.

The config edits it does make are idempotent now: every run used to append
another PATH line to .bashrc/.zshrc/config.fish.
## What

- `--no-modify-path` skips `update_shell_config`, so a scripted install
can place `bb` in a chosen `BB_PATH` without editing the invoking user's
`.bashrc`/`.zshrc`/`config.fish`.
- The shell-config edits it *does* make are idempotent: every run used
to append another `PATH` line to each config.
- README documents the flag alongside `BB_PATH`.

Required for
https://linear.app/aztec-labs/issue/A-1532/source-bbnargo-from-an-aztec-toolchain-directory-for-labs
.

## Why now

`labs-aztec-toolchain` provisions its pinned `bb` by fetching `bbup`
from this repo and running it with `--no-modify-path` into the
component's `bin/`. That branch pins the raw URL, so this has to be on
`next` before the pin can point at a commit.

## Verification

Ran the real script against the pinned nightly with `HOME` redirected to
a scratch dir seeded with an empty `.bashrc`, `.zshrc` and
`config.fish`:

- with `--no-modify-path`: `bb` installed into the given `BB_PATH` (`bb
--version` → `6.0.0-nightly.20260729`), all three configs still 0 lines.
- without the flag, run twice: exactly one entry in each of the three
configs.
Remove the retention/prune machinery entirely: the shallow depth=1 append
is unaffected by repo history size, so maintenance is not needed to fix
the upload time and any history rewriting is better done out-of-band.
Adds `spartan/benchmarks/README.md`. There was no existing doc covering
the nightly network benchmarks, so this writes one up from the workflows
and scripts as they stand on `next`.

Covers the three benchmarks:

- **Inclusion sweep** (`nightly-bench-inclusion-sweep.yml`, daily) —
1/5/10 TPS points run sequentially against a single network, sharing a
sweep id, with a fixed 1 TPS high-value lane and background traffic
making up the target.
- **Proving** — nightly simulated (`nightly-spartan-bench.yml`,
`prove-n-tps-fake`) and weekly real proving (`weekly-proving-bench.yml`,
`prove-n-tps-real`), which share the test and CI3 target and differ only
in environment.
- **Block capacity** (`nightly-spartan-bench.yml`, daily) — per-workload
block fill, including the workload/transaction-count table.

Also documents the shared deploy / wait-for-first-block / bench /
teardown shape, the dispatch chain from workflow through `ci3.sh` and
`bootstrap_ec2` to the `spartan/bootstrap.sh` bench functions and their
e2e tests, how the scraped run payload and its index manifest are
published (and the guards on that upload), schema version history, and
how to run each benchmark locally.

Two things worth a reviewer's eye:

- The **Known issues** section records that the bench functions scrape
whenever the timing-metadata file exists without checking its `runId`
against `BENCH_RUN_ID`. A test that fails before writing that file
leaves the previous run's metadata in place, and the scraper will build
a complete, plausible-looking document from it and publish it under the
new run's id. I hit this in practice. Not fixed here — flagging it as
documentation only.
- The `nightly-block-capacity` namespace differs from the
`block-capacity` env file's default `NAMESPACE`, which matters for
manual teardown; called out explicitly.

Documentation only, no code or workflow changes.
The "Upload benchmarks" CI step takes ~8 minutes. Root cause:
`benchmark-action/github-action-benchmark` does a **full clone** of
`AztecProtocol/benchmark-page-data` (no depth/filter/single-branch) to
append one datapoint. That repo's gh-pages history is **~4GB**.

## Changes

`ci3/upload_benchmarks` replaces the action at all three upload sites in
`ci3.yml`. It writes the identical `window.BENCHMARK_DATA` format
(verified against the live data), so the dashboards are unaffected. It
is deliberately append-only — no retention or history maintenance:

- Appends use a `--depth=1 --filter=blob:none --sparse` clone scoped to
the target data dir: measured against the live repo, **~4.5s / 89MB**
versus ~8min / 4GB. Because the clone is depth=1, this stays fast no
matter how large history grows. Push conflicts with concurrent uploads
are handled by retrying from a fresh clone.
- Commit metadata for datapoints (author/message/link) comes from the
GitHub API, matching what the action recorded; it degrades to bare-sha
metadata if the API is unavailable.
- The datapoint entry is passed to jq as a file, never argv: a full CI
entry exceeds Linux's 128KB per-argv-element cap (`Argument list too
long`).
- Every critical step aborts the upload attempt explicitly (`|| return
1`): the retry loop's `if` suppresses `set -e` inside the function, and
a swallowed mid-append failure would otherwise commit and push a
truncated `data.js` as a "success".
- `ci3/upload_benchmarks_test` is a self-contained fixture-repo test
(run it directly) covering append, new-dir initialization, `MAX_ITEMS`
trimming, >128KB entries, and loud failure on an unreachable repo.

An earlier revision of this PR also squashed/pruned old history in-job
("retention maintenance"). That was removed: a merge-queue run showed
that pushing rewritten history from a partial clone lazy-fetches
promisor objects one at a time (93 minutes, then the connection
dropped), and measurement shows ~96% of the repo's weight is the
*recent* six months of large `data.js` versions anyway — old-history
squashing barely shrinks it and is unnecessary for upload speed.

## Notes

- Dropped behavior from the action: the `alert-threshold` comparison. It
was configured with `comment-on-alert: false` / `fail-on-alert: false`
at all three sites, so it had no observable effect.
- Pre-existing quirk, preserved: the nightly tag job runs with an empty
`BENCH_BRANCH` and writes to `bench/data.js` at the repo top level
(updated as recently as today). The script keeps writing there rather
than silently changing the destination.
- Follow-up worth considering: `bench/next/data.js` is ~70MB *at the
tip* because every datapoint embeds the full metric set (~700KB), which
is also why the data repo grows ~25MB/day and the dashboard ships 70MB
to every browser. Narrowing the schema is where the real size win is.
BEGIN_COMMIT_OVERRIDE
docs(spartan): document the nightly network benchmarks (#25064)
END_COMMIT_OVERRIDE
aminsammara and others added 17 commits August 3, 2026 10:19
Adds `client13` to the mainnet RPC consumers.

Secret created in Secret Manager and `terraform apply`-ed; plan was the
expected 2 resources (KongConsumer + ExternalSecret), 0 to change, 0 to
destroy. Rate limit 0 = unlimited, matching the other entries in
`consumer_secret_names`.

Verified live: KongConsumer `PROGRAMMED=True`, ExternalSecret
`SecretSynced`, and an authenticated `node_getNodeInfo` against
`canonical.mainnet.rpc.aztec-labs.com` returns a result (keyless still
401s).
…index (#25068)

Next-line counterpart of #25058 (itself a rework of #24923), which
targets the v5 line. Closes A-1443 alongside it.

Three commits, kept separate (`ci-no-squash`).

### `feat(slasher): warn and expose metrics when own validators are
slash targets`

- Warns when an onchain slashing vote names one of the node's own
validators, and when an executed round slashes one of them.
- Adds five node-level metrics: `own_validator.targeted_count`,
`own_validator.current_round_votes_max`, `own_validator.slashed_count`,
`own_validator.slashed_amount`, and `quorum_size`.
- Tallies per flattened committee position, which is the unit the
contract tallies quorum by: a validator sitting in several of a round's
committees holds several positions, each racing quorum independently.
Warnings report the validator's highest position tally.
- The whole feature is skipped when the node runs no validators, so
those nodes pay no extra L1 subscription.

### `feat(l1): emit vote index in SlashingProposer VoteCast event`

- `VoteCast` gains a non-indexed `uint256 voteIndex` carrying the index
of the vote it recorded within the round (the value `getVotes(round,
index)` accepts).
- The event becomes self-identifying: a listener can read the vote back
without re-deriving the index from the round's vote count, which needed
an extra L1 read per event and could only ever approximate which vote
the event referred to.
- This changes the event signature and therefore its topic0. External
indexers filtering on `VoteCast` need to update their ABI. The unrelated
`VoteCast` on `Governance` is untouched.
- TS ripple: `SlashingProposerContract.listenToVoteCast` now hands `{
round, voteIndex, proposer }` to its callback.

### `refactor(slasher): drive own-validator vote tracking from the
VoteCast vote index`

- The monitor's cursor is now fed purely by event indices: no `getRound`
read per event, and no startup baseline read (`start()` is synchronous,
and the client no longer has to await it before subscribing).
- A missed event delivery is healed by gap-filling from the cursor up to
the latest event's index; a duplicate or out-of-order delivery is a
no-op. A failed vote read leaves the cursor put, so the next event
retries it.
- Starting mid-round still counts only votes cast from the first event
onwards, so cumulative counters are not double-counted across restarts.
- Vote processing stays serialized through the existing queue, which is
what keeps the cursor sound and the warning tallies monotonic.

### Tests

- `l1-contracts`: 34 tests under `test/slashing/` pass, including a new
`test_voteEmitsVoteIndex` asserting the index the event carries across
two votes in a round.
- `@aztec/ethereum`: 22 tests in `slashing_proposer.test.ts` pass; the
anvil-backed vote test now also asserts the emitted event's `voteIndex`.
- `@aztec/slasher`: 22 tests in `own_validator_slash_monitor.test.ts`
(duplicate delivery, gap-fill, stale index, mid-round start, failed-read
retry, drain serialization, rollover mid-drain, stop/restart) and 44 in
`slasher_client.test.ts` pass.
Port of #25057 and #25047 to `merge-train/fairies`, cherry-picked in the
order they landed on the labs line (0f8d8ad, then b556724). Both
picks are line-identical to the originals; the conflicts were only
against fairies-side context.

- #25057 removes the protocol fuzzer
(`noir-projects/labs/protocol-fuzzer/` and its format-check/pre-commit
hook entries).
- #25047 makes labs-side components (`noir-projects/labs`, `boxes`,
`docs`, `aztec-up`, parts of `yarn-project` tests) take their
`bb`/`nargo`/`noir-profiler`/`bb-avm`/`acvm` binaries from
`labs-aztec-toolchain/bin` instead of reaching into the monorepo build
trees directly. On the monorepo the toolchain bootstrap symlinks to the
existing build outputs, so nothing is rebuilt or downloaded.

Closes https://linear.app/aztec-labs/issue/A-1559/backport-prs-to-next .
`fast`/`full`/`bench`/`release` each gain `-foundation` and `-labs`
variants, with the old target as the union of the two, so either side of
the repo split can be built on its own.

Part of
https://linear.app/aztec-labs/issue/A-1458/split-labsfoundation-makefile-and-bootstrap
(will close when changes are done in the `monorepo-split/labs` branch)
BEGIN_COMMIT_OVERRIDE
chore: port of #25057 and #25047 to next (#25078)
chore: split make targets into foundation and labs (#25079)
END_COMMIT_OVERRIDE
## Summary

- publish `v5.1.0` as the shared release for both **Alpha V5** and **Testnet** across developer and network/operator documentation
- configure both `mainnet` and `testnet` selectors to resolve to the same `v5.1.0` snapshot, rendering `Alpha / Testnet (v5.1.0)`
- remove the deprecated `v5.0.1` developer and network snapshots
- regenerate the v5.1.0 Aztec, wallet, operator, Node JSON-RPC, Aztec.nr, and TypeScript API references
- provide identical generated API artifacts under the stable `mainnet` and `testnet` paths, with the shared snapshot using the canonical `mainnet` paths
- refresh Testnet network metadata from `https://v5.testnet.rpc.aztec-labs.com` and checksum the documented Sepolia addresses
- carry forward release-valid documentation fixes and role-based operator structure while resolving code snippets against the `v5.1.0` tag

## Release details

The Testnet RPC still reports node version `5.0.0`, so this uses the requested pre-release workflow for the tagged `v5.1.0` upgrade. The RPC-confirmed Testnet L1 deployment, chain ID (`11155111`), and rollup version (`1821665230`) remain unchanged. Alpha V5 retains its existing deployment metadata while its documentation version advances to the same `v5.1.0` release.

Canonical Testnet L2 values are derived from the `v5.1.0` tooling where the pre-upgrade RPC differs:

- MultiCall Entrypoint: `0x246d60af8b79a5dceece7d2388921203401c0df02ce674c5781c6c2162922986`
- Sponsored FPC: `0x130925fbd734a252e3d8ddff87f6c346052dd5c13314eb96026b32baa1923296`

The Sponsored FPC address changed from the previous docs and must be funded for Testnet use. Alpha V5 continues to document Sponsored FPC as not deployed.

## Validation

- `MAINNET_TAG=5.1.0 TESTNET_TAG=5.1.0 RELEASE_TYPE=mainnet COMMIT_TAG=v5.1.0 yarn build`
  - CSpell: 0 issues
  - redirect targets: valid
  - Docusaurus production build: successful
  - developer and operator pages render `Alpha / Testnet (v5.1.0)`
- `yarn validate:api-ref-links`
  - 112 API links checked
  - 0 broken links
  - 0 version mismatches
- generated `mainnet` and `testnet` Aztec.nr and TypeScript API directories are byte-identical
- new versioned snapshots contain no unresolved release/include macros
- version configs and version lists contain one shared `v5.1.0` snapshot for both Alpha V5 and Testnet

The build retains existing non-fatal broken-anchor warnings from generated CLI aliases and operator compose-page anchors.

---
*Updated by [claudebox](https://claudebox.work/v2/sessions/8446a113e20bc334/jobs/3) · group: `slackbot` · requested by Alejo Amiras · [Slack thread](https://aztecfoundation.slack.com/archives/C0B24G1GFGB/p1785769938239119?thread_ts=1785769938.239119&cid=C0B24G1GFGB)*

---
*Created by [claudebox](https://claudebox.work/v2/sessions/8446a113e20bc334/jobs/2) · group: `slackbot` · requested by Alejo Amiras · [Slack thread](https://aztecfoundation.slack.com/archives/C0B24G1GFGB/p1785769938239119?thread_ts=1785769938.239119&cid=C0B24G1GFGB)*
## Summary

- publish `v5.1.0` as the shared release for both **Alpha V5** and
**Testnet** across developer and network/operator documentation
- configure both `mainnet` and `testnet` selectors to resolve to the
same `v5.1.0` snapshot, rendering `Alpha / Testnet (v5.1.0)`
- remove the deprecated `v5.0.1` developer and network snapshots
- regenerate the v5.1.0 Aztec, wallet, operator, Node JSON-RPC,
Aztec.nr, and TypeScript API references
- provide identical generated API artifacts under the stable `mainnet`
and `testnet` paths, with the shared snapshot using the canonical
`mainnet` paths
- refresh Testnet network metadata from
`https://v5.testnet.rpc.aztec-labs.com` and checksum the documented
Sepolia addresses
- carry forward release-valid documentation fixes and role-based
operator structure while resolving code snippets against the `v5.1.0`
tag

## Release details

The Testnet RPC still reports node version `5.0.0`, so this uses the
requested pre-release workflow for the tagged `v5.1.0` upgrade. The
RPC-confirmed Testnet L1 deployment, chain ID (`11155111`), and rollup
version (`1821665230`) remain unchanged. Alpha V5 retains its existing
deployment metadata while its documentation version advances to the same
`v5.1.0` release.

Canonical Testnet L2 values are derived from the `v5.1.0` tooling where
the pre-upgrade RPC differs:

- MultiCall Entrypoint:
`0x246d60af8b79a5dceece7d2388921203401c0df02ce674c5781c6c2162922986`
- Sponsored FPC:
`0x130925fbd734a252e3d8ddff87f6c346052dd5c13314eb96026b32baa1923296`

The Sponsored FPC address changed from the previous docs and must be
funded for Testnet use. Alpha V5 continues to document Sponsored FPC as
not deployed.

## Validation

- `MAINNET_TAG=5.1.0 TESTNET_TAG=5.1.0 RELEASE_TYPE=mainnet
COMMIT_TAG=v5.1.0 yarn build`
  - CSpell: 0 issues
  - redirect targets: valid
  - Docusaurus production build: successful
  - developer and operator pages render `Alpha / Testnet (v5.1.0)`
- `yarn validate:api-ref-links`
  - 112 API links checked
  - 0 broken links
  - 0 version mismatches
- generated `mainnet` and `testnet` Aztec.nr and TypeScript API
directories are byte-identical
- new versioned snapshots contain no unresolved release/include macros
- version configs and version lists contain one shared `v5.1.0` snapshot
for both Alpha V5 and Testnet

The build retains existing non-fatal broken-anchor warnings from
generated CLI aliases and operator compose-page anchors.

---
*Updated by
[claudebox](https://claudebox.work/v2/sessions/8446a113e20bc334/jobs/3)
· group: `slackbot` · requested by Alejo Amiras · [Slack
thread](https://aztecfoundation.slack.com/archives/C0B24G1GFGB/p1785769938239119?thread_ts=1785769938.239119&cid=C0B24G1GFGB)*

---
*Created by
[claudebox](https://claudebox.work/v2/sessions/8446a113e20bc334/jobs/2)
· group: `slackbot` · requested by Alejo Amiras · [Slack
thread](https://aztecfoundation.slack.com/archives/C0B24G1GFGB/p1785769938239119?thread_ts=1785769938.239119&cid=C0B24G1GFGB)*
BEGIN_COMMIT_OVERRIDE
chore: add new client (#25080)
feat(slasher): warn on own-validator slash votes using VoteCast vote
index (#25068)
chore: new client (#25082)
END_COMMIT_OVERRIDE
BEGIN_COMMIT_OVERRIDE
feat(pxe): cache tag log queries bounded at the anchor block (#25074)
END_COMMIT_OVERRIDE
@socket-security

socket-security Bot commented Aug 4, 2026 •

Copy link
Copy Markdown

Review the following changes in direct dependencies. Learn more about Socket for GitHub.

Diff Package Supply Chain
Security
Vulnerability Quality Maintenance License
Updatednpm/​@​aztec/​noir-noir_js@​1.0.0-beta.25 ⏵ 1.0.0-beta.26N/AN/AN/AN/AN/A

View full report

@fcarreiro fcarreiro added the ci-draft Run CI on draft PRs. label Aug 4, 2026
@fcarreiro
fcarreiro force-pushed the fc/labs-next-merge branch from 991ee7d to 69642a1 Compare August 4, 2026 10:40
@fcarreiro
fcarreiro marked this pull request as ready for review August 4, 2026 11:12
@fcarreiro
fcarreiro merged commit 10a9159 into monorepo-split/labs Aug 4, 2026
21 checks passed
@fcarreiro
fcarreiro deleted the fc/labs-next-merge branch August 4, 2026 11:13
nchamo pushed a commit that referenced this pull request Aug 4, 2026
Moves yarn-project's foundation dependencies from source links (portals)
to npm packages pinned at `6.0.0-nightly.20260804`.

## Changes

- **npm pins**: `@aztec/bb.js`, `bb-avm-sim` (+platform packages),
`wsdb` (+platform packages), `ipc-runtime`, `l1-artifacts`,
`constants-codegen`, and the `@aztec/noir-*` packages (the noir
submodule's JS packages, republished by our release CI under the aztec
version) are now consumed from npm. Workspace `package.json`s use a
`0.1.0-dummy` version resolved by the root `resolutions` block, so
bumping the pin is a one-place change. `yarn.lock` carries them as real
registry entries with checksums.
- **`BB_VERSION` → `6.0.0-nightly.20260804`** in labs-aztec-toolchain —
now *exactly* paired with `NOIR_VERSION=1.0.0-beta.26` (that release was
built against the beta.26 submodule, closing the two-commit skew noted
in #25091). The `protocol_types` git tag and the docs
recursive-verification example pins (`config.yaml` + `Nargo.toml`) move
with it; `check_pin_drift` passes.
- **`.yarnrc.yml`**: `npmPreapprovedPackages: ['@aztec/*']` — the 7d
`npmMinimalAgeGate` would quarantine same-day nightlies, which is
exactly how these pins are consumed. First-party, exact-version pins.
Same change in `docs/.yarnrc.yml`, which previously enumerated the five
packages the recursive-verification example needed.
- **docs webapp-tutorial validation** (`docs/examples/bootstrap.sh`):
the dependency-closure walk that builds the tutorial's standalone yarn
project used to discover the externally-built packages through `portal:`
entries in yarn-project's root `resolutions`; those entries are now
plain npm versions, so the placeholder workspace versions
(`@aztec/ipc-runtime@0.1.0`, ...) leaked into a project where no
resolutions rewrite them. The walk now mirrors the pins: any `@aztec`
name resolved to a plain version is consumed from npm at exactly that
version, never linked — which also moves `bb.js`/`noir-*` off the local
`barretenberg/ts` and `noir/packages` dirs that won't exist in the labs
repo. Verified end to end (`validate-webapp-tutorial` green locally).
- **yarn-project `hash` reworked**: composes component bootstrap hashes
(toolchain, labs noir-contracts, aztec-nr, fnd noir-protocol-circuits)
plus fnd source patterns, new `^ipc-codegen/` +
`^barretenberg/cpp/src/barretenberg/cdb/` patterns (the simulator's cdb
server codegen runs ipc-codegen against bb's `cdb_schema.json` on every
build, output uncommitted), and its own patterns (which cover
`yarn.lock`, hence all the npm pins). Wholesale inclusion of
barretenberg / ipc-codegen / l1-contracts is dropped — those now reach
the key via yarn.lock or the toolchain binaries.
- **`stdlib/scripts/copy-contracts.sh`** post-processes fixtures with
the toolchain `bin/bb` instead of barretenberg's `find-bb` (matching
what labs noir-contracts already uses for the same `aztec_process` call;
the monorepo build dir won't exist on the split repo).

- **yarn-project's build now warms solc into `~/.svm`**
(`warm_solc_cache`). The npm l1-artifacts foundry bundle references solc
by version instead of shipping the binary like the portal-built bundle
did, so the runtime forge deploy resolves it through `~/.svm` — which
the network-less e2e containers inherit from the host's home mount. The
warming lives labs-side (not in l1-contracts, which won't exist in the
labs repo) and reads the version from the installed bundle so it cannot
drift. Verified red/green with `forge build --offline` against the npm
bundle; a no-op on the monorepo where `l1-contracts-solc` has already
populated the cache.

## Latent type errors surfaced by the pins

With portals, tsc resolves a linked package's own imports from its
realpath (`noir/packages/...`), where no `node_modules` exists — so the
`noir_js` -> `noirc_abi` -> `noir-types` re-export chain never resolved,
`InputMap`/`abiEncode`'s parameter types degraded to `any`, and two
latent type errors in our own source never fired. The npm packages
resolve fully (their type surface is byte-identical to the portals —
this is not a version incompatibility) and surfaced them; both fixed
here:

- `noir-protocol-circuits-types/src/execution/server.ts`:
`convertPrivateInputsToWitnessMap`'s generic is now constrained to
`InputValue`.
- `noir_codegen` emits `InputMap` as a value import in generated types,
which trips TS1484 under `verbatimModuleSyntax`. Both codegen call sites
(`noir-protocol-circuits-types` and `ivc-integration`) now rewrite it to
a type-only import post-generation, until the generator is fixed
upstream in Noir (issue to be filed; tracked as A-1611).

## Validation

- `yarn install` resolves cleanly (only pre-existing peer warnings); all
pinned packages verified present on npm at the exact version.
- `nargo check` in `aztec-nr/aztec` resolves the new `protocol_types`
tag.
- `copy-contracts.sh` processes all three fixtures with the toolchain bb
(byte-identical output).
- `check_pin_drift` green.

## Follow-ups

- **fnd circuit/contract artifacts are still read from source** at
generate time — `noir-protocol-circuits-types` copies
`fnd/noir-protocol-circuits/target/*` and reads
`private_kernel_reset_config.json`, `ivc-integration` copies
`fnd/mock-protocol-circuits/target/*`, `protocol-contracts` reads
`fnd/noir-contracts`. The hash keeps the fnd components until those are
consumed as published packages — @nchamo is picking this up.
- Inside fnd noir-protocol-circuits, the per-VK cache key
(`$BB_HASH-$bytecode_hash-$name-3`) doesn't include the circuit's scheme
classification, so a `chonk_circuits.json` reclassification would still
cache-hit the VK generated under the old scheme; the trailing `-3` salt
needs a manual bump on such a change (the `hash` subcommand itself was
already widened in #25083 to cover the pin tarball and configs).
- `yarn-project/simulator` still reaches into source at generate time:
its `generate` script runs `../../ipc-codegen/src/generate.ts` against
`../../barretenberg/cpp/src/barretenberg/cdb/cdb_schema.json`
([package.json#L22](https://github.com/AztecProtocol/aztec-packages/blob/next/yarn-project/simulator/package.json#L22)).
This PR covers those inputs in the hash, but the dependency itself needs
solving — e.g. consuming ipc-codegen as a published package and shipping
the cdb schema with it (or committing the generated output).
- `boxes` still portals to source (`bb.js`, `yarn-project`) — same
pinning exercise pending there.
- Remove the `InputMap` type-import rewrites in both codegen scripts
once the upstream `noir_codegen` fix ships in a pinned release.
- `release-image` / `aztec-up` hashes still compose `wsdb` / `bb-ts`
bootstrap hashes; they can be slimmed once their consumption also goes
through pins.
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.

Projects

None yet

Development

Successfully merging this pull request may close these issues.