@aztec/validator-client 0.0.1-commit.d431d1c → 0.0.1-commit.d58ff9d0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/README.md +64 -19
- package/dest/checkpoint_builder.d.ts +29 -15
- package/dest/checkpoint_builder.d.ts.map +1 -1
- package/dest/checkpoint_builder.js +144 -45
- package/dest/config.d.ts +9 -3
- package/dest/config.d.ts.map +1 -1
- package/dest/config.js +49 -13
- package/dest/duties/validation_service.d.ts +12 -13
- package/dest/duties/validation_service.d.ts.map +1 -1
- package/dest/duties/validation_service.js +33 -45
- package/dest/factory.d.ts +10 -4
- package/dest/factory.d.ts.map +1 -1
- package/dest/factory.js +19 -6
- package/dest/index.d.ts +2 -3
- package/dest/index.d.ts.map +1 -1
- package/dest/index.js +1 -2
- package/dest/key_store/ha_key_store.d.ts +1 -1
- package/dest/key_store/ha_key_store.d.ts.map +1 -1
- package/dest/key_store/ha_key_store.js +3 -3
- package/dest/key_store/web3signer_key_store.d.ts +10 -2
- package/dest/key_store/web3signer_key_store.d.ts.map +1 -1
- package/dest/key_store/web3signer_key_store.js +32 -41
- package/dest/metrics.d.ts +16 -3
- package/dest/metrics.d.ts.map +1 -1
- package/dest/metrics.js +58 -5
- package/dest/proposal_handler.d.ts +165 -0
- package/dest/proposal_handler.d.ts.map +1 -0
- package/dest/proposal_handler.js +1207 -0
- package/dest/validator.d.ts +65 -25
- package/dest/validator.d.ts.map +1 -1
- package/dest/validator.js +377 -240
- package/package.json +19 -17
- package/src/checkpoint_builder.ts +196 -54
- package/src/config.ts +57 -15
- package/src/duties/validation_service.ts +59 -54
- package/src/factory.ts +29 -4
- package/src/index.ts +1 -2
- package/src/key_store/ha_key_store.ts +3 -3
- package/src/key_store/web3signer_key_store.ts +43 -59
- package/src/metrics.ts +81 -6
- package/src/proposal_handler.ts +1314 -0
- package/src/validator.ts +512 -291
- package/dest/block_proposal_handler.d.ts +0 -65
- package/dest/block_proposal_handler.d.ts.map +0 -1
- package/dest/block_proposal_handler.js +0 -561
- package/dest/tx_validator/index.d.ts +0 -3
- package/dest/tx_validator/index.d.ts.map +0 -1
- package/dest/tx_validator/index.js +0 -2
- package/dest/tx_validator/nullifier_cache.d.ts +0 -14
- package/dest/tx_validator/nullifier_cache.d.ts.map +0 -1
- package/dest/tx_validator/nullifier_cache.js +0 -24
- package/dest/tx_validator/tx_validator_factory.d.ts +0 -18
- package/dest/tx_validator/tx_validator_factory.d.ts.map +0 -1
- package/dest/tx_validator/tx_validator_factory.js +0 -54
- package/src/block_proposal_handler.ts +0 -576
- package/src/tx_validator/index.ts +0 -2
- package/src/tx_validator/nullifier_cache.ts +0 -30
- package/src/tx_validator/tx_validator_factory.ts +0 -135
package/README.md
CHANGED
|
@@ -77,6 +77,8 @@ These rules must always hold:
|
|
|
77
77
|
2. **Global variables match within checkpoint**: All blocks within the same checkpoint must have identical global variables (except `blockNumber`), which includes the slot number
|
|
78
78
|
3. **inHash is constant**: All blocks in a checkpoint share the same L1-to-L2 messages hash
|
|
79
79
|
4. **Sequential indexWithinCheckpoint**: Block N must have `indexWithinCheckpoint = parent.indexWithinCheckpoint + 1`
|
|
80
|
+
5. **One proposer per slot**: Each slot has exactly one designated proposer. Sending multiple proposals for the same position (slot, indexWithinCheckpoint) with different content is equivocation and slashable
|
|
81
|
+
6. **One attestation per slot**: Validators should only attest to one checkpoint per slot. Attesting to different proposals (different archives) for the same slot is equivocation and slashable
|
|
80
82
|
|
|
81
83
|
## Validation Flow
|
|
82
84
|
|
|
@@ -87,15 +89,14 @@ When a `BlockProposal` is received via P2P, the `BlockProposalHandler` performs:
|
|
|
87
89
|
```
|
|
88
90
|
1. Verify proposer signature
|
|
89
91
|
2. Check proposal is from current/next slot proposer (via BlockProposalValidator)
|
|
90
|
-
3.
|
|
91
|
-
4.
|
|
92
|
-
5.
|
|
93
|
-
|
|
94
|
-
|
|
95
|
-
|
|
96
|
-
|
|
97
|
-
|
|
98
|
-
9. Compare re-execution result with proposal
|
|
92
|
+
3. Detect duplicate proposals (same slot + indexWithinCheckpoint, different archive) slashing proposer on equivocation
|
|
93
|
+
4. Find parent block by archive root (wait/retry if not synced)
|
|
94
|
+
5. Compute checkpoint number from parent
|
|
95
|
+
6. If indexWithinCheckpoint > 0, then validate global variables match parent (chainId, version, slotNumber, timestamp, coinbase, feeRecipient, gasFees)
|
|
96
|
+
7. Verify inHash matches computed from L1-to-L2 messages
|
|
97
|
+
8. Collect transactions from pool/network/proposal
|
|
98
|
+
9. Re-execute transactions (if enabled)
|
|
99
|
+
10. Compare re-execution result with proposal
|
|
99
100
|
```
|
|
100
101
|
|
|
101
102
|
### Checkpoint Proposal Validation
|
|
@@ -155,15 +156,16 @@ Time | Proposer | Validator
|
|
|
155
156
|
|
|
156
157
|
## Configuration
|
|
157
158
|
|
|
158
|
-
| Flag
|
|
159
|
-
|
|
|
160
|
-
| `
|
|
161
|
-
| `
|
|
162
|
-
| `
|
|
163
|
-
| `
|
|
164
|
-
| `
|
|
165
|
-
| `
|
|
166
|
-
| `
|
|
159
|
+
| Flag | Purpose |
|
|
160
|
+
| -------------------------------------------------- | -------------------------------------------------------------------- |
|
|
161
|
+
| `fishermanMode` | Validate proposals but don't broadcast attestations (monitoring only) |
|
|
162
|
+
| `alwaysReexecuteBlockProposals` | Force re-execution even when not in committee |
|
|
163
|
+
| `slashBroadcastedInvalidBlockPenalty` | Penalty amount for invalid proposals (0 = disabled) |
|
|
164
|
+
| `slashBroadcastedInvalidCheckpointProposalPenalty` | Penalty amount for invalid checkpoint proposals (0 = disabled) |
|
|
165
|
+
| `slashDuplicateProposalPenalty` | Penalty amount for duplicate proposals (0 = disabled) |
|
|
166
|
+
| `slashDuplicateAttestationPenalty` | Penalty amount for duplicate attestations (0 = disabled) |
|
|
167
|
+
| `attestationPollingIntervalMs` | How often to poll for attestations when collecting |
|
|
168
|
+
| `disabledValidators` | Validator addresses to exclude from duties |
|
|
167
169
|
|
|
168
170
|
### High Availability (HA) Keystore
|
|
169
171
|
|
|
@@ -220,6 +222,49 @@ This is useful for monitoring network health without participating in consensus.
|
|
|
220
222
|
- `createCheckpointProposal(...)` → `CheckpointProposal`: Signs checkpoint proposal
|
|
221
223
|
- `attestToCheckpointProposal(proposal, attestors)` → `CheckpointAttestation[]`: Creates attestations for given addresses
|
|
222
224
|
|
|
225
|
+
## Block Building Limits
|
|
226
|
+
|
|
227
|
+
L1 enforces gas and blob capacity per checkpoint. The node enforces these during block building to avoid L1 rejection. Three dimensions are metered: L2 gas (mana), DA gas, and blob fields. DA gas maps to blob fields today (`daGas = blobFields * 32`) but both are tracked independently.
|
|
228
|
+
|
|
229
|
+
The full per-tx → per-block → per-checkpoint limits hierarchy, including how the per-block budgets relate to the network admission limits, is documented in [`stdlib/src/gas/README.md`](../stdlib/src/gas/README.md) under "Gas and Data Limits".
|
|
230
|
+
|
|
231
|
+
### Checkpoint limits
|
|
232
|
+
|
|
233
|
+
| Dimension | Source | Budget |
|
|
234
|
+
| --- | --- | --- |
|
|
235
|
+
| L2 gas (mana) | `rollup.getManaLimit()` | Fetched from L1 at startup |
|
|
236
|
+
| DA gas | `MAX_PROCESSABLE_DA_GAS_PER_CHECKPOINT` | 786,432 (6 blobs × 4096 fields × 32 gas/field) |
|
|
237
|
+
| Blob fields | `BLOBS_PER_CHECKPOINT × FIELDS_PER_BLOB` | 24,576 minus checkpoint/block-end overhead |
|
|
238
|
+
|
|
239
|
+
### Per-block budgets
|
|
240
|
+
|
|
241
|
+
Per-block budgets prevent one block from consuming the entire checkpoint budget. The checkpoint builder dynamically computes per-block limits before each block based on the remaining checkpoint budget and the number of remaining blocks.
|
|
242
|
+
|
|
243
|
+
**Proposer**: When building a proposal (`isBuildingProposal: true`), the `CheckpointProposalJob` passes `maxBlocksPerCheckpoint` (from the timetable) and `perBlockAllocationMultiplier` (default 1.2) via opts to `CheckpointBuilder.buildBlock`. The builder computes a fair share as `min(perBlockLimit, ceil(remainingBudget / remainingBlocks * multiplier), remainingBudget)`. The multiplier greater than 1 allows early blocks to use more than their even share, since different blocks hit different limit dimensions (L2 gas, DA gas, blob fields) — a strict even split would waste capacity. As prior blocks consume budget, later blocks see tightened limits. This applies to all four dimensions (L2 gas, DA gas, blob fields, transaction count). Operators can set hard per-block caps via `SEQ_MAX_L2_BLOCK_GAS` / `SEQ_MAX_DA_BLOCK_GAS` / `SEQ_MAX_TX_PER_BLOCK` (capped at checkpoint limits at startup); these act as additional upper bounds alongside the redistribution.
|
|
244
|
+
|
|
245
|
+
**Validator**: When re-executing a proposal (`isBuildingProposal` unset), `capLimitsByCheckpointBudgets` only caps by the per-block limit and the total remaining checkpoint budget — no redistribution or multiplier is applied. This avoids false rejections due to differences between proposer and validator fair-share calculations. Validators can optionally set hard per-block limits via `VALIDATOR_MAX_L2_BLOCK_GAS`, `VALIDATOR_MAX_DA_BLOCK_GAS`, and `VALIDATOR_MAX_TX_PER_BLOCK`. When unset, no per-block limit is enforced (checkpoint-level protocol limits still apply). These are independent of the `SEQ_` vars so operators can tune proposer and validation limits separately.
|
|
246
|
+
|
|
247
|
+
### Per-transaction enforcement
|
|
248
|
+
|
|
249
|
+
**Mempool entry** (`GasLimitsValidator`): L2 gas must be ≤ `MAX_PROCESSABLE_L2_GAS` (6,540,000) and ≥ fixed minimums.
|
|
250
|
+
|
|
251
|
+
**Block building** (`PublicProcessor.process`): Before processing, txs are skipped if their estimated blob fields or gas limits would exceed the block budget. After processing, actual values are checked and the tx is reverted if limits are exceeded.
|
|
252
|
+
|
|
253
|
+
### Gas limit configuration
|
|
254
|
+
|
|
255
|
+
| Variable | Default | Description |
|
|
256
|
+
| --- | --- | --- |
|
|
257
|
+
| `SEQ_MAX_L2_BLOCK_GAS` | *none* | Hard per-block L2 gas cap. Capped at `rollupManaLimit` at startup. When unset, redistribution dynamically computes per-block limits. |
|
|
258
|
+
| `SEQ_MAX_DA_BLOCK_GAS` | *none* | Hard per-block DA gas cap. Capped at `MAX_PROCESSABLE_DA_GAS_PER_CHECKPOINT` at startup. When unset, redistribution handles it. |
|
|
259
|
+
| `SEQ_MAX_TX_PER_BLOCK` | *none* | Hard per-block tx count cap. Capped at `SEQ_MAX_TX_PER_CHECKPOINT` at startup (if set). |
|
|
260
|
+
| `SEQ_MAX_TX_PER_CHECKPOINT` | *none* | Total txs across all blocks in a checkpoint. When set, checkpoint-level capping and redistribution are enforced for tx count. |
|
|
261
|
+
| `SEQ_PER_BLOCK_ALLOCATION_MULTIPLIER` | 1.2 | Multiplier for per-block budget redistribution. Passed via opts to the checkpoint builder during proposal building. |
|
|
262
|
+
| `SEQ_REDISTRIBUTE_CHECKPOINT_BUDGET` | true | Legacy flag; redistribution is now always active during proposal building and inactive during validation. |
|
|
263
|
+
| `VALIDATOR_MAX_L2_BLOCK_GAS` | *none* | Per-block L2 gas limit for validation. Proposals exceeding this are rejected. |
|
|
264
|
+
| `VALIDATOR_MAX_DA_BLOCK_GAS` | *none* | Per-block DA gas limit for validation. Proposals exceeding this are rejected. |
|
|
265
|
+
| `VALIDATOR_MAX_TX_PER_BLOCK` | *none* | Per-block tx count limit for validation. Proposals exceeding this are rejected. |
|
|
266
|
+
| `VALIDATOR_MAX_TX_PER_CHECKPOINT` | *none* | Per-checkpoint tx count limit for validation. Proposals exceeding this are rejected. |
|
|
267
|
+
|
|
223
268
|
## Testing Patterns
|
|
224
269
|
|
|
225
270
|
### Common Mocks
|
|
@@ -268,7 +313,7 @@ For tests that exercise re-execution:
|
|
|
268
313
|
```typescript
|
|
269
314
|
// Mock parent block lookup
|
|
270
315
|
blockSource.getBlockHeaderByArchive.mockResolvedValue(parentBlockHeader);
|
|
271
|
-
blockSource.
|
|
316
|
+
blockSource.getL2Block.mockResolvedValue({
|
|
272
317
|
checkpointNumber: CheckpointNumber(1),
|
|
273
318
|
indexWithinCheckpoint: 0,
|
|
274
319
|
header: { globalVariables: parentGlobalVariables },
|
|
@@ -1,20 +1,18 @@
|
|
|
1
1
|
import { BlockNumber, CheckpointNumber } from '@aztec/foundation/branded-types';
|
|
2
2
|
import { Fr } from '@aztec/foundation/curves/bn254';
|
|
3
|
-
import {
|
|
3
|
+
import { type LoggerBindings } from '@aztec/foundation/log';
|
|
4
|
+
import { DateProvider } from '@aztec/foundation/timer';
|
|
4
5
|
import { LightweightCheckpointBuilder } from '@aztec/prover-client/light';
|
|
5
|
-
import { PublicProcessor } from '@aztec/simulator/server';
|
|
6
|
-
import {
|
|
6
|
+
import { type AvmSimulator, PublicContractsDB, PublicProcessor } from '@aztec/simulator/server';
|
|
7
|
+
import { L2Block } from '@aztec/stdlib/block';
|
|
7
8
|
import { Checkpoint } from '@aztec/stdlib/checkpoint';
|
|
8
9
|
import type { ContractDataSource } from '@aztec/stdlib/contract';
|
|
9
10
|
import type { L1RollupConstants } from '@aztec/stdlib/epoch-helpers';
|
|
10
|
-
import { type BuildBlockInCheckpointResult, type FullNodeBlockBuilderConfig, type ICheckpointBlockBuilder, type ICheckpointsBuilder, type MerkleTreeWriteOperations, type PublicProcessorLimits, type WorldStateSynchronizer } from '@aztec/stdlib/interfaces/server';
|
|
11
|
+
import { type BlockBuilderOptions, type BuildBlockInCheckpointResult, type FullNodeBlockBuilderConfig, type ICheckpointBlockBuilder, type ICheckpointsBuilder, type MerkleTreeWriteOperations, type PublicProcessorLimits, type WorldStateSynchronizer } from '@aztec/stdlib/interfaces/server';
|
|
12
|
+
import { type DebugLogStore } from '@aztec/stdlib/logs';
|
|
11
13
|
import { type CheckpointGlobalVariables, GlobalVariables, StateReference, Tx } from '@aztec/stdlib/tx';
|
|
12
14
|
import { type TelemetryClient } from '@aztec/telemetry-client';
|
|
13
15
|
export type { BuildBlockInCheckpointResult } from '@aztec/stdlib/interfaces/server';
|
|
14
|
-
/** Result of building a block within a checkpoint. Extends the base interface with timer. */
|
|
15
|
-
export interface BuildBlockInCheckpointResultWithTimer extends BuildBlockInCheckpointResult {
|
|
16
|
-
blockBuildingTimer: Timer;
|
|
17
|
-
}
|
|
18
16
|
/**
|
|
19
17
|
* Builder for a single checkpoint. Handles building blocks within the checkpoint
|
|
20
18
|
* and completing it.
|
|
@@ -26,18 +24,31 @@ export declare class CheckpointBuilder implements ICheckpointBlockBuilder {
|
|
|
26
24
|
private contractDataSource;
|
|
27
25
|
private dateProvider;
|
|
28
26
|
private telemetryClient;
|
|
29
|
-
|
|
27
|
+
private avmSimulator;
|
|
28
|
+
private debugLogStore;
|
|
29
|
+
private log;
|
|
30
|
+
/** Persistent contracts DB shared across all blocks in this checkpoint. */
|
|
31
|
+
protected contractsDB: PublicContractsDB;
|
|
32
|
+
constructor(checkpointBuilder: LightweightCheckpointBuilder, fork: MerkleTreeWriteOperations, config: FullNodeBlockBuilderConfig, contractDataSource: ContractDataSource, dateProvider: DateProvider, telemetryClient: TelemetryClient, avmSimulator: AvmSimulator, bindings?: LoggerBindings, debugLogStore?: DebugLogStore);
|
|
30
33
|
getConstantData(): CheckpointGlobalVariables;
|
|
31
34
|
/**
|
|
32
35
|
* Builds a single block within this checkpoint.
|
|
36
|
+
* Automatically caps gas and blob field limits based on checkpoint-level budgets and prior blocks.
|
|
33
37
|
*/
|
|
34
|
-
buildBlock(pendingTxs: Iterable<Tx> | AsyncIterable<Tx>, blockNumber: BlockNumber, timestamp: bigint, opts:
|
|
38
|
+
buildBlock(pendingTxs: Iterable<Tx> | AsyncIterable<Tx>, blockNumber: BlockNumber, timestamp: bigint, opts: BlockBuilderOptions & {
|
|
35
39
|
expectedEndState?: StateReference;
|
|
36
|
-
}): Promise<
|
|
40
|
+
}): Promise<BuildBlockInCheckpointResult>;
|
|
37
41
|
/** Completes the checkpoint and returns it. */
|
|
38
42
|
completeCheckpoint(): Promise<Checkpoint>;
|
|
39
43
|
/** Gets the checkpoint currently in progress. */
|
|
40
44
|
getCheckpoint(): Promise<Checkpoint>;
|
|
45
|
+
/**
|
|
46
|
+
* Caps per-block gas and blob field limits by remaining checkpoint-level budgets.
|
|
47
|
+
* When building a proposal (isBuildingProposal=true), computes a fair share of remaining budget
|
|
48
|
+
* across remaining blocks scaled by the multiplier. When validating, only caps by per-block limit
|
|
49
|
+
* and remaining checkpoint budget (no redistribution or multiplier).
|
|
50
|
+
*/
|
|
51
|
+
protected capLimitsByCheckpointBudgets(opts: BlockBuilderOptions): Pick<PublicProcessorLimits, 'maxBlockGas' | 'maxBlobFields' | 'maxTransactions'>;
|
|
41
52
|
protected makeBlockBuilderDeps(globalVariables: GlobalVariables, fork: MerkleTreeWriteOperations): Promise<{
|
|
42
53
|
processor: PublicProcessor;
|
|
43
54
|
validator: import("@aztec/stdlib/interfaces/server").PublicProcessorValidator;
|
|
@@ -49,19 +60,22 @@ export declare class FullNodeCheckpointsBuilder implements ICheckpointsBuilder {
|
|
|
49
60
|
private worldState;
|
|
50
61
|
private contractDataSource;
|
|
51
62
|
private dateProvider;
|
|
63
|
+
private avmSimulator;
|
|
52
64
|
private telemetryClient;
|
|
53
|
-
|
|
65
|
+
private debugLogStore;
|
|
66
|
+
private log;
|
|
67
|
+
constructor(config: FullNodeBlockBuilderConfig & Pick<L1RollupConstants, 'l1GenesisTime' | 'slotDuration'>, worldState: WorldStateSynchronizer, contractDataSource: ContractDataSource, dateProvider: DateProvider, avmSimulator: AvmSimulator, telemetryClient?: TelemetryClient, debugLogStore?: DebugLogStore);
|
|
54
68
|
getConfig(): FullNodeBlockBuilderConfig;
|
|
55
69
|
updateConfig(config: Partial<FullNodeBlockBuilderConfig>): void;
|
|
56
70
|
/**
|
|
57
71
|
* Starts a new checkpoint and returns a CheckpointBuilder to build blocks within it.
|
|
58
72
|
*/
|
|
59
|
-
startCheckpoint(checkpointNumber: CheckpointNumber, constants: CheckpointGlobalVariables, l1ToL2Messages: Fr[], previousCheckpointOutHashes: Fr[], fork: MerkleTreeWriteOperations): Promise<CheckpointBuilder>;
|
|
73
|
+
startCheckpoint(checkpointNumber: CheckpointNumber, constants: CheckpointGlobalVariables, feeAssetPriceModifier: bigint, l1ToL2Messages: Fr[], previousCheckpointOutHashes: Fr[], fork: MerkleTreeWriteOperations, bindings?: LoggerBindings): Promise<CheckpointBuilder>;
|
|
60
74
|
/**
|
|
61
75
|
* Opens a checkpoint, either starting fresh or resuming from existing blocks.
|
|
62
76
|
*/
|
|
63
|
-
openCheckpoint(checkpointNumber: CheckpointNumber, constants: CheckpointGlobalVariables, l1ToL2Messages: Fr[], previousCheckpointOutHashes: Fr[], fork: MerkleTreeWriteOperations, existingBlocks?:
|
|
77
|
+
openCheckpoint(checkpointNumber: CheckpointNumber, constants: CheckpointGlobalVariables, feeAssetPriceModifier: bigint, l1ToL2Messages: Fr[], previousCheckpointOutHashes: Fr[], fork: MerkleTreeWriteOperations, existingBlocks?: L2Block[], bindings?: LoggerBindings): Promise<CheckpointBuilder>;
|
|
64
78
|
/** Returns a fork of the world state at the given block number. */
|
|
65
79
|
getFork(blockNumber: BlockNumber): Promise<MerkleTreeWriteOperations>;
|
|
66
80
|
}
|
|
67
|
-
//# sourceMappingURL=data:application/json;base64,
|
|
81
|
+
//# sourceMappingURL=data:application/json;base64,eyJ2ZXJzaW9uIjozLCJmaWxlIjoiY2hlY2twb2ludF9idWlsZGVyLmQudHMiLCJzb3VyY2VSb290IjoiIiwic291cmNlcyI6WyIuLi9zcmMvY2hlY2twb2ludF9idWlsZGVyLnRzIl0sIm5hbWVzIjpbXSwibWFwcGluZ3MiOiJBQUVBLE9BQU8sRUFBRSxXQUFXLEVBQUUsZ0JBQWdCLEVBQUUsTUFBTSxpQ0FBaUMsQ0FBQztBQUVoRixPQUFPLEVBQUUsRUFBRSxFQUFFLE1BQU0sZ0NBQWdDLENBQUM7QUFDcEQsT0FBTyxFQUFlLEtBQUssY0FBYyxFQUFnQixNQUFNLHVCQUF1QixDQUFDO0FBRXZGLE9BQU8sRUFBRSxZQUFZLEVBQVcsTUFBTSx5QkFBeUIsQ0FBQztBQUVoRSxPQUFPLEVBQUUsNEJBQTRCLEVBQUUsTUFBTSw0QkFBNEIsQ0FBQztBQUMxRSxPQUFPLEVBQ0wsS0FBSyxZQUFZLEVBRWpCLGlCQUFpQixFQUNqQixlQUFlLEVBRWhCLE1BQU0seUJBQXlCLENBQUM7QUFDakMsT0FBTyxFQUFFLE9BQU8sRUFBRSxNQUFNLHFCQUFxQixDQUFDO0FBQzlDLE9BQU8sRUFBRSxVQUFVLEVBQUUsTUFBTSwwQkFBMEIsQ0FBQztBQUN0RCxPQUFPLEtBQUssRUFBRSxrQkFBa0IsRUFBRSxNQUFNLHdCQUF3QixDQUFDO0FBQ2pFLE9BQU8sS0FBSyxFQUFFLGlCQUFpQixFQUFFLE1BQU0sNkJBQTZCLENBQUM7QUFFckUsT0FBTyxFQUNMLEtBQUssbUJBQW1CLEVBQ3hCLEtBQUssNEJBQTRCLEVBQ2pDLEtBQUssMEJBQTBCLEVBRS9CLEtBQUssdUJBQXVCLEVBQzVCLEtBQUssbUJBQW1CLEVBRXhCLEtBQUsseUJBQXlCLEVBQzlCLEtBQUsscUJBQXFCLEVBQzFCLEtBQUssc0JBQXNCLEVBQzVCLE1BQU0saUNBQWlDLENBQUM7QUFDekMsT0FBTyxFQUFFLEtBQUssYUFBYSxFQUFxQixNQUFNLG9CQUFvQixDQUFDO0FBRTNFLE9BQU8sRUFBRSxLQUFLLHlCQUF5QixFQUFFLGVBQWUsRUFBRSxjQUFjLEVBQUUs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
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"checkpoint_builder.d.ts","sourceRoot":"","sources":["../src/checkpoint_builder.ts"],"names":[],"mappings":"
|
|
1
|
+
{"version":3,"file":"checkpoint_builder.d.ts","sourceRoot":"","sources":["../src/checkpoint_builder.ts"],"names":[],"mappings":"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"}
|
|
@@ -1,17 +1,19 @@
|
|
|
1
|
-
import {
|
|
1
|
+
import { NUM_CHECKPOINT_END_MARKER_FIELDS, getNumBlockEndBlobFields } from '@aztec/blob-lib/encoding';
|
|
2
|
+
import { BLOBS_PER_CHECKPOINT, FIELDS_PER_BLOB, MAX_PROCESSABLE_DA_GAS_PER_CHECKPOINT } from '@aztec/constants';
|
|
3
|
+
import { merge, pick, sum } from '@aztec/foundation/collection';
|
|
2
4
|
import { createLogger } from '@aztec/foundation/log';
|
|
3
5
|
import { bufferToHex } from '@aztec/foundation/string';
|
|
4
|
-
import {
|
|
5
|
-
import { getDefaultAllowedSetupFunctions } from '@aztec/p2p/msg_validators';
|
|
6
|
+
import { elapsed } from '@aztec/foundation/timer';
|
|
7
|
+
import { createTxValidatorForBlockBuilding, getDefaultAllowedSetupFunctions } from '@aztec/p2p/msg_validators';
|
|
6
8
|
import { LightweightCheckpointBuilder } from '@aztec/prover-client/light';
|
|
7
9
|
import { GuardedMerkleTreeOperations, PublicContractsDB, PublicProcessor, createPublicTxSimulatorForBlockBuilding } from '@aztec/simulator/server';
|
|
8
10
|
import { Gas } from '@aztec/stdlib/gas';
|
|
9
|
-
import { FullNodeBlockBuilderConfigKeys } from '@aztec/stdlib/interfaces/server';
|
|
11
|
+
import { FullNodeBlockBuilderConfigKeys, InsufficientValidTxsError } from '@aztec/stdlib/interfaces/server';
|
|
12
|
+
import { NullDebugLogStore } from '@aztec/stdlib/logs';
|
|
10
13
|
import { MerkleTreeId } from '@aztec/stdlib/trees';
|
|
11
14
|
import { GlobalVariables } from '@aztec/stdlib/tx';
|
|
12
15
|
import { getTelemetryClient } from '@aztec/telemetry-client';
|
|
13
|
-
import {
|
|
14
|
-
const log = createLogger('checkpoint-builder');
|
|
16
|
+
import { ForkCheckpoint } from '@aztec/world-state';
|
|
15
17
|
/**
|
|
16
18
|
* Builder for a single checkpoint. Handles building blocks within the checkpoint
|
|
17
19
|
* and completing it.
|
|
@@ -22,23 +24,34 @@ const log = createLogger('checkpoint-builder');
|
|
|
22
24
|
contractDataSource;
|
|
23
25
|
dateProvider;
|
|
24
26
|
telemetryClient;
|
|
25
|
-
|
|
27
|
+
avmSimulator;
|
|
28
|
+
debugLogStore;
|
|
29
|
+
log;
|
|
30
|
+
/** Persistent contracts DB shared across all blocks in this checkpoint. */ contractsDB;
|
|
31
|
+
constructor(checkpointBuilder, fork, config, contractDataSource, dateProvider, telemetryClient, avmSimulator, bindings, debugLogStore = new NullDebugLogStore()){
|
|
26
32
|
this.checkpointBuilder = checkpointBuilder;
|
|
27
33
|
this.fork = fork;
|
|
28
34
|
this.config = config;
|
|
29
35
|
this.contractDataSource = contractDataSource;
|
|
30
36
|
this.dateProvider = dateProvider;
|
|
31
37
|
this.telemetryClient = telemetryClient;
|
|
38
|
+
this.avmSimulator = avmSimulator;
|
|
39
|
+
this.debugLogStore = debugLogStore;
|
|
40
|
+
this.log = createLogger('checkpoint-builder', {
|
|
41
|
+
...bindings,
|
|
42
|
+
instanceId: `checkpoint-${checkpointBuilder.checkpointNumber}`
|
|
43
|
+
});
|
|
44
|
+
this.contractsDB = new PublicContractsDB(this.contractDataSource, this.log.getBindings());
|
|
32
45
|
}
|
|
33
46
|
getConstantData() {
|
|
34
47
|
return this.checkpointBuilder.constants;
|
|
35
48
|
}
|
|
36
49
|
/**
|
|
37
50
|
* Builds a single block within this checkpoint.
|
|
51
|
+
* Automatically caps gas and blob field limits based on checkpoint-level budgets and prior blocks.
|
|
38
52
|
*/ async buildBlock(pendingTxs, blockNumber, timestamp, opts) {
|
|
39
|
-
const blockBuildingTimer = new Timer();
|
|
40
53
|
const slot = this.checkpointBuilder.constants.slotNumber;
|
|
41
|
-
log.verbose(`Building block ${blockNumber} for slot ${slot} within checkpoint`, {
|
|
54
|
+
this.log.verbose(`Building block ${blockNumber} for slot ${slot} within checkpoint`, {
|
|
42
55
|
slot,
|
|
43
56
|
blockNumber,
|
|
44
57
|
...opts,
|
|
@@ -56,29 +69,54 @@ const log = createLogger('checkpoint-builder');
|
|
|
56
69
|
gasFees: constants.gasFees
|
|
57
70
|
});
|
|
58
71
|
const { processor, validator } = await this.makeBlockBuilderDeps(globalVariables, this.fork);
|
|
59
|
-
|
|
60
|
-
|
|
61
|
-
|
|
62
|
-
|
|
63
|
-
});
|
|
64
|
-
// How much public gas was processed
|
|
65
|
-
const publicGas = processedTxs.reduce((acc, tx)=>acc.add(tx.gasUsed.publicGas), Gas.empty());
|
|
66
|
-
const res = {
|
|
67
|
-
block,
|
|
68
|
-
publicGas,
|
|
69
|
-
publicProcessorDuration,
|
|
70
|
-
numTxs: processedTxs.length,
|
|
71
|
-
failedTxs,
|
|
72
|
-
blockBuildingTimer,
|
|
73
|
-
usedTxs,
|
|
74
|
-
usedTxBlobFields
|
|
72
|
+
// Cap gas limits amd available blob fields by remaining checkpoint-level budgets
|
|
73
|
+
const cappedOpts = {
|
|
74
|
+
...opts,
|
|
75
|
+
...this.capLimitsByCheckpointBudgets(opts)
|
|
75
76
|
};
|
|
76
|
-
|
|
77
|
-
|
|
77
|
+
// Create a block-level checkpoint on the contracts DB so we can roll back on failure
|
|
78
|
+
this.contractsDB.createCheckpoint();
|
|
79
|
+
// We execute all merkle tree operations on a world state fork checkpoint
|
|
80
|
+
// This enables us to discard all modifications in the event that we fail to successfully process sufficient transactions
|
|
81
|
+
const forkCheckpoint = await ForkCheckpoint.new(this.fork);
|
|
82
|
+
try {
|
|
83
|
+
const [publicProcessorDuration, [processedTxs, failedTxs, usedTxs]] = await elapsed(()=>processor.process(pendingTxs, cappedOpts, validator));
|
|
84
|
+
// Throw before updating state if we don't have enough valid txs
|
|
85
|
+
const minValidTxs = opts.minValidTxs ?? 0;
|
|
86
|
+
if (processedTxs.length < minValidTxs) {
|
|
87
|
+
throw new InsufficientValidTxsError(processedTxs.length, minValidTxs, failedTxs);
|
|
88
|
+
}
|
|
89
|
+
// Commit the fork checkpoint
|
|
90
|
+
await forkCheckpoint.commit();
|
|
91
|
+
// Add block to checkpoint
|
|
92
|
+
const { block } = await this.checkpointBuilder.addBlock(globalVariables, processedTxs, {
|
|
93
|
+
expectedEndState: opts.expectedEndState
|
|
94
|
+
});
|
|
95
|
+
this.contractsDB.commitCheckpoint();
|
|
96
|
+
this.log.debug('Built block within checkpoint', {
|
|
97
|
+
header: block.header.toInspect(),
|
|
98
|
+
processedTxs: processedTxs.map((tx)=>tx.hash.toString()),
|
|
99
|
+
failedTxs: failedTxs.map((tx)=>tx.tx.txHash.toString())
|
|
100
|
+
});
|
|
101
|
+
return {
|
|
102
|
+
block,
|
|
103
|
+
publicProcessorDuration,
|
|
104
|
+
numTxs: processedTxs.length,
|
|
105
|
+
failedTxs,
|
|
106
|
+
usedTxs
|
|
107
|
+
};
|
|
108
|
+
} catch (err) {
|
|
109
|
+
// Revert all changes to contracts db
|
|
110
|
+
this.contractsDB.revertCheckpoint();
|
|
111
|
+
// If we reached the point of committing the checkpoint, this does nothing
|
|
112
|
+
// Otherwise it reverts any changes made to the fork for this failed block
|
|
113
|
+
await forkCheckpoint.revert();
|
|
114
|
+
throw err;
|
|
115
|
+
}
|
|
78
116
|
}
|
|
79
117
|
/** Completes the checkpoint and returns it. */ async completeCheckpoint() {
|
|
80
118
|
const checkpoint = await this.checkpointBuilder.completeCheckpoint();
|
|
81
|
-
log.verbose(`Completed checkpoint ${checkpoint.number}`, {
|
|
119
|
+
this.log.verbose(`Completed checkpoint ${checkpoint.number}`, {
|
|
82
120
|
checkpointNumber: checkpoint.number,
|
|
83
121
|
numBlocks: checkpoint.blocks.length,
|
|
84
122
|
archiveRoot: checkpoint.archive.root.toString()
|
|
@@ -88,13 +126,66 @@ const log = createLogger('checkpoint-builder');
|
|
|
88
126
|
/** Gets the checkpoint currently in progress. */ getCheckpoint() {
|
|
89
127
|
return this.checkpointBuilder.clone().completeCheckpoint();
|
|
90
128
|
}
|
|
129
|
+
/**
|
|
130
|
+
* Caps per-block gas and blob field limits by remaining checkpoint-level budgets.
|
|
131
|
+
* When building a proposal (isBuildingProposal=true), computes a fair share of remaining budget
|
|
132
|
+
* across remaining blocks scaled by the multiplier. When validating, only caps by per-block limit
|
|
133
|
+
* and remaining checkpoint budget (no redistribution or multiplier).
|
|
134
|
+
*/ capLimitsByCheckpointBudgets(opts) {
|
|
135
|
+
const existingBlocks = this.checkpointBuilder.getBlocks();
|
|
136
|
+
// Remaining L2 gas (mana)
|
|
137
|
+
// IMPORTANT: This assumes mana is computed solely based on L2 gas used in transactions.
|
|
138
|
+
// This may change in the future.
|
|
139
|
+
const usedMana = sum(existingBlocks.map((b)=>b.header.totalManaUsed.toNumber()));
|
|
140
|
+
const remainingMana = this.config.rollupManaLimit - usedMana;
|
|
141
|
+
// Remaining DA gas
|
|
142
|
+
const usedDAGas = sum(existingBlocks.map((b)=>b.computeDAGasUsed())) ?? 0;
|
|
143
|
+
const remainingDAGas = MAX_PROCESSABLE_DA_GAS_PER_CHECKPOINT - usedDAGas;
|
|
144
|
+
// Remaining blob fields (block blob fields include both tx data and block-end overhead)
|
|
145
|
+
const usedBlobFields = sum(existingBlocks.map((b)=>b.toBlobFields().length));
|
|
146
|
+
const totalBlobCapacity = BLOBS_PER_CHECKPOINT * FIELDS_PER_BLOB - NUM_CHECKPOINT_END_MARKER_FIELDS;
|
|
147
|
+
const isFirstBlock = existingBlocks.length === 0;
|
|
148
|
+
const blockEndOverhead = getNumBlockEndBlobFields(isFirstBlock);
|
|
149
|
+
const maxBlobFieldsForTxs = totalBlobCapacity - usedBlobFields - blockEndOverhead;
|
|
150
|
+
// Remaining txs
|
|
151
|
+
const usedTxs = sum(existingBlocks.map((b)=>b.body.txEffects.length));
|
|
152
|
+
const remainingTxs = Math.max(0, (this.config.maxTxsPerCheckpoint ?? Infinity) - usedTxs);
|
|
153
|
+
// Cap by per-block limit + remaining checkpoint budget
|
|
154
|
+
let cappedL2Gas = Math.min(opts.maxBlockGas?.l2Gas ?? Infinity, remainingMana);
|
|
155
|
+
let cappedDAGas = Math.min(opts.maxBlockGas?.daGas ?? Infinity, remainingDAGas);
|
|
156
|
+
let cappedBlobFields = Math.min(opts.maxBlobFields ?? Infinity, maxBlobFieldsForTxs);
|
|
157
|
+
let cappedMaxTransactions = Math.min(opts.maxTransactions ?? Infinity, remainingTxs);
|
|
158
|
+
// Proposer mode: further cap by fair share of remaining budget across remaining blocks
|
|
159
|
+
if (opts.isBuildingProposal) {
|
|
160
|
+
const remainingBlocks = Math.max(1, opts.maxBlocksPerCheckpoint - existingBlocks.length);
|
|
161
|
+
const multiplier = opts.perBlockAllocationMultiplier;
|
|
162
|
+
// DA gas and blob fields use a higher multiplier so the largest contract class deploy fits a block.
|
|
163
|
+
const daMultiplier = opts.perBlockDAAllocationMultiplier ?? multiplier;
|
|
164
|
+
cappedL2Gas = Math.min(cappedL2Gas, Math.ceil(remainingMana / remainingBlocks * multiplier));
|
|
165
|
+
cappedDAGas = Math.min(cappedDAGas, Math.ceil(remainingDAGas / remainingBlocks * daMultiplier));
|
|
166
|
+
cappedBlobFields = Math.min(cappedBlobFields, Math.ceil(maxBlobFieldsForTxs / remainingBlocks * daMultiplier));
|
|
167
|
+
cappedMaxTransactions = Math.min(cappedMaxTransactions, Math.ceil(remainingTxs / remainingBlocks * multiplier));
|
|
168
|
+
}
|
|
169
|
+
return {
|
|
170
|
+
maxBlockGas: new Gas(cappedDAGas, cappedL2Gas),
|
|
171
|
+
maxBlobFields: cappedBlobFields,
|
|
172
|
+
maxTransactions: Number.isFinite(cappedMaxTransactions) ? cappedMaxTransactions : undefined
|
|
173
|
+
};
|
|
174
|
+
}
|
|
91
175
|
async makeBlockBuilderDeps(globalVariables, fork) {
|
|
92
|
-
const txPublicSetupAllowList =
|
|
93
|
-
|
|
176
|
+
const txPublicSetupAllowList = [
|
|
177
|
+
...await getDefaultAllowedSetupFunctions(),
|
|
178
|
+
...this.config.txPublicSetupAllowListExtend ?? []
|
|
179
|
+
];
|
|
180
|
+
const contractsDB = this.contractsDB;
|
|
94
181
|
const guardedFork = new GuardedMerkleTreeOperations(fork);
|
|
95
|
-
const
|
|
96
|
-
|
|
97
|
-
|
|
182
|
+
const bindings = this.log.getBindings();
|
|
183
|
+
// Extract the WSDB fork ID so the C++ AVM can modify the same fork in-place; the simulator reads
|
|
184
|
+
// contract data from `contractsDB`, scoped to this fork for the duration of each simulation.
|
|
185
|
+
const wsdbForkId = fork.getRevision().forkId;
|
|
186
|
+
const publicTxSimulator = createPublicTxSimulatorForBlockBuilding(this.avmSimulator, globalVariables, contractsDB, wsdbForkId, this.telemetryClient, bindings, this.debugLogStore?.isEnabled ?? false);
|
|
187
|
+
const processor = new PublicProcessor(globalVariables, guardedFork, contractsDB, publicTxSimulator, this.dateProvider, this.telemetryClient, createLogger('simulator:public-processor', bindings), this.config, this.debugLogStore);
|
|
188
|
+
const validator = createTxValidatorForBlockBuilding(fork, this.contractDataSource, globalVariables, txPublicSetupAllowList, this.log.getBindings());
|
|
98
189
|
return {
|
|
99
190
|
processor,
|
|
100
191
|
validator
|
|
@@ -106,13 +197,19 @@ const log = createLogger('checkpoint-builder');
|
|
|
106
197
|
worldState;
|
|
107
198
|
contractDataSource;
|
|
108
199
|
dateProvider;
|
|
200
|
+
avmSimulator;
|
|
109
201
|
telemetryClient;
|
|
110
|
-
|
|
202
|
+
debugLogStore;
|
|
203
|
+
log;
|
|
204
|
+
constructor(config, worldState, contractDataSource, dateProvider, avmSimulator, telemetryClient = getTelemetryClient(), debugLogStore = new NullDebugLogStore()){
|
|
111
205
|
this.config = config;
|
|
112
206
|
this.worldState = worldState;
|
|
113
207
|
this.contractDataSource = contractDataSource;
|
|
114
208
|
this.dateProvider = dateProvider;
|
|
209
|
+
this.avmSimulator = avmSimulator;
|
|
115
210
|
this.telemetryClient = telemetryClient;
|
|
211
|
+
this.debugLogStore = debugLogStore;
|
|
212
|
+
this.log = createLogger('checkpoint-builder');
|
|
116
213
|
}
|
|
117
214
|
getConfig() {
|
|
118
215
|
return this.config;
|
|
@@ -122,37 +219,39 @@ const log = createLogger('checkpoint-builder');
|
|
|
122
219
|
}
|
|
123
220
|
/**
|
|
124
221
|
* Starts a new checkpoint and returns a CheckpointBuilder to build blocks within it.
|
|
125
|
-
*/ async startCheckpoint(checkpointNumber, constants, l1ToL2Messages, previousCheckpointOutHashes, fork) {
|
|
222
|
+
*/ async startCheckpoint(checkpointNumber, constants, feeAssetPriceModifier, l1ToL2Messages, previousCheckpointOutHashes, fork, bindings) {
|
|
126
223
|
const stateReference = await fork.getStateReference();
|
|
127
224
|
const archiveTree = await fork.getTreeInfo(MerkleTreeId.ARCHIVE);
|
|
128
|
-
log.verbose(`Building new checkpoint ${checkpointNumber}`, {
|
|
225
|
+
this.log.verbose(`Building new checkpoint ${checkpointNumber}`, {
|
|
129
226
|
checkpointNumber,
|
|
130
227
|
msgCount: l1ToL2Messages.length,
|
|
131
228
|
initialStateReference: stateReference.toInspect(),
|
|
132
229
|
initialArchiveRoot: bufferToHex(archiveTree.root),
|
|
133
|
-
constants
|
|
230
|
+
constants,
|
|
231
|
+
feeAssetPriceModifier
|
|
134
232
|
});
|
|
135
|
-
const lightweightBuilder = await LightweightCheckpointBuilder.startNewCheckpoint(checkpointNumber, constants, l1ToL2Messages, previousCheckpointOutHashes, fork);
|
|
136
|
-
return new CheckpointBuilder(lightweightBuilder, fork, this.config, this.contractDataSource, this.dateProvider, this.telemetryClient);
|
|
233
|
+
const lightweightBuilder = await LightweightCheckpointBuilder.startNewCheckpoint(checkpointNumber, constants, l1ToL2Messages, previousCheckpointOutHashes, fork, bindings, feeAssetPriceModifier);
|
|
234
|
+
return new CheckpointBuilder(lightweightBuilder, fork, this.config, this.contractDataSource, this.dateProvider, this.telemetryClient, this.avmSimulator, bindings, this.debugLogStore);
|
|
137
235
|
}
|
|
138
236
|
/**
|
|
139
237
|
* Opens a checkpoint, either starting fresh or resuming from existing blocks.
|
|
140
|
-
*/ async openCheckpoint(checkpointNumber, constants, l1ToL2Messages, previousCheckpointOutHashes, fork, existingBlocks = []) {
|
|
238
|
+
*/ async openCheckpoint(checkpointNumber, constants, feeAssetPriceModifier, l1ToL2Messages, previousCheckpointOutHashes, fork, existingBlocks = [], bindings) {
|
|
141
239
|
const stateReference = await fork.getStateReference();
|
|
142
240
|
const archiveTree = await fork.getTreeInfo(MerkleTreeId.ARCHIVE);
|
|
143
241
|
if (existingBlocks.length === 0) {
|
|
144
|
-
return this.startCheckpoint(checkpointNumber, constants, l1ToL2Messages, previousCheckpointOutHashes, fork);
|
|
242
|
+
return this.startCheckpoint(checkpointNumber, constants, feeAssetPriceModifier, l1ToL2Messages, previousCheckpointOutHashes, fork, bindings);
|
|
145
243
|
}
|
|
146
|
-
log.verbose(`Resuming checkpoint ${checkpointNumber} with ${existingBlocks.length} existing blocks`, {
|
|
244
|
+
this.log.verbose(`Resuming checkpoint ${checkpointNumber} with ${existingBlocks.length} existing blocks`, {
|
|
147
245
|
checkpointNumber,
|
|
148
246
|
msgCount: l1ToL2Messages.length,
|
|
149
247
|
existingBlockCount: existingBlocks.length,
|
|
150
248
|
initialStateReference: stateReference.toInspect(),
|
|
151
249
|
initialArchiveRoot: bufferToHex(archiveTree.root),
|
|
152
|
-
constants
|
|
250
|
+
constants,
|
|
251
|
+
feeAssetPriceModifier
|
|
153
252
|
});
|
|
154
|
-
const lightweightBuilder = await LightweightCheckpointBuilder.resumeCheckpoint(checkpointNumber, constants, l1ToL2Messages, previousCheckpointOutHashes, fork, existingBlocks);
|
|
155
|
-
return new CheckpointBuilder(lightweightBuilder, fork, this.config, this.contractDataSource, this.dateProvider, this.telemetryClient);
|
|
253
|
+
const lightweightBuilder = await LightweightCheckpointBuilder.resumeCheckpoint(checkpointNumber, constants, feeAssetPriceModifier, l1ToL2Messages, previousCheckpointOutHashes, fork, existingBlocks, bindings);
|
|
254
|
+
return new CheckpointBuilder(lightweightBuilder, fork, this.config, this.contractDataSource, this.dateProvider, this.telemetryClient, this.avmSimulator, bindings, this.debugLogStore);
|
|
156
255
|
}
|
|
157
256
|
/** Returns a fork of the world state at the given block number. */ getFork(blockNumber) {
|
|
158
257
|
return this.worldState.fork(blockNumber);
|
package/dest/config.d.ts
CHANGED
|
@@ -1,11 +1,17 @@
|
|
|
1
1
|
import { type ConfigMappingsType } from '@aztec/foundation/config';
|
|
2
|
+
import { type SequencerConfig } from '@aztec/stdlib/config';
|
|
2
3
|
import type { ValidatorClientConfig } from '@aztec/stdlib/interfaces/server';
|
|
3
4
|
export type { ValidatorClientConfig };
|
|
4
|
-
|
|
5
|
+
/**
|
|
6
|
+
* Default clock-disparity tolerance (ms) for proposal/attestation receive windows, mirroring the p2p config
|
|
7
|
+
* default. Used by the validator-client validators when the merged node config does not carry the value.
|
|
8
|
+
*/
|
|
9
|
+
export declare const DEFAULT_MAX_GOSSIP_CLOCK_DISPARITY_MS = 500;
|
|
10
|
+
export declare const validatorClientConfigMappings: ConfigMappingsType<ValidatorClientConfig & Pick<SequencerConfig, 'blockDurationMs'>>;
|
|
5
11
|
/**
|
|
6
12
|
* Returns the prover configuration from the environment variables.
|
|
7
13
|
* Note: If an environment variable is not set, the default value is used.
|
|
8
14
|
* @returns The validator configuration.
|
|
9
15
|
*/
|
|
10
|
-
export declare function getProverEnvVars(): ValidatorClientConfig
|
|
11
|
-
//# sourceMappingURL=data:application/json;base64,
|
|
16
|
+
export declare function getProverEnvVars(): ValidatorClientConfig & Pick<SequencerConfig, 'blockDurationMs'>;
|
|
17
|
+
//# sourceMappingURL=data:application/json;base64,eyJ2ZXJzaW9uIjozLCJmaWxlIjoiY29uZmlnLmQudHMiLCJzb3VyY2VSb290IjoiIiwic291cmNlcyI6WyIuLi9zcmMvY29uZmlnLnRzIl0sIm5hbWVzIjpbXSwibWFwcGluZ3MiOiJBQUFBLE9BQU8sRUFDTCxLQUFLLGtCQUFrQixFQU94QixNQUFNLDBCQUEwQixDQUFDO0FBRWxDLE9BQU8sRUFBRSxLQUFLLGVBQWUsRUFBaUMsTUFBTSxzQkFBc0IsQ0FBQztBQUUzRixPQUFPLEtBQUssRUFBRSxxQkFBcUIsRUFBRSxNQUFNLGlDQUFpQyxDQUFDO0FBRTdFLFlBQVksRUFBRSxxQkFBcUIsRUFBRSxDQUFDO0FBRXRDOzs7R0FHRztBQUNILGVBQU8sTUFBTSxxQ0FBcUMsTUFBTSxDQUFDO0FBRXpELGVBQU8sTUFBTSw2QkFBNkIsRUFBRSxrQkFBa0IsQ0FDNUQscUJBQXFCLEdBQUcsSUFBSSxDQUFDLGVBQWUsRUFBRSxpQkFBaUIsQ0FBQyxDQStGakUsQ0FBQztBQUVGOzs7O0dBSUc7QUFDSCx3QkFBZ0IsZ0JBQWdCLElBQUkscUJBQXFCLEdBQUcsSUFBSSxDQUFDLGVBQWUsRUFBRSxpQkFBaUIsQ0FBQyxDQUluRyJ9
|
package/dest/config.d.ts.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"config.d.ts","sourceRoot":"","sources":["../src/config.ts"],"names":[],"mappings":"AAAA,OAAO,EACL,KAAK,kBAAkB,
|
|
1
|
+
{"version":3,"file":"config.d.ts","sourceRoot":"","sources":["../src/config.ts"],"names":[],"mappings":"AAAA,OAAO,EACL,KAAK,kBAAkB,EAOxB,MAAM,0BAA0B,CAAC;AAElC,OAAO,EAAE,KAAK,eAAe,EAAiC,MAAM,sBAAsB,CAAC;AAE3F,OAAO,KAAK,EAAE,qBAAqB,EAAE,MAAM,iCAAiC,CAAC;AAE7E,YAAY,EAAE,qBAAqB,EAAE,CAAC;AAEtC;;;GAGG;AACH,eAAO,MAAM,qCAAqC,MAAM,CAAC;AAEzD,eAAO,MAAM,6BAA6B,EAAE,kBAAkB,CAC5D,qBAAqB,GAAG,IAAI,CAAC,eAAe,EAAE,iBAAiB,CAAC,CA+FjE,CAAC;AAEF;;;;GAIG;AACH,wBAAgB,gBAAgB,IAAI,qBAAqB,GAAG,IAAI,CAAC,eAAe,EAAE,iBAAiB,CAAC,CAInG"}
|