Skip to content

chore: port-to-v6 rolling port - #25575

Merged
IlyasRidhuan merged 19 commits into
v6from
cb/port-to-v6
Oct 4, 2026
Merged

IlyasRidhuan merged 19 commits into
v6from
cb/port-to-v6

Conversation

@AztecBot

@AztecBot AztecBot commented Oct 2, 2026 •

Copy link
Copy Markdown
Collaborator

Rolling integration PR for changes labelled port-to-v6 on next. Each merged source PR is cherry-picked onto cb/port-to-v6 as its own commit, keeping (#N) in the title.

Ported

Protocol impact

Testing


Created by claudebox · group: slackbot · Slack thread

@AztecBot AztecBot added ci-draft Run CI on draft PRs. ci-no-fail-fast Sets NO_FAIL_FAST in the CI so the run is not aborted on the first failure claudebox Owned by claudebox. it can push to this PR. labels Oct 2, 2026
@IlyasRidhuan
IlyasRidhuan marked this pull request as ready for review October 4, 2026 10:34
@IlyasRidhuan IlyasRidhuan added the ci-full Run all master checks. label Oct 4, 2026
AztecBot and others added 13 commits October 4, 2026 12:54
Refs AztecProtocol/aztec-claude#857

## Problem

`meter_gas_used` (`private-kernel-lib/src/components/gas_meter.nr`)
charges `FIXED_AVM_STARTUP_L2_GAS` (20_000, "base cost for a single
public call") once per entry of `end.public_call_requests`. The teardown
call is stored in its own field, `public_teardown_call_request`, so it
is never counted there. For teardown the meter adds only
`teardown_gas_limits`, and the AVM later refunds that against the
teardown's actual usage (`total_gas = gas_used + (gas_used_by_teardown -
teardown_gas_limit)`). The AVM dispatches the teardown call through the
same enqueued-call path as setup and app-logic calls, and it charges no
startup gas of its own. As a result, every public tx with a teardown
call is metered 20_000 L2 gas below the per-call pricing model.
`TailToPublicOutputValidator::validate_gas_used` pins `gas_used` to the
meter's output.

## Change

- `gas_meter.nr`: when a teardown call request is present, add
`Gas::new(0, FIXED_AVM_STARTUP_L2_GAS)` alongside `teardown_gas_limits`.
This reuses the existing `!is_for_public | is_empty()` branch rather
than adding a second teardown predicate. Private-only txs and public txs
without a teardown call are metered exactly as before.
- `labs-patches/0001-...patch`: the PXE mirror in
`generateSimulatedProvingResult`
(`yarn-project/pxe/src/contract_function_simulator/contract_function_simulator.ts`)
adds the same startup gas in its existing `if
(publicTeardownCallRequest)` branch. The TS `meterGasUsed` only sees the
accumulated-data halves, not the teardown request, so the teardown
branch is the one place where both meters can charge it the same way.
Gas estimation runs on kernelless simulation, so without this patch a tx
with a teardown call would be estimated 20_000 L2 gas below the
`gas_used` the kernel proves.

## Tests (red then green)

In `validate_gas_used_tests.nr`
(`tests/tail_to_public_validators/tail_to_public_output_validator/`):

- `with_teardown_call_request` now expects `teardown_gas_limits +
Gas::new(0, FIXED_AVM_STARTUP_L2_GAS)` on top of the minimum public tx.
- `full_side_effects` now expects `(MAX_ENQUEUED_CALLS_PER_TX + 1) *
FIXED_AVM_STARTUP_L2_GAS`; the `+1` is its teardown call.

Both tests drive the real terminal path
(`validate_previous_kernel_for_tail`, then `tail_to_public_finalize`,
which runs `TailToPublicOutputValidator::validate`).

Run on `next` @ `411a411842e` with `nargo 1.0.0-rc.3+5a7ee9bf` (the
`noir/noir-repo` pin):

```
cd noir-projects/fnd/noir-protocol-circuits/crates/private-kernel-lib
# tests updated, gas_meter.nr as on next:
nargo test --silence-warnings validate_gas_used_tests   # 23 passed, 2 failed (with_teardown_call_request, full_side_effects)
# with the fix:
nargo test --silence-warnings                            # 1043 passed
nargo fmt --check                                        # clean
```

The labs side has no unit-level test. Its red→green coverage is the e2e
`single-node/fees/gas_estimation.parallel.test.ts` › "estimates gas with
public payment method" (a tx with an FPC teardown call), which asserts
the estimated fee equals the fee of the sent tx. It was not run locally;
CI covers it. The patch applies with `git am --3way` onto the pinned
`labs` commit `54e3383c4b`.

## Notes for review

- This is a repricing: `gas_used.within(gas_limits)` means a
public-with-teardown tx whose limits sit within 20_000 L2 gas of its
usage becomes unprovable until it is re-estimated.
- A teardown request that is present but has a zero callee
(AztecProtocol/aztec-claude#533) now also pays the startup gas, which
only increases what such a tx is charged.

🤖 Generated with [Claude Code](https://claude.com/claude-code)

---
*Created by
[claudebox](https://claudebox.work/v2/sessions/49b51266962c69a3/jobs/3)
· group: `slackbot` · requested by Mike (@iAmMichaelConnor) · [Slack
thread](https://aztecfoundation.slack.com/archives/D0B2N7W1WJD/p1790276959367319?thread_ts=1790276959.367319&cid=D0B2N7W1WJD)*

(cherry picked from commit 21b2e32)
Drop labs-patches/0001: the labs pin on v6 (a0d73c0aed) already carries
the PXE mirror upstream as aztec-labs-eng/aztec-node#364, so the patch
has nothing to apply to and the series stays empty.
Charging the teardown call's AVM startup gas changes the private kernel
circuits, so the VK tree root v6 builds moves to
0x21f06c3b82320ea5f80646751cdd9fa023dfd61400a42b8c952aa32e8f155793. Labs
patch 0001 re-pins testnet_compatibility.test.ts to it; the protocol
contracts hash and genesis root are unchanged.
…(labs patch) (#25576)

This adds labs patch `0010`. With it, `DataTxValidator` rejects a
contract class log whose `length` is anything other than its trimmed
length (`1 + lastNonZeroIndex`). Before, it only rejected lengths below
that.

The tx base requires exactly the trimmed length. So a node that accepts
`length > trimmed` can admit and include a tx that nobody can prove, and
its epoch can't be proven either. Honest producers already emit the
trimmed length, so valid txs are unaffected.

The patch changes the comparison and its log message. In the existing
`rejects txs with mismatched contract class logs length` test, the
`length += 1` case that was asserted valid is now asserted invalid.

Fixes AztecProtocol/aztec-claude#2485

Tested locally: the full series applies with `git am` on the labs
gitlink `54e3383c4b`, and prettier passes on the changed files. The jest
tests haven't run; CI will be their first run.

---
*Created by
[claudebox](https://claudebox.work/v2/sessions/0dda1b136c5cf7a7/jobs/9)
· group: `slackbot` · requested by Mike (@iAmMichaelConnor) · [Slack
thread](https://aztecfoundation.slack.com/archives/D0B2N7W1WJD/p1790933755978059?thread_ts=1790933755.978059&cid=D0B2N7W1WJD)*

(cherry picked from commit a773535)
…5577)

## Problem
`l1-contracts/generated/HonkVerifier.sol` is copied from
`noir-projects/fnd/noir-protocol-circuits/target/keys/rollup_root_verifier.sol`,
which is produced by compiling the protocol circuits with `nargo`. The
`l1-contracts-verifier-$hash` and `l1-contracts-ts-$hash` artifacts
therefore depend on the `noir/noir-repo` commit. The l1-contracts cache
hash only listed `../noir/.rebuild_patterns`, which matches
`^noir/bootstrap.sh` and not the submodule gitlink. So a Noir-only bump
left the hash unchanged and reused the cached verifier and TypeScript
artifacts from before the bump.

## Fix
`l1-contracts/bootstrap.sh` now builds its hash the same way the other
Noir consumers do (`avm-transpiler/bootstrap.sh`, and `NOIR_HASH` in
`noir-projects/fnd/noir-protocol-circuits/bootstrap.sh`):

```bash
export hash=$(hash_str $(../noir/bootstrap.sh hash) $(cache_content_hash \
  .rebuild_patterns \
  ../noir-projects/fnd/noir-protocol-circuits \
  ../barretenberg/cpp/.rebuild_patterns
))
```

`noir/bootstrap.sh hash` is `hash_str <noir-repo commit> <noir rebuild
patterns>`, so it already covers `noir/bootstrap.sh`. The explicit
`../noir/.rebuild_patterns` entry is therefore removed. `hash_str`
passes a `disabled-cache` content hash through unchanged, so dirty-tree
behaviour is the same.

## Trade-off
l1-contracts uses one hash for `build_src`, the verifier, the TS
artifacts and its tests. A Noir bump now invalidates all of them,
including `l1-contracts-src`, which does not depend on the circuits. The
same hash already rotates on any change under `noir-protocol-circuits`,
and Noir bumps are infrequent, so the single hash is kept.

## Tests
There is no unit-test harness for bootstrap hashes, so this is a
reproducible check across 7d61007 ("chore: update Noir to
v1.0.0-rc.3"), which changes the `noir/noir-repo` gitlink plus two files
that are not l1-contracts inputs.

Run from `l1-contracts`:
```bash
NO_CD=1 source ../ci3/source
for c in 7d61007^ 7d61007; do
  export AZTEC_CACHE_COMMIT=$(git rev-parse $c)
  old=$(cache_content_hash .rebuild_patterns ../noir/.rebuild_patterns ../noir-projects/fnd/noir-protocol-circuits ../barretenberg/cpp/.rebuild_patterns)
  noir=$(hash_str $(git rev-parse $c:noir/noir-repo) $(cd ../noir && cache_content_hash .rebuild_patterns))
  new=$(hash_str $noir $(cache_content_hash .rebuild_patterns ../noir-projects/fnd/noir-protocol-circuits ../barretenberg/cpp/.rebuild_patterns))
  echo "$c noir-repo=$(git rev-parse --short $c:noir/noir-repo) old=$old new=$new"
done
```
Output on this branch's base:
```
7d61007^ noir-repo=0ecc97a242e old=d81cb180157f7564 new=011632566d883a46
7d61007  noir-repo=5a7ee9bf5ed old=d81cb180157f7564 new=0f66c61198db6e31
```
The old formula gives the same hash on both sides of the bump; the new
one does not.

The same change was also run as a real build: with a different Noir
commit checked out in the submodule, `./bootstrap.sh build_verifier`
under the old hash restored the previously cached
`generated/HonkVerifier.sol`, and under the new hash it missed the
cache, copied the current circuits-side verifier and compiled it with
forge. With the Noir commit unchanged the new hash is stable and hits
the cache.

## Out of scope
`noir/bootstrap.sh` reads the Noir commit with `git -C noir-repo
rev-parse HEAD`. With the submodule uninitialised that resolves to the
superproject HEAD, which is unique per commit and so only causes cache
misses. Every Noir consumer shares this behaviour and it is left
unchanged.

Closes AztecProtocol/aztec-claude#1955

---
*Created by
[claudebox](https://claudebox.work/v2/sessions/f45fcb875796a470/jobs/11)
· group: `slackbot` · requested by Mike (@iAmMichaelConnor) · [Slack
thread](https://aztecfoundation.slack.com/archives/D0B2N7W1WJD/p1790886022336469?thread_ts=1790886022.336469&cid=D0B2N7W1WJD)*

(cherry picked from commit f7ee597)
…e L1 verifier (#25578)

## Problem
`generate_vk` in `noir-projects/fnd/noir-protocol-circuits/bootstrap.sh`
cached each circuit's VK under `BB_HASH`, the bytecode hash, the circuit
name and a hand-bumped `-3`. Two inputs were missing:

- **The scheme and circuit kind.** These are chosen by `circuit_kind`
from `chonk_circuits.json` and `rollup_honk_circuits.json`, and mapped
to `bb write_vk` flags by the script. A change to a manifest or to the
flag mapping left the key unchanged, so the shared cache served the VK
for the previous scheme.
- **The Solidity verifier flags.** For `rollup_root`, the same cache
entry also carried `rollup_root_verifier.sol`. A change to the `bb
write_solidity_verifier` flags left the key unchanged, so the cache
restored the previous verifier. `l1-contracts` then copied that file
into `generated/HonkVerifier.sol` and compiled it.

Nothing on `next` compares the compiled `HonkVerifier` with its source,
so a stale L1 verifier would go unnoticed.

## Fix
- **VK cache key.** The key is now `BB_HASH`, bytecode hash, name, the
circuit's kind, and the content hash of `bootstrap.sh`. The kind
captures what the manifests decide for that circuit. The script hash
captures the kind-to-flags mapping. That hash is computed once as
`script_hash` and shared with the `compile` key, which already used it;
the `compile` key's value is unchanged. The manual `-3` epoch is gone.
- **Solidity verifier.** It is no longer stored in the cache.
`generate_vk` writes it on every build from the current VK and the
current flags, so it cannot be stale.
- **Freshness check.** `l1-contracts` `test_cmds` gains one test on
every branch: `cmp generated/HonkVerifier.sol` against
`target/keys/rollup_root_verifier.sol`. Its test-cache key includes the
digest of the source verifier, so it reruns whenever that verifier
changes even if the l1-contracts hash does not.

## Suggestions from the issue not taken
- **Make `check_pinned_vk` bypass the cache.** With the complete key, a
cache hit is a VK computed from the same bb, bytecode, kind and script.
Bypassing the cache would regenerate every VK on every pinned build,
which removes the benefit of the pin.
- **Output-addressed `l1-contracts-verifier` key.** It does not help
this path (a stale file has the same digest), and it needs
`l1-contracts` hashing to be restructured. The freshness check covers
the l1-side cache instead.

## Effects to expect
- Every VK cache entry is regenerated once, because the key formula
changed.
- Any later edit to this `bootstrap.sh` regenerates all VKs. The
`compile` key already recompiles all circuits in that case.
- `bb write_solidity_verifier` runs once per build for `rollup_root` and
`mock_rollup_root`, including on cache hits. It takes under a second.

## Tests
On this branch: `bash -n` on both bootstrap scripts, and
`scripts/circuit_kind.test.sh` passes (18 of 18). The full build is
covered by CI.

The same diff was exercised as a real build before this PR was opened,
on a checkout where the touched hunks are identical, against the shared
build cache with uploads disabled:

1. **Warm and cold paths agree.** `./bootstrap.sh compile rollup-root`
(VK from the cache) and `NO_CACHE=1 ./bootstrap.sh generate_vk
rollup_root` (VK regenerated) produced identical VK bytes and the same
`rollup_root_verifier.sol` (sha256 `a7bf113d…`, 327,282 B).
2. **Verifier-flag change.** With a commit that only drops
`--optimized`, the old code hit the VK cache and restored the optimized
verifier (`a7bf113d…`). With this change the build wrote `c7f26a79…`
(96,610 B), which equals a direct `bb write_solidity_verifier` without
`--optimized` on the same VK.
3. **Manifest-only change.** With a commit that only adds `inbox_parity`
to `rollup_honk_circuits.json`, the old code kept the same VK cache key
and served the VK for the old kind. With this change the key moved and
the VK was regenerated with different bytes.
4. **l1 freshness test.** With `generated/HonkVerifier.sol` restored
from the l1 cache, the `cmp` test exited 1 (`differ: byte 1, line 1`)
when the circuits-side verifier was different and 0 when it matched. Its
test-cache key differed between the two cases.

Not run: the pinned-build path (`pinned-build.tar.gz` is absent on
`next`).

## Related
#25577 fixes the separate Noir-commit omission in the `l1-contracts`
hash (AztecProtocol/aztec-claude#1955). The two PRs touch different
parts of `l1-contracts/bootstrap.sh` and do not depend on each other.

Closes AztecProtocol/aztec-claude#2122

---
*Created by
[claudebox](https://claudebox.work/v2/sessions/f45fcb875796a470/jobs/11)
· group: `slackbot` · requested by Mike (@iAmMichaelConnor) · [Slack
thread](https://aztecfoundation.slack.com/archives/D0B2N7W1WJD/p1790886022336469?thread_ts=1790886022.336469&cid=D0B2N7W1WJD)*

(cherry picked from commit b0a7559)
… non-revertible note hash (#25579)

## Summary

The tail kernel checks every nullifier that survives with a non-zero
`note_hash` link: the link must equal the output value of a surviving
note hash from the same contract with a lower counter. This PR adds one
condition in tail-to-public: the matched note hash must be
**non-revertible** (`counter < min_revertible_side_effect_counter`).

The private-only tail does not run the new check. There every note hash
is output unique, so the check could never fail, and the circuit is
unchanged.

## Why

The check compares the link with the terminal reset's output as-is. It
does not recompute a unique note hash. In a tx with public calls that
output is:

```
non-revertible note hash -> unique   u = H(nonce, s)
revertible note hash     -> siloed   s   (the AVM applies the nonce later)
```

The one pair that legitimately survives to the tail is a note created
before `end_setup` and nullified after it. Its link is `u`, and the
check is what pins the oracle-supplied nonce behind it. A revertible
note hash's output is `s`, so before this PR a nullifier linked to `s`
passed the value check too. The note then settles as `u` while its
nullifier was derived from `s`, so the note can be spent again later.

Only the app circuit can write such a link. Honest aztec-nr never writes
`s` (it writes `0`, the inner hash, or `u`), so no legitimate tx is
rejected, and a prover cannot change an honest app's link. Siloing
confines the effect to the misbehaving contract's own notes, so this is
hardening: it makes the check match its intent.

Comments next to the checks say what the note hash side of the
comparison holds, why a revertible match is rejected, and what these
checks cannot catch: an app that misstates its own link.

## Related issues

This PR does not fully resolve an open issue, so it carries no closing
keyword.

- Part of AztecProtocol/aztec-claude#1605. That issue's executed witness
links a nullifier to the siloed value of a revertible decoy note in a tx
with public calls. This PR rejects it. Two shapes from that issue still
pass after this PR: a decoy link to a non-revertible note's unique hash,
and a zero link on a pending note (AztecProtocol/aztec-claude#1739). A
nullifier's value is opaque to the kernel, so no kernel check can rule
those out; the new code comment records that boundary.
- Part of AztecProtocol/aztec-claude#2441. This PR adds two public-bound
tests that run the terminal reset and then the tail check for a
non-revertible linked pair, which that issue asks for. Its doc-comment
and private-only fixture items are not addressed here.

## Tests

`private_kernel_lib`, `nargo 1.0.0-rc.3` (tagged at the pinned
`noir/noir-repo` commit `5a7ee9bf5e`): full crate, 1048 passed, 0
failed. `nargo fmt --check` clean.

Validator tests, on a prebuilt previous kernel:
- `tail_to_public_validators::nullifier_linked_to_revertible_note_hash`:
link to a revertible note's siloed value, rejected. With the new
assertion removed it reports `Test passed when it should have failed`.
-
`tail_to_public_validators::nullifier_linked_to_non_revertible_note_hash`:
note before `end_setup`, nullifier after, accepted.
- `tail_validators::nullifier_linked_to_note_hash_after_end_setup`:
private-only tx, note after `end_setup`, accepted. It fails if the new
check also runs in the private-only tail.

Reset followed by the tail check, as
`private_kernel_reset_tail_to_public` runs them
(`private_kernel_reset::siloing_tests`):
-
`nullifier_linked_to_previous_phase_unique_note_hash_is_accepted_by_tail`:
an unsiloed note hash before `end_setup` and a nullifier after it,
linked to the unique hash computed for the note's index. The reset keeps
both and the tail accepts the link.
- `nullifier_linked_with_wrong_note_nonce_is_rejected_by_tail`: the same
pair with the unique hash computed for a different index. The tail
rejects it, which is the constraint that pins the nonce.

## Gate cost

- **Private-only tail: +0.** `is_for_public` is known at compile time,
so the check is not compiled in. The compiled
`private-kernel-reset-tail` bytecode is byte-identical to the one built
from `next`.
- **Tail-to-public:** one `u32` comparison per nullifier slot, 64 slots
in every variant (5 ACIR opcodes per slot). A costlier form of the same
check (7 opcodes per slot) measured +400 gates per variant with `bb
gates --scheme chonk`, so this should be at or below that. CI reports
the exact count.

## Compatibility

Changes behaviour only for a witness shape no honest client produces.
Circuit bytecode and VKs change for
`private-kernel-reset-tail-to-public` only; no genesis constant depends
on them.

---
*Created by
[claudebox](https://claudebox.work/v2/sessions/7305da0f9f6e9e0c/jobs/22)
· group: `slackbot` · requested by Mike (@iAmMichaelConnor) · [Slack
thread](https://aztecfoundation.slack.com/archives/D0B2N7W1WJD/p1790888798827949?thread_ts=1790888798.827949&cid=D0B2N7W1WJD)*

(cherry picked from commit 25cd834)
…esolve to a non-revertible note hash

The non-revertible link check changes the private-kernel-reset-tail-to-public
circuits, so the VK tree root v6 builds moves to
0x05b95d9ef57c61d1c6626545101db55ae2d1f98ecb618d1c220610c049ee522b. Labs
patch 0001 pins testnet_compatibility.test.ts to it; the protocol
contracts hash and genesis root are unchanged.
The Grumpkin IPA SRS is reproducible from a fixed seed, but the native
loader only checked whether the first point was on curve and the BB API
ingress did not authenticate its input. A modified cache or downloaded
artifact could therefore substitute points with known discrete-log
relationships and undermine IPA binding.

Pin SHA-256 hashes for all four 65536-point chunks of the canonical v2
SRS and authenticate the bytes before deserializing points:

- Native loads read and verify complete chunks covering the requested
prefix. Short caches are regenerated to a complete chunk boundary when
generation is allowed; otherwise they are rejected. Generated caches are
verified before writing.
- BB API ingress requires one to four complete chunks and verifies every
supplied byte. Empty, partial, oversized, or corrupted buffers and
out-of-range point counts are rejected. The requested point count may
select a smaller prefix of the authenticated buffer.
- Tests bind the pins to both the deterministic generator and the v2
artifact, and cover tampered caches, short-cache regeneration,
corruption in every chunk, and API input coverage.

Targets `next`, which already contains the canonical generator fix and
v2 artifact migration. The standard bb.js initialization supplies one
complete chunk and remains compatible. The canonical generators and
pinned hashes are unchanged by the follow-up fixes.

Validation: reproduced the short-cache and incomplete-buffer bypasses
with failing regression tests before fixing them. The SRS suite passes
(37 passed, one skipped; one additional test disabled). BB API tests
excluding `ChonkPinnedIvcInputsTest.*` pass (39 passed). A WASM build
and the pinned Chonk flow suite were not run locally.

---------

Co-authored-by: iakovenkos <sergey.s.yakovenko@gmail.com>
Co-authored-by: sergei iakovenko <105737703+iakovenkos@users.noreply.github.com>
(cherry picked from commit 08f90e6)
…d an inactive squashing hint (#25580)

Test-only. No circuit change and no VK change: one test and its import
in `validate_transient_data_squashing_hints.nr`.

Refs AztecProtocol/aztec-claude#2313.

## What the test covers

`validate_transient_data_squashing_hints` proves that the active hints'
nullifier indices are unique through a sorted side-table of `(elem,
original_index)` tuples. A prover controls those tuples.
`fails_duplicate_nullifier_index_with_sorted_tuple_from_inactive_hint`
builds the forgery the last step of that argument exists to stop:

- two active hints share nullifier index 0;
- the second sorted tuple points at an inactive hint, so it carries the
sentinel index instead of the repeated 0 and the "increasing order"
check passes;
- one extra `nullifier_squash_flags` entry is set, so the removed-count
check balances and a nullifier that no hint names would be dropped.

With a full nullifiers array (claimed length equal to the sentinel), the
circuit rejects this at `Nullifier index hint exceeds claimed length`.
The existing duplicate tests use honestly derived tuples and are
rejected one step earlier, so nothing covered this path.

## Why it is worth having

Mutation check: replacing the range check on the last sorted value with
a range check on each active hint's `nullifier_index` (a plausible
refactor that keeps every other test green) makes the circuit accept
this witness. All 92 existing `reset::transient_data` tests still pass
under that mutation; this test fails with `Test passed when it should
have failed`.

## Checks run locally

Pinned `nargo` 1.0.0-rc.3: the 9 tests in this file pass and `nargo fmt
--check` is clean. The rest is left to CI.

---
*Created by
[claudebox](https://claudebox.work/v2/sessions/bcd0da92a2cf9af3/jobs/14)
· group: `slackbot` · requested by Mike (@iAmMichaelConnor) · [Slack
thread](https://aztecfoundation.slack.com/archives/D0B2N7W1WJD/p1790886272710929?thread_ts=1790886272.710929&cid=D0B2N7W1WJD)*

(cherry picked from commit b1b6871)
Caused some issues to close while just being mentioned

(cherry picked from commit 411a411)
…yte length (#25566)

## Summary

`poseidon2_hash_bytes` packs its input into 31-byte little-endian chunks
and returns `poseidon2_hash` of the resulting fields. The hash commits
to the number of chunks but not to the byte length, so zero bytes at the
end of the last chunk do not change the result: `[1]`, `[1, 0]` and `[1,
0×30]` hash to the same value.

This PR documents that property and pins it with tests. It does not
change the function.

## Why the function is unchanged

All callers hash fixed identifiers: string literals (domain separator
names, a few literal identifiers, hand-written selector signatures) or
signatures the aztec-nr macros build from function and type names. None
of these contains a zero byte, no Noir caller passes runtime bytes, and
the derived domain separators are asserted unique by
`constants_tests.nr`. Changing the encoding in place would rotate every
selector and every derived domain separator, which is not justified.

This is a statement about the current callers, not about the encoding:
two identifiers that differ only by trailing zero bytes in the last
chunk still hash to the same value, and a caller that commits to
variable-length data with this function, for example a payload
zero-padded to a maximum length, would accept `m` and `m‖0` as the same
message. The doc comment tells callers to bind the length separately.

## Changes

- Doc comment on `poseidon2_hash_bytes` describing the packing, the
missing byte-length commitment, and the intended use (fixed strings).
- `poseidon2_hash_bytes_matches_hash_of_packed_chunks`: the result
equals `poseidon2_hash` of the little-endian 31-byte chunks.
- `poseidon2_hash_bytes_ignores_trailing_zeros_in_last_chunk`: `[1]`,
`[1, 0]` and `[1, 0×30]` hash to the same value.
- `poseidon2_hash_bytes_commits_to_chunk_count`: the 31-byte and 32-byte
inputs `[1, 0, ...]` hash differently.

A comment and tests only: no constraints, VKs or constants change.

## Considered and dropped

Adding `std::assert_constant(inputs)` in constrained code, so that a
private function passing witness bytes would fail to compile, was tried
and dropped:

- it had no effect on current callers, which all pass constants;
- it could not cover unconstrained code, which includes public
functions, because helpers taking the string as a parameter are not
inlined there (the aztec-nr domain separator test has that shape);
- it rejected safe constrained uses, such as fixed-length runtime bytes
and literals passed through a `#[fold]` function.

## Testing

`nargo test poseidon2_hash_bytes` in
`noir-protocol-circuits/crates/types`: 3 tests passed. `nargo fmt
--check` is clean.

(cherry picked from commit 4f4bef8)
AztecBot and others added 6 commits October 4, 2026 12:54
Review follow-up for #25582, which merged before this was opened. No
contract logic changes.

Refs AztecProtocol/aztec-claude#2467

## Tests

- **Shares are replaced on upgrade** (`handleRewards.t.sol`,
`test_WhenTheProofIsFullEpoch`). Before, the prover had the minimum
shares before and after the upgrade, so a version of the code that kept
the old shares passed all tests. The test now raises the prover's score
first (560 full-epoch proofs), then asserts that the upgrade stores
different shares.
- **Invalidated-tail trigger** (`ValidatorSelection.t.sol`,
`testFullEpochProofUpgradesRegistrationAfterTailInvalidation`). An epoch
ends with a valid checkpoint and a checkpoint with too few attestations.
A proof of the first checkpoint is not full-epoch. After
`invalidateInsufficientAttestations`, the same proof is full-epoch,
upgrades the registration and increases the score. This is trigger (2)
of the issue.
- `test_GivenTheExistingRegistrationIsFullEpoch` asserts that a first
full-epoch proof sets `getHasSubmittedFullEpoch`.

## Other changes

- `RewardLib.sol`: one correction to the `fullEpoch` field comment. It
said the flag is set when the registration "was submitted after the
epoch is closed". A partial proof submitted after the epoch closed does
not set it; the flag is set by a full epoch proof.
- `RewardLibWrapper`: the two-argument `handleRewardsAndFees` calls the
three-argument overload.

## Checks run locally

- `forge fmt --check`
- `forge test` on `MultiProof.t.sol`, `ValidatorSelection.t.sol` and
`handleRewards.t.sol`: 43 pass.
- Two deliberate breakages of `RewardLib.handleRewardsAndFees`, both
fail the tests: keep the old shares on upgrade (fails
`test_WhenTheProofIsFullEpoch`), and remove the upgrade path (fails the
new integration test and two existing tests).

The full suite is left to CI.

## Not in this PR

The prover node still skips submission when `getHasSubmitted` is true
(`yarn-project/prover-node/src/prover-node-publisher.ts`, aztec-node
repo). It must use `getHasSubmittedFullEpoch` for full-epoch proofs
before the issue is fixed for honest provers. That change needs a
separate PR in `aztec-labs-eng/aztec-node`.

---
*Created by
[claudebox](https://claudebox.work/v2/sessions/966f467da8c8b731/jobs/7)
· group: `slackbot` · requested by Mike (@iAmMichaelConnor) · [Slack
thread](https://aztecfoundation.slack.com/archives/D0B2N7W1WJD/p1790965530798319?thread_ts=1790965530.798319&cid=D0B2N7W1WJD)*

(cherry picked from commit 99b8b97)
Removes the per-registry checkpoint reward overrides built into the
rollup (#25312, #25426, #25461), ahead of AZIP-28, which moves sequencer
reward policy into a governance-set calculator contract (next PR in this
stack).

- Restores the pre-override reward path: every proposer gets the default
sequencer share, with the pre-override arithmetic (including dust to the
prover).
- Keeps the proof-submission optimizations (#25404, #25406, #25419) and
all later v6 work in the touched files.
- Removes the override config
(`RollupConfigInput.registryRewardOverrides`,
`AZTEC_REGISTRY_REWARD_OVERRIDE_*`), the `getRegistryRewardOverrides`
getter, the ATP probes, their errors, tests, mocks and the mainnet
fixture (the fixture comes back in the reduction-calculator PR).
- Gas reports regenerated; partial epoch proof gas is back to within
~100 gas of pre-override numbers.

Rollup bytecode: 23,947 bytes (629 spare). `forge test`: 1089 passed, 0
failed.

## Gas across the stack

Partial epoch proof submission gas from
`partial_epoch_proof_gas_report.md` (mock epoch proof verifier,
48-member committee fixture). Rows 3–5 come from the top of the stack
(#25573). Δ is measured against row 1 at 32 checkpoints.

| | 1 checkpoint | 8 checkpoints | 16 checkpoints | 32 checkpoints | Δ
at 32 |
|---|---:|---:|---:|---:|---:|
| 1. Before the reward-override stack (`819a18a4365`) | 654,930 |
956,937 | 1,246,308 | 1,732,713 | — |
| 2. Reward-override stack merged (`6c514c6e442`), no overrides
configured | 658,562 | 963,412 | 1,256,031 | 1,748,935 | +16,222 |
| **2b. Reward-override stack, two overrides, two shared mock stakers**
| 688,985 | 1,071,574 | 1,437,827 | 2,031,299 | +298,586 |
| 3. This stack, no calculator configured | 656,517 | 954,825 |
1,239,917 | 1,717,875 | −14,838 |
| 3b. This stack, table-lookup calculator (one storage read per
proposer) | 677,325 | 1,017,817 | 1,346,913 | 1,893,982 | +161,269 |
| **4a. Reduction calculator, two shared mock stakers (same scenario as
2b)** | 692,905 | 1,086,424 | 1,474,921 | 2,130,609 | +397,896 |
| **5a. Premium calculator, two shared premium stakers (same scenario as
2b)** | 714,982 | 1,169,970 | 1,604,427 | 2,319,016 | +586,303 |
| 4b. Reduction calculator, one cold mainnet-shaped position per
validator | 702,626 | 1,165,408 | 1,621,316 | 2,363,373 | +630,660 |
| 5b. Premium calculator, one cold position per validator | 700,404 |
1,173,877 | 1,633,453 | 2,430,012 | +697,299 |

**Rows 4a and 5a are the ones to compare with the old implementation
(2b).**
- They use 2b's scenario: two registries, two shared stakers, validators
alternating between them by index, and every proposer matched.
- At 32 checkpoints the reduction calculator costs 99,310 more than the
in-rollup overrides, and the premium calculator 287,717 more.
- 4a uses the same 10e18 / 20e18 rewards as 2b.
- 5a pays 30e18 / 40e18, above the 25e18 default. A premium calculator
pays rewards at or below the default without checking provenance, so
2b's values would have skipped the three authentication probes (`isATP`,
`getStaker`, `isAttester`). Its stakers are genuine positions created by
the factory, so their `isAttester` reads are per attester.

**Rows 4b and 5b** are the worst honest case. Every validator has its
own position, so no lookup is warmed by another proposer.
- 4b mirrors mainnet: a proxy staker and a clone ATP per validator,
across three registries paying ½, ¼ and 1× the default.
- 5b splits the validators into thirds: genuine premium positions,
reduced positions, and fake withdrawers that are rejected.

**Other notes**
- Row 3 is below row 1 because this stack keeps the proof-submission
optimizations (#25404, #25406, #25419).
- With a calculator configured, the rollup's own overhead is about 14k
fixed plus 1.3k per checkpoint, measured with a calculator that returns
the defaults. The rest is the calculator's own execution, bounded by the
stipend of 200k + 100k per checkpoint.

(cherry picked from commit 8debae0)
Implements AZIP-28: the rollup calls a governance-set
`ISequencerRewardCalculator` once per epoch proof to get one sequencer
reward per newly proven checkpoint.

**Rollup changes**
- `sequencerRewardCalculator` in the namespaced reward storage;
`setSequencerRewardCalculator` (owner only, emits
`SequencerRewardCalculatorUpdated(old, new)`),
`getSequencerRewardCalculator`, optional initial value via
`RollupConfigInput.sequencerRewardCalculator` /
`AZTEC_SEQUENCER_REWARD_CALCULATOR` (default zero). Setter/getter go
through `RewardExtLib` for bytecode size.
- Proposers are derived from the committee the proof already verifies
(slot + sample seed). Escape-hatch epochs and empty committees skip the
calculator.
- `SequencerRewardCalculatorLib`: `staticcall` with exactly
`CALCULATOR_GAS_BASE + n * CALCULATOR_GAS_PER_CHECKPOINT` (200k +
100k·n). Nothing is copied unless `returndatasize == 64 + 32n`; the head
must be offset 32 / length n; every value `<=
MAX_SEQUENCER_REWARD_PER_CHECKPOINT` (1e24). Any failure pays the
default to every checkpoint.
- Distribution: no calculator, skipped, or rejected response uses the
pre-AZIP arithmetic exactly. An accepted response draws `n ×
(checkpointReward − default) + Σ rewards`, scales sequencer rewards by
`available / desired` under shortfall, and gives the prover the
remainder. Prover rewards are now written to storage once per proof.

**Deviations from the AZIP text (spec should be amended)**
- The rollup reverts with
`SequencerRewardCalculatorLib__InsufficientGas` if the transaction
cannot forward the full stipend (EIP-150 63/64 rule plus a 10k reserve).
Otherwise the prover could starve the calculator and force defaults. The
requirement depends on constants only (≈3.46M at n = 32), so
`eth_estimateGas` covers it.
- Under a distributor shortfall the prover's payout depends on the
calculator's values (it is a consequence of the AZIP's proportional
rule); "prover share MUST NOT depend on the calculator" holds only
without a shortfall.
- A calculator that returns exactly the default can differ from the
zero-calculator split by at most 1 wei per checkpoint, only under a
shortfall and only when `checkpointReward * bps` is not a multiple of
10,000.

**Gas (partial epoch proof, mock verifier)**: no calculator 656,493 /
954,823 / 1,240,004 / 1,717,873 for 1 / 8 / 16 / 32 checkpoints (−14.9k
at 32 vs. the previous PR). Rollup's own overhead with a calculator:
~14k + ~1.3k per checkpoint.

Rollup bytecode: 24,131 bytes (445 spare). Every AZIP "Test Cases"
bullet maps to a test (unit, fuzz, through-the-rollup, escape hatch,
zero-size committee, deploy config, gas rows at 1/8/16/32). `forge
test`: 1164 passed, 0 failed.

`RollupConfigInput` gains a trailing `address`; no labs change needed.
Client mirrors (node-side reward prediction) are left for a follow-up in
aztec-node, since no predictor exists today.

(cherry picked from commit c85ce19)
…25572)

Adds a reference `ISequencerRewardCalculator` in
`l1-contracts/test/reward-calculators/reduction/` that pays reduced
rewards to positions of configured ATP registries, i.e. the policy from
#25312/#25426 expressed as an AZIP-28 calculator. Test-only; no `src/`
change.

- Resolves `GSE.getWithdrawer(attester) → withdrawer.getATP() →
atp.getRegistry()` with never-reverting probes (`ProbeLib`: code check,
20k gas stipend, exactly 32 bytes, clean upper bits).
- Owner-set table `registry → reward`; pays `min(default, entry)`
(capped at read time, so a later `setRewardConfig` can never turn an
entry into a premium). Everyone else gets the default.
- Dedupes proposers in memory, caches per attester, returns one value
per input in order, never reverts.
- Shared pieces for the premium calculator: `ProbeLib`, `IATP`, ATP
mocks (incl. mainnet-shaped ERC1967 staker / EIP-1167 ATP and
adversarial getters), `FakeGSE`.

**Mainnet fork test**: `test/fork/MainnetReductionCalculator.t.sol`
deploys the calculator against the real mainnet GSE using real
attester/staker/ATP cases (auction and genesis-sale registries, v1/v2
stakers, a StakingRegistry-provided validator). It runs offline from
`test/fixtures/mainnet_atp_reduction_calculator.json` (block
25,934,884); refresh with `MAINNET_ATP_FIXTURE_RPC_URL`. Real cold probe
costs: `getATP` 7,288 gas, `getRegistry` 2,923.

**Gas** (worst case: cold, distinct proposers, expensive successful
probes): 62,799 / 450,789 / 907,957 / 1,866,299 at n = 1 / 8 / 16 / 32,
i.e. ≤ 55% of the stipend. Through the rollup at n = 32: 2,363,417.

`forge test`: 1239 passed, 0 failed.

(cherry picked from commit cc4e90f)
…ce-tracking ATPs (#25573)

Adds a reference premium `ISequencerRewardCalculator` that pays
**above** the default, plus the provenance-tracking ATP flavour it
needs, under `l1-contracts/test/reward-calculators/premium/`. Test-only;
no `src/` change.

**Why a new ATP flavour.** With today's ATPs a premium is unsafe: anyone
can deploy a withdrawer whose `getATP()` points at a contract answering
`getRegistry()` with the premium registry; anyone can clone the genuine
ATP implementation; and anyone can deposit liquid stake naming a genuine
ATP staker as withdrawer.

**Contracts**
- `PremiumATPFactory`: minter-only creation, `isATP` recorded at
creation. Bound to one GSE, which every staker it creates inherits.
- `PremiumATP`: clone, factory-only one-shot init, lock schedule, no
sweep. `claim` is bounded by the lock and by `claimed + reserved <=
allocation`.
- `PremiumATPStaker`: non-upgradeable, bound once to its ATP. Reserves
allocation before each deposit and records the attester. Provider path
checks the entry queue grew by one with this staker as withdrawer.
Stakes only into rollups on its factory's GSE (provider path included).
Exits always pay the ATP. Release is operator-only. `returnTokensToATP`
is permissionless (recovers failed-deposit refunds).
- `PremiumRewardCalculator`: table `registry → {reward,
provenanceSource}`. Entries without a source are capped at the default.
A source is accepted only if its `getGSE()` is the calculator's GSE.
Premiums require `factory.isATP(atp)`, `atp.getStaker() == withdrawer`
and `staker.isAttester(attester)`, all via 10k-gas never-reverting
probes. Per-attester cache only.

**Invariant**: per position, `claimed + reserved <= allocation`, with
`reserved = threshold × recorded attesters`; only recorded attesters
earn a premium; stake exits land in the ATP. So premium-earning stake
never exceeds the allocation, and an equal amount stays locked whoever
funded the deposit.

**GSE binding.** An attester address registers at most once per GSE, not
across GSEs. Without the binding, a rollup registry holding rollups on
two GSEs (for example after a GSE upgrade) let one reservation back two
premium-earning validators: a liquid deposit for an attester on one GSE
naming the staker, plus the staker's own stake of the same attester
address on the other. If the thresholds differed, a record made on the
lower-threshold GSE could also be paid by the higher-threshold
calculator. Factories and stakers are now bound to one GSE, and
calculators refuse factories bound to another, at configuration time, so
the check costs nothing per proposer. `PremiumGSEBinding.t.sol` covers
both scenarios with two rollups on two GSEs in one rollup registry.

**Tests**: happy path and provider path on the real Rollup/GSE (real PoP
and key-reuse checks), one test per threat (fake withdrawer, attacker
clone, liquid deposit behind a genuine staker, duplicate/front-run
deposit + refund recovery, top-up + claim, re-initialisation, two GSEs
in one rollup registry, ejecting and in-exit slashes, migration to a new
rollup, release before/after exit, re-registration, attester-initiated
exit, full slash, registry-keyed cache confusion, hostile output at each
of the six probes), invariant/fuzz over random
stake/claim/release/exit/top-up sequences, a shortfall with premiums,
gas rows through the rollup.

**Gas** (n = 32, cold, distinct, stipend 3.4M): genuine premiums
1,025,924 (30%); worst attacker-built set 1,338,620 (39%); theoretical
five-burned-probes worst 2,434,424 (72%). Through the rollup at n = 32:
2,430,012, or 2,319,016 with two shared premium stakers (same scenario
as the old two-overrides bench; see the table in #25570).

**Accepted residual risks**
- Trust roots: factory owner/minters, registry owner, the staking
registry used for the provider path (not trusted for the reservation
invariant).
- State at proof time: a fully slashed attester whose record remains
still earns the premium for checkpoints it proposed before the slash and
that are proven after it. Exposure is bounded to proposals already made.
- GSE proof-of-possession does not bind the attester, so a third party
can register a pending deposit's keys first. The genuine validator is
delayed (refund is recoverable); no premium is gained.
- Provider stakes: rewards, the premium included, go to the coinbase the
provider's node sets; the protocol does not tie it to the split
contract, so the premium's destination is provider-trusted, like base
rewards.
- `PROBE_GAS = 10k` fits the reference clone staker (~5.3k cold, ~5.7k
under EIP-8038). A production calculator over proxied stakers (~7.3k)
needs it, or `CALCULATOR_GAS_PER_CHECKPOINT`, re-derived.

The mock staking registry matches ignition's `StakingRegistry` (provider
ids from 1, exact approval, `QueueIsEmpty`). `stakeWithProvider` was
also run end to end against the real `StakingRegistry` and 0xSplits
contracts (not committed).

`forge test`: 1385 passed, 0 failed.

(cherry picked from commit 551aa41)
…laudeBox port-to-* labels (#25533)

## Why

CI in this repo no longer triggers ClaudeBox.
`.github/workflows/claudebox.yml` forwarded events to
`claudebox.work/run` with `CLAUDEBOX_API_SECRET`. That secret is not in
Aztec CI and won't be re-added, because it would let a ClaudeBox session
credential pass through CI. Every dispatch has been failing without any
error showing up.

Ports between release lines move entirely to ClaudeBox. It watches
merged PRs through the GitHub webhook, and a `port-to-<branch>` label is
all that's needed. ClaudeBox ports the change onto one rolling `cb/…`
branch per target and keeps a single PR into that branch, reporting in
#backports. The server side, the `port-to-branch` procedure and the
label list are in
[claudebox#2633](AztecProtocol/claudebox#2633).

## What this removes

**ClaudeBox dispatch**
- `.github/workflows/claudebox.yml`, which includes the `/claudebox`
comment command. Its `claude-review` job was also starting a second
review session, because claudebox-server already handles that label from
the PR webhook.
- `ci3/slack_notify_with_claudebox_kickoff`. The merge-train,
release-canary and barretenberg nightly failure alerts now post the same
Slack message through `ci3/slack_notify`, without dispatching anything.

**Backport machinery**
- `.github/workflows/backport.yml`, `scripts/backport_to_staging.sh`,
`scripts/find_missing_backports.sh`, `.backportrc.json`,
`.claude/claudebox/backport.md`, and the `/backport` skill.
- Staging-branch hooks: the backport-train auto-merge step in
`merge-train-auto-merge.yml`, the `backport-to-*-staging` trigger in
`merge-train-update-pr-body.yml`, and the backport CI-failure Slack step
in `ci3.yml`.
- `ci3/run_test_cmd`: the `backport-to-v2-staging` flake-notification
case.

**Docs**
- The root `CLAUDE.md` gets a `<release_ports>` block. It says ports are
done by ClaudeBox from `port-to-<branch>` labels, that backport
workflows or dispatch steps must not be added here, and that label and
behavior changes belong in the claudebox repo.
- `.github/NOTES.md` is rewritten around `port-to-<branch>` labels and
points to the claudebox repo. It no longer describes `v4-next`.
- The `merge-trains` and `merge-train-infra` skills no longer describe
backport trains, staging branches or dispatch.

## Labels

A PR can't change labels, so a repo admin needs to apply these. Add the
new labels before this PR and claudebox#2633 merge.

**Add**, in both `AztecProtocol/aztec-packages` and
`AztecProtocol/aztec-packages-private`:
- `port-to-v6`
- `port-to-next`

**Remove** from `AztecProtocol/aztec-packages`:
- `backport`
- `backport-to-master`
- `backport-to-staging`
- `backport-to-v2`
- `backport-to-v3`
- `backport-to-v4`
- `backport-to-v4-next`
- `backport-to-v5-next`
- `backport-to-v6`

**Remove** from `AztecProtocol/aztec-packages-private`:
- `backport-to-v5-next`
- `backport-to-v6`

`v5-next` has no `port-to-*` label. If that line still needs ports, it
takes one entry per repo in claudebox's `config.yml` plus the label.

Any open "Accumulated backports to …" PRs from `backport-to-*-staging`
branches should be merged or closed by hand. Nothing updates them once
this lands.

## Testing

- The edited workflows parse as YAML, and `bash -n` passes on the edited
ci3 scripts.
- `git grep` finds no references to `backport`, `claudebox.yml`,
`.claude/claudebox`, `slack_notify_with_claudebox_kickoff` or
`CLAUDEBOX_API_SECRET` outside changelogs, the `labs` submodule, and a
vendored header.
- End-to-end check: once the labels exist and claudebox#2633 is
deployed, merging a `port-to-v6` PR should open a #backports thread and
a rolling `cb/port-to-v6` → `v6` PR.

🤖 Generated with [Claude Code](https://claude.com/claude-code)

---
*Created by
[claudebox](https://claudebox.work/v2/sessions/6f2edaa85335b3c0/jobs/3)
· group: `slackbot` · requested by ludamad (@ludamad) · [Slack
thread](https://aztecfoundation.slack.com/archives/C0B1HE6ELG2/p1790260907101329?thread_ts=1790260907.101329&cid=C0B1HE6ELG2)*

---------

Co-authored-by: ludamad <adam.domurad@gmail.com>
(cherry picked from commit 9fdb42c)
@IlyasRidhuan
IlyasRidhuan merged commit 8fbd463 into v6 Oct 4, 2026
9 checks passed
@IlyasRidhuan
IlyasRidhuan deleted the cb/port-to-v6 branch October 4, 2026 13:29
IlyasRidhuan added a commit that referenced this pull request Oct 5, 2026
Rolling integration PR for changes labelled `port-to-v6` on `next`. Each
merged source PR is cherry-picked onto `cb/port-to-v6` as its own
commit, keeping `(#N)` in the title.

## Ported

- [x]
[#25589](#25589)
chore: blobs and docs (pick of the merge commit, `-m 1`, applied without
conflicts, plus one `fix(port)` commit)
- All eight files end up identical to `next` at 86d0021, as do the
`blob` and `rollup-lib` crates and the whole `l1-contracts` directory.
  - It adds two labs patches, which keep their `next` numbering:
- `0006-fix-blob-lib-bind-checkpoint-boundaries-into-the-blo.patch`
(`yarn-project/blob-lib`, a test fixture path and the L1 publisher
integration test)
- `0007-docs-aztec-nr-private-log-fields-past-the-log-s-leng.patch` (a
doc comment in `aztec-nr`'s `private_context.nr`)
- Every file those two patches touch has the same pre-image blob on the
`v6` labs pin `a0d73c0aed` as the patch expects.
- The `fix(port)` commit updates labs patch
`0001-test-pin-testnet-compatibility-to-the-v6-kernel-VK-t.patch` to the
VK tree root `v6` builds with this change.

## Protocol impact

- The blob commitments hash now binds checkpoint boundaries: each
commitment is hashed with a one-byte flag that is `0x01` for a
checkpoint's first blob and `0x00` otherwise. The change is made in
three places that have to agree:
  - L1: `BlobLib.calculateBlobCommitmentsHash`
- circuits: the `blob` crate (`blob_batching.nr`, the accumulator ABIs),
consumed by the rollup circuits
  - node: `yarn-project/blob-lib`, through labs patch 0006
- This changes the rollup circuits, so the VK tree root that `v6` builds
moves:
- from
`0x1032cbb2f61a9c1151370ebc35c8ea20d1a726e3388eb94e84291c2b2fecb5d3`
(pinned on `v6` since #25587)
- to
`0x031139abb5b9f51ca0e55a6e2022d567029f50acc9428506f05c91ae27e7f75d`
(taken from this PR's failing CI run on `b2cd9f3f`), which is what labs
patch 0001 now pins
- The testnet deployed from `v6` has root
`0x2d89003cc2dc62b06f07d83d3635c66c63fc43668369d30e7ee516f908ee10e3`;
`v6` has not matched it since #25575. The re-pin follows the decision
recorded on #25549 (a breaking circuit change ported to `v6` re-pins
testnet in the same PR).
- The protocol contracts hash and the genesis root are unchanged; those
two assertions passed on `b2cd9f3f`.
- The L1 change takes effect only on a rollup deployed from this code. A
node built from this branch computes the new hash, so it does not agree
with a rollup deployed before it.

## Testing

- CI3 on `b2cd9f3f` (before the re-pin): `testnet_compatibility.test.ts`
› "has expected VK tree root" was the only failure in the fast run,
which covers the `blob` and rollup circuit tests, the new
`blobCommitmentsHash.t.sol` forge test and the labs `blob-lib` tests.
- `./labs-patches/bootstrap.sh check`: the series (0001, 0006, 0007,
0010) applies cleanly to the labs pin `a0d73c0aed`. Patch 0001 was
produced with `bootstrap.sh apply` / `export`.
- No circuits or L1 contracts were built locally (no `nargo` and no
pinned `solc` in the port environment); the re-pinned test runs on this
PR's CI.

---
*Created by
[claudebox](https://claudebox.work/v2/sessions/134efca9a11ee14f/jobs/29)
· group: `slackbot` · [Slack
thread](https://aztecprotocol.slack.com/archives/C0AGN2WT3CP/p1790609320989739?thread_ts=1790609320.989739&cid=C0AGN2WT3CP)*
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-full Run all master checks. ci-no-fail-fast Sets NO_FAIL_FAST in the CI so the run is not aborted on the first failure claudebox Owned by claudebox. it can push to this PR.

Projects

None yet

Development

Successfully merging this pull request may close these issues.

8 participants