feat: merge-train/spartan#21784
Merged
Merged
Conversation
Use chunk + asyncPool to replace splice-based batching in BrokerCircuitProverFacade. Both getAllCompletedJobs and job retrieval now use non-mutating patterns with bounded concurrency. Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
Validates that contract instance deployment logs contain correct addresses by recomputing the address from the event fields and rejecting mismatches. Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.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
#21759) ## Summary - Replace `splice(0, N)` with index-based `slice(i, i+N)` in `BrokerCircuitProverFacade` to avoid mutating the caller's `ids` array during snapshot sync batching. Fixes A-718 ## Test plan - Build passes - The fix is mechanical: replacing mutating `splice(0, N)` with non-mutating `slice(i, i+N)` in a for-loop 🤖 Generated with [Claude Code](https://claude.com/claude-code)
Adds a defense-in-depth check in the archiver's data store updater that recomputes contract instance addresses from their fields before storing them, filtering out any instances with mismatched addresses. Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
…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)
Replace silent overwrites with explicit errors when adding a contract class or instance that already exists in the store. This catches unexpected double-adds that could lead to data loss on rollback. Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
When REF_NAME has a 'private' semver prerelease (e.g. v5.0.0-private.20260318), ci-release fetches the matching tag from aztec-packages-private, creates a worktree, and runs the release from there. Cache uploads are suppressed to avoid leaking private source artifacts. Also locks down ci3-external.yml to use github.token instead of AZTEC_BOT_GITHUB_TOKEN.
Adds TypeScript integration for the batch chonk verifier C++ service: - BatchChonkVerifier: TS orchestrator managing bb subprocess, FIFO pipe, and proof lifecycle (peer path with batching) - FifoFrameReader: length-delimited frame reader for named pipes - TestCircuitVerifier used for both peer and RPC in fake-proof mode - BBCircuitVerifier + QueuedIVCVerifier for RPC path (real proofs) - Server splits proofVerifier into peerProofVerifier + rpcProofVerifier Config changes: - numConcurrentIVCVerifiers -> bbRpcVerifyConcurrency + bbPeerVerifyBatchSize - bbIVCConcurrency -> bbBatchVerifyThreads - QueuedIVCVerifier takes (verifier, concurrency) instead of (config, verifier) Integration tests and queue robustness tests via bb.js bindings.
…proposals When the dateProvider wall clock is ahead of the latest mined L1 block, getNextL1SlotTimestamp can return a timestamp in a future L2 slot. The canProposeAt simulation passes (with time override) but the actual tx lands in an L1 block still in the previous slot, causing silent rejection. Floor the computed timestamp with latestBlock.timestamp + slotDuration to ensure we never target a slot beyond what the next L1 block can reach. Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
#21799) ## Motivation The contract instance store used `.set()` which silently overwrote existing entries, while the contract class store used `.setIfNotExists()` which silently ignored duplicates. Neither behavior catches the unexpected case of a double-add, which could lead to data loss on rollback — if an instance is added at block N and again at block M, rolling back block M would delete the instance entirely, invalidating the first add. The protocol prevents this via deployer nullifiers, but the store should enforce it as defense-in-depth. ## Approach Both `addContractInstance` and `addContractClass` now check for existing entries and throw if the key already exists. This surfaces any unexpected double-adds as errors rather than silently corrupting state. ## Changes - **archiver (contract_instance_store)**: `addContractInstance` checks `hasAsync` before writing; throws with a descriptive error on duplicate - **archiver (contract_class_store)**: `addContractClass` replaces `setIfNotExists` with explicit `hasAsync` check and throw on duplicate - **archiver (tests)**: Updated "add twice" tests to expect throws instead of silent success
## Motivation The `PrivateFunctionBroadcastedEvent` and `UtilityFunctionBroadcastedEvent` were removed from the ContractClassRegistry Noir contract, making all supporting TypeScript infrastructure dead code. This cleans it up. ## Approach Removed the event types, membership proof creation and validation functions, the archiver data flow that processed these events (`storeBroadcastedIndividualFunctions`), the store methods that persisted them (`addFunctions`), and the `privateFunctions`/`utilityFunctions` fields from `ContractClassPublic`. Bumps the `ARCHIVER_DB_VERSION` to account for the schema change in the store. ## Changes - **stdlib**: Removed `ExecutablePrivateFunctionWithMembershipProof`, `UtilityFunctionWithMembershipProof`, and related types from `ContractClassPublic`. Deleted membership proof files and their tests. - **protocol-contracts**: Deleted `PrivateFunctionBroadcastedEvent` and `UtilityFunctionBroadcastedEvent` classes, their tests, snapshots, and hex fixtures. - **archiver**: Removed `storeBroadcastedIndividualFunctions` from the data store updater, `addFunctions` from the contract class store, and related serialization helpers and tests. - **txe, end-to-end**: Removed references to the deleted fields.
Anvil logs block timestamps to stdout on each mined block. Parse these and update the TestDateProvider so it stays in lockstep with the L1 chain, eliminating drift between wall clock and anvil chain time. Also rename cheatCodes.timestamp() to lastBlockTimestamp() to clarify it returns the latest block's discrete timestamp, not the current time. Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
Anvil logs block timestamps to stdout on each mined block. Parse these and update the TestDateProvider so it stays in lockstep with the L1 chain, eliminating drift between wall clock and anvil chain time. Also rename cheatCodes.timestamp() to lastBlockTimestamp() to clarify it returns the latest block's discrete timestamp, not the current time.
… slot estimation (#21769) ## Motivation When an Ethereum slot is missed (no block produced), the next L1 block lands 24+ seconds after the previous one instead of 12. Computing the next block timestamp as `getBlock().timestamp + ethereumSlotDuration` produces wrong results, causing incorrect L2 slot, committee, and proposer calculations. Additionally, the archiver's sync check would block the sequencer from building when L1 blocks were delayed, even if the previous checkpoint had already been synced. Fixes #14766 ## Approach Replace all `getBlock().timestamp + ethereumSlotDuration` patterns with a new `getNextL1SlotTimestamp(dateProvider.nowInSeconds(), constants)` helper that rounds wall-clock time up to the next L1 slot boundary. This is correct regardless of missed slots. Additionally, `getSyncedL2SlotNumber` now uses the latest synced checkpoint slot as a second signal (alongside L1 block timestamps) to determine sync progress, so the sequencer can start building even when L1 blocks are delayed. ## Changes - **stdlib**: Added `getNextL1SlotTimestamp` helper in epoch-helpers that computes the next L1 slot boundary from wall-clock time - **ethereum**: Renamed `canProposeAtNextEthBlock` to `canProposeAt` on `RollupContract`, now accepts a precomputed timestamp instead of computing it internally - **sequencer-client**: Injected `DateProvider` into `GlobalVariableBuilder` (now receives it as first arg + public client as second arg instead of creating its own). Publisher and global variable builder use `getNextL1SlotTimestamp` instead of `getBlock().timestamp` - **epoch-cache**: Updated `getEpochAndSlotInNextL1Slot` to use `getNextL1SlotTimestamp` - **archiver**: `getSyncedL2SlotNumber` now returns the max of L1-timestamp-based sync and checkpoint-based sync, handling missed L1 blocks via the inbox LAG mechanism - **end-to-end (tests)**: Added `epochs_missed_l1_slot` e2e test that pauses L1 mining after a checkpoint and verifies the sequencer still builds during the pause
…est (#21848) ## Summary Fix TypeScript compilation error in the new `epochs_missed_l1_slot.test.ts` introduced by #21769. The test calls `eth.timestamp()` but the method on `EthCheatCodes` is actually `lastBlockTimestamp()`. This caused `yarn tsgo -b --emitDeclarationOnly` to fail with: ``` error TS2339: Property 'timestamp' does not exist on type 'EthCheatCodes'. ``` ## Fix Changed `eth.timestamp()` → `eth.lastBlockTimestamp()` on line 104 of the test file. ClaudeBox log: https://claudebox.work/s/e62ab0794047aa8c?run=1
## Motivation Contract class registration events contain a class ID alongside the fields needed to recompute it (artifactHash, privateFunctionsRoot, packed bytecode). This adds a validation to avoid a malicious tx from registering a class with a mismatched ID if it found a bug in the registry contract, poisoning the archiver's contract data. ## Approach Made `toContractClassPublic()` a simple synchronous conversion with no validation (symmetric with how `toContractInstance()` works for contract instances). Validation is done explicitly at each call site that needs it: the `DataTxValidator` and the archiver's `updatePublishedContractClasses`. ## Changes - **protocol-contracts**: `toContractClassPublic()` is now sync and returns `ContractClassPublic` without validation or bytecode commitment; `toContractClassPublicWithBytecodeCommitment()` adds the commitment but also does not validate - **stdlib**: Added `TX_ERROR_INCORRECT_CONTRACT_CLASS_ID` and `TX_ERROR_MALFORMED_CONTRACT_CLASS_LOG` error constants; added elapsed timing test for `computeContractClassId` with real artifacts - **p2p**: Extended `DataTxValidator` with explicit contract class ID verification (recomputes class ID from event fields and compares) - **p2p (tests)**: Added contract class ID validation tests to `data_validator.test.ts`; updated factory tests - **archiver**: `updatePublishedContractClasses` explicitly validates class IDs and collects bytecode commitments in a single pass; `addContractClasses` now takes `ContractClassPublicWithCommitment[]` instead of separate arrays - **simulator**: Simplified `addContractClassesFromEvents` and callers from async to sync since `toContractClassPublic()` is no longer async Co-authored-by: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
Was needed due to clock drift between sequencer and anvil, but PR #21829 should now remove the need for that.
Ref: A-16 - Add automatic publisher funding: when a publisher's ETH balance drops below a configurable threshold, a dedicated funding account tops it up - Funding account is configured via the keystore's fundingAccount field and controlled by PUBLISHER_FUNDING_THRESHOLD / PUBLISHER_FUNDING_AMOUNT env vars
…ough terraform - BB_CHONK_VERIFY_BATCH_CONCURRENCY default 0 (auto) → 6 to leave cores for the rest of the node on recommended 8-core machines - Wire BB_CHONK_VERIFY_MAX_BATCH and BB_CHONK_VERIFY_BATCH_CONCURRENCY through terraform variables.tf and main.tf to all 5 node types
Adds `BatchChonkVerifier`, the TS integration for the C++ batch chonk verifier service. Proofs arriving over P2P are batched so a single IPA SRS MSM covers the entire batch, with bisection to isolate bad proofs on failure. The node now runs two separate verification paths: - **Peer**: `BatchChonkVerifier` — persistent bb subprocess, FIFO pipe, batched IPA - **RPC**: `BBCircuitVerifier` wrapped in `QueuedIVCVerifier` — file-based, concurrency-limited, with OTel metrics - **Test mode**: `TestCircuitVerifier` for both (always valid) ``` BB_CHONK_VERIFY_MAX_BATCH=16 # peer: proofs per batch (see note below) BB_CHONK_VERIFY_BATCH_CONCURRENCY=0 # peer: worker threads (0=auto) BB_NUM_IVC_VERIFIERS=8 # rpc: max concurrent verifications BB_IVC_CONCURRENCY=1 # rpc: threads per verification ``` > Default batch size of 16 chosen because at 4 cores, a full batch of 16 e2e app proofs verifies in ~245ms — roughly the latency budget for P2P gossip validation in a busy block. Single-proof latency is ~80ms at 4 cores. **[Interactive review page](https://aztecprotocol.github.io/dev-pages/batch-chonk-verifier.html)** with real benchmark data, work-stealing simulation, and bisection animation. New files: `BatchChonkVerifier`, `FifoFrameReader`, integration tests, queue robustness tests, bench (wired into `bootstrap.sh`). `QueuedIVCVerifier` constructor simplified from `(config, verifier)` to `(verifier, concurrency)`.
Was needed due to clock drift between sequencer and anvil, but PR #21829 should now remove the need for that.
## Summary The `batch_verifier.bench.test.ts` benchmark (added in #21823) was downloading pinned IVC inputs from S3 at test runtime, but bench tests run in Docker containers with `--net=none` (no network), causing all 7 tests to fail. Instead of adding network access, this uses the pre-generated `example-app-ivc-inputs-out` folder that's already built by `end-to-end/bootstrap.sh build_bench` — the same pattern used by the IVC flow benchmarks in `barretenberg/cpp/scripts/ci_benchmark_ivc_flows.sh`. ## Changes - `batch_verifier.bench.test.ts`: Replace S3 download with local `../end-to-end/example-app-ivc-inputs-out` path - `yarn-project/bootstrap.sh`: Keep original bench command (no `NET=1` needed) ## CI Log http://ci.aztec-labs.com/fafcdc0ea9a5d52b
…21863) ## Summary Gossipsub message validation had double-penalization paths: inner validation functions called `penalizePeer` directly, and the outer `validateReceivedMessage` wrapper could penalize again on errors. Attestation cap exceeded was also inconsistently handled (ignored instead of rejected like proposals). ## Approach Centralized all gossipsub penalization into `validateReceivedMessage` by adding a `severity` field to the `Reject` variant of `ReceivedMessageValidationResult`. Inner functions now return severity instead of calling `penalizePeer` directly. Added `tryDeserialize` helper for graceful deserialization failure handling. ## Changes - **p2p (libp2p_service)**: Centralized penalization in `validateReceivedMessage`, removed direct `penalizePeer` calls from `handleGossipedTx`, `validateAndStoreBlockProposal`, `validateAndStoreCheckpointProposal`, and `validateAndStoreCheckpointAttestation`. Changed attestation cap exceeded from `Ignore` to `Reject` with `HighToleranceError`. Fixes A-705 Co-authored-by: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
## Summary - Move automatic GitHub release creation from `AztecProtocol/aztec-packages` to `AztecProtocol/barretenberg` — bb artifacts are the only reason we need programmatic releases - Update all bb artifact download URLs (`barretenberg-rs build.rs`, rust bootstrap) to point to `AztecProtocol/barretenberg` releases - `bbup` tries `AztecProtocol/barretenberg` first, falls back to `aztec-packages` indefinitely - Users can still create `aztec-packages` releases manually via the GitHub "Create a release" button when needed --------- Co-authored-by: ludamad <adam.domurad@gmail.com>
ludamad
approved these changes
Mar 20, 2026
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.
BEGIN_COMMIT_OVERRIDE
feat(p2p): add tx validator for contract instance deployment addresses (#21771)
fix: always deploy IRM for testnet (#21755)
fix: avoid mutating caller's array via splice in snapshot sync (A-718) (#21759)
chore: update network logs skill (#21785)
feat(archiver): validate contract instance addresses before storing (#21787)
fix: ensure no division by 0 (#21786)
feat: support private fork releases via ci-release (#21778)
fix: restrict scenario deployments to only nightly (#21798)
fix(stdlib): zero-pad bufferFromFields when declared length exceeds payload (#21802)
test(protocol-contracts): verify max-size bytecode fits in contract class log (#21818)
fix: wire BOT_DA_GAS_LIMIT through helm/terraform for staging-public (#21809)
fix: remove jest-mock-extended from worker processes + fix parallelize_strict silent failures (#21821)
fix(archiver): throw on duplicate contract class or instance additions (#21799)
chore: remove broadcasted function events (#21805)
fix: sync dateProvider from anvil stdout on every mined block (#21829)
fix(sequencer): use wall-clock time instead of L1 block timestamp for slot estimation (#21769)
fix: use correct EthCheatCodes method name in epochs_missed_l1_slot test (#21848)
feat(p2p): add tx validator for contract class id verification (#21788)
feat: publisher funding (#21631)
feat: batch chonk verifier TS integration (#21823)
fix(sequencer): remove l1 block timestamp check (#21853)
fix: use local IVC inputs for batch_verifier bench test (#21857)
fix(p2p): centralize gossipsub penalization and fix inconsistencies (#21863)
chore: publish GitHub releases to AztecProtocol/barretenberg (#21775)
END_COMMIT_OVERRIDE