Conversation
This PR introduces additional block/checkpoint proposal validation to ensure `SEQ_MAX_TX_PER_BLOCK` is not breached. Also adds additional tests for existing validation criteria. --------- Co-authored-by: Claude Opus 4.6 <noreply@anthropic.com>
## Summary - Reject `rollbackTo` calls targeting a block that is not the last block of its checkpoint, since rollback operates at checkpoint granularity. The error message indicates the nearest valid checkpoint boundaries so the caller can retry with a correct target. - Fix proven checkpoint number to roll back to the target checkpoint instead of resetting to zero. Fixes A-552 ## Test plan - Unit tests added in `archiver-store.test.ts` covering: - Rejection of non-boundary blocks with correct error message - Successful rollback to checkpoint boundary with sync point verification - Proven checkpoint rollback when target is before proven block - Proven checkpoint preservation when target is after proven block - e2e test `e2e_epochs/manual_rollback` passes 🤖 Generated with [Claude Code](https://claude.com/claude-code) Co-authored-by: Claude Opus 4.6 <noreply@anthropic.com>
Ref: A-493 - Split `peerCount` metric into total connections and healthy connections - Fixed memory leak in peer manager: `peerConnectedAt` map entries are now deleted after recording connection duration - Fixed mined-delay tracking for `TxPoolV2` - Added attestation pool instrumentation - Renamed metrics/groups - Other zero metric fixes
Collaborator
Author
|
🤖 Auto-merge enabled after 4 hours of inactivity. This PR will be merged automatically once all checks pass. |
BigInt() doesn't accept scientific notation strings like "1e+23" or "2E+23". This caused a crash when starting a node with --network testnet, as config values like 200000e18 get converted to "2e+23" by the JSON pipeline. Parse scientific notation losslessly using bigint arithmetic instead of going through float64, preserving exact values.
## Summary
- Fixes `bigintConfigHelper` to handle scientific notation strings (e.g.
`1e+23`, `2E+23`) that `BigInt()` can't parse directly
- Uses lossless bigint arithmetic to parse scientific notation instead
of going through float64
- Fixes crash when starting a node with `--network testnet` where config
values like `200000e18` get converted to `2e+23` by JSON
## Context
The bug surfaces because `network-defaults.yml` values like `200000e18`
pass through `yq -o json | jq`, which converts them to float64
scientific notation (`2E+23`). At runtime, `BigInt("2e+23")` throws
`SyntaxError: Cannot convert 2e+23 to a BigInt`.
This fix makes the parsing layer resilient to scientific notation,
regardless of how the values arrive.
## Test plan
- Added unit tests covering: plain integers, scientific notation
(`1e+23`, `2E+23`, `1e23`, `5e18`), decimal mantissa (`1.5e10`), empty
string default, and error on non-integer results (`1e-3`)
- All 10 test cases verified passing
[ClaudeBox log](http://ci.aztec-labs.com/e312c3dcef56fc86-1)
Closes A-547 Forward-port of #20937. ## Summary - Before calling `getL1Config()`, the node now compares its local genesis archive root against the canonical rollup's via `archiveAt(0)`. - If the roots don't match (e.g. during L1 contract upgrades where the old rollup ABI is incompatible), the node enters **standby mode** instead of crashing. - In standby mode, a lightweight HTTP server is started for K8s liveness probes, and the node polls every 10 minutes until a compatible rollup becomes canonical. - When `rollupVersion` is not explicitly configured (`undefined`), it now falls back to `'canonical'` instead of passing `0` to the registry. ### Tested against testnet (incompatible rollup): ``` Genesis archive root: 0x2727683df35594b1f073a681532520056ca8a775398c8b5a94574c67ef1ce6de Genesis root mismatch: expected 0x2727683df35594b1f073a681532520056ca8a775398c8b5a94574c67ef1ce6de, got 0x0ae6138310f7b877b6c68856451eddec0873fb63f9033931cedcdc46815729e1 from rollup at 0x66a41cb55f9a1e38a45a2ac8685f12a61fbfab77. Entering standby mode. Will poll every 10s for a compatible rollup... Standby status server listening on port 8080 Still waiting. Rollup at 0x66a41cb55f9a1e38a45a2ac8685f12a61fbfab77 has genesis root 0x0ae6138310f7b877b6c68856451eddec0873fb63f9033931cedcdc46815729e1. ``` ``` $ curl http://localhost:8080/status OK ``` ## Test plan - Run `aztec start --node --archiver --network testnet` against an incompatible rollup: verify standby mode with health check responding OK - Run against a compatible network: verify normal startup without entering standby - Ctrl+C during standby: verify clean exit
#20942) ## Summary Closes A-596 - Anchors `SLASH_GRACE_PERIOD_L2_SLOTS` to the `CanonicalRollupUpdated` event emitted by the Registry when the rollup becomes canonical, instead of comparing against genesis slot 0 - Adds `getCanonicalRollupRegistrationTimestamp()` to `RegistryContract` to query the registration event timestamp - Computes and caches the canonical rollup registration L2 slot in the slasher factory, threading it through to the `SlashOffensesCollector` where the grace period comparison now uses `offenseSlot < registeredSlot + gracePeriodSlots` ## Motivation The rollup can be deployed weeks/months before becoming canonical (registered via `addRollup()`). By upgrade time, the current slot is far past any "slot from genesis" value, making the grace period ineffective. Now operators just set a duration (e.g. 3600 slots = 3 days) and the system anchors it to the actual upgrade time automatically. ## Test plan - Unit tests updated and passing for `SlashOffensesCollector`, `EmpireSlasherClient`, and `TallySlasherClient` - Grace period test verifies offenses within `registeredSlot + gracePeriod` are skipped and offenses after are not
Collaborator
Author
|
🤖 Auto-merge enabled after 4 hours of inactivity. This PR will be merged automatically once all checks pass. |
2 tasks
## Summary - Sets `wallet.setMinFeePadding(config.minFeePadding)` in the `BotFactory` constructor so that all transactions during bot setup (token deployment, minting) use the configured fee padding instead of the wallet's default (0.5). - Previously, only account deployment explicitly used `config.minFeePadding` (line 226 of factory.ts), while token deploy and minting relied on the wallet default, causing insufficient fee headroom when gas prices escalate during rapid block building in tests. ## Root cause The merge-train/spartan PR (#20899) was dequeued because `e2e_bot.test.ts` ("does not reuse prior bridge claims if recipient address changes") failed with: ``` maxFeesPerGas.feePerL2Gas must be greater than or equal to gasFees.feePerL2Gas, but got maxFeesPerGas.feePerL2Gas=698400000 and gasFees.feePerL2Gas=932700000 ``` The test config had `minFeePadding: 99` (100x multiplier), but this was only applied during account deployment, not during subsequent token deployment/minting which used the wallet's default 1.5x multiplier. ## Test plan - [x] `make yarn-project` builds successfully - [ ] CI e2e_bot test passes with the fix [ClaudeBox log](http://ci.aztec-labs.com/e9fdbc1ddac8e593-1)
## Summary - Fix flaky "proposer invalidates previous block with shuffled attestations" e2e test that fails with `ValidatorSelection__InvalidCommitteeCommitment` - Only swap two signed attestation positions in `manipulateAttestations`, preserving the bitmap so `MaliciousCommitteeAttestationsAndSigners` signers stay aligned with L1's `reconstructCommitteeFromSigners` ## Root cause `trimAttestations` reduces signed attestations to the minimum required (4 of 5), leaving one position with only an address (no signature). The old swap formula `(proposerIndex+1)%N, (proposerIndex+2)%N` could swap a signed position with an unsigned one, changing the bitmap pattern. `MaliciousCommitteeAttestationsAndSigners` provides the `_signers` array in the original bitmap order, but L1's `reconstructCommitteeFromSigners` maps signers to the new bitmap positions, producing a mismatched committee commitment hash. Whether the swap crosses a signed/unsigned boundary depends on the proposer index and which attestation was trimmed, explaining the flakiness. ## Test plan - Confirmed the bug reproduces deterministically by forcing a signed/unsigned swap (test times out with 15 `InvalidCommitteeCommitment` reverts) - After fix, test passes cleanly with zero committee commitment errors Fixes A-590
…int attestations (#20971) Test that high-s or invalid ECDSA signatures posted by a malicious proposer can be properly invalidated. ## Summary - Adds e2e tests for A-71: nodes correctly detect and invalidate checkpoints with malleable (high-s) or unrecoverable attestation signatures - Adds `injectHighSValueAttestation` and `injectUnrecoverableSignatureAttestation` sequencer config options for testing - Updates `Signature.random()` to produce valid ECDSA signatures with low s-values - Adds `generateRecoverableSignature` / `generateUnrecoverableSignature` utilities with unit tests - Adds unit test for high-s value attestation validation in archiver - Refactors e2e invalidate block tests with shared helpers to reduce duplication Fixes A-71 ## Test plan - [x] Two new e2e tests pass: high-s value attestation invalidation, unrecoverable signature invalidation - [x] Unit tests pass: `Signature.random()` validity, `generateRecoverableSignature`, `generateUnrecoverableSignature`, high-s validation - [x] Existing e2e invalidate block tests unchanged in behavior (refactored with helpers) 🤖 Generated with [Claude Code](https://claude.com/claude-code) Co-authored-by: Claude Opus 4.6 <noreply@anthropic.com>
Fix flakiness in duplicate_proposal_slash and duplicate_attestation_slash e2e tests. Both tests flake at a 3-13% rate because the malicious proposer (1 of 4 validators) is never selected within the timeout window. Three root causes are addressed: 1. **GossipSub mesh checked only for TX topic** — The tests need block proposals and checkpoint proposals to propagate, but `waitForP2PMeshConnectivity` only verified the `tx` topic mesh. Added a `topics` parameter so callers can specify which topics to wait on. Both slash tests now wait on `tx`, `block_proposal`, and `checkpoint_proposal`. 2. **Proposer selection is probabilistic** — With 4 validators and 2 slots/epoch, the malicious proposer has ~25% chance per slot. Added `awaitEpochWithProposer` helper that advances epochs (via L1 time warp) until the target proposer is deterministically selected for at least one slot in the current epoch. 3. **Race between node startup and first proposal** — Nodes started sequencing immediately upon creation, potentially proposing before the P2P mesh was ready. Now all nodes are created with `dontStartSequencer: true`, and sequencers are started simultaneously only after mesh formation, committee existence, and epoch advancement are confirmed. Fixes A-593 Fixes A-595
## Summary - Fixes flaky `epochs_mbps.parallel` test by adding a `retryUntil` poll to `assertMultipleBlocksPerSlot`, closing a race condition between two independently-syncing archivers ## Details The `epochs_mbps.parallel` test has been flaking in CI (9 recent failures across PRs 20562-20868) on the "checkpointed block" test case. The root cause is a race condition: 1. `waitForTx` polls the **initial setup node's** archiver and returns when it sees the tx as `CHECKPOINTED`. 2. `assertMultipleBlocksPerSlot` then queries the **first validator node's** (`nodes[0]`) archiver via `archiver.getCheckpoints()`. 3. These are different nodes with independent L1 polling cycles (~50ms interval each). 4. The first validator's archiver may not have indexed the latest checkpoint yet (~200-400ms race window). CI logs confirm: the checkpoint with the expected block count is always produced and published to L1, but the first validator's archiver hasn't indexed it when the assertion runs. ### Fix Added a `retryUntil` poll at the start of `assertMultipleBlocksPerSlot` that waits (up to `L2_SLOT_DURATION_IN_S * 3` = 108s, polling every 0.5s) for `nodes[0]`'s archiver to index a checkpoint with at least `targetBlockCount` blocks. Once found, the existing validation logic runs as before. Fixes A-594
## Summary Re-enables function selector checking in the transaction setup phase allow list. Previously, selector restrictions were removed with the comment "We can't restrict the selector because public functions get routed via dispatch," but the current code already correctly extracts selectors from calldata (`calldata[0]` contains the target selector). This fix closes a vulnerability where ANY public function on whitelisted contracts/classes was permitted during setup. - **Made `AllowedElement` require selectors**: Removed `AllowedInstance` and `AllowedClass` variants — all entries now require both an identifier (address or classId) and a function selector - **Re-enabled selectors in the default allow list** with the five traced setup-phase functions: `AuthRegistry._set_authorized` (private FPC path), `AuthRegistry.set_authorized` (public FPC path), `FeeJuice._increase_public_balance`, `Token._increase_public_balance`, `Token.transfer_in_public` - **Removed the unnecessary FPC entry** — FPC's public functions (`_complete_refund`, `_pay_refund`) are set via `set_as_teardown()`, not enqueued in setup - **Changed config from override to extend**: The internal config key is now `txPublicSetupAllowListExtend` (env var `TX_PUBLIC_SETUP_ALLOWLIST` unchanged). Defaults are always present; the config only adds entries on top of them - **Added network-json support**: The extend list can be distributed via `txPublicSetupAllowListExtend` in the network config schema - **Replaced `isOnAllowList` with `checkAllowList`**: Returns a specific rejection reason instead of a boolean. Removed dead branches for selector-less entries. Contract instance is now fetched lazily (only once, only when class-based entries exist). Unknown contracts now return `TX_ERROR_SETUP_FUNCTION_UNKNOWN_CONTRACT` instead of a generic validation error - **Improved `parseAllowList`**: Requires selectors, rejects unknown type prefixes, handles whitespace - **Added tests**: Wrong-selector rejection for both address and class matches, unknown contract rejection, lazy fetch verification, config parsing edge cases Fixes A-463
So it is respected when we deploy a network.
…21017) So it is respected when we deploy a network.
Collaborator
Author
|
🤖 Auto-merge enabled after 4 hours of inactivity. This PR will be merged automatically once all checks pass. |
johnathan79717
pushed a commit
that referenced
this pull request
Mar 4, 2026
## Summary - Sets `wallet.setMinFeePadding(config.minFeePadding)` in the `BotFactory` constructor so that all transactions during bot setup (token deployment, minting) use the configured fee padding instead of the wallet's default (0.5). - Previously, only account deployment explicitly used `config.minFeePadding` (line 226 of factory.ts), while token deploy and minting relied on the wallet default, causing insufficient fee headroom when gas prices escalate during rapid block building in tests. ## Root cause The merge-train/spartan PR (#20899) was dequeued because `e2e_bot.test.ts` ("does not reuse prior bridge claims if recipient address changes") failed with: ``` maxFeesPerGas.feePerL2Gas must be greater than or equal to gasFees.feePerL2Gas, but got maxFeesPerGas.feePerL2Gas=698400000 and gasFees.feePerL2Gas=932700000 ``` The test config had `minFeePadding: 99` (100x multiplier), but this was only applied during account deployment, not during subsequent token deployment/minting which used the wallet's default 1.5x multiplier. ## Test plan - [x] `make yarn-project` builds successfully - [ ] CI e2e_bot test passes with the fix [ClaudeBox log](http://ci.aztec-labs.com/e9fdbc1ddac8e593-1)
AztecBot
added a commit
that referenced
this pull request
Mar 5, 2026
## Summary - Sets `wallet.setMinFeePadding(config.minFeePadding)` in the `BotFactory` constructor so that all transactions during bot setup (token deployment, minting) use the configured fee padding instead of the wallet's default (0.5). - Previously, only account deployment explicitly used `config.minFeePadding` (line 226 of factory.ts), while token deploy and minting relied on the wallet default, causing insufficient fee headroom when gas prices escalate during rapid block building in tests. ## Root cause The merge-train/spartan PR (#20899) was dequeued because `e2e_bot.test.ts` ("does not reuse prior bridge claims if recipient address changes") failed with: ``` maxFeesPerGas.feePerL2Gas must be greater than or equal to gasFees.feePerL2Gas, but got maxFeesPerGas.feePerL2Gas=698400000 and gasFees.feePerL2Gas=932700000 ``` The test config had `minFeePadding: 99` (100x multiplier), but this was only applied during account deployment, not during subsequent token deployment/minting which used the wallet's default 1.5x multiplier. ## Test plan - [x] `make yarn-project` builds successfully - [ ] CI e2e_bot test passes with the fix [ClaudeBox log](http://ci.aztec-labs.com/e9fdbc1ddac8e593-1)
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
fix: track last seen nonce in case of stale fallback L1 RPC node (#20855)
feat: Validate num txs in block proposals (#20850)
fix(archiver): enforce checkpoint boundary on rollbackTo (#20908)
fix: tps zero metrics (#20656)
fix: handle scientific notation in bigintConfigHelper (#20929)
feat(aztec): node enters standby mode on genesis root mismatch (#20938)
fix: logging of class instances (#20807)
feat(slasher): make slash grace period relative to rollup upgrade time (#20942)
chore: add script to find PRs to backport (#20956)
chore: remove unused prover-node dep (#20955)
fix: increase minFeePadding in e2e_bot bridge resume tests and harden GasFees.mul() (#20962)
feat(sequencer): (A-526) rotate publishers when send fails (#20888)
chore: (A-554) bump reth version 1.6.0 -> 1.11.1 for eth devnet (#20889)
chore: metric on how many epochs validator has been on committee (#20967)
fix: set wallet minFeePadding in BotFactory constructor (#20992)
chore: deflake epoch invalidate block test (#21001)
chore(sequencer): e2e tests for invalid signature recovery in checkpoint attestations (#20971)
chore: deflake duplicate proposals and attestations (#20990)
chore: deflake epochs mbps test (#21003)
feat: reenable function selectors in txPublicSetupAllowList (#20909)
fix: limit offenses when voting in tally slashing mode by slashMaxPayloadSize (#20683)
fix(spartan): wire SEQ_L1_PUBLISHING_TIME_ALLOWANCE_IN_SLOT env var (#21017)
END_COMMIT_OVERRIDE