Skip to content

chore: merge v4 into backport-to-v4-next-staging#22010

Merged
spalladino merged 24 commits intobackport-to-v4-next-stagingfrom
claudebox/merge-v4-into-v4-next-staging
Mar 26, 2026
Merged

chore: merge v4 into backport-to-v4-next-staging#22010
spalladino merged 24 commits intobackport-to-v4-next-stagingfrom
claudebox/merge-v4-into-v4-next-staging

Conversation

@AztecBot
Copy link
Copy Markdown
Collaborator

Summary

Merges v4 branch into backport-to-v4-next-staging to bring in 17 commits from v4 that were missing.

Key changes from v4:

Conflicts resolved

6 files had merge conflicts, all resolved:

  • archiver/src/factory.ts — kept ContractClassPublicWithCommitment type from staging
  • archiver/src/modules/data_store_updater.ts — merged imports from both branches
  • archiver/src/store/kv_archiver_store.test.ts — took v4's richer describe block structure, adapted to singular addProposedBlock API
  • aztec-node/src/aztec-node/server.ts — kept staging's block 0 check and getWorldState method name
  • stdlib/src/tx/validator/error_texts.ts — kept staging's contract class error constants
  • world-state/src/synchronizer/server_world_state_synchronizer.ts — kept verbose log level

Test plan

  • CI should verify the merge compiles and tests pass
  • Once merged, this branch can be merged into the backport-to-v4-next branch

ClaudeBox log: https://claudebox.work/s/0150633f06bfb379?run=1

