@aztec/validator-client 0.0.1-commit.381b1a9 → 0.0.1-commit.3a4ae741b
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 +9 -10
- package/dest/block_proposal_handler.d.ts +1 -1
- package/dest/block_proposal_handler.d.ts.map +1 -1
- package/dest/block_proposal_handler.js +14 -8
- package/dest/checkpoint_builder.d.ts +10 -8
- package/dest/checkpoint_builder.d.ts.map +1 -1
- package/dest/checkpoint_builder.js +30 -20
- package/dest/config.d.ts +1 -1
- package/dest/config.d.ts.map +1 -1
- package/dest/config.js +2 -1
- package/dest/factory.d.ts +3 -1
- package/dest/factory.d.ts.map +1 -1
- package/dest/factory.js +1 -1
- package/dest/validator.d.ts +5 -5
- package/dest/validator.d.ts.map +1 -1
- package/dest/validator.js +46 -41
- package/package.json +19 -19
- package/src/block_proposal_handler.ts +11 -5
- package/src/checkpoint_builder.ts +39 -26
- package/src/config.ts +2 -1
- package/src/factory.ts +3 -0
- package/src/validator.ts +55 -49
package/README.md
CHANGED
|
@@ -237,13 +237,11 @@ L1 enforces gas and blob capacity per checkpoint. The node enforces these during
|
|
|
237
237
|
|
|
238
238
|
### Per-block budgets
|
|
239
239
|
|
|
240
|
-
Per-block budgets prevent one block from consuming the entire checkpoint budget.
|
|
240
|
+
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.
|
|
241
241
|
|
|
242
|
-
**Proposer**:
|
|
242
|
+
**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.
|
|
243
243
|
|
|
244
|
-
**Validator**:
|
|
245
|
-
|
|
246
|
-
**Checkpoint-level capping**: `CheckpointBuilder.capLimitsByCheckpointBudgets()` always runs before tx processing, capping per-block limits by `checkpointBudget - sum(used by prior blocks)` for all three gas dimensions and for transaction count (when `SEQ_MAX_TX_PER_CHECKPOINT` is set). This applies to both proposer and validator paths.
|
|
244
|
+
**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.
|
|
247
245
|
|
|
248
246
|
### Per-transaction enforcement
|
|
249
247
|
|
|
@@ -255,11 +253,12 @@ Per-block budgets prevent one block from consuming the entire checkpoint budget.
|
|
|
255
253
|
|
|
256
254
|
| Variable | Default | Description |
|
|
257
255
|
| --- | --- | --- |
|
|
258
|
-
| `SEQ_MAX_L2_BLOCK_GAS` | *
|
|
259
|
-
| `SEQ_MAX_DA_BLOCK_GAS` | *
|
|
260
|
-
| `SEQ_MAX_TX_PER_BLOCK` | *none* |
|
|
261
|
-
| `SEQ_MAX_TX_PER_CHECKPOINT` | *none* | Total txs across all blocks in a checkpoint. When set,
|
|
262
|
-
| `SEQ_PER_BLOCK_ALLOCATION_MULTIPLIER` | 2 | Multiplier for per-block budget
|
|
256
|
+
| `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. |
|
|
257
|
+
| `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. |
|
|
258
|
+
| `SEQ_MAX_TX_PER_BLOCK` | *none* | Hard per-block tx count cap. Capped at `SEQ_MAX_TX_PER_CHECKPOINT` at startup (if set). |
|
|
259
|
+
| `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. |
|
|
260
|
+
| `SEQ_PER_BLOCK_ALLOCATION_MULTIPLIER` | 1.2 | Multiplier for per-block budget redistribution. Passed via opts to the checkpoint builder during proposal building. |
|
|
261
|
+
| `SEQ_REDISTRIBUTE_CHECKPOINT_BUDGET` | true | Legacy flag; redistribution is now always active during proposal building and inactive during validation. |
|
|
263
262
|
| `VALIDATOR_MAX_L2_BLOCK_GAS` | *none* | Per-block L2 gas limit for validation. Proposals exceeding this are rejected. |
|
|
264
263
|
| `VALIDATOR_MAX_DA_BLOCK_GAS` | *none* | Per-block DA gas limit for validation. Proposals exceeding this are rejected. |
|
|
265
264
|
| `VALIDATOR_MAX_TX_PER_BLOCK` | *none* | Per-block tx count limit for validation. Proposals exceeding this are rejected. |
|
|
@@ -61,4 +61,4 @@ export declare class BlockProposalHandler {
|
|
|
61
61
|
reexecuteTransactions(proposal: BlockProposal, blockNumber: BlockNumber, checkpointNumber: CheckpointNumber, txs: Tx[], l1ToL2Messages: Fr[], previousCheckpointOutHashes: Fr[]): Promise<ReexecuteTransactionsResult>;
|
|
62
62
|
}
|
|
63
63
|
export {};
|
|
64
|
-
//# sourceMappingURL=data:application/json;base64,
|
|
64
|
+
//# sourceMappingURL=data:application/json;base64,eyJ2ZXJzaW9uIjozLCJmaWxlIjoiYmxvY2tfcHJvcG9zYWxfaGFuZGxlci5kLnRzIiwic291cmNlUm9vdCI6IiIsInNvdXJjZXMiOlsiLi4vc3JjL2Jsb2NrX3Byb3Bvc2FsX2hhbmRsZXIudHMiXSwibmFtZXMiOltdLCJtYXBwaW5ncyI6IkFBQ0EsT0FBTyxLQUFLLEVBQUUsVUFBVSxFQUFFLE1BQU0sb0JBQW9CLENBQUM7QUFDckQsT0FBTyxFQUFFLFdBQVcsRUFBRSxnQkFBZ0IsRUFBYyxNQUFNLGlDQUFpQyxDQUFDO0FBRTVGLE9BQU8sRUFBRSxFQUFFLEVBQUUsTUFBTSxnQ0FBZ0MsQ0FBQztBQUlwRCxPQUFPLEVBQUUsWUFBWSxFQUFTLE1BQU0seUJBQXlCLENBQUM7QUFDOUQsT0FBTyxLQUFLLEVBQUUsR0FBRyxFQUFFLE1BQU0sRUFBRSxNQUFNLFlBQVksQ0FBQztBQUM5QyxPQUFPLEVBQUUsc0JBQXNCLEVBQUUsTUFBTSwyQkFBMkIsQ0FBQztBQUNuRSxPQUFPLEtBQUssRUFBYSxPQUFPLEVBQUUsV0FBVyxFQUFFLGFBQWEsRUFBRSxNQUFNLHFCQUFxQixDQUFDO0FBRzFGLE9BQU8sS0FBSyxFQUFFLFdBQVcsRUFBRSx5QkFBeUIsRUFBRSxzQkFBc0IsRUFBRSxNQUFNLGlDQUFpQyxDQUFDO0FBQ3RILE9BQU8sRUFBRSxLQUFLLG1CQUFtQixFQUFtQyxNQUFNLHlCQUF5QixDQUFDO0FBQ3BHLE9BQU8sS0FBSyxFQUFFLGFBQWEsRUFBRSxNQUFNLG1CQUFtQixDQUFDO0FBRXZELE9BQU8sS0FBSyxFQUE2QixRQUFRLEVBQUUsRUFBRSxFQUFFLE1BQU0sa0JBQWtCLENBQUM7QUFRaEYsT0FBTyxFQUFFLEtBQUssZUFBZSxFQUFFLEtBQUssTUFBTSxFQUFzQixNQUFNLHlCQUF5QixDQUFDO0FBRWhHLE9BQU8sS0FBSyxFQUFFLDBCQUEwQixFQUFFLE1BQU0seUJBQXlCLENBQUM7QUFDMUUsT0FBTyxLQUFLLEVBQUUsZ0JBQWdCLEVBQUUsTUFBTSxjQUFjLENBQUM7QUFFckQsTUFBTSxNQUFN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
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"block_proposal_handler.d.ts","sourceRoot":"","sources":["../src/block_proposal_handler.ts"],"names":[],"mappings":"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
|
|
1
|
+
{"version":3,"file":"block_proposal_handler.d.ts","sourceRoot":"","sources":["../src/block_proposal_handler.ts"],"names":[],"mappings":"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"}
|
|
@@ -176,14 +176,18 @@ export class BlockProposalHandler {
|
|
|
176
176
|
// since a pending checkpoint prune may remove blocks we'd otherwise find.
|
|
177
177
|
// This affects mostly the block_number_already_exists check, since a pending
|
|
178
178
|
// checkpoint prune could remove a block that would conflict with this proposal.
|
|
179
|
-
//
|
|
180
|
-
|
|
181
|
-
|
|
182
|
-
|
|
183
|
-
|
|
184
|
-
|
|
185
|
-
|
|
186
|
-
|
|
179
|
+
// When pipelining is enabled, the proposer builds ahead of L1 submission, so the
|
|
180
|
+
// block source won't have synced to the proposed slot yet. Skip the sync wait to
|
|
181
|
+
// avoid eating into the attestation window.
|
|
182
|
+
if (!this.epochCache.isProposerPipeliningEnabled()) {
|
|
183
|
+
const blockSourceSync = await this.waitForBlockSourceSync(slotNumber);
|
|
184
|
+
if (!blockSourceSync) {
|
|
185
|
+
this.log.warn(`Block source is not synced, skipping processing`, proposalInfo);
|
|
186
|
+
return {
|
|
187
|
+
isValid: false,
|
|
188
|
+
reason: 'block_source_not_synced'
|
|
189
|
+
};
|
|
190
|
+
}
|
|
187
191
|
}
|
|
188
192
|
// Check that the parent proposal is a block we know, otherwise reexecution would fail.
|
|
189
193
|
// If we don't find it immediately, we keep retrying for a while; it may be we still
|
|
@@ -552,6 +556,8 @@ export class BlockProposalHandler {
|
|
|
552
556
|
const deadline = this.getReexecutionDeadline(slot, config);
|
|
553
557
|
const maxBlockGas = this.config.validateMaxL2BlockGas !== undefined || this.config.validateMaxDABlockGas !== undefined ? new Gas(this.config.validateMaxDABlockGas ?? Infinity, this.config.validateMaxL2BlockGas ?? Infinity) : undefined;
|
|
554
558
|
const result = await checkpointBuilder.buildBlock(txs, blockNumber, blockHeader.globalVariables.timestamp, {
|
|
559
|
+
isBuildingProposal: false,
|
|
560
|
+
minValidTxs: 0,
|
|
555
561
|
deadline,
|
|
556
562
|
expectedEndState: blockHeader.state,
|
|
557
563
|
maxTransactions: this.config.validateMaxTxsPerBlock,
|
|
@@ -3,12 +3,12 @@ import { Fr } from '@aztec/foundation/curves/bn254';
|
|
|
3
3
|
import { type LoggerBindings } from '@aztec/foundation/log';
|
|
4
4
|
import { DateProvider } from '@aztec/foundation/timer';
|
|
5
5
|
import { LightweightCheckpointBuilder } from '@aztec/prover-client/light';
|
|
6
|
-
import { PublicProcessor } from '@aztec/simulator/server';
|
|
6
|
+
import { PublicContractsDB, PublicProcessor } from '@aztec/simulator/server';
|
|
7
7
|
import { L2Block } from '@aztec/stdlib/block';
|
|
8
8
|
import { Checkpoint } from '@aztec/stdlib/checkpoint';
|
|
9
9
|
import type { ContractDataSource } from '@aztec/stdlib/contract';
|
|
10
10
|
import type { L1RollupConstants } from '@aztec/stdlib/epoch-helpers';
|
|
11
|
-
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
12
|
import { type DebugLogStore } from '@aztec/stdlib/logs';
|
|
13
13
|
import { type CheckpointGlobalVariables, GlobalVariables, StateReference, Tx } from '@aztec/stdlib/tx';
|
|
14
14
|
import { type TelemetryClient } from '@aztec/telemetry-client';
|
|
@@ -26,15 +26,16 @@ export declare class CheckpointBuilder implements ICheckpointBlockBuilder {
|
|
|
26
26
|
private telemetryClient;
|
|
27
27
|
private debugLogStore;
|
|
28
28
|
private log;
|
|
29
|
+
/** Persistent contracts DB shared across all blocks in this checkpoint. */
|
|
30
|
+
protected contractsDB: PublicContractsDB;
|
|
29
31
|
constructor(checkpointBuilder: LightweightCheckpointBuilder, fork: MerkleTreeWriteOperations, config: FullNodeBlockBuilderConfig, contractDataSource: ContractDataSource, dateProvider: DateProvider, telemetryClient: TelemetryClient, bindings?: LoggerBindings, debugLogStore?: DebugLogStore);
|
|
30
32
|
getConstantData(): CheckpointGlobalVariables;
|
|
31
33
|
/**
|
|
32
34
|
* Builds a single block within this checkpoint.
|
|
33
35
|
* Automatically caps gas and blob field limits based on checkpoint-level budgets and prior blocks.
|
|
34
36
|
*/
|
|
35
|
-
buildBlock(pendingTxs: Iterable<Tx> | AsyncIterable<Tx>, blockNumber: BlockNumber, timestamp: bigint, opts
|
|
37
|
+
buildBlock(pendingTxs: Iterable<Tx> | AsyncIterable<Tx>, blockNumber: BlockNumber, timestamp: bigint, opts: BlockBuilderOptions & {
|
|
36
38
|
expectedEndState?: StateReference;
|
|
37
|
-
minValidTxs?: number;
|
|
38
39
|
}): Promise<BuildBlockInCheckpointResult>;
|
|
39
40
|
/** Completes the checkpoint and returns it. */
|
|
40
41
|
completeCheckpoint(): Promise<Checkpoint>;
|
|
@@ -42,10 +43,11 @@ export declare class CheckpointBuilder implements ICheckpointBlockBuilder {
|
|
|
42
43
|
getCheckpoint(): Promise<Checkpoint>;
|
|
43
44
|
/**
|
|
44
45
|
* Caps per-block gas and blob field limits by remaining checkpoint-level budgets.
|
|
45
|
-
*
|
|
46
|
-
*
|
|
46
|
+
* When building a proposal (isBuildingProposal=true), computes a fair share of remaining budget
|
|
47
|
+
* across remaining blocks scaled by the multiplier. When validating, only caps by per-block limit
|
|
48
|
+
* and remaining checkpoint budget (no redistribution or multiplier).
|
|
47
49
|
*/
|
|
48
|
-
protected capLimitsByCheckpointBudgets(opts:
|
|
50
|
+
protected capLimitsByCheckpointBudgets(opts: BlockBuilderOptions): Pick<PublicProcessorLimits, 'maxBlockGas' | 'maxBlobFields' | 'maxTransactions'>;
|
|
49
51
|
protected makeBlockBuilderDeps(globalVariables: GlobalVariables, fork: MerkleTreeWriteOperations): Promise<{
|
|
50
52
|
processor: PublicProcessor;
|
|
51
53
|
validator: import("@aztec/stdlib/interfaces/server").PublicProcessorValidator;
|
|
@@ -74,4 +76,4 @@ export declare class FullNodeCheckpointsBuilder implements ICheckpointsBuilder {
|
|
|
74
76
|
/** Returns a fork of the world state at the given block number. */
|
|
75
77
|
getFork(blockNumber: BlockNumber): Promise<MerkleTreeWriteOperations>;
|
|
76
78
|
}
|
|
77
|
-
//# sourceMappingURL=data:application/json;base64,
|
|
79
|
+
//# sourceMappingURL=data:application/json;base64,eyJ2ZXJzaW9uIjozLCJmaWxlIjoiY2hlY2twb2ludF9idWlsZGVyLmQudHMiLCJzb3VyY2VSb290IjoiIiwic291cmNlcyI6WyIuLi9zcmMvY2hlY2twb2ludF9idWlsZGVyLnRzIl0sIm5hbWVzIjpbXSwibWFwcGluZ3MiOiJBQUVBLE9BQU8sRUFBRSxXQUFXLEVBQUUsZ0JBQWdCLEVBQUUsTUFBTSxpQ0FBaUMsQ0FBQztBQUVoRixPQUFPLEVBQUUsRUFBRSxFQUFFLE1BQU0sZ0NBQWdDLENBQUM7QUFDcEQsT0FBTyxFQUFlLEtBQUssY0FBYyxFQUFnQixNQUFNLHVCQUF1QixDQUFDO0FBRXZGLE9BQU8sRUFBRSxZQUFZLEVBQVcsTUFBTSx5QkFBeUIsQ0FBQztBQUVoRSxPQUFPLEVBQUUsNEJBQTRCLEVBQUUsTUFBTSw0QkFBNEIsQ0FBQztBQUMxRSxPQUFPLEVBRUwsaUJBQWlCLEVBQ2pCLGVBQWUsRUFFaEIsTUFBTSx5QkFBeUIsQ0FBQztBQUNqQyxPQUFPLEVBQUUsT0FBTyxFQUFFLE1BQU0scUJBQXFCLENBQUM7QUFDOUMsT0FBTyxFQUFFLFVBQVUsRUFBRSxNQUFNLDBCQUEwQixDQUFDO0FBQ3RELE9BQU8sS0FBSyxFQUFFLGtCQUFrQixFQUFFLE1BQU0sd0JBQXdCLENBQUM7QUFDakUsT0FBTyxLQUFLLEVBQUUsaUJBQWlCLEVBQUUsTUFBTSw2QkFBNkIsQ0FBQztBQUVyRSxPQUFPLEVBQ0wsS0FBSyxtQkFBbUIsRUFDeEIsS0FBSyw0QkFBNEIsRUFDakMsS0FBSywwQkFBMEIsRUFFL0IsS0FBSyx1QkFBdUIsRUFDNUIsS0FBSyxtQkFBbUIsRUFFeEIsS0FBSyx5QkFBeUIsRUFDOUIsS0FBSyxxQkFBcUIsRUFDMUIsS0FBSyxzQkFBc0IsRUFDNUIsTUFBTSxpQ0FBaUMsQ0FBQztBQUN6QyxPQUFPLEVBQUUsS0FBSyxhQUFhLEVBQXFCLE1BQU0sb0JBQW9CLENBQUM7QUFFM0UsT0FBTyxFQUFFLEtBQUsseUJBQXlCLEVBQUUsZUFBZSxFQUFFLGNBQWMsRUFBRSxFQUFFLEVBQUUsTUFBTSxrQkFBa0IsQ0FBQztBQUN2RyxPQUFPLEVBQUUsS0FBSyxlQUFlLEVBQXNCLE1BQU0seUJBQXlCLENBQUM7QUFJbkYsWUFBWSxFQUFFLDRCQUE0QixFQUFFLE1BQU0saUNBQWlDLENBQUM7QUFFcEY7OztHQUdHO0FBQ0gscUJBQWEsaUJBQWtCLFlBQVcsdUJBQXVCO0lBTzdELE9BQU8sQ0FBQyxpQkFBaUI7SUFDekIsT0FBTyxDQUFDLElBQUk7SUFDWixPQUFPLENBQUMsTUFBTTtJQUNkLE9BQU8sQ0FBQyxrQkFBa0I7SUFDMUIsT0FBTyxDQUFDLFlBQVk7SUFDcEIsT0FBTyxDQUFDLGVBQWU7SUFFdkIsT0FBTyxDQUFDLGFBQWE7SUFidkIsT0FBTyxDQUFDLEdBQUcsQ0FBUztJQUVwQiwyRUFBMkU7SUFDM0UsU0FBUyxDQUFDLFdBQVcsRUFBRSxpQkFBaUIsQ0FBQztJQUV6QyxZQUNVLGlCQUFpQixFQUFFLDRCQUE0QixFQUMvQyxJQUFJLEVBQUUseUJBQXlCLEVBQy9CLE1BQU0sRUFBRSwwQkFBMEIsRUFDbEMsa0JBQWtCLEVBQUUsa0JBQWtCLEVBQ3RDLFlBQVksRUFBRSxZQUFZLEVBQzFCLGVBQWUsRUFBRSxlQUFlLEVBQ3hDLFFBQVEsQ0FBQyxFQUFFLGNBQWMsRUFDakIsYUFBYSxHQUFFLGFBQXVDLEVBTy9EO0lBRUQsZUFBZSxJQUFJLHlCQUF5QixDQUUzQztJQUVEOzs7T0FHRztJQUNHLFVBQVUsQ0FDZCxVQUFVLEVBQUUsUUFBUSxDQUFDLEVBQUUsQ0FBQyxHQUFHLGFBQWEsQ0FBQyxFQUFFLENBQUMsRUFDNUMsV0FBVyxFQUFFLFdBQVcsRUFDeEIsU0FBUyxFQUFFLE1BQU0sRUFDakIsSUFBSSxFQUFFLG1CQUFtQixHQUFHO1FBQUUsZ0JBQWdCLENBQUMsRUFBRSxjQUFjLENBQUE7S0FBRSxHQUNoRSxPQUFPLENBQUMsNEJBQTRCLENBQUMsQ0E2RXZDO0lBRUQsK0NBQStDO0lBQ3pDLGtCQUFrQixJQUFJLE9BQU8sQ0FBQyxVQUFVLENBQUMsQ0FVOUM7SUFFRCxpREFBaUQ7SUFDakQsYUFBYSxJQUFJLE9BQU8sQ0FBQyxVQUFVLENBQUMsQ0FFbkM7SUFFRDs7Ozs7T0FLRztJQUNILFNBQVMsQ0FBQyw0QkFBNEIsQ0FDcEMsSUFBSSxFQUFFLG1CQUFtQixHQUN4QixJQUFJLENBQUMscUJBQXFCLEVBQUUsYUFBYSxHQUFHLGVBQWUsR0FBRyxpQkFBaUIsQ0FBQyxDQThDbEY7SUFFRCxVQUFnQixvQkFBb0IsQ0FBQyxlQUFlLEVBQUUsZUFBZSxFQUFFLElBQUksRUFBRSx5QkFBeUI7OztPQTRDckc7Q0FDRjtBQUVELGdEQUFnRDtBQUNoRCxxQkFBYSwwQkFBMkIsWUFBVyxtQkFBbUI7SUFJbEUsT0FBTyxDQUFDLE1BQU07SUFDZCxPQUFPLENBQUMsVUFBVTtJQUNsQixPQUFPLENBQUMsa0JBQWtCO0lBQzFCLE9BQU8sQ0FBQyxZQUFZO0lBQ3BCLE9BQU8sQ0FBQyxlQUFlO0lBQ3ZCLE9BQU8sQ0FBQyxhQUFhO0lBUnZCLE9BQU8sQ0FBQyxHQUFHLENBQVM7SUFFcEIsWUFDVSxNQUFNLEVBQUUsMEJBQTBCLEdBQUcsSUFBSSxDQUFDLGlCQUFpQixFQUFFLGVBQWUsR0FBRyxjQUFjLENBQUMsRUFDOUYsVUFBVSxFQUFFLHNCQUFzQixFQUNsQyxrQkFBa0IsRUFBRSxrQkFBa0IsRUFDdEMsWUFBWSxFQUFFLFlBQVksRUFDMUIsZUFBZSxHQUFFLGVBQXNDLEVBQ3ZELGFBQWEsR0FBRSxhQUF1QyxFQUcvRDtJQUVNLFNBQVMsSUFBSSwwQkFBMEIsQ0FFN0M7SUFFTSxZQUFZLENBQUMsTUFBTSxFQUFFLE9BQU8sQ0FBQywwQkFBMEIsQ0FBQyxRQUU5RDtJQUVEOztPQUVHO0lBQ0csZUFBZSxDQUNuQixnQkFBZ0IsRUFBRSxnQkFBZ0IsRUFDbEMsU0FBUyxFQUFFLHlCQUF5QixFQUNwQyxxQkFBcUIsRUFBRSxNQUFNLEVBQzdCLGNBQWMsRUFBRSxFQUFFLEVBQUUsRUFDcEIsMkJBQTJCLEVBQUUsRUFBRSxFQUFFLEVBQ2pDLElBQUksRUFBRSx5QkFBeUIsRUFDL0IsUUFBUSxDQUFDLEVBQUUsY0FBYyxHQUN4QixPQUFPLENBQUMsaUJBQWlCLENBQUMsQ0FpQzVCO0lBRUQ7O09BRUc7SUFDRyxjQUFjLENBQ2xCLGdCQUFnQixFQUFFLGdCQUFnQixFQUNsQyxTQUFTLEVBQUUseUJBQXlCLEVBQ3BDLHFCQUFxQixFQUFFLE1BQU0sRUFDN0IsY0FBYyxFQUFFLEVBQUUsRUFBRSxFQUNwQiwyQkFBMkIsRUFBRSxFQUFFLEVBQUUsRUFDakMsSUFBSSxFQUFFLHlCQUF5QixFQUMvQixjQUFjLEdBQUUsT0FBTyxFQUFPLEVBQzlCLFFBQVEsQ0FBQyxFQUFFLGNBQWMsR0FDeEIsT0FBTyxDQUFDLGlCQUFpQixDQUFDLENBK0M1QjtJQUVELG1FQUFtRTtJQUNuRSxPQUFPLENBQUMsV0FBVyxFQUFFLFdBQVcsR0FBRyxPQUFPLENBQUMseUJBQXlCLENBQUMsQ0FFcEU7Q0FDRiJ9
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"checkpoint_builder.d.ts","sourceRoot":"","sources":["../src/checkpoint_builder.ts"],"names":[],"mappings":"AAEA,OAAO,EAAE,WAAW,EAAE,gBAAgB,EAAE,MAAM,iCAAiC,CAAC;AAEhF,OAAO,EAAE,EAAE,EAAE,MAAM,gCAAgC,CAAC;AACpD,OAAO,EAAe,KAAK,cAAc,EAAgB,MAAM,uBAAuB,CAAC;AAEvF,OAAO,EAAE,YAAY,EAAW,MAAM,yBAAyB,CAAC;AAEhE,OAAO,EAAE,4BAA4B,EAAE,MAAM,4BAA4B,CAAC;AAC1E,OAAO,
|
|
1
|
+
{"version":3,"file":"checkpoint_builder.d.ts","sourceRoot":"","sources":["../src/checkpoint_builder.ts"],"names":[],"mappings":"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"}
|
|
@@ -26,6 +26,7 @@ import { ForkCheckpoint } from '@aztec/world-state';
|
|
|
26
26
|
telemetryClient;
|
|
27
27
|
debugLogStore;
|
|
28
28
|
log;
|
|
29
|
+
/** Persistent contracts DB shared across all blocks in this checkpoint. */ contractsDB;
|
|
29
30
|
constructor(checkpointBuilder, fork, config, contractDataSource, dateProvider, telemetryClient, bindings, debugLogStore = new NullDebugLogStore()){
|
|
30
31
|
this.checkpointBuilder = checkpointBuilder;
|
|
31
32
|
this.fork = fork;
|
|
@@ -38,6 +39,7 @@ import { ForkCheckpoint } from '@aztec/world-state';
|
|
|
38
39
|
...bindings,
|
|
39
40
|
instanceId: `checkpoint-${checkpointBuilder.checkpointNumber}`
|
|
40
41
|
});
|
|
42
|
+
this.contractsDB = new PublicContractsDB(this.contractDataSource, this.log.getBindings());
|
|
41
43
|
}
|
|
42
44
|
getConstantData() {
|
|
43
45
|
return this.checkpointBuilder.constants;
|
|
@@ -45,7 +47,7 @@ import { ForkCheckpoint } from '@aztec/world-state';
|
|
|
45
47
|
/**
|
|
46
48
|
* Builds a single block within this checkpoint.
|
|
47
49
|
* Automatically caps gas and blob field limits based on checkpoint-level budgets and prior blocks.
|
|
48
|
-
*/ async buildBlock(pendingTxs, blockNumber, timestamp, opts
|
|
50
|
+
*/ async buildBlock(pendingTxs, blockNumber, timestamp, opts) {
|
|
49
51
|
const slot = this.checkpointBuilder.constants.slotNumber;
|
|
50
52
|
this.log.verbose(`Building block ${blockNumber} for slot ${slot} within checkpoint`, {
|
|
51
53
|
slot,
|
|
@@ -70,6 +72,8 @@ import { ForkCheckpoint } from '@aztec/world-state';
|
|
|
70
72
|
...opts,
|
|
71
73
|
...this.capLimitsByCheckpointBudgets(opts)
|
|
72
74
|
};
|
|
75
|
+
// Create a block-level checkpoint on the contracts DB so we can roll back on failure
|
|
76
|
+
this.contractsDB.createCheckpoint();
|
|
73
77
|
// We execute all merkle tree operations on a world state fork checkpoint
|
|
74
78
|
// This enables us to discard all modifications in the event that we fail to successfully process sufficient transactions
|
|
75
79
|
const forkCheckpoint = await ForkCheckpoint.new(this.fork);
|
|
@@ -83,9 +87,10 @@ import { ForkCheckpoint } from '@aztec/world-state';
|
|
|
83
87
|
// Commit the fork checkpoint
|
|
84
88
|
await forkCheckpoint.commit();
|
|
85
89
|
// Add block to checkpoint
|
|
86
|
-
const block = await this.checkpointBuilder.addBlock(globalVariables, processedTxs, {
|
|
90
|
+
const { block } = await this.checkpointBuilder.addBlock(globalVariables, processedTxs, {
|
|
87
91
|
expectedEndState: opts.expectedEndState
|
|
88
92
|
});
|
|
93
|
+
this.contractsDB.commitCheckpoint();
|
|
89
94
|
this.log.debug('Built block within checkpoint', {
|
|
90
95
|
header: block.header.toInspect(),
|
|
91
96
|
processedTxs: processedTxs.map((tx)=>tx.hash.toString()),
|
|
@@ -99,6 +104,8 @@ import { ForkCheckpoint } from '@aztec/world-state';
|
|
|
99
104
|
usedTxs
|
|
100
105
|
};
|
|
101
106
|
} catch (err) {
|
|
107
|
+
// Revert all changes to contracts db
|
|
108
|
+
this.contractsDB.revertCheckpoint();
|
|
102
109
|
// If we reached the point of committing the checkpoint, this does nothing
|
|
103
110
|
// Otherwise it reverts any changes made to the fork for this failed block
|
|
104
111
|
await forkCheckpoint.revert();
|
|
@@ -119,8 +126,9 @@ import { ForkCheckpoint } from '@aztec/world-state';
|
|
|
119
126
|
}
|
|
120
127
|
/**
|
|
121
128
|
* Caps per-block gas and blob field limits by remaining checkpoint-level budgets.
|
|
122
|
-
*
|
|
123
|
-
*
|
|
129
|
+
* When building a proposal (isBuildingProposal=true), computes a fair share of remaining budget
|
|
130
|
+
* across remaining blocks scaled by the multiplier. When validating, only caps by per-block limit
|
|
131
|
+
* and remaining checkpoint budget (no redistribution or multiplier).
|
|
124
132
|
*/ capLimitsByCheckpointBudgets(opts) {
|
|
125
133
|
const existingBlocks = this.checkpointBuilder.getBlocks();
|
|
126
134
|
// Remaining L2 gas (mana)
|
|
@@ -137,25 +145,27 @@ import { ForkCheckpoint } from '@aztec/world-state';
|
|
|
137
145
|
const isFirstBlock = existingBlocks.length === 0;
|
|
138
146
|
const blockEndOverhead = getNumBlockEndBlobFields(isFirstBlock);
|
|
139
147
|
const maxBlobFieldsForTxs = totalBlobCapacity - usedBlobFields - blockEndOverhead;
|
|
140
|
-
//
|
|
141
|
-
const
|
|
142
|
-
|
|
143
|
-
|
|
144
|
-
|
|
145
|
-
|
|
146
|
-
|
|
147
|
-
let cappedMaxTransactions;
|
|
148
|
-
|
|
149
|
-
|
|
150
|
-
const
|
|
151
|
-
|
|
152
|
-
|
|
153
|
-
|
|
148
|
+
// Remaining txs
|
|
149
|
+
const usedTxs = sum(existingBlocks.map((b)=>b.body.txEffects.length));
|
|
150
|
+
const remainingTxs = Math.max(0, (this.config.maxTxsPerCheckpoint ?? Infinity) - usedTxs);
|
|
151
|
+
// Cap by per-block limit + remaining checkpoint budget
|
|
152
|
+
let cappedL2Gas = Math.min(opts.maxBlockGas?.l2Gas ?? Infinity, remainingMana);
|
|
153
|
+
let cappedDAGas = Math.min(opts.maxBlockGas?.daGas ?? Infinity, remainingDAGas);
|
|
154
|
+
let cappedBlobFields = Math.min(opts.maxBlobFields ?? Infinity, maxBlobFieldsForTxs);
|
|
155
|
+
let cappedMaxTransactions = Math.min(opts.maxTransactions ?? Infinity, remainingTxs);
|
|
156
|
+
// Proposer mode: further cap by fair share of remaining budget across remaining blocks
|
|
157
|
+
if (opts.isBuildingProposal) {
|
|
158
|
+
const remainingBlocks = Math.max(1, opts.maxBlocksPerCheckpoint - existingBlocks.length);
|
|
159
|
+
const multiplier = opts.perBlockAllocationMultiplier;
|
|
160
|
+
cappedL2Gas = Math.min(cappedL2Gas, Math.ceil(remainingMana / remainingBlocks * multiplier));
|
|
161
|
+
cappedDAGas = Math.min(cappedDAGas, Math.ceil(remainingDAGas / remainingBlocks * multiplier));
|
|
162
|
+
cappedBlobFields = Math.min(cappedBlobFields, Math.ceil(maxBlobFieldsForTxs / remainingBlocks * multiplier));
|
|
163
|
+
cappedMaxTransactions = Math.min(cappedMaxTransactions, Math.ceil(remainingTxs / remainingBlocks * multiplier));
|
|
154
164
|
}
|
|
155
165
|
return {
|
|
156
166
|
maxBlockGas: new Gas(cappedDAGas, cappedL2Gas),
|
|
157
167
|
maxBlobFields: cappedBlobFields,
|
|
158
|
-
maxTransactions: cappedMaxTransactions
|
|
168
|
+
maxTransactions: Number.isFinite(cappedMaxTransactions) ? cappedMaxTransactions : undefined
|
|
159
169
|
};
|
|
160
170
|
}
|
|
161
171
|
async makeBlockBuilderDeps(globalVariables, fork) {
|
|
@@ -163,7 +173,7 @@ import { ForkCheckpoint } from '@aztec/world-state';
|
|
|
163
173
|
...await getDefaultAllowedSetupFunctions(),
|
|
164
174
|
...this.config.txPublicSetupAllowListExtend ?? []
|
|
165
175
|
];
|
|
166
|
-
const contractsDB =
|
|
176
|
+
const contractsDB = this.contractsDB;
|
|
167
177
|
const guardedFork = new GuardedMerkleTreeOperations(fork);
|
|
168
178
|
const collectDebugLogs = this.debugLogStore.isEnabled;
|
|
169
179
|
const bindings = this.log.getBindings();
|
package/dest/config.d.ts
CHANGED
|
@@ -8,4 +8,4 @@ export declare const validatorClientConfigMappings: ConfigMappingsType<Validator
|
|
|
8
8
|
* @returns The validator configuration.
|
|
9
9
|
*/
|
|
10
10
|
export declare function getProverEnvVars(): ValidatorClientConfig;
|
|
11
|
-
//# sourceMappingURL=data:application/json;base64,
|
|
11
|
+
//# sourceMappingURL=data:application/json;base64,eyJ2ZXJzaW9uIjozLCJmaWxlIjoiY29uZmlnLmQudHMiLCJzb3VyY2VSb290IjoiIiwic291cmNlcyI6WyIuLi9zcmMvY29uZmlnLnRzIl0sIm5hbWVzIjpbXSwibWFwcGluZ3MiOiJBQUFBLE9BQU8sRUFDTCxLQUFLLGtCQUFrQixFQUt4QixNQUFNLDBCQUEwQixDQUFDO0FBR2xDLE9BQU8sS0FBSyxFQUFFLHFCQUFxQixFQUFFLE1BQU0saUNBQWlDLENBQUM7QUFFN0UsWUFBWSxFQUFFLHFCQUFxQixFQUFFLENBQUM7QUFFdEMsZUFBTyxNQUFNLDZCQUE2QixFQUFFLGtCQUFrQixDQUFDLHFCQUFxQixDQXdGbkYsQ0FBQztBQUVGOzs7O0dBSUc7QUFDSCx3QkFBZ0IsZ0JBQWdCLElBQUkscUJBQXFCLENBRXhEIn0=
|
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,EAKxB,MAAM,0BAA0B,CAAC;
|
|
1
|
+
{"version":3,"file":"config.d.ts","sourceRoot":"","sources":["../src/config.ts"],"names":[],"mappings":"AAAA,OAAO,EACL,KAAK,kBAAkB,EAKxB,MAAM,0BAA0B,CAAC;AAGlC,OAAO,KAAK,EAAE,qBAAqB,EAAE,MAAM,iCAAiC,CAAC;AAE7E,YAAY,EAAE,qBAAqB,EAAE,CAAC;AAEtC,eAAO,MAAM,6BAA6B,EAAE,kBAAkB,CAAC,qBAAqB,CAwFnF,CAAC;AAEF;;;;GAIG;AACH,wBAAgB,gBAAgB,IAAI,qBAAqB,CAExD"}
|
package/dest/config.js
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
import { booleanConfigHelper, getConfigFromMappings, numberConfigHelper, secretValueConfigHelper } from '@aztec/foundation/config';
|
|
2
2
|
import { EthAddress } from '@aztec/foundation/eth-address';
|
|
3
|
-
import { validatorHASignerConfigMappings } from '@aztec/
|
|
3
|
+
import { localSignerConfigMappings, validatorHASignerConfigMappings } from '@aztec/stdlib/ha-signing';
|
|
4
4
|
export const validatorClientConfigMappings = {
|
|
5
5
|
validatorPrivateKeys: {
|
|
6
6
|
env: 'VALIDATOR_PRIVATE_KEYS',
|
|
@@ -77,6 +77,7 @@ export const validatorClientConfigMappings = {
|
|
|
77
77
|
description: 'Maximum transactions per checkpoint for validation. Proposals exceeding this limit are rejected.',
|
|
78
78
|
parseEnv: (val)=>val ? parseInt(val, 10) : undefined
|
|
79
79
|
},
|
|
80
|
+
...localSignerConfigMappings,
|
|
80
81
|
...validatorHASignerConfigMappings
|
|
81
82
|
};
|
|
82
83
|
/**
|
package/dest/factory.d.ts
CHANGED
|
@@ -7,6 +7,7 @@ import type { L2BlockSink, L2BlockSource } from '@aztec/stdlib/block';
|
|
|
7
7
|
import type { ValidatorClientFullConfig, WorldStateSynchronizer } from '@aztec/stdlib/interfaces/server';
|
|
8
8
|
import type { L1ToL2MessageSource } from '@aztec/stdlib/messaging';
|
|
9
9
|
import type { TelemetryClient } from '@aztec/telemetry-client';
|
|
10
|
+
import type { SlashingProtectionDatabase } from '@aztec/validator-ha-signer/types';
|
|
10
11
|
import { BlockProposalHandler } from './block_proposal_handler.js';
|
|
11
12
|
import type { FullNodeCheckpointsBuilder } from './checkpoint_builder.js';
|
|
12
13
|
import { ValidatorClient } from './validator.js';
|
|
@@ -31,5 +32,6 @@ export declare function createValidatorClient(config: ValidatorClientFullConfig,
|
|
|
31
32
|
epochCache: EpochCache;
|
|
32
33
|
keyStoreManager: KeystoreManager | undefined;
|
|
33
34
|
blobClient: BlobClientInterface;
|
|
35
|
+
slashingProtectionDb?: SlashingProtectionDatabase;
|
|
34
36
|
}): Promise<ValidatorClient> | undefined;
|
|
35
|
-
//# sourceMappingURL=data:application/json;base64,
|
|
37
|
+
//# sourceMappingURL=data:application/json;base64,eyJ2ZXJzaW9uIjozLCJmaWxlIjoiZmFjdG9yeS5kLnRzIiwic291cmNlUm9vdCI6IiIsInNvdXJjZXMiOlsiLi4vc3JjL2ZhY3RvcnkudHMiXSwibmFtZXMiOltdLCJtYXBwaW5ncyI6IkFBQUEsT0FBTyxLQUFLLEVBQUUsbUJBQW1CLEVBQUUsTUFBTSwyQkFBMkIsQ0FBQztBQUNyRSxPQUFPLEtBQUssRUFBRSxVQUFVLEVBQUUsTUFBTSxvQkFBb0IsQ0FBQztBQUNyRCxPQUFPLEtBQUssRUFBRSxZQUFZLEVBQUUsTUFBTSx5QkFBeUIsQ0FBQztBQUM1RCxPQUFPLEtBQUssRUFBRSxlQUFlLEVBQUUsTUFBTSxzQkFBc0IsQ0FBQztBQUM1RCxPQUFPLEVBQTBCLEtBQUssU0FBUyxFQUFFLE1BQU0sWUFBWSxDQUFDO0FBQ3BFLE9BQU8sS0FBSyxFQUFFLFdBQVcsRUFBRSxhQUFhLEVBQUUsTUFBTSxxQkFBcUIsQ0FBQztBQUN0RSxPQUFPLEtBQUssRUFBRSx5QkFBeUIsRUFBRSxzQkFBc0IsRUFBRSxNQUFNLGlDQUFpQyxDQUFDO0FBQ3pHLE9BQU8sS0FBSyxFQUFFLG1CQUFtQixFQUFFLE1BQU0seUJBQXlCLENBQUM7QUFDbkUsT0FBTyxLQUFLLEVBQUUsZUFBZSxFQUFFLE1BQU0seUJBQXlCLENBQUM7QUFDL0QsT0FBTyxLQUFLLEVBQUUsMEJBQTBCLEVBQUUsTUFBTSxrQ0FBa0MsQ0FBQztBQUVuRixPQUFPLEVBQUUsb0JBQW9CLEVBQUUsTUFBTSw2QkFBNkIsQ0FBQztBQUNuRSxPQUFPLEtBQUssRUFBRSwwQkFBMEIsRUFBRSxNQUFNLHlCQUF5QixDQUFDO0FBRTFFLE9BQU8sRUFBRSxlQUFlLEVBQUUsTUFBTSxnQkFBZ0IsQ0FBQztBQUVqRCx3QkFBZ0IsMEJBQTBCLENBQ3hDLE1BQU0sRUFBRSx5QkFBeUIsRUFDakMsSUFBSSxFQUFFO0lBQ0osa0JBQWtCLEVBQUUsMEJBQTBCLENBQUM7SUFDL0MsVUFBVSxFQUFFLHNCQUFzQixDQUFDO0lBQ25DLFdBQVcsRUFBRSxhQUFhLEdBQUcsV0FBVyxDQUFDO0lBQ3pDLG1CQUFtQixFQUFFLG1CQUFtQixDQUFDO0lBQ3pDLFNBQVMsRUFBRSxTQUFTLENBQUM7SUFDckIsVUFBVSxFQUFFLFVBQVUsQ0FBQztJQUN2QixZQUFZLEVBQUUsWUFBWSxDQUFDO0lBQzNCLFNBQVMsRUFBRSxlQUFlLENBQUM7Q0FDNUIsd0JBb0JGO0FBRUQsd0JBQWdCLHFCQUFxQixDQUNuQyxNQUFNLEVBQUUseUJBQXlCLEVBQ2pDLElBQUksRUFBRTtJQUNKLGtCQUFrQixFQUFFLDBCQUEwQixDQUFDO0lBQy9DLFVBQVUsRUFBRSxzQkFBc0IsQ0FBQztJQUNuQyxTQUFTLEVBQUUsU0FBUyxDQUFDO0lBQ3JCLFdBQVcsRUFBRSxhQUFhLEdBQUcsV0FBVyxDQUFDO0lBQ3pDLG1CQUFtQixFQUFFLG1CQUFtQixDQUFDO0lBQ3pDLFNBQVMsRUFBRSxlQUFlLENBQUM7SUFDM0IsWUFBWSxFQUFFLFlBQVksQ0FBQztJQUMzQixVQUFVLEVBQUUsVUFBVSxDQUFDO0lBQ3ZCLGVBQWUsRUFBRSxlQUFlLEdBQUcsU0FBUyxDQUFDO0lBQzdDLFVBQVUsRUFBRSxtQkFBbUIsQ0FBQztJQUNoQyxvQkFBb0IsQ0FBQyxFQUFFLDBCQUEwQixDQUFDO0NBQ25ELHdDQXNCRiJ9
|
package/dest/factory.d.ts.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"factory.d.ts","sourceRoot":"","sources":["../src/factory.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,mBAAmB,EAAE,MAAM,2BAA2B,CAAC;AACrE,OAAO,KAAK,EAAE,UAAU,EAAE,MAAM,oBAAoB,CAAC;AACrD,OAAO,KAAK,EAAE,YAAY,EAAE,MAAM,yBAAyB,CAAC;AAC5D,OAAO,KAAK,EAAE,eAAe,EAAE,MAAM,sBAAsB,CAAC;AAC5D,OAAO,EAA0B,KAAK,SAAS,EAAE,MAAM,YAAY,CAAC;AACpE,OAAO,KAAK,EAAE,WAAW,EAAE,aAAa,EAAE,MAAM,qBAAqB,CAAC;AACtE,OAAO,KAAK,EAAE,yBAAyB,EAAE,sBAAsB,EAAE,MAAM,iCAAiC,CAAC;AACzG,OAAO,KAAK,EAAE,mBAAmB,EAAE,MAAM,yBAAyB,CAAC;AACnE,OAAO,KAAK,EAAE,eAAe,EAAE,MAAM,yBAAyB,CAAC;
|
|
1
|
+
{"version":3,"file":"factory.d.ts","sourceRoot":"","sources":["../src/factory.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,mBAAmB,EAAE,MAAM,2BAA2B,CAAC;AACrE,OAAO,KAAK,EAAE,UAAU,EAAE,MAAM,oBAAoB,CAAC;AACrD,OAAO,KAAK,EAAE,YAAY,EAAE,MAAM,yBAAyB,CAAC;AAC5D,OAAO,KAAK,EAAE,eAAe,EAAE,MAAM,sBAAsB,CAAC;AAC5D,OAAO,EAA0B,KAAK,SAAS,EAAE,MAAM,YAAY,CAAC;AACpE,OAAO,KAAK,EAAE,WAAW,EAAE,aAAa,EAAE,MAAM,qBAAqB,CAAC;AACtE,OAAO,KAAK,EAAE,yBAAyB,EAAE,sBAAsB,EAAE,MAAM,iCAAiC,CAAC;AACzG,OAAO,KAAK,EAAE,mBAAmB,EAAE,MAAM,yBAAyB,CAAC;AACnE,OAAO,KAAK,EAAE,eAAe,EAAE,MAAM,yBAAyB,CAAC;AAC/D,OAAO,KAAK,EAAE,0BAA0B,EAAE,MAAM,kCAAkC,CAAC;AAEnF,OAAO,EAAE,oBAAoB,EAAE,MAAM,6BAA6B,CAAC;AACnE,OAAO,KAAK,EAAE,0BAA0B,EAAE,MAAM,yBAAyB,CAAC;AAE1E,OAAO,EAAE,eAAe,EAAE,MAAM,gBAAgB,CAAC;AAEjD,wBAAgB,0BAA0B,CACxC,MAAM,EAAE,yBAAyB,EACjC,IAAI,EAAE;IACJ,kBAAkB,EAAE,0BAA0B,CAAC;IAC/C,UAAU,EAAE,sBAAsB,CAAC;IACnC,WAAW,EAAE,aAAa,GAAG,WAAW,CAAC;IACzC,mBAAmB,EAAE,mBAAmB,CAAC;IACzC,SAAS,EAAE,SAAS,CAAC;IACrB,UAAU,EAAE,UAAU,CAAC;IACvB,YAAY,EAAE,YAAY,CAAC;IAC3B,SAAS,EAAE,eAAe,CAAC;CAC5B,wBAoBF;AAED,wBAAgB,qBAAqB,CACnC,MAAM,EAAE,yBAAyB,EACjC,IAAI,EAAE;IACJ,kBAAkB,EAAE,0BAA0B,CAAC;IAC/C,UAAU,EAAE,sBAAsB,CAAC;IACnC,SAAS,EAAE,SAAS,CAAC;IACrB,WAAW,EAAE,aAAa,GAAG,WAAW,CAAC;IACzC,mBAAmB,EAAE,mBAAmB,CAAC;IACzC,SAAS,EAAE,eAAe,CAAC;IAC3B,YAAY,EAAE,YAAY,CAAC;IAC3B,UAAU,EAAE,UAAU,CAAC;IACvB,eAAe,EAAE,eAAe,GAAG,SAAS,CAAC;IAC7C,UAAU,EAAE,mBAAmB,CAAC;IAChC,oBAAoB,CAAC,EAAE,0BAA0B,CAAC;CACnD,wCAsBF"}
|
package/dest/factory.js
CHANGED
|
@@ -15,5 +15,5 @@ export function createValidatorClient(config, deps) {
|
|
|
15
15
|
return undefined;
|
|
16
16
|
}
|
|
17
17
|
const txProvider = deps.p2pClient.getTxProvider();
|
|
18
|
-
return ValidatorClient.new(config, deps.checkpointsBuilder, deps.worldState, deps.epochCache, deps.p2pClient, deps.blockSource, deps.l1ToL2MessageSource, txProvider, deps.keyStoreManager, deps.blobClient, deps.dateProvider, deps.telemetry);
|
|
18
|
+
return ValidatorClient.new(config, deps.checkpointsBuilder, deps.worldState, deps.epochCache, deps.p2pClient, deps.blockSource, deps.l1ToL2MessageSource, txProvider, deps.keyStoreManager, deps.blobClient, deps.dateProvider, deps.telemetry, deps.slashingProtectionDb);
|
|
19
19
|
}
|
package/dest/validator.d.ts
CHANGED
|
@@ -17,7 +17,7 @@ import { type BlockProposal, type BlockProposalOptions, type CheckpointAttestati
|
|
|
17
17
|
import type { CheckpointHeader } from '@aztec/stdlib/rollup';
|
|
18
18
|
import type { BlockHeader, Tx } from '@aztec/stdlib/tx';
|
|
19
19
|
import { type TelemetryClient, type Tracer } from '@aztec/telemetry-client';
|
|
20
|
-
import { type SigningContext } from '@aztec/validator-ha-signer/types';
|
|
20
|
+
import { type SigningContext, type SlashingProtectionDatabase } from '@aztec/validator-ha-signer/types';
|
|
21
21
|
import type { ValidatorHASigner } from '@aztec/validator-ha-signer/validator-ha-signer';
|
|
22
22
|
import type { TypedDataDefinition } from 'viem';
|
|
23
23
|
import { BlockProposalHandler } from './block_proposal_handler.js';
|
|
@@ -38,7 +38,7 @@ export declare class ValidatorClient extends ValidatorClient_base implements Val
|
|
|
38
38
|
private l1ToL2MessageSource;
|
|
39
39
|
private config;
|
|
40
40
|
private blobClient;
|
|
41
|
-
private
|
|
41
|
+
private slashingProtectionSigner;
|
|
42
42
|
private dateProvider;
|
|
43
43
|
readonly tracer: Tracer;
|
|
44
44
|
private validationService;
|
|
@@ -56,10 +56,10 @@ export declare class ValidatorClient extends ValidatorClient_base implements Val
|
|
|
56
56
|
private proposersOfInvalidBlocks;
|
|
57
57
|
/** Tracks the last checkpoint proposal we attested to, to prevent equivocation. */
|
|
58
58
|
private lastAttestedProposal?;
|
|
59
|
-
protected constructor(keyStore: ExtendedValidatorKeyStore, epochCache: EpochCache, p2pClient: P2P, blockProposalHandler: BlockProposalHandler, blockSource: L2BlockSource, checkpointsBuilder: FullNodeCheckpointsBuilder, worldState: WorldStateSynchronizer, l1ToL2MessageSource: L1ToL2MessageSource, config: ValidatorClientFullConfig, blobClient: BlobClientInterface,
|
|
59
|
+
protected constructor(keyStore: ExtendedValidatorKeyStore, epochCache: EpochCache, p2pClient: P2P, blockProposalHandler: BlockProposalHandler, blockSource: L2BlockSource, checkpointsBuilder: FullNodeCheckpointsBuilder, worldState: WorldStateSynchronizer, l1ToL2MessageSource: L1ToL2MessageSource, config: ValidatorClientFullConfig, blobClient: BlobClientInterface, slashingProtectionSigner: ValidatorHASigner, dateProvider?: DateProvider, telemetry?: TelemetryClient, log?: Logger);
|
|
60
60
|
static validateKeyStoreConfiguration(keyStoreManager: KeystoreManager, logger?: Logger): void;
|
|
61
61
|
private handleEpochCommitteeUpdate;
|
|
62
|
-
static new(config: ValidatorClientFullConfig, checkpointsBuilder: FullNodeCheckpointsBuilder, worldState: WorldStateSynchronizer, epochCache: EpochCache, p2pClient: P2P, blockSource: L2BlockSource & L2BlockSink, l1ToL2MessageSource: L1ToL2MessageSource, txProvider: ITxProvider, keyStoreManager: KeystoreManager, blobClient: BlobClientInterface, dateProvider?: DateProvider, telemetry?: TelemetryClient): Promise<ValidatorClient>;
|
|
62
|
+
static new(config: ValidatorClientFullConfig, checkpointsBuilder: FullNodeCheckpointsBuilder, worldState: WorldStateSynchronizer, epochCache: EpochCache, p2pClient: P2P, blockSource: L2BlockSource & L2BlockSink, l1ToL2MessageSource: L1ToL2MessageSource, txProvider: ITxProvider, keyStoreManager: KeystoreManager, blobClient: BlobClientInterface, dateProvider?: DateProvider, telemetry?: TelemetryClient, slashingProtectionDb?: SlashingProtectionDatabase): Promise<ValidatorClient>;
|
|
63
63
|
getValidatorAddresses(): EthAddress[];
|
|
64
64
|
getBlockProposalHandler(): BlockProposalHandler;
|
|
65
65
|
signWithAddress(addr: EthAddress, msg: TypedDataDefinition, context: SigningContext): Promise<Signature>;
|
|
@@ -120,4 +120,4 @@ export declare class ValidatorClient extends ValidatorClient_base implements Val
|
|
|
120
120
|
private handleAuthRequest;
|
|
121
121
|
}
|
|
122
122
|
export {};
|
|
123
|
-
//# sourceMappingURL=data:application/json;base64,
|
|
123
|
+
//# sourceMappingURL=data:application/json;base64,eyJ2ZXJzaW9uIjozLCJmaWxlIjoidmFsaWRhdG9yLmQudHMiLCJzb3VyY2VSb290IjoiIiwic291cmNlcyI6WyIuLi9zcmMvdmFsaWRhdG9yLnRzIl0sIm5hbWVzIjpbXSwibWFwcGluZ3MiOiJBQUFBLE9BQU8sS0FBSyxFQUFFLG1CQUFtQixFQUFFLE1BQU0sMkJBQTJCLENBQUM7QUFFckUsT0FBTyxLQUFLLEVBQUUsVUFBVSxFQUFFLE1BQU0sb0JBQW9CLENBQUM7QUFFckQsT0FBTyxFQUNMLFdBQVcsRUFDWCxnQkFBZ0IsRUFFaEIscUJBQXFCLEVBQ3JCLFVBQVUsRUFDWCxNQUFNLGlDQUFpQyxDQUFDO0FBQ3pDLE9BQU8sRUFBRSxFQUFFLEVBQUUsTUFBTSxnQ0FBZ0MsQ0FBQztBQUVwRCxPQUFPLEtBQUssRUFBRSxVQUFVLEVBQUUsTUFBTSwrQkFBK0IsQ0FBQztBQUNoRSxPQUFPLEtBQUssRUFBRSxTQUFTLEVBQUUsTUFBTSxpQ0FBaUMsQ0FBQztBQUNqRSxPQUFPLEVBQUUsS0FBSyxPQUFPLEVBQUUsS0FBSyxNQUFNLEVBQWdCLE1BQU0sdUJBQXVCLENBQUM7QUFJaEYsT0FBTyxFQUFFLFlBQVksRUFBRSxNQUFNLHlCQUF5QixDQUFDO0FBQ3ZELE9BQU8sS0FBSyxFQUFFLGVBQWUsRUFBRSxNQUFNLHNCQUFzQixDQUFDO0FBQzVELE9BQU8sS0FBSyxFQUFtRCxHQUFHLEVBQUUsTUFBTSxFQUFFLE1BQU0sWUFBWSxDQUFDO0FBRS9GLE9BQU8sRUFBb0MsS0FBSyxPQUFPLEVBQUUsS0FBSyxjQUFjLEVBQUUsTUFBTSxnQkFBZ0IsQ0FBQztBQUNyRyxPQUFPLEtBQUssRUFBRSxZQUFZLEVBQUUsTUFBTSw2QkFBNkIsQ0FBQztBQUNoRSxPQUFPLEtBQUssRUFBRSwrQkFBK0IsRUFBVyxXQUFXLEVBQUUsYUFBYSxFQUFFLE1BQU0scUJBQXFCLENBQUM7QUFHaEgsT0FBTyxLQUFLLEVBQ1YscUNBQXFDLEVBQ3JDLFdBQVcsRUFDWCxTQUFTLEVBQ1QseUJBQXlCLEVBQ3pCLHNCQUFzQixFQUN2QixN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
|
package/dest/validator.d.ts.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"validator.d.ts","sourceRoot":"","sources":["../src/validator.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,mBAAmB,EAAE,MAAM,2BAA2B,CAAC;AAErE,OAAO,KAAK,EAAE,UAAU,EAAE,MAAM,oBAAoB,CAAC;AAErD,OAAO,EACL,WAAW,EACX,gBAAgB,EAEhB,qBAAqB,EACrB,UAAU,EACX,MAAM,iCAAiC,CAAC;AACzC,OAAO,EAAE,EAAE,EAAE,MAAM,gCAAgC,CAAC;AAEpD,OAAO,KAAK,EAAE,UAAU,EAAE,MAAM,+BAA+B,CAAC;AAChE,OAAO,KAAK,EAAE,SAAS,EAAE,MAAM,iCAAiC,CAAC;AACjE,OAAO,EAAE,KAAK,OAAO,EAAE,KAAK,MAAM,EAAgB,MAAM,uBAAuB,CAAC;AAIhF,OAAO,EAAE,YAAY,EAAE,MAAM,yBAAyB,CAAC;AACvD,OAAO,KAAK,EAAE,eAAe,EAAE,MAAM,sBAAsB,CAAC;AAC5D,OAAO,KAAK,EAAmD,GAAG,EAAE,MAAM,EAAE,MAAM,YAAY,CAAC;AAE/F,OAAO,EAAoC,KAAK,OAAO,EAAE,KAAK,cAAc,EAAE,MAAM,gBAAgB,CAAC;AACrG,OAAO,KAAK,EAAE,YAAY,EAAE,MAAM,6BAA6B,CAAC;AAChE,OAAO,KAAK,EAAE,+BAA+B,EAAW,WAAW,EAAE,aAAa,EAAE,MAAM,qBAAqB,CAAC;AAGhH,OAAO,KAAK,EACV,qCAAqC,EACrC,WAAW,EACX,SAAS,EACT,yBAAyB,EACzB,sBAAsB,EACvB,MAAM,iCAAiC,CAAC;AACzC,OAAO,EAAE,KAAK,mBAAmB,EAAiC,MAAM,yBAAyB,CAAC;AAClG,OAAO,EACL,KAAK,aAAa,EAClB,KAAK,oBAAoB,EACzB,KAAK,qBAAqB,EAC1B,kBAAkB,EAClB,KAAK,sBAAsB,EAC3B,KAAK,yBAAyB,EAC/B,MAAM,mBAAmB,CAAC;AAC3B,OAAO,KAAK,EAAE,gBAAgB,EAAE,MAAM,sBAAsB,CAAC;AAC7D,OAAO,KAAK,EAAE,WAAW,EAA6B,EAAE,EAAE,MAAM,kBAAkB,CAAC;AAEnF,OAAO,EAAE,KAAK,eAAe,EAAE,KAAK,MAAM,EAAsB,MAAM,yBAAyB,CAAC;
|
|
1
|
+
{"version":3,"file":"validator.d.ts","sourceRoot":"","sources":["../src/validator.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,mBAAmB,EAAE,MAAM,2BAA2B,CAAC;AAErE,OAAO,KAAK,EAAE,UAAU,EAAE,MAAM,oBAAoB,CAAC;AAErD,OAAO,EACL,WAAW,EACX,gBAAgB,EAEhB,qBAAqB,EACrB,UAAU,EACX,MAAM,iCAAiC,CAAC;AACzC,OAAO,EAAE,EAAE,EAAE,MAAM,gCAAgC,CAAC;AAEpD,OAAO,KAAK,EAAE,UAAU,EAAE,MAAM,+BAA+B,CAAC;AAChE,OAAO,KAAK,EAAE,SAAS,EAAE,MAAM,iCAAiC,CAAC;AACjE,OAAO,EAAE,KAAK,OAAO,EAAE,KAAK,MAAM,EAAgB,MAAM,uBAAuB,CAAC;AAIhF,OAAO,EAAE,YAAY,EAAE,MAAM,yBAAyB,CAAC;AACvD,OAAO,KAAK,EAAE,eAAe,EAAE,MAAM,sBAAsB,CAAC;AAC5D,OAAO,KAAK,EAAmD,GAAG,EAAE,MAAM,EAAE,MAAM,YAAY,CAAC;AAE/F,OAAO,EAAoC,KAAK,OAAO,EAAE,KAAK,cAAc,EAAE,MAAM,gBAAgB,CAAC;AACrG,OAAO,KAAK,EAAE,YAAY,EAAE,MAAM,6BAA6B,CAAC;AAChE,OAAO,KAAK,EAAE,+BAA+B,EAAW,WAAW,EAAE,aAAa,EAAE,MAAM,qBAAqB,CAAC;AAGhH,OAAO,KAAK,EACV,qCAAqC,EACrC,WAAW,EACX,SAAS,EACT,yBAAyB,EACzB,sBAAsB,EACvB,MAAM,iCAAiC,CAAC;AACzC,OAAO,EAAE,KAAK,mBAAmB,EAAiC,MAAM,yBAAyB,CAAC;AAClG,OAAO,EACL,KAAK,aAAa,EAClB,KAAK,oBAAoB,EACzB,KAAK,qBAAqB,EAC1B,kBAAkB,EAClB,KAAK,sBAAsB,EAC3B,KAAK,yBAAyB,EAC/B,MAAM,mBAAmB,CAAC;AAC3B,OAAO,KAAK,EAAE,gBAAgB,EAAE,MAAM,sBAAsB,CAAC;AAC7D,OAAO,KAAK,EAAE,WAAW,EAA6B,EAAE,EAAE,MAAM,kBAAkB,CAAC;AAEnF,OAAO,EAAE,KAAK,eAAe,EAAE,KAAK,MAAM,EAAsB,MAAM,yBAAyB,CAAC;AAMhG,OAAO,EAAY,KAAK,cAAc,EAAE,KAAK,0BAA0B,EAAE,MAAM,kCAAkC,CAAC;AAClH,OAAO,KAAK,EAAE,iBAAiB,EAAE,MAAM,gDAAgD,CAAC;AAGxF,OAAO,KAAK,EAAE,mBAAmB,EAAE,MAAM,MAAM,CAAC;AAEhD,OAAO,EAAE,oBAAoB,EAA6C,MAAM,6BAA6B,CAAC;AAC9G,OAAO,KAAK,EAAE,0BAA0B,EAAE,MAAM,yBAAyB,CAAC;AAG1E,OAAO,KAAK,EAAE,yBAAyB,EAAE,MAAM,0BAA0B,CAAC;;AAc1E;;GAEG;AACH,qBAAa,eAAgB,SAAQ,oBAA2C,YAAW,SAAS,EAAE,OAAO;IAyBzG,OAAO,CAAC,QAAQ;IAChB,OAAO,CAAC,UAAU;IAClB,OAAO,CAAC,SAAS;IACjB,OAAO,CAAC,oBAAoB;IAC5B,OAAO,CAAC,WAAW;IACnB,OAAO,CAAC,kBAAkB;IAC1B,OAAO,CAAC,UAAU;IAClB,OAAO,CAAC,mBAAmB;IAC3B,OAAO,CAAC,MAAM;IACd,OAAO,CAAC,UAAU;IAClB,OAAO,CAAC,wBAAwB;IAChC,OAAO,CAAC,YAAY;IAnCtB,SAAgB,MAAM,EAAE,MAAM,CAAC;IAC/B,OAAO,CAAC,iBAAiB,CAAoB;IAC7C,OAAO,CAAC,OAAO,CAAmB;IAClC,OAAO,CAAC,GAAG,CAAS;IAEpB,OAAO,CAAC,qBAAqB,CAAS;IAEtC,wFAAwF;IACxF,OAAO,CAAC,iBAAiB,CAAC,CAAgB;IAE1C,sDAAsD;IACtD,OAAO,CAAC,sBAAsB,CAAC,CAAqB;IAEpD,OAAO,CAAC,+BAA+B,CAA0B;IACjE,OAAO,CAAC,oBAAoB,CAAiB;IAC7C,oGAAoG;IACpG,OAAO,CAAC,2BAA2B,CAAuC;IAE1E,OAAO,CAAC,wBAAwB,CAA0B;IAE1D,mFAAmF;IACnF,OAAO,CAAC,oBAAoB,CAAC,CAAyB;IAEtD,SAAS,aACC,QAAQ,EAAE,yBAAyB,EACnC,UAAU,EAAE,UAAU,EACtB,SAAS,EAAE,GAAG,EACd,oBAAoB,EAAE,oBAAoB,EAC1C,WAAW,EAAE,aAAa,EAC1B,kBAAkB,EAAE,0BAA0B,EAC9C,UAAU,EAAE,sBAAsB,EAClC,mBAAmB,EAAE,mBAAmB,EACxC,MAAM,EAAE,yBAAyB,EACjC,UAAU,EAAE,mBAAmB,EAC/B,wBAAwB,EAAE,iBAAiB,EAC3C,YAAY,GAAE,YAAiC,EACvD,SAAS,GAAE,eAAsC,EACjD,GAAG,SAA4B,EAiBhC;IAED,OAAc,6BAA6B,CAAC,eAAe,EAAE,eAAe,EAAE,MAAM,CAAC,EAAE,MAAM,QAuB5F;YAEa,0BAA0B;IA4BxC,OAAa,GAAG,CACd,MAAM,EAAE,yBAAyB,EACjC,kBAAkB,EAAE,0BAA0B,EAC9C,UAAU,EAAE,sBAAsB,EAClC,UAAU,EAAE,UAAU,EACtB,SAAS,EAAE,GAAG,EACd,WAAW,EAAE,aAAa,GAAG,WAAW,EACxC,mBAAmB,EAAE,mBAAmB,EACxC,UAAU,EAAE,WAAW,EACvB,eAAe,EAAE,eAAe,EAChC,UAAU,EAAE,mBAAmB,EAC/B,YAAY,GAAE,YAAiC,EAC/C,SAAS,GAAE,eAAsC,EACjD,oBAAoB,CAAC,EAAE,0BAA0B,4BAmElD;IAEM,qBAAqB,iBAI3B;IAEM,uBAAuB,yBAE7B;IAEM,eAAe,CAAC,IAAI,EAAE,UAAU,EAAE,GAAG,EAAE,mBAAmB,EAAE,OAAO,EAAE,cAAc,sBAEzF;IAEM,sBAAsB,CAAC,QAAQ,EAAE,UAAU,GAAG,UAAU,CAE9D;IAEM,0BAA0B,CAAC,QAAQ,EAAE,UAAU,GAAG,YAAY,CAEpE;IAEM,SAAS,IAAI,yBAAyB,CAE5C;IAEM,YAAY,CAAC,MAAM,EAAE,OAAO,CAAC,yBAAyB,CAAC,QAE7D;IAEM,cAAc,CAAC,UAAU,EAAE,eAAe,GAAG,IAAI,CAIvD;IAEY,KAAK,kBAmBjB;IAEY,IAAI,kBAGhB;IAED,0CAA0C;IAC7B,gBAAgB,kBAkC5B;IAED;;;;OAIG;IACG,qBAAqB,CAAC,QAAQ,EAAE,aAAa,EAAE,cAAc,EAAE,MAAM,GAAG,OAAO,CAAC,OAAO,CAAC,CAkG7F;IAED;;;;;OAKG;IACG,0BAA0B,CAC9B,QAAQ,EAAE,sBAAsB,EAChC,eAAe,EAAE,MAAM,GACtB,OAAO,CAAC,qBAAqB,EAAE,GAAG,SAAS,CAAC,CAuH9C;IAED;;;OAGG;IACH,OAAO,CAAC,kBAAkB;YAiBZ,wCAAwC;YAsBxC,0BAA0B;IAkJxC;;OAEG;IACH,OAAO,CAAC,0BAA0B;IAalC;;OAEG;IACH,UAAgB,wBAAwB,CAAC,QAAQ,EAAE,sBAAsB,EAAE,YAAY,EAAE,OAAO,GAAG,OAAO,CAAC,IAAI,CAAC,CAwB/G;IAED,OAAO,CAAC,iBAAiB;IA2BzB;;;OAGG;IACH,OAAO,CAAC,uBAAuB;IAoB/B;;;OAGG;IACH,OAAO,CAAC,0BAA0B;IAkB5B,mBAAmB,CACvB,WAAW,EAAE,WAAW,EACxB,qBAAqB,EAAE,qBAAqB,EAC5C,MAAM,EAAE,EAAE,EACV,OAAO,EAAE,EAAE,EACX,GAAG,EAAE,EAAE,EAAE,EACT,eAAe,EAAE,UAAU,GAAG,SAAS,EACvC,OAAO,GAAE,oBAAyB,GACjC,OAAO,CAAC,aAAa,CAAC,CAgCxB;IAEK,wBAAwB,CAC5B,gBAAgB,EAAE,gBAAgB,EAClC,OAAO,EAAE,EAAE,EACX,qBAAqB,EAAE,MAAM,EAC7B,aAAa,EAAE,qCAAqC,GAAG,SAAS,EAChE,eAAe,EAAE,UAAU,GAAG,SAAS,EACvC,OAAO,GAAE,yBAA8B,GACtC,OAAO,CAAC,kBAAkB,CAAC,CAyB7B;IAEK,sBAAsB,CAAC,QAAQ,EAAE,aAAa,GAAG,OAAO,CAAC,IAAI,CAAC,CAEnE;IAEK,0BAA0B,CAC9B,sBAAsB,EAAE,+BAA+B,EACvD,QAAQ,EAAE,UAAU,EACpB,IAAI,EAAE,UAAU,EAChB,WAAW,EAAE,WAAW,GAAG,gBAAgB,GAC1C,OAAO,CAAC,SAAS,CAAC,CAEpB;IAEK,sBAAsB,CAAC,QAAQ,EAAE,kBAAkB,GAAG,OAAO,CAAC,qBAAqB,EAAE,CAAC,CAiB3F;IAEK,mBAAmB,CACvB,QAAQ,EAAE,kBAAkB,EAC5B,QAAQ,EAAE,MAAM,EAChB,QAAQ,EAAE,IAAI,GACb,OAAO,CAAC,qBAAqB,EAAE,CAAC,CAiElC;YAEa,iBAAiB;CAwBhC"}
|
package/dest/validator.js
CHANGED
|
@@ -14,7 +14,7 @@ import { getEpochAtSlot, getTimestampForSlot } from '@aztec/stdlib/epoch-helpers
|
|
|
14
14
|
import { accumulateCheckpointOutHashes } from '@aztec/stdlib/messaging';
|
|
15
15
|
import { AttestationTimeoutError } from '@aztec/stdlib/validators';
|
|
16
16
|
import { getTelemetryClient } from '@aztec/telemetry-client';
|
|
17
|
-
import { createHASigner } from '@aztec/validator-ha-signer/factory';
|
|
17
|
+
import { createHASigner, createLocalSignerWithProtection, createSignerFromSharedDb } from '@aztec/validator-ha-signer/factory';
|
|
18
18
|
import { DutyType } from '@aztec/validator-ha-signer/types';
|
|
19
19
|
import { EventEmitter } from 'events';
|
|
20
20
|
import { BlockProposalHandler } from './block_proposal_handler.js';
|
|
@@ -43,7 +43,7 @@ const SLASHABLE_BLOCK_PROPOSAL_VALIDATION_RESULT = [
|
|
|
43
43
|
l1ToL2MessageSource;
|
|
44
44
|
config;
|
|
45
45
|
blobClient;
|
|
46
|
-
|
|
46
|
+
slashingProtectionSigner;
|
|
47
47
|
dateProvider;
|
|
48
48
|
tracer;
|
|
49
49
|
validationService;
|
|
@@ -58,8 +58,8 @@ const SLASHABLE_BLOCK_PROPOSAL_VALIDATION_RESULT = [
|
|
|
58
58
|
/** Tracks the last epoch in which each attester successfully submitted at least one attestation. */ lastAttestedEpochByAttester;
|
|
59
59
|
proposersOfInvalidBlocks;
|
|
60
60
|
/** Tracks the last checkpoint proposal we attested to, to prevent equivocation. */ lastAttestedProposal;
|
|
61
|
-
constructor(keyStore, epochCache, p2pClient, blockProposalHandler, blockSource, checkpointsBuilder, worldState, l1ToL2MessageSource, config, blobClient,
|
|
62
|
-
super(), this.keyStore = keyStore, this.epochCache = epochCache, this.p2pClient = p2pClient, this.blockProposalHandler = blockProposalHandler, this.blockSource = blockSource, this.checkpointsBuilder = checkpointsBuilder, this.worldState = worldState, this.l1ToL2MessageSource = l1ToL2MessageSource, this.config = config, this.blobClient = blobClient, this.
|
|
61
|
+
constructor(keyStore, epochCache, p2pClient, blockProposalHandler, blockSource, checkpointsBuilder, worldState, l1ToL2MessageSource, config, blobClient, slashingProtectionSigner, dateProvider = new DateProvider(), telemetry = getTelemetryClient(), log = createLogger('validator')){
|
|
62
|
+
super(), this.keyStore = keyStore, this.epochCache = epochCache, this.p2pClient = p2pClient, this.blockProposalHandler = blockProposalHandler, this.blockSource = blockSource, this.checkpointsBuilder = checkpointsBuilder, this.worldState = worldState, this.l1ToL2MessageSource = l1ToL2MessageSource, this.config = config, this.blobClient = blobClient, this.slashingProtectionSigner = slashingProtectionSigner, this.dateProvider = dateProvider, this.hasRegisteredHandlers = false, this.lastAttestedEpochByAttester = new Map(), this.proposersOfInvalidBlocks = new Set();
|
|
63
63
|
// Create child logger with fisherman prefix if in fisherman mode
|
|
64
64
|
this.log = config.fishermanMode ? log.createChild('[FISHERMAN]') : log;
|
|
65
65
|
this.tracer = telemetry.getTracer('Validator');
|
|
@@ -114,7 +114,7 @@ const SLASHABLE_BLOCK_PROPOSAL_VALIDATION_RESULT = [
|
|
|
114
114
|
this.log.error(`Error updating epoch committee`, err);
|
|
115
115
|
}
|
|
116
116
|
}
|
|
117
|
-
static async new(config, checkpointsBuilder, worldState, epochCache, p2pClient, blockSource, l1ToL2MessageSource, txProvider, keyStoreManager, blobClient, dateProvider = new DateProvider(), telemetry = getTelemetryClient()) {
|
|
117
|
+
static async new(config, checkpointsBuilder, worldState, epochCache, p2pClient, blockSource, l1ToL2MessageSource, txProvider, keyStoreManager, blobClient, dateProvider = new DateProvider(), telemetry = getTelemetryClient(), slashingProtectionDb) {
|
|
118
118
|
const metrics = new ValidatorMetrics(telemetry);
|
|
119
119
|
const blockProposalValidator = new BlockProposalValidator(epochCache, {
|
|
120
120
|
txsPermitted: !config.disableTransactions,
|
|
@@ -122,19 +122,34 @@ const SLASHABLE_BLOCK_PROPOSAL_VALIDATION_RESULT = [
|
|
|
122
122
|
});
|
|
123
123
|
const blockProposalHandler = new BlockProposalHandler(checkpointsBuilder, worldState, blockSource, l1ToL2MessageSource, txProvider, blockProposalValidator, epochCache, config, metrics, dateProvider, telemetry);
|
|
124
124
|
const nodeKeystoreAdapter = NodeKeystoreAdapter.fromKeyStoreManager(keyStoreManager);
|
|
125
|
-
let
|
|
126
|
-
|
|
127
|
-
|
|
125
|
+
let slashingProtectionSigner;
|
|
126
|
+
if (slashingProtectionDb) {
|
|
127
|
+
// Shared database mode: use a pre-existing database (e.g. for testing HA setups).
|
|
128
|
+
({ signer: slashingProtectionSigner } = createSignerFromSharedDb(slashingProtectionDb, config, {
|
|
129
|
+
telemetryClient: telemetry,
|
|
130
|
+
dateProvider
|
|
131
|
+
}));
|
|
132
|
+
} else if (config.haSigningEnabled) {
|
|
133
|
+
// Multi-node HA mode: use PostgreSQL-backed distributed locking.
|
|
128
134
|
// If maxStuckDutiesAgeMs is not explicitly set, compute it from Aztec slot duration
|
|
129
135
|
const haConfig = {
|
|
130
136
|
...config,
|
|
131
137
|
maxStuckDutiesAgeMs: config.maxStuckDutiesAgeMs ?? epochCache.getL1Constants().slotDuration * 2 * 1000
|
|
132
138
|
};
|
|
133
|
-
|
|
134
|
-
|
|
135
|
-
|
|
136
|
-
|
|
137
|
-
|
|
139
|
+
({ signer: slashingProtectionSigner } = await createHASigner(haConfig, {
|
|
140
|
+
telemetryClient: telemetry,
|
|
141
|
+
dateProvider
|
|
142
|
+
}));
|
|
143
|
+
} else {
|
|
144
|
+
// Single-node mode: use LMDB-backed local signing protection.
|
|
145
|
+
// This prevents double-signing if the node crashes and restarts mid-proposal.
|
|
146
|
+
({ signer: slashingProtectionSigner } = await createLocalSignerWithProtection(config, {
|
|
147
|
+
telemetryClient: telemetry,
|
|
148
|
+
dateProvider
|
|
149
|
+
}));
|
|
150
|
+
}
|
|
151
|
+
const validatorKeyStore = new HAKeyStore(nodeKeystoreAdapter, slashingProtectionSigner);
|
|
152
|
+
const validator = new ValidatorClient(validatorKeyStore, epochCache, p2pClient, blockProposalHandler, blockSource, checkpointsBuilder, worldState, l1ToL2MessageSource, config, blobClient, slashingProtectionSigner, dateProvider, telemetry);
|
|
138
153
|
return validator;
|
|
139
154
|
}
|
|
140
155
|
getValidatorAddresses() {
|
|
@@ -162,17 +177,8 @@ const SLASHABLE_BLOCK_PROPOSAL_VALIDATION_RESULT = [
|
|
|
162
177
|
};
|
|
163
178
|
}
|
|
164
179
|
reloadKeystore(newManager) {
|
|
165
|
-
if (this.config.haSigningEnabled && !this.haSigner) {
|
|
166
|
-
this.log.warn('HA signing is enabled in config but was not initialized at startup. ' + 'Restart the node to enable HA signing.');
|
|
167
|
-
} else if (!this.config.haSigningEnabled && this.haSigner) {
|
|
168
|
-
this.log.warn('HA signing was disabled via config update but the HA signer is still active. ' + 'Restart the node to fully disable HA signing.');
|
|
169
|
-
}
|
|
170
180
|
const newAdapter = NodeKeystoreAdapter.fromKeyStoreManager(newManager);
|
|
171
|
-
|
|
172
|
-
this.keyStore = new HAKeyStore(newAdapter, this.haSigner);
|
|
173
|
-
} else {
|
|
174
|
-
this.keyStore = newAdapter;
|
|
175
|
-
}
|
|
181
|
+
this.keyStore = new HAKeyStore(newAdapter, this.slashingProtectionSigner);
|
|
176
182
|
this.validationService = new ValidationService(this.keyStore, this.log.createChild('validation-service'));
|
|
177
183
|
}
|
|
178
184
|
async start() {
|
|
@@ -235,13 +241,12 @@ const SLASHABLE_BLOCK_PROPOSAL_VALIDATION_RESULT = [
|
|
|
235
241
|
this.log.warn(`Received block proposal with invalid signature for slot ${slotNumber}`);
|
|
236
242
|
return false;
|
|
237
243
|
}
|
|
238
|
-
//
|
|
244
|
+
// Log self-proposals from HA peers (same validator key on different nodes)
|
|
239
245
|
if (this.getValidatorAddresses().some((addr)=>addr.equals(proposer))) {
|
|
240
|
-
this.log.
|
|
246
|
+
this.log.verbose(`Processing block proposal from HA peer for slot ${slotNumber}`, {
|
|
241
247
|
proposer: proposer.toString(),
|
|
242
248
|
slotNumber
|
|
243
249
|
});
|
|
244
|
-
return false;
|
|
245
250
|
}
|
|
246
251
|
// Check if we're in the committee (for metrics purposes)
|
|
247
252
|
const inCommittee = await this.epochCache.filterInCommittee(slotNumber, this.getValidatorAddresses());
|
|
@@ -302,46 +307,46 @@ const SLASHABLE_BLOCK_PROPOSAL_VALIDATION_RESULT = [
|
|
|
302
307
|
* the lastBlock is extracted and processed separately via the block handler.
|
|
303
308
|
* @returns Checkpoint attestations if valid, undefined otherwise
|
|
304
309
|
*/ async attestToCheckpointProposal(proposal, _proposalSender) {
|
|
305
|
-
const
|
|
310
|
+
const proposalSlotNumber = proposal.slotNumber;
|
|
306
311
|
const proposer = proposal.getSender();
|
|
307
312
|
// If escape hatch is open for this slot's epoch, do not attest.
|
|
308
|
-
if (await this.epochCache.isEscapeHatchOpenAtSlot(
|
|
309
|
-
this.log.warn(`Escape hatch open for slot ${
|
|
313
|
+
if (await this.epochCache.isEscapeHatchOpenAtSlot(proposalSlotNumber)) {
|
|
314
|
+
this.log.warn(`Escape hatch open for slot ${proposalSlotNumber}, skipping checkpoint attestation handling`);
|
|
310
315
|
return undefined;
|
|
311
316
|
}
|
|
312
317
|
// Reject proposals with invalid signatures
|
|
313
318
|
if (!proposer) {
|
|
314
|
-
this.log.warn(`Received checkpoint proposal with invalid signature for slot ${
|
|
319
|
+
this.log.warn(`Received checkpoint proposal with invalid signature for proposal slot ${proposalSlotNumber}`);
|
|
315
320
|
return undefined;
|
|
316
321
|
}
|
|
317
322
|
// Ignore proposals from ourselves (may happen in HA setups)
|
|
318
323
|
if (this.getValidatorAddresses().some((addr)=>addr.equals(proposer))) {
|
|
319
|
-
this.log.debug(`Ignoring block proposal from self for slot ${
|
|
324
|
+
this.log.debug(`Ignoring block proposal from self for slot ${proposalSlotNumber}`, {
|
|
320
325
|
proposer: proposer.toString(),
|
|
321
|
-
|
|
326
|
+
proposalSlotNumber
|
|
322
327
|
});
|
|
323
328
|
return undefined;
|
|
324
329
|
}
|
|
325
330
|
// Validate fee asset price modifier is within allowed range
|
|
326
331
|
if (!validateFeeAssetPriceModifier(proposal.feeAssetPriceModifier)) {
|
|
327
|
-
this.log.warn(`Received checkpoint proposal with invalid feeAssetPriceModifier ${proposal.feeAssetPriceModifier} for slot ${
|
|
332
|
+
this.log.warn(`Received checkpoint proposal with invalid feeAssetPriceModifier ${proposal.feeAssetPriceModifier} for slot ${proposalSlotNumber}`);
|
|
328
333
|
return undefined;
|
|
329
334
|
}
|
|
330
|
-
// Check that I have any address in
|
|
331
|
-
const inCommittee = await this.epochCache.filterInCommittee(
|
|
335
|
+
// Check that I have any address in the committee where this checkpoint will land before attesting
|
|
336
|
+
const inCommittee = await this.epochCache.filterInCommittee(proposalSlotNumber, this.getValidatorAddresses());
|
|
332
337
|
const partOfCommittee = inCommittee.length > 0;
|
|
333
338
|
const proposalInfo = {
|
|
334
|
-
|
|
339
|
+
proposalSlotNumber,
|
|
335
340
|
archive: proposal.archive.toString(),
|
|
336
341
|
proposer: proposer.toString()
|
|
337
342
|
};
|
|
338
|
-
this.log.info(`Received checkpoint proposal for slot ${
|
|
343
|
+
this.log.info(`Received checkpoint proposal for slot ${proposalSlotNumber}`, {
|
|
339
344
|
...proposalInfo,
|
|
340
345
|
fishermanMode: this.config.fishermanMode || false
|
|
341
346
|
});
|
|
342
347
|
// Validate the checkpoint proposal before attesting (unless skipCheckpointProposalValidation is set)
|
|
343
348
|
if (this.config.skipCheckpointProposalValidation) {
|
|
344
|
-
this.log.warn(`Skipping checkpoint proposal validation for slot ${
|
|
349
|
+
this.log.warn(`Skipping checkpoint proposal validation for slot ${proposalSlotNumber}`, proposalInfo);
|
|
345
350
|
} else {
|
|
346
351
|
const validationResult = await this.validateCheckpointProposal(proposal, proposalInfo);
|
|
347
352
|
if (!validationResult.isValid) {
|
|
@@ -360,14 +365,14 @@ const SLASHABLE_BLOCK_PROPOSAL_VALIDATION_RESULT = [
|
|
|
360
365
|
return undefined;
|
|
361
366
|
}
|
|
362
367
|
// Provided all of the above checks pass, we can attest to the proposal
|
|
363
|
-
this.log.info(`${partOfCommittee ? 'Attesting to' : 'Validated'} checkpoint proposal for slot ${
|
|
368
|
+
this.log.info(`${partOfCommittee ? 'Attesting to' : 'Validated'} checkpoint proposal for slot ${proposalSlotNumber}`, {
|
|
364
369
|
...proposalInfo,
|
|
365
370
|
inCommittee: partOfCommittee,
|
|
366
371
|
fishermanMode: this.config.fishermanMode || false
|
|
367
372
|
});
|
|
368
373
|
this.metrics.incSuccessfulAttestations(inCommittee.length);
|
|
369
374
|
// Track epoch participation per attester: count each (attester, epoch) pair at most once
|
|
370
|
-
const proposalEpoch = getEpochAtSlot(
|
|
375
|
+
const proposalEpoch = getEpochAtSlot(proposalSlotNumber, this.epochCache.getL1Constants());
|
|
371
376
|
for (const attester of inCommittee){
|
|
372
377
|
const key = attester.toString();
|
|
373
378
|
const lastEpoch = this.lastAttestedEpochByAttester.get(key);
|
|
@@ -392,7 +397,7 @@ const SLASHABLE_BLOCK_PROPOSAL_VALIDATION_RESULT = [
|
|
|
392
397
|
}
|
|
393
398
|
if (this.config.fishermanMode) {
|
|
394
399
|
// bail out early and don't save attestations to the pool in fisherman mode
|
|
395
|
-
this.log.info(`Creating checkpoint attestations for slot ${
|
|
400
|
+
this.log.info(`Creating checkpoint attestations for slot ${proposalSlotNumber}`, {
|
|
396
401
|
...proposalInfo,
|
|
397
402
|
attestors: attestors.map((a)=>a.toString())
|
|
398
403
|
});
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@aztec/validator-client",
|
|
3
|
-
"version": "0.0.1-commit.
|
|
3
|
+
"version": "0.0.1-commit.3a4ae741b",
|
|
4
4
|
"main": "dest/index.js",
|
|
5
5
|
"type": "module",
|
|
6
6
|
"exports": {
|
|
@@ -64,30 +64,30 @@
|
|
|
64
64
|
]
|
|
65
65
|
},
|
|
66
66
|
"dependencies": {
|
|
67
|
-
"@aztec/blob-client": "0.0.1-commit.
|
|
68
|
-
"@aztec/blob-lib": "0.0.1-commit.
|
|
69
|
-
"@aztec/constants": "0.0.1-commit.
|
|
70
|
-
"@aztec/epoch-cache": "0.0.1-commit.
|
|
71
|
-
"@aztec/ethereum": "0.0.1-commit.
|
|
72
|
-
"@aztec/foundation": "0.0.1-commit.
|
|
73
|
-
"@aztec/node-keystore": "0.0.1-commit.
|
|
74
|
-
"@aztec/noir-protocol-circuits-types": "0.0.1-commit.
|
|
75
|
-
"@aztec/p2p": "0.0.1-commit.
|
|
76
|
-
"@aztec/protocol-contracts": "0.0.1-commit.
|
|
77
|
-
"@aztec/prover-client": "0.0.1-commit.
|
|
78
|
-
"@aztec/simulator": "0.0.1-commit.
|
|
79
|
-
"@aztec/slasher": "0.0.1-commit.
|
|
80
|
-
"@aztec/stdlib": "0.0.1-commit.
|
|
81
|
-
"@aztec/telemetry-client": "0.0.1-commit.
|
|
82
|
-
"@aztec/validator-ha-signer": "0.0.1-commit.
|
|
67
|
+
"@aztec/blob-client": "0.0.1-commit.3a4ae741b",
|
|
68
|
+
"@aztec/blob-lib": "0.0.1-commit.3a4ae741b",
|
|
69
|
+
"@aztec/constants": "0.0.1-commit.3a4ae741b",
|
|
70
|
+
"@aztec/epoch-cache": "0.0.1-commit.3a4ae741b",
|
|
71
|
+
"@aztec/ethereum": "0.0.1-commit.3a4ae741b",
|
|
72
|
+
"@aztec/foundation": "0.0.1-commit.3a4ae741b",
|
|
73
|
+
"@aztec/node-keystore": "0.0.1-commit.3a4ae741b",
|
|
74
|
+
"@aztec/noir-protocol-circuits-types": "0.0.1-commit.3a4ae741b",
|
|
75
|
+
"@aztec/p2p": "0.0.1-commit.3a4ae741b",
|
|
76
|
+
"@aztec/protocol-contracts": "0.0.1-commit.3a4ae741b",
|
|
77
|
+
"@aztec/prover-client": "0.0.1-commit.3a4ae741b",
|
|
78
|
+
"@aztec/simulator": "0.0.1-commit.3a4ae741b",
|
|
79
|
+
"@aztec/slasher": "0.0.1-commit.3a4ae741b",
|
|
80
|
+
"@aztec/stdlib": "0.0.1-commit.3a4ae741b",
|
|
81
|
+
"@aztec/telemetry-client": "0.0.1-commit.3a4ae741b",
|
|
82
|
+
"@aztec/validator-ha-signer": "0.0.1-commit.3a4ae741b",
|
|
83
83
|
"koa": "^2.16.1",
|
|
84
84
|
"koa-router": "^13.1.1",
|
|
85
85
|
"tslib": "^2.4.0",
|
|
86
86
|
"viem": "npm:@aztec/viem@2.38.2"
|
|
87
87
|
},
|
|
88
88
|
"devDependencies": {
|
|
89
|
-
"@aztec/archiver": "0.0.1-commit.
|
|
90
|
-
"@aztec/world-state": "0.0.1-commit.
|
|
89
|
+
"@aztec/archiver": "0.0.1-commit.3a4ae741b",
|
|
90
|
+
"@aztec/world-state": "0.0.1-commit.3a4ae741b",
|
|
91
91
|
"@electric-sql/pglite": "^0.3.14",
|
|
92
92
|
"@jest/globals": "^30.0.0",
|
|
93
93
|
"@types/jest": "^30.0.0",
|
|
@@ -166,11 +166,15 @@ export class BlockProposalHandler {
|
|
|
166
166
|
// since a pending checkpoint prune may remove blocks we'd otherwise find.
|
|
167
167
|
// This affects mostly the block_number_already_exists check, since a pending
|
|
168
168
|
// checkpoint prune could remove a block that would conflict with this proposal.
|
|
169
|
-
//
|
|
170
|
-
|
|
171
|
-
|
|
172
|
-
|
|
173
|
-
|
|
169
|
+
// When pipelining is enabled, the proposer builds ahead of L1 submission, so the
|
|
170
|
+
// block source won't have synced to the proposed slot yet. Skip the sync wait to
|
|
171
|
+
// avoid eating into the attestation window.
|
|
172
|
+
if (!this.epochCache.isProposerPipeliningEnabled()) {
|
|
173
|
+
const blockSourceSync = await this.waitForBlockSourceSync(slotNumber);
|
|
174
|
+
if (!blockSourceSync) {
|
|
175
|
+
this.log.warn(`Block source is not synced, skipping processing`, proposalInfo);
|
|
176
|
+
return { isValid: false, reason: 'block_source_not_synced' };
|
|
177
|
+
}
|
|
174
178
|
}
|
|
175
179
|
|
|
176
180
|
// Check that the parent proposal is a block we know, otherwise reexecution would fail.
|
|
@@ -569,6 +573,8 @@ export class BlockProposalHandler {
|
|
|
569
573
|
? new Gas(this.config.validateMaxDABlockGas ?? Infinity, this.config.validateMaxL2BlockGas ?? Infinity)
|
|
570
574
|
: undefined;
|
|
571
575
|
const result = await checkpointBuilder.buildBlock(txs, blockNumber, blockHeader.globalVariables.timestamp, {
|
|
576
|
+
isBuildingProposal: false,
|
|
577
|
+
minValidTxs: 0,
|
|
572
578
|
deadline,
|
|
573
579
|
expectedEndState: blockHeader.state,
|
|
574
580
|
maxTransactions: this.config.validateMaxTxsPerBlock,
|
|
@@ -20,6 +20,7 @@ import type { ContractDataSource } from '@aztec/stdlib/contract';
|
|
|
20
20
|
import type { L1RollupConstants } from '@aztec/stdlib/epoch-helpers';
|
|
21
21
|
import { Gas } from '@aztec/stdlib/gas';
|
|
22
22
|
import {
|
|
23
|
+
type BlockBuilderOptions,
|
|
23
24
|
type BuildBlockInCheckpointResult,
|
|
24
25
|
type FullNodeBlockBuilderConfig,
|
|
25
26
|
FullNodeBlockBuilderConfigKeys,
|
|
@@ -46,6 +47,9 @@ export type { BuildBlockInCheckpointResult } from '@aztec/stdlib/interfaces/serv
|
|
|
46
47
|
export class CheckpointBuilder implements ICheckpointBlockBuilder {
|
|
47
48
|
private log: Logger;
|
|
48
49
|
|
|
50
|
+
/** Persistent contracts DB shared across all blocks in this checkpoint. */
|
|
51
|
+
protected contractsDB: PublicContractsDB;
|
|
52
|
+
|
|
49
53
|
constructor(
|
|
50
54
|
private checkpointBuilder: LightweightCheckpointBuilder,
|
|
51
55
|
private fork: MerkleTreeWriteOperations,
|
|
@@ -60,6 +64,7 @@ export class CheckpointBuilder implements ICheckpointBlockBuilder {
|
|
|
60
64
|
...bindings,
|
|
61
65
|
instanceId: `checkpoint-${checkpointBuilder.checkpointNumber}`,
|
|
62
66
|
});
|
|
67
|
+
this.contractsDB = new PublicContractsDB(this.contractDataSource, this.log.getBindings());
|
|
63
68
|
}
|
|
64
69
|
|
|
65
70
|
getConstantData(): CheckpointGlobalVariables {
|
|
@@ -74,7 +79,7 @@ export class CheckpointBuilder implements ICheckpointBlockBuilder {
|
|
|
74
79
|
pendingTxs: Iterable<Tx> | AsyncIterable<Tx>,
|
|
75
80
|
blockNumber: BlockNumber,
|
|
76
81
|
timestamp: bigint,
|
|
77
|
-
opts:
|
|
82
|
+
opts: BlockBuilderOptions & { expectedEndState?: StateReference },
|
|
78
83
|
): Promise<BuildBlockInCheckpointResult> {
|
|
79
84
|
const slot = this.checkpointBuilder.constants.slotNumber;
|
|
80
85
|
|
|
@@ -104,6 +109,8 @@ export class CheckpointBuilder implements ICheckpointBlockBuilder {
|
|
|
104
109
|
...this.capLimitsByCheckpointBudgets(opts),
|
|
105
110
|
};
|
|
106
111
|
|
|
112
|
+
// Create a block-level checkpoint on the contracts DB so we can roll back on failure
|
|
113
|
+
this.contractsDB.createCheckpoint();
|
|
107
114
|
// We execute all merkle tree operations on a world state fork checkpoint
|
|
108
115
|
// This enables us to discard all modifications in the event that we fail to successfully process sufficient transactions
|
|
109
116
|
const forkCheckpoint = await ForkCheckpoint.new(this.fork);
|
|
@@ -112,6 +119,7 @@ export class CheckpointBuilder implements ICheckpointBlockBuilder {
|
|
|
112
119
|
const [publicProcessorDuration, [processedTxs, failedTxs, usedTxs]] = await elapsed(() =>
|
|
113
120
|
processor.process(pendingTxs, cappedOpts, validator),
|
|
114
121
|
);
|
|
122
|
+
|
|
115
123
|
// Throw before updating state if we don't have enough valid txs
|
|
116
124
|
const minValidTxs = opts.minValidTxs ?? 0;
|
|
117
125
|
if (processedTxs.length < minValidTxs) {
|
|
@@ -122,10 +130,12 @@ export class CheckpointBuilder implements ICheckpointBlockBuilder {
|
|
|
122
130
|
await forkCheckpoint.commit();
|
|
123
131
|
|
|
124
132
|
// Add block to checkpoint
|
|
125
|
-
const block = await this.checkpointBuilder.addBlock(globalVariables, processedTxs, {
|
|
133
|
+
const { block } = await this.checkpointBuilder.addBlock(globalVariables, processedTxs, {
|
|
126
134
|
expectedEndState: opts.expectedEndState,
|
|
127
135
|
});
|
|
128
136
|
|
|
137
|
+
this.contractsDB.commitCheckpoint();
|
|
138
|
+
|
|
129
139
|
this.log.debug('Built block within checkpoint', {
|
|
130
140
|
header: block.header.toInspect(),
|
|
131
141
|
processedTxs: processedTxs.map(tx => tx.hash.toString()),
|
|
@@ -140,6 +150,8 @@ export class CheckpointBuilder implements ICheckpointBlockBuilder {
|
|
|
140
150
|
usedTxs,
|
|
141
151
|
};
|
|
142
152
|
} catch (err) {
|
|
153
|
+
// Revert all changes to contracts db
|
|
154
|
+
this.contractsDB.revertCheckpoint();
|
|
143
155
|
// If we reached the point of committing the checkpoint, this does nothing
|
|
144
156
|
// Otherwise it reverts any changes made to the fork for this failed block
|
|
145
157
|
await forkCheckpoint.revert();
|
|
@@ -167,11 +179,12 @@ export class CheckpointBuilder implements ICheckpointBlockBuilder {
|
|
|
167
179
|
|
|
168
180
|
/**
|
|
169
181
|
* Caps per-block gas and blob field limits by remaining checkpoint-level budgets.
|
|
170
|
-
*
|
|
171
|
-
*
|
|
182
|
+
* When building a proposal (isBuildingProposal=true), computes a fair share of remaining budget
|
|
183
|
+
* across remaining blocks scaled by the multiplier. When validating, only caps by per-block limit
|
|
184
|
+
* and remaining checkpoint budget (no redistribution or multiplier).
|
|
172
185
|
*/
|
|
173
186
|
protected capLimitsByCheckpointBudgets(
|
|
174
|
-
opts:
|
|
187
|
+
opts: BlockBuilderOptions,
|
|
175
188
|
): Pick<PublicProcessorLimits, 'maxBlockGas' | 'maxBlobFields' | 'maxTransactions'> {
|
|
176
189
|
const existingBlocks = this.checkpointBuilder.getBlocks();
|
|
177
190
|
|
|
@@ -192,31 +205,31 @@ export class CheckpointBuilder implements ICheckpointBlockBuilder {
|
|
|
192
205
|
const blockEndOverhead = getNumBlockEndBlobFields(isFirstBlock);
|
|
193
206
|
const maxBlobFieldsForTxs = totalBlobCapacity - usedBlobFields - blockEndOverhead;
|
|
194
207
|
|
|
195
|
-
//
|
|
196
|
-
const
|
|
197
|
-
|
|
198
|
-
|
|
199
|
-
|
|
200
|
-
|
|
201
|
-
|
|
202
|
-
|
|
203
|
-
|
|
204
|
-
|
|
205
|
-
//
|
|
206
|
-
|
|
207
|
-
|
|
208
|
-
const
|
|
209
|
-
|
|
210
|
-
|
|
211
|
-
|
|
212
|
-
|
|
213
|
-
cappedMaxTransactions =
|
|
208
|
+
// Remaining txs
|
|
209
|
+
const usedTxs = sum(existingBlocks.map(b => b.body.txEffects.length));
|
|
210
|
+
const remainingTxs = Math.max(0, (this.config.maxTxsPerCheckpoint ?? Infinity) - usedTxs);
|
|
211
|
+
|
|
212
|
+
// Cap by per-block limit + remaining checkpoint budget
|
|
213
|
+
let cappedL2Gas = Math.min(opts.maxBlockGas?.l2Gas ?? Infinity, remainingMana);
|
|
214
|
+
let cappedDAGas = Math.min(opts.maxBlockGas?.daGas ?? Infinity, remainingDAGas);
|
|
215
|
+
let cappedBlobFields = Math.min(opts.maxBlobFields ?? Infinity, maxBlobFieldsForTxs);
|
|
216
|
+
let cappedMaxTransactions = Math.min(opts.maxTransactions ?? Infinity, remainingTxs);
|
|
217
|
+
|
|
218
|
+
// Proposer mode: further cap by fair share of remaining budget across remaining blocks
|
|
219
|
+
if (opts.isBuildingProposal) {
|
|
220
|
+
const remainingBlocks = Math.max(1, opts.maxBlocksPerCheckpoint - existingBlocks.length);
|
|
221
|
+
const multiplier = opts.perBlockAllocationMultiplier;
|
|
222
|
+
|
|
223
|
+
cappedL2Gas = Math.min(cappedL2Gas, Math.ceil((remainingMana / remainingBlocks) * multiplier));
|
|
224
|
+
cappedDAGas = Math.min(cappedDAGas, Math.ceil((remainingDAGas / remainingBlocks) * multiplier));
|
|
225
|
+
cappedBlobFields = Math.min(cappedBlobFields, Math.ceil((maxBlobFieldsForTxs / remainingBlocks) * multiplier));
|
|
226
|
+
cappedMaxTransactions = Math.min(cappedMaxTransactions, Math.ceil((remainingTxs / remainingBlocks) * multiplier));
|
|
214
227
|
}
|
|
215
228
|
|
|
216
229
|
return {
|
|
217
230
|
maxBlockGas: new Gas(cappedDAGas, cappedL2Gas),
|
|
218
231
|
maxBlobFields: cappedBlobFields,
|
|
219
|
-
maxTransactions: cappedMaxTransactions,
|
|
232
|
+
maxTransactions: Number.isFinite(cappedMaxTransactions) ? cappedMaxTransactions : undefined,
|
|
220
233
|
};
|
|
221
234
|
}
|
|
222
235
|
|
|
@@ -225,7 +238,7 @@ export class CheckpointBuilder implements ICheckpointBlockBuilder {
|
|
|
225
238
|
...(await getDefaultAllowedSetupFunctions()),
|
|
226
239
|
...(this.config.txPublicSetupAllowListExtend ?? []),
|
|
227
240
|
];
|
|
228
|
-
const contractsDB =
|
|
241
|
+
const contractsDB = this.contractsDB;
|
|
229
242
|
const guardedFork = new GuardedMerkleTreeOperations(fork);
|
|
230
243
|
|
|
231
244
|
const collectDebugLogs = this.debugLogStore.isEnabled;
|
package/src/config.ts
CHANGED
|
@@ -6,8 +6,8 @@ import {
|
|
|
6
6
|
secretValueConfigHelper,
|
|
7
7
|
} from '@aztec/foundation/config';
|
|
8
8
|
import { EthAddress } from '@aztec/foundation/eth-address';
|
|
9
|
+
import { localSignerConfigMappings, validatorHASignerConfigMappings } from '@aztec/stdlib/ha-signing';
|
|
9
10
|
import type { ValidatorClientConfig } from '@aztec/stdlib/interfaces/server';
|
|
10
|
-
import { validatorHASignerConfigMappings } from '@aztec/validator-ha-signer/config';
|
|
11
11
|
|
|
12
12
|
export type { ValidatorClientConfig };
|
|
13
13
|
|
|
@@ -97,6 +97,7 @@ export const validatorClientConfigMappings: ConfigMappingsType<ValidatorClientCo
|
|
|
97
97
|
description: 'Maximum transactions per checkpoint for validation. Proposals exceeding this limit are rejected.',
|
|
98
98
|
parseEnv: (val: string) => (val ? parseInt(val, 10) : undefined),
|
|
99
99
|
},
|
|
100
|
+
...localSignerConfigMappings,
|
|
100
101
|
...validatorHASignerConfigMappings,
|
|
101
102
|
};
|
|
102
103
|
|
package/src/factory.ts
CHANGED
|
@@ -7,6 +7,7 @@ import type { L2BlockSink, L2BlockSource } from '@aztec/stdlib/block';
|
|
|
7
7
|
import type { ValidatorClientFullConfig, WorldStateSynchronizer } from '@aztec/stdlib/interfaces/server';
|
|
8
8
|
import type { L1ToL2MessageSource } from '@aztec/stdlib/messaging';
|
|
9
9
|
import type { TelemetryClient } from '@aztec/telemetry-client';
|
|
10
|
+
import type { SlashingProtectionDatabase } from '@aztec/validator-ha-signer/types';
|
|
10
11
|
|
|
11
12
|
import { BlockProposalHandler } from './block_proposal_handler.js';
|
|
12
13
|
import type { FullNodeCheckpointsBuilder } from './checkpoint_builder.js';
|
|
@@ -59,6 +60,7 @@ export function createValidatorClient(
|
|
|
59
60
|
epochCache: EpochCache;
|
|
60
61
|
keyStoreManager: KeystoreManager | undefined;
|
|
61
62
|
blobClient: BlobClientInterface;
|
|
63
|
+
slashingProtectionDb?: SlashingProtectionDatabase;
|
|
62
64
|
},
|
|
63
65
|
) {
|
|
64
66
|
if (config.disableValidator || !deps.keyStoreManager) {
|
|
@@ -79,5 +81,6 @@ export function createValidatorClient(
|
|
|
79
81
|
deps.blobClient,
|
|
80
82
|
deps.dateProvider,
|
|
81
83
|
deps.telemetry,
|
|
84
|
+
deps.slashingProtectionDb,
|
|
82
85
|
);
|
|
83
86
|
}
|
package/src/validator.ts
CHANGED
|
@@ -46,8 +46,12 @@ import type { CheckpointHeader } from '@aztec/stdlib/rollup';
|
|
|
46
46
|
import type { BlockHeader, CheckpointGlobalVariables, Tx } from '@aztec/stdlib/tx';
|
|
47
47
|
import { AttestationTimeoutError } from '@aztec/stdlib/validators';
|
|
48
48
|
import { type TelemetryClient, type Tracer, getTelemetryClient } from '@aztec/telemetry-client';
|
|
49
|
-
import {
|
|
50
|
-
|
|
49
|
+
import {
|
|
50
|
+
createHASigner,
|
|
51
|
+
createLocalSignerWithProtection,
|
|
52
|
+
createSignerFromSharedDb,
|
|
53
|
+
} from '@aztec/validator-ha-signer/factory';
|
|
54
|
+
import { DutyType, type SigningContext, type SlashingProtectionDatabase } from '@aztec/validator-ha-signer/types';
|
|
51
55
|
import type { ValidatorHASigner } from '@aztec/validator-ha-signer/validator-ha-signer';
|
|
52
56
|
|
|
53
57
|
import { EventEmitter } from 'events';
|
|
@@ -109,7 +113,7 @@ export class ValidatorClient extends (EventEmitter as new () => WatcherEmitter)
|
|
|
109
113
|
private l1ToL2MessageSource: L1ToL2MessageSource,
|
|
110
114
|
private config: ValidatorClientFullConfig,
|
|
111
115
|
private blobClient: BlobClientInterface,
|
|
112
|
-
private
|
|
116
|
+
private slashingProtectionSigner: ValidatorHASigner,
|
|
113
117
|
private dateProvider: DateProvider = new DateProvider(),
|
|
114
118
|
telemetry: TelemetryClient = getTelemetryClient(),
|
|
115
119
|
log = createLogger('validator'),
|
|
@@ -197,6 +201,7 @@ export class ValidatorClient extends (EventEmitter as new () => WatcherEmitter)
|
|
|
197
201
|
blobClient: BlobClientInterface,
|
|
198
202
|
dateProvider: DateProvider = new DateProvider(),
|
|
199
203
|
telemetry: TelemetryClient = getTelemetryClient(),
|
|
204
|
+
slashingProtectionDb?: SlashingProtectionDatabase,
|
|
200
205
|
) {
|
|
201
206
|
const metrics = new ValidatorMetrics(telemetry);
|
|
202
207
|
const blockProposalValidator = new BlockProposalValidator(epochCache, {
|
|
@@ -218,18 +223,33 @@ export class ValidatorClient extends (EventEmitter as new () => WatcherEmitter)
|
|
|
218
223
|
);
|
|
219
224
|
|
|
220
225
|
const nodeKeystoreAdapter = NodeKeystoreAdapter.fromKeyStoreManager(keyStoreManager);
|
|
221
|
-
let
|
|
222
|
-
|
|
223
|
-
|
|
226
|
+
let slashingProtectionSigner: ValidatorHASigner;
|
|
227
|
+
if (slashingProtectionDb) {
|
|
228
|
+
// Shared database mode: use a pre-existing database (e.g. for testing HA setups).
|
|
229
|
+
({ signer: slashingProtectionSigner } = createSignerFromSharedDb(slashingProtectionDb, config, {
|
|
230
|
+
telemetryClient: telemetry,
|
|
231
|
+
dateProvider,
|
|
232
|
+
}));
|
|
233
|
+
} else if (config.haSigningEnabled) {
|
|
234
|
+
// Multi-node HA mode: use PostgreSQL-backed distributed locking.
|
|
224
235
|
// If maxStuckDutiesAgeMs is not explicitly set, compute it from Aztec slot duration
|
|
225
236
|
const haConfig = {
|
|
226
237
|
...config,
|
|
227
238
|
maxStuckDutiesAgeMs: config.maxStuckDutiesAgeMs ?? epochCache.getL1Constants().slotDuration * 2 * 1000,
|
|
228
239
|
};
|
|
229
|
-
|
|
230
|
-
|
|
231
|
-
|
|
240
|
+
({ signer: slashingProtectionSigner } = await createHASigner(haConfig, {
|
|
241
|
+
telemetryClient: telemetry,
|
|
242
|
+
dateProvider,
|
|
243
|
+
}));
|
|
244
|
+
} else {
|
|
245
|
+
// Single-node mode: use LMDB-backed local signing protection.
|
|
246
|
+
// This prevents double-signing if the node crashes and restarts mid-proposal.
|
|
247
|
+
({ signer: slashingProtectionSigner } = await createLocalSignerWithProtection(config, {
|
|
248
|
+
telemetryClient: telemetry,
|
|
249
|
+
dateProvider,
|
|
250
|
+
}));
|
|
232
251
|
}
|
|
252
|
+
const validatorKeyStore: ExtendedValidatorKeyStore = new HAKeyStore(nodeKeystoreAdapter, slashingProtectionSigner);
|
|
233
253
|
|
|
234
254
|
const validator = new ValidatorClient(
|
|
235
255
|
validatorKeyStore,
|
|
@@ -242,7 +262,7 @@ export class ValidatorClient extends (EventEmitter as new () => WatcherEmitter)
|
|
|
242
262
|
l1ToL2MessageSource,
|
|
243
263
|
config,
|
|
244
264
|
blobClient,
|
|
245
|
-
|
|
265
|
+
slashingProtectionSigner,
|
|
246
266
|
dateProvider,
|
|
247
267
|
telemetry,
|
|
248
268
|
);
|
|
@@ -281,24 +301,8 @@ export class ValidatorClient extends (EventEmitter as new () => WatcherEmitter)
|
|
|
281
301
|
}
|
|
282
302
|
|
|
283
303
|
public reloadKeystore(newManager: KeystoreManager): void {
|
|
284
|
-
if (this.config.haSigningEnabled && !this.haSigner) {
|
|
285
|
-
this.log.warn(
|
|
286
|
-
'HA signing is enabled in config but was not initialized at startup. ' +
|
|
287
|
-
'Restart the node to enable HA signing.',
|
|
288
|
-
);
|
|
289
|
-
} else if (!this.config.haSigningEnabled && this.haSigner) {
|
|
290
|
-
this.log.warn(
|
|
291
|
-
'HA signing was disabled via config update but the HA signer is still active. ' +
|
|
292
|
-
'Restart the node to fully disable HA signing.',
|
|
293
|
-
);
|
|
294
|
-
}
|
|
295
|
-
|
|
296
304
|
const newAdapter = NodeKeystoreAdapter.fromKeyStoreManager(newManager);
|
|
297
|
-
|
|
298
|
-
this.keyStore = new HAKeyStore(newAdapter, this.haSigner);
|
|
299
|
-
} else {
|
|
300
|
-
this.keyStore = newAdapter;
|
|
301
|
-
}
|
|
305
|
+
this.keyStore = new HAKeyStore(newAdapter, this.slashingProtectionSigner);
|
|
302
306
|
this.validationService = new ValidationService(this.keyStore, this.log.createChild('validation-service'));
|
|
303
307
|
}
|
|
304
308
|
|
|
@@ -385,13 +389,12 @@ export class ValidatorClient extends (EventEmitter as new () => WatcherEmitter)
|
|
|
385
389
|
return false;
|
|
386
390
|
}
|
|
387
391
|
|
|
388
|
-
//
|
|
392
|
+
// Log self-proposals from HA peers (same validator key on different nodes)
|
|
389
393
|
if (this.getValidatorAddresses().some(addr => addr.equals(proposer))) {
|
|
390
|
-
this.log.
|
|
394
|
+
this.log.verbose(`Processing block proposal from HA peer for slot ${slotNumber}`, {
|
|
391
395
|
proposer: proposer.toString(),
|
|
392
396
|
slotNumber,
|
|
393
397
|
});
|
|
394
|
-
return false;
|
|
395
398
|
}
|
|
396
399
|
|
|
397
400
|
// Check if we're in the committee (for metrics purposes)
|
|
@@ -481,26 +484,26 @@ export class ValidatorClient extends (EventEmitter as new () => WatcherEmitter)
|
|
|
481
484
|
proposal: CheckpointProposalCore,
|
|
482
485
|
_proposalSender: PeerId,
|
|
483
486
|
): Promise<CheckpointAttestation[] | undefined> {
|
|
484
|
-
const
|
|
487
|
+
const proposalSlotNumber = proposal.slotNumber;
|
|
485
488
|
const proposer = proposal.getSender();
|
|
486
489
|
|
|
487
490
|
// If escape hatch is open for this slot's epoch, do not attest.
|
|
488
|
-
if (await this.epochCache.isEscapeHatchOpenAtSlot(
|
|
489
|
-
this.log.warn(`Escape hatch open for slot ${
|
|
491
|
+
if (await this.epochCache.isEscapeHatchOpenAtSlot(proposalSlotNumber)) {
|
|
492
|
+
this.log.warn(`Escape hatch open for slot ${proposalSlotNumber}, skipping checkpoint attestation handling`);
|
|
490
493
|
return undefined;
|
|
491
494
|
}
|
|
492
495
|
|
|
493
496
|
// Reject proposals with invalid signatures
|
|
494
497
|
if (!proposer) {
|
|
495
|
-
this.log.warn(`Received checkpoint proposal with invalid signature for slot ${
|
|
498
|
+
this.log.warn(`Received checkpoint proposal with invalid signature for proposal slot ${proposalSlotNumber}`);
|
|
496
499
|
return undefined;
|
|
497
500
|
}
|
|
498
501
|
|
|
499
502
|
// Ignore proposals from ourselves (may happen in HA setups)
|
|
500
503
|
if (this.getValidatorAddresses().some(addr => addr.equals(proposer))) {
|
|
501
|
-
this.log.debug(`Ignoring block proposal from self for slot ${
|
|
504
|
+
this.log.debug(`Ignoring block proposal from self for slot ${proposalSlotNumber}`, {
|
|
502
505
|
proposer: proposer.toString(),
|
|
503
|
-
|
|
506
|
+
proposalSlotNumber,
|
|
504
507
|
});
|
|
505
508
|
return undefined;
|
|
506
509
|
}
|
|
@@ -508,28 +511,28 @@ export class ValidatorClient extends (EventEmitter as new () => WatcherEmitter)
|
|
|
508
511
|
// Validate fee asset price modifier is within allowed range
|
|
509
512
|
if (!validateFeeAssetPriceModifier(proposal.feeAssetPriceModifier)) {
|
|
510
513
|
this.log.warn(
|
|
511
|
-
`Received checkpoint proposal with invalid feeAssetPriceModifier ${proposal.feeAssetPriceModifier} for slot ${
|
|
514
|
+
`Received checkpoint proposal with invalid feeAssetPriceModifier ${proposal.feeAssetPriceModifier} for slot ${proposalSlotNumber}`,
|
|
512
515
|
);
|
|
513
516
|
return undefined;
|
|
514
517
|
}
|
|
515
518
|
|
|
516
|
-
// Check that I have any address in
|
|
517
|
-
const inCommittee = await this.epochCache.filterInCommittee(
|
|
519
|
+
// Check that I have any address in the committee where this checkpoint will land before attesting
|
|
520
|
+
const inCommittee = await this.epochCache.filterInCommittee(proposalSlotNumber, this.getValidatorAddresses());
|
|
518
521
|
const partOfCommittee = inCommittee.length > 0;
|
|
519
522
|
|
|
520
523
|
const proposalInfo = {
|
|
521
|
-
|
|
524
|
+
proposalSlotNumber,
|
|
522
525
|
archive: proposal.archive.toString(),
|
|
523
526
|
proposer: proposer.toString(),
|
|
524
527
|
};
|
|
525
|
-
this.log.info(`Received checkpoint proposal for slot ${
|
|
528
|
+
this.log.info(`Received checkpoint proposal for slot ${proposalSlotNumber}`, {
|
|
526
529
|
...proposalInfo,
|
|
527
530
|
fishermanMode: this.config.fishermanMode || false,
|
|
528
531
|
});
|
|
529
532
|
|
|
530
533
|
// Validate the checkpoint proposal before attesting (unless skipCheckpointProposalValidation is set)
|
|
531
534
|
if (this.config.skipCheckpointProposalValidation) {
|
|
532
|
-
this.log.warn(`Skipping checkpoint proposal validation for slot ${
|
|
535
|
+
this.log.warn(`Skipping checkpoint proposal validation for slot ${proposalSlotNumber}`, proposalInfo);
|
|
533
536
|
} else {
|
|
534
537
|
const validationResult = await this.validateCheckpointProposal(proposal, proposalInfo);
|
|
535
538
|
if (!validationResult.isValid) {
|
|
@@ -551,16 +554,19 @@ export class ValidatorClient extends (EventEmitter as new () => WatcherEmitter)
|
|
|
551
554
|
}
|
|
552
555
|
|
|
553
556
|
// Provided all of the above checks pass, we can attest to the proposal
|
|
554
|
-
this.log.info(
|
|
555
|
-
|
|
556
|
-
|
|
557
|
-
|
|
558
|
-
|
|
557
|
+
this.log.info(
|
|
558
|
+
`${partOfCommittee ? 'Attesting to' : 'Validated'} checkpoint proposal for slot ${proposalSlotNumber}`,
|
|
559
|
+
{
|
|
560
|
+
...proposalInfo,
|
|
561
|
+
inCommittee: partOfCommittee,
|
|
562
|
+
fishermanMode: this.config.fishermanMode || false,
|
|
563
|
+
},
|
|
564
|
+
);
|
|
559
565
|
|
|
560
566
|
this.metrics.incSuccessfulAttestations(inCommittee.length);
|
|
561
567
|
|
|
562
568
|
// Track epoch participation per attester: count each (attester, epoch) pair at most once
|
|
563
|
-
const proposalEpoch = getEpochAtSlot(
|
|
569
|
+
const proposalEpoch = getEpochAtSlot(proposalSlotNumber, this.epochCache.getL1Constants());
|
|
564
570
|
for (const attester of inCommittee) {
|
|
565
571
|
const key = attester.toString();
|
|
566
572
|
const lastEpoch = this.lastAttestedEpochByAttester.get(key);
|
|
@@ -588,7 +594,7 @@ export class ValidatorClient extends (EventEmitter as new () => WatcherEmitter)
|
|
|
588
594
|
|
|
589
595
|
if (this.config.fishermanMode) {
|
|
590
596
|
// bail out early and don't save attestations to the pool in fisherman mode
|
|
591
|
-
this.log.info(`Creating checkpoint attestations for slot ${
|
|
597
|
+
this.log.info(`Creating checkpoint attestations for slot ${proposalSlotNumber}`, {
|
|
592
598
|
...proposalInfo,
|
|
593
599
|
attestors: attestors.map(a => a.toString()),
|
|
594
600
|
});
|