diff --git a/docs/docs-operate/operators/reference/changelog/v4.md b/docs/docs-operate/operators/reference/changelog/v4.md index 774d43713996..599c58e8cfa6 100644 --- a/docs/docs-operate/operators/reference/changelog/v4.md +++ b/docs/docs-operate/operators/reference/changelog/v4.md @@ -87,13 +87,23 @@ The byte-based block size limit has been removed and replaced with field-based b --maxDABlockGas ($SEQ_MAX_DA_BLOCK_GAS) ``` -**New:** +**New (proposer):** ```bash --gasPerBlockAllocationMultiplier ($SEQ_GAS_PER_BLOCK_ALLOCATION_MULTIPLIER) +--maxTxsPerCheckpoint ($SEQ_MAX_TX_PER_CHECKPOINT) ``` -**Migration**: Remove `SEQ_MAX_BLOCK_SIZE_IN_BYTES` from your configuration. Per-block L2 and DA gas budgets are now derived automatically as `(checkpointLimit / maxBlocks) * multiplier`, where the multiplier defaults to 2. You can still override `SEQ_MAX_L2_BLOCK_GAS` and `SEQ_MAX_DA_BLOCK_GAS` explicitly, but they will be capped at the checkpoint-level limits. +**New (validator):** + +```bash +--validateMaxL2BlockGas ($VALIDATOR_MAX_L2_BLOCK_GAS) +--validateMaxDABlockGas ($VALIDATOR_MAX_DA_BLOCK_GAS) +--validateMaxTxsPerBlock ($VALIDATOR_MAX_TX_PER_BLOCK) +--validateMaxTxsPerCheckpoint ($VALIDATOR_MAX_TX_PER_CHECKPOINT) +``` + +**Migration**: Remove `SEQ_MAX_BLOCK_SIZE_IN_BYTES` from your configuration. Per-block L2 and DA gas budgets are now derived automatically as `(checkpointLimit / maxBlocks) * multiplier`, where the multiplier defaults to 2. You can still override `SEQ_MAX_L2_BLOCK_GAS` and `SEQ_MAX_DA_BLOCK_GAS` explicitly, but they will be capped at the checkpoint-level limits. Validators can now set independent per-block and per-checkpoint limits via the `VALIDATOR_` env vars; when not set, only checkpoint-level protocol limits are enforced. ### Setup phase allow list requires function selectors @@ -201,6 +211,21 @@ P2P_RPC_PRICE_BUMP_PERCENTAGE=10 # default: 10 (percent) Set to `0` to disable the percentage-based bump (still requires strictly higher fee). +### Validator-specific block limits + +Validators can now enforce per-block and per-checkpoint limits independently from the sequencer (proposer) limits. This allows operators to accept proposals that exceed their own proposer settings, or to reject proposals that are too large even if the proposer's limits allow them. + +**Configuration:** + +```bash +VALIDATOR_MAX_L2_BLOCK_GAS= # Max L2 gas per block for validation +VALIDATOR_MAX_DA_BLOCK_GAS= # Max DA gas per block for validation +VALIDATOR_MAX_TX_PER_BLOCK= # Max txs per block for validation +VALIDATOR_MAX_TX_PER_CHECKPOINT= # Max txs per checkpoint for validation +``` + +When not set, no per-block limit is enforced for that dimension — only checkpoint-level protocol limits apply. These do not fall back to the `SEQ_` values. + ### Setup allow list extendable via network config The setup phase allow list can now be extended via the network configuration JSON (`txPublicSetupAllowListExtend` field). This allows network operators to distribute additional allowed setup functions to all nodes without requiring code changes. The local environment variable takes precedence over the network-json value. diff --git a/yarn-project/aztec-node/src/aztec-node/server.ts b/yarn-project/aztec-node/src/aztec-node/server.ts index 6d1a4ce06bee..260402b368b4 100644 --- a/yarn-project/aztec-node/src/aztec-node/server.ts +++ b/yarn-project/aztec-node/src/aztec-node/server.ts @@ -346,9 +346,16 @@ export class AztecNodeService implements AztecNode, AztecNodeAdmin, Traceable { // We'll accumulate sentinel watchers here const watchers: Watcher[] = []; - // Create FullNodeCheckpointsBuilder for block proposal handling and tx validation + // Create FullNodeCheckpointsBuilder for block proposal handling and tx validation. + // Override maxTxsPerCheckpoint with the validator-specific limit if set. const validatorCheckpointsBuilder = new FullNodeCheckpointsBuilder( - { ...config, l1GenesisTime, slotDuration: Number(slotDuration), rollupManaLimit }, + { + ...config, + l1GenesisTime, + slotDuration: Number(slotDuration), + rollupManaLimit, + maxTxsPerCheckpoint: config.validateMaxTxsPerCheckpoint, + }, worldStateSynchronizer, archiver, dateProvider, diff --git a/yarn-project/foundation/src/config/env_var.ts b/yarn-project/foundation/src/config/env_var.ts index 45fe01dcdc11..7bbe37fb0947 100644 --- a/yarn-project/foundation/src/config/env_var.ts +++ b/yarn-project/foundation/src/config/env_var.ts @@ -278,6 +278,10 @@ export type EnvVar = | 'TRANSACTIONS_DISABLED' | 'VALIDATOR_ATTESTATIONS_POLLING_INTERVAL_MS' | 'VALIDATOR_DISABLED' + | 'VALIDATOR_MAX_DA_BLOCK_GAS' + | 'VALIDATOR_MAX_L2_BLOCK_GAS' + | 'VALIDATOR_MAX_TX_PER_BLOCK' + | 'VALIDATOR_MAX_TX_PER_CHECKPOINT' | 'VALIDATOR_PRIVATE_KEYS' | 'VALIDATOR_PRIVATE_KEY' | 'VALIDATOR_REEXECUTE' diff --git a/yarn-project/p2p/src/config.ts b/yarn-project/p2p/src/config.ts index 5189cab7adb9..fc27123df79c 100644 --- a/yarn-project/p2p/src/config.ts +++ b/yarn-project/p2p/src/config.ts @@ -40,6 +40,9 @@ export interface P2PConfig TxCollectionConfig, TxFileStoreConfig, Pick { + /** Maximum transactions per block for validation. Overrides maxTxsPerBlock for gossip validation when set. */ + validateMaxTxsPerBlock?: number; + /** A flag dictating whether the P2P subsystem should be enabled. */ p2pEnabled: boolean; @@ -199,6 +202,12 @@ export interface P2PConfig export const DEFAULT_P2P_PORT = 40400; export const p2pConfigMappings: ConfigMappingsType = { + validateMaxTxsPerBlock: { + env: 'VALIDATOR_MAX_TX_PER_BLOCK', + description: + 'Maximum transactions per block for validation. Overrides maxTxsPerBlock for gossip validation when set.', + parseEnv: (val: string) => (val ? parseInt(val, 10) : undefined), + }, p2pEnabled: { env: 'P2P_ENABLED', description: 'A flag dictating whether the P2P subsystem should be enabled.', diff --git a/yarn-project/p2p/src/services/libp2p/libp2p_service.ts b/yarn-project/p2p/src/services/libp2p/libp2p_service.ts index de3c5c9f8fc8..2a81e7a1350d 100644 --- a/yarn-project/p2p/src/services/libp2p/libp2p_service.ts +++ b/yarn-project/p2p/src/services/libp2p/libp2p_service.ts @@ -224,7 +224,7 @@ export class LibP2PService extends WithTracer implements P2PService { const proposalValidatorOpts = { txsPermitted: !config.disableTransactions, - maxTxsPerBlock: config.maxTxsPerBlock, + maxTxsPerBlock: config.validateMaxTxsPerBlock, }; this.blockProposalValidator = new BlockProposalValidator(epochCache, proposalValidatorOpts); this.checkpointProposalValidator = new CheckpointProposalValidator(epochCache, proposalValidatorOpts); diff --git a/yarn-project/stdlib/src/interfaces/validator.ts b/yarn-project/stdlib/src/interfaces/validator.ts index c6596a6aca72..f0b1c05e2209 100644 --- a/yarn-project/stdlib/src/interfaces/validator.ts +++ b/yarn-project/stdlib/src/interfaces/validator.ts @@ -59,10 +59,22 @@ export type ValidatorClientConfig = ValidatorHASignerConfig & { /** Agree to attest to equivocated checkpoint proposals (for testing purposes only) */ attestToEquivocatedProposals?: boolean; + + /** Maximum L2 gas per block for validation. Proposals exceeding this limit are rejected. */ + validateMaxL2BlockGas?: number; + + /** Maximum DA gas per block for validation. Proposals exceeding this limit are rejected. */ + validateMaxDABlockGas?: number; + + /** Maximum transactions per block for validation. Proposals exceeding this limit are rejected. */ + validateMaxTxsPerBlock?: number; + + /** Maximum transactions per checkpoint for validation. Proposals exceeding this limit are rejected. */ + validateMaxTxsPerCheckpoint?: number; }; export type ValidatorClientFullConfig = ValidatorClientConfig & - Pick & + Pick & Pick< SlasherConfig, 'slashBroadcastedInvalidBlockPenalty' | 'slashDuplicateProposalPenalty' | 'slashDuplicateAttestationPenalty' @@ -86,6 +98,10 @@ export const ValidatorClientConfigSchema = zodFor (val ? parseInt(val, 10) : undefined), + }, + validateMaxDABlockGas: { + env: 'VALIDATOR_MAX_DA_BLOCK_GAS', + description: 'Maximum DA block gas for validation. Proposals exceeding this limit are rejected.', + parseEnv: (val: string) => (val ? parseInt(val, 10) : undefined), + }, + validateMaxTxsPerBlock: { + env: 'VALIDATOR_MAX_TX_PER_BLOCK', + description: 'Maximum transactions per block for validation. Proposals exceeding this limit are rejected.', + parseEnv: (val: string) => (val ? parseInt(val, 10) : undefined), + }, + validateMaxTxsPerCheckpoint: { + env: 'VALIDATOR_MAX_TX_PER_CHECKPOINT', + description: 'Maximum transactions per checkpoint for validation. Proposals exceeding this limit are rejected.', + parseEnv: (val: string) => (val ? parseInt(val, 10) : undefined), + }, ...validatorHASignerConfigMappings, }; diff --git a/yarn-project/validator-client/src/factory.ts b/yarn-project/validator-client/src/factory.ts index eacdb5322965..b7645d48c485 100644 --- a/yarn-project/validator-client/src/factory.ts +++ b/yarn-project/validator-client/src/factory.ts @@ -29,7 +29,7 @@ export function createBlockProposalHandler( const metrics = new ValidatorMetrics(deps.telemetry); const blockProposalValidator = new BlockProposalValidator(deps.epochCache, { txsPermitted: !config.disableTransactions, - maxTxsPerBlock: config.maxTxsPerBlock, + maxTxsPerBlock: config.validateMaxTxsPerBlock, }); return new BlockProposalHandler( deps.checkpointsBuilder, diff --git a/yarn-project/validator-client/src/validator.ts b/yarn-project/validator-client/src/validator.ts index 2fad5db0bca7..76f97ed0d86b 100644 --- a/yarn-project/validator-client/src/validator.ts +++ b/yarn-project/validator-client/src/validator.ts @@ -201,7 +201,7 @@ export class ValidatorClient extends (EventEmitter as new () => WatcherEmitter) const metrics = new ValidatorMetrics(telemetry); const blockProposalValidator = new BlockProposalValidator(epochCache, { txsPermitted: !config.disableTransactions, - maxTxsPerBlock: config.maxTxsPerBlock, + maxTxsPerBlock: config.validateMaxTxsPerBlock, }); const blockProposalHandler = new BlockProposalHandler( checkpointsBuilder, @@ -771,8 +771,10 @@ export class ValidatorClient extends (EventEmitter as new () => WatcherEmitter) try { validateCheckpoint(computedCheckpoint, { rollupManaLimit: this.checkpointsBuilder.getConfig().rollupManaLimit, - maxDABlockGas: undefined, - maxL2BlockGas: undefined, + maxDABlockGas: this.config.validateMaxDABlockGas, + maxL2BlockGas: this.config.validateMaxL2BlockGas, + maxTxsPerBlock: this.config.validateMaxTxsPerBlock, + maxTxsPerCheckpoint: this.config.validateMaxTxsPerCheckpoint, }); } catch (err) { this.log.warn(`Checkpoint validation failed: ${err}`, proposalInfo);