AztecBot and others added 19 commits March 17, 2026 15:26
BEGIN_COMMIT_OVERRIDE
fix(aztec-nr): return Option from decode functions and fix event
commitment capacity (backport #21264) (#21360)
fix: backport #21271 — handle bad note lengths on
compute_note_hash_and_nullifier (#21364)
fix: not reusing tags of partially reverted txs (#20817)
chore: revert accidental backport of #20817 (#21583)
feat: Implement commit all and revert all for world state checkpoints
(#21532)
cherry-pick: fix: dependabot alerts (#21531)
fix: dependabot alerts (backport #21531 to v4) (#21592)
fix: backport #21443 — Don't update state if we failed to execute
sufficient transactions (v4) (#21610)
chore: Fix msgpack serialisation (#21612)
fix(p2p): fall back to maxTxsPerCheckpoint for per-block tx validation
(#21605)
chore: merge v4 into backport-to-v4-staging (#21618)
fix(revert): avm sim uses event loop again (#21138) (#21630)
fix(e2e): remove historic/finalized block checks from epochs_multiple
test (#21642)
fix: clamp finalized block to oldest available in world-state (#21643)
fix: skip handleChainFinalized when block is behind oldest available
(#21656)
chore: demote finalized block skip log to trace (#21661)
fix: off-by-1 in getBlockHashMembershipWitness archive snapshot
(backport #21648) (#21663)
fix: capture txs not available error reason in proposal handler (#21670)
chore: add L1 inclusion time to stg public (#21665)
END_COMMIT_OVERRIDE

---------

Co-authored-by: Jan Beneš <janbenes1234@gmail.com>
Co-authored-by: PhilWindle <60546371+PhilWindle@users.noreply.github.com>
Co-authored-by: Phil Windle <philip.windle@gmail.com>
Co-authored-by: Santiago Palladino <santiago@aztecprotocol.com>
Co-authored-by: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
Co-authored-by: ludamad <adam.domurad@gmail.com>
Co-authored-by: Alex Gherghisan <alexghr@users.noreply.github.com>
change ordering for `lastBlock` case when creating a checkpoint
proposal, so that we first sign the last block and then the checkpoint
…ons (A-683) (#21686)

Remove early return in for...of loop that caused only the first contract
class's functions to be stored when multiple classes had broadcasts in
the same block.

Fixes https://linear.app/aztec-labs/issue/A-683
BEGIN_COMMIT_OVERRIDE
fix: HA deadlock for last block edge case (#21690)
fix: process all contract classes in storeBroadcastedIndividualFunctions
(A-683) (#21686)
END_COMMIT_OVERRIDE
…entire tag (A-686) (#21713)

## Summary
Backport of #21687
to v4.

During reorg, `deleteLogs` was deleting the entire log entry for a tag
instead of only removing logs from the rolled-back blocks. This caused
logs from earlier blocks to be lost.

## Cherry-pick conflicts
The automatic cherry-pick failed due to API differences between `next`
and `v4`:
- `next` uses `store.addProposedBlock(block)` (singular) — v4 uses
`store.addProposedBlocks([block])` (plural, takes array)
- `next` uses a helper `addProposedBlocks(store, ...)` — adapted to call
`store.addProposedBlocks(...)` directly in v4

## Commit structure
1. **Cherry-pick with conflicts** — raw cherry-pick preserving conflict
markers
2. **Conflict resolution** — adapted `addProposedBlock` →
`addProposedBlocks` API calls

Fixes https://linear.app/aztec-labs/issue/A-686

ClaudeBox log: https://claudebox.work/s/1f9640fef77e1838?run=2
## Summary

Testnet validators were detecting inactive validators and starting
slashing rounds, but all votes were computed as zero because the
per-offense penalty (`10e18` = 10 TST) was far below the L1 contract's
minimum slash threshold (`100000e18` = 100,000 TST).

This PR sets all testnet slashing penalty values to `100000e18` to match
`AZTEC_SLASH_AMOUNT_SMALL`, which is the minimum amount needed for a
vote to register as 1 slash unit.

## Root Cause

The vote computation in `getSlashUnitsForAmount()`
(`yarn-project/stdlib/src/slashing/tally.ts`) checks if the accumulated
offense amount reaches `slashingAmounts[0]` (=
`AZTEC_SLASH_AMOUNT_SMALL`). Since `10e18 < 100000e18`, the function
always returned 0 slash units, causing all votes to be skipped.

## BigInt Parsing Verification

- The penalty values flow through env vars as strings (e.g.
`"100000e18"`)
- `bigintConfigHelper` in `foundation/src/config/index.ts` handles
scientific notation losslessly using bigint arithmetic (not float64)
- The parsing regex correctly handles `100000e18` → `BigInt("100000") *
10n ** 18n` = exact result

## Changes

- `spartan/environments/network-defaults.yml`: Updated all testnet
`SLASH_*_PENALTY` values from `10e18` to `100000e18`


ClaudeBox log: https://claudebox.work/s/a2a0d7830a3d8ce3?run=2

---------

Co-authored-by: ludamad <adam.domurad@gmail.com>
Co-authored-by: Amin Sammara <84764772+aminsammara@users.noreply.github.com>
#21771)

## Motivation

When a contract instance is deployed, a `ContractInstancePublishedEvent`
is emitted as a private log containing the contract address and all
fields needed to recompute it. Currently the archiver blindly trusts
these addresses. A malicious or buggy client could submit a tx with an
incorrect address, poisoning the archiver's contract data.

## Approach

Added a new stateless tx validator that extracts
`ContractInstancePublishedEvent` logs from a tx's private logs,
recomputes the contract address via
`computeContractAddressFromInstance`, and rejects the tx if the claimed
address doesn't match. The validator is wired into all tx entry points
(gossip, JSON-RPC, req/resp, and block proposals).

## Changes

- **stdlib**: Added `TX_ERROR_INCORRECT_CONTRACT_ADDRESS` and
`TX_ERROR_MALFORMED_CONTRACT_INSTANCE_LOG` error constants
- **p2p**: New `ContractInstanceTxValidator` that validates contract
instance deployment addresses in private logs
- **p2p**: Wired the validator into all three entry-point factory
functions (gossip stage 1, req/resp + block proposals, JSON-RPC)
- **p2p (tests)**: Unit tests for the new validator (correct address,
wrong address, malformed log, no instance logs) and updated factory
tests
…21787)

## Motivation

The archiver blindly stores contract instance data extracted from
private logs without verifying that the claimed address matches the
instance fields. While the p2p tx validator (#21771) catches this at the
network layer, blocks received via req/resp or proposals skip that
check. This adds a second line of defense at the storage layer.

## Approach

Before storing contract instances, the archiver now recomputes the
address from the instance fields via
`computeContractAddressFromInstance` and filters out any with mismatched
addresses. The check is skipped during delete operations since we need
to remove instances regardless.

## Changes

- **archiver**: Validate contract instance addresses in
`updateDeployedContractInstances` before storing, filtering out
mismatches with a warning log
- **stdlib (tests)**: Add elapsed timing to
`computeContractAddressFromInstance` test (~1.3ms per call)
BEGIN_COMMIT_OVERRIDE
feat(p2p): add tx validator for contract instance deployment addresses
(#21771)
END_COMMIT_OVERRIDE
Fixes

[A-551](https://linear.app/aztec-labs/issue/A-551/properly-compute-finalized-block)

Replaces the heuristic finalized block computation (`provenBlock - 2 *
epochDuration`) with L1 finality.

On each archiver sync iteration, we now:
1. Fetch the finalized L1 block via `getBlock({ blockTag: 'finalized'
})`
2. Query the rollup contract for the proven checkpoint number at that L1
block
3. Persist that as the finalized checkpoint, from which the finalized L2
block number is derived

Failures in this step are caught and logged as warnings so they don't
disrupt the rest of the sync loop (e.g. if the RPC node can't serve
state at the finalized block).

- `RollupContract.getProvenCheckpointNumber` now accepts an optional `{
blockNumber }` to query historical contract state
- `BlockStore` stores a `lastFinalizedCheckpoint` singleton and derives
`getFinalizedL2BlockNumber` from it instead of the old arithmetic
heuristic
- `ArchiverL1Synchronizer` gains `updateFinalizedCheckpoint()`, called
every sync iteration
- `KVArchiverDataStore` constructor no longer takes `l1Constants` (the
`epochDuration` it was used for is no longer needed)
- `FakeL1State` updated to support `blockTag: 'finalized'` and
`getProvenCheckpointNumber` with a block number, enabling new sync tests

---------

Co-authored-by: AztecBot <tech@aztec-labs.com>
Fixes


[A-551](https://linear.app/aztec-labs/issue/A-551/properly-compute-finalized-block)

Replaces the heuristic finalized block computation (`provenBlock - 2 *
epochDuration`) with L1 finality.

On each archiver sync iteration, we now:
1. Fetch the finalized L1 block via `getBlock({ blockTag: 'finalized'
})`
2. Query the rollup contract for the proven checkpoint number at that L1
block
3. Persist that as the finalized checkpoint, from which the finalized L2
block number is derived

Failures in this step are caught and logged as warnings so they don't
disrupt the rest of the sync loop (e.g. if the RPC node can't serve
state at the finalized block).

- `RollupContract.getProvenCheckpointNumber` now accepts an optional `{
blockNumber }` to query historical contract state
- `BlockStore` stores a `lastFinalizedCheckpoint` singleton and derives
`getFinalizedL2BlockNumber` from it instead of the old arithmetic
heuristic
- `ArchiverL1Synchronizer` gains `updateFinalizedCheckpoint()`, called
every sync iteration
- `KVArchiverDataStore` constructor no longer takes `l1Constants` (the
`epochDuration` it was used for is no longer needed)
- `FakeL1State` updated to support `blockTag: 'finalized'` and
`getProvenCheckpointNumber` with a block number, enabling new sync tests

---------
Backport of 50ba735 to v4. The native ChonkVerifier::verify was not
checking kernel_io.pairing_inputs (accumulated pairing points from the
IVC chain), while the recursive verifier was. This adds the missing
check to ensure parity between native and recursive verification paths.
…ckport) (#21975)

## Summary

- Backport of 50ba735 to v4
- Native `ChonkVerifier::verify` was missing
`kernel_io.pairing_inputs.check()` — the accumulated pairing points from
inner recursive verifications
- The recursive verifier already included this check; the native
verifier did not
- Adds the missing check for parity between native and recursive
verification paths
Conflicts resolved in 6 files:
- archiver/src/factory.ts: keep ContractClassPublicWithCommitment from staging
- archiver/src/modules/data_store_updater.ts: keep all imports (both branches needed)
- archiver/src/store/kv_archiver_store.test.ts: take v4 describe block structure, use singular addProposedBlock API
- aztec-node/src/aztec-node/server.ts: keep staging's block 0 check and getWorldState method
- stdlib/src/tx/validator/error_texts.ts: keep staging's contract class error constants
- world-state/src/synchronizer/server_world_state_synchronizer.ts: use verbose log level with v4's message
@AztecBot AztecBot added ci-draft Run CI on draft PRs. claudebox Owned by claudebox. it can push to this PR. labels Mar 25, 2026
@AztecBot AztecBot force-pushed the claudebox/merge-v4-into-v4-next-staging branch from e3db730 to 53242ff Compare March 25, 2026 18:56
@spalladino spalladino marked this pull request as ready for review March 26, 2026 13:44
@spalladino spalladino requested a review from nventuro as a code owner March 26, 2026 13:44
@spalladino spalladino removed the request for review from nventuro March 26, 2026 14:02
@spalladino spalladino enabled auto-merge March 26, 2026 14:29
@spalladino spalladino added the ci-no-fail-fast Sets NO_FAIL_FAST in the CI so the run is not aborted on the first failure label Mar 26, 2026
@AztecBot
Copy link
Copy Markdown
Collaborator Author

Flakey Tests

🤖 says: This CI run detected 1 tests that failed, but were tolerated due to a .test_patterns.yml entry.

\033FLAKED\033 (8;;http://ci.aztec-labs.com/0ab26e10c9077935�0ab26e10c90779358;;�):  yarn-project/end-to-end/scripts/run_test.sh simple src/e2e_p2p/multiple_validators_sentinel.parallel.test.ts "collects attestations for all validators on a node" (271s) (code: 0) group:e2e-p2p-epoch-flakes

@spalladino spalladino merged commit 48f9044 into backport-to-v4-next-staging Mar 26, 2026
16 of 17 checks passed
@spalladino spalladino deleted the claudebox/merge-v4-into-v4-next-staging branch March 26, 2026 15:03
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

ci-draft Run CI on draft PRs. ci-no-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.

6 participants