@aztec/validator-client 0.0.1-commit.2ed92850 → 0.0.1-commit.54489865
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/dest/block_proposal_handler.d.ts +3 -4
- package/dest/block_proposal_handler.d.ts.map +1 -1
- package/dest/block_proposal_handler.js +5 -4
- package/dest/checkpoint_builder.d.ts +8 -5
- package/dest/checkpoint_builder.d.ts.map +1 -1
- package/dest/checkpoint_builder.js +26 -19
- package/dest/config.d.ts +1 -1
- package/dest/config.d.ts.map +1 -1
- package/dest/config.js +2 -3
- package/dest/metrics.d.ts +4 -3
- package/dest/metrics.d.ts.map +1 -1
- package/dest/metrics.js +34 -5
- package/dest/tx_validator/tx_validator_factory.d.ts +4 -3
- package/dest/tx_validator/tx_validator_factory.d.ts.map +1 -1
- package/dest/tx_validator/tx_validator_factory.js +16 -16
- package/dest/validator.d.ts +7 -8
- package/dest/validator.d.ts.map +1 -1
- package/dest/validator.js +21 -27
- package/package.json +19 -17
- package/src/block_proposal_handler.ts +7 -6
- package/src/checkpoint_builder.ts +40 -14
- package/src/config.ts +2 -3
- package/src/metrics.ts +45 -6
- package/src/tx_validator/tx_validator_factory.ts +51 -32
- package/src/validator.ts +20 -31
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;AACrD,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,EAAgB,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,EAAE,GAAG,EAAE,MAAM,EAAE,
|
|
1
|
+
{"version":3,"file":"validator.d.ts","sourceRoot":"","sources":["../src/validator.ts"],"names":[],"mappings":"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"}
|
package/dest/validator.js
CHANGED
|
@@ -9,6 +9,7 @@ import { DateProvider } from '@aztec/foundation/timer';
|
|
|
9
9
|
import { AuthRequest, AuthResponse, BlockProposalValidator, ReqRespSubProtocol } from '@aztec/p2p';
|
|
10
10
|
import { OffenseType, WANT_TO_SLASH_EVENT } from '@aztec/slasher';
|
|
11
11
|
import { getEpochAtSlot } from '@aztec/stdlib/epoch-helpers';
|
|
12
|
+
import { accumulateCheckpointOutHashes } from '@aztec/stdlib/messaging';
|
|
12
13
|
import { AttestationTimeoutError } from '@aztec/stdlib/validators';
|
|
13
14
|
import { getTelemetryClient } from '@aztec/telemetry-client';
|
|
14
15
|
import { createHASigner } from '@aztec/validator-ha-signer/factory';
|
|
@@ -52,12 +53,8 @@ const SLASHABLE_BLOCK_PROPOSAL_VALIDATION_RESULT = [
|
|
|
52
53
|
lastEpochForCommitteeUpdateLoop;
|
|
53
54
|
epochCacheUpdateLoop;
|
|
54
55
|
proposersOfInvalidBlocks;
|
|
55
|
-
// TODO(palla/mbps): Remove this once checkpoint validation is stable and we can validate all blocks properly.
|
|
56
|
-
// Tracks slots for which we have successfully validated a block proposal, so we can attest to checkpoint proposals for those slots.
|
|
57
|
-
// eslint-disable-next-line aztec-custom/no-non-primitive-in-collections
|
|
58
|
-
validatedBlockSlots;
|
|
59
56
|
constructor(keyStore, epochCache, p2pClient, blockProposalHandler, blockSource, checkpointsBuilder, worldState, l1ToL2MessageSource, config, blobClient, dateProvider = new DateProvider(), telemetry = getTelemetryClient(), log = createLogger('validator')){
|
|
60
|
-
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.dateProvider = dateProvider, this.hasRegisteredHandlers = false, this.proposersOfInvalidBlocks = new Set()
|
|
57
|
+
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.dateProvider = dateProvider, this.hasRegisteredHandlers = false, this.proposersOfInvalidBlocks = new Set();
|
|
61
58
|
// Create child logger with fisherman prefix if in fisherman mode
|
|
62
59
|
this.log = config.fishermanMode ? log.createChild('[FISHERMAN]') : log;
|
|
63
60
|
this.tracer = telemetry.getTracer('Validator');
|
|
@@ -257,9 +254,6 @@ const SLASHABLE_BLOCK_PROPOSAL_VALIDATION_RESULT = [
|
|
|
257
254
|
this.log.warn(`Escape hatch open for slot ${slotNumber}, rejecting block proposal`, proposalInfo);
|
|
258
255
|
return false;
|
|
259
256
|
}
|
|
260
|
-
// TODO(palla/mbps): Remove this once checkpoint validation is stable.
|
|
261
|
-
// Track that we successfully validated a block for this slot, so we can attest to checkpoint proposals for it.
|
|
262
|
-
this.validatedBlockSlots.add(slotNumber);
|
|
263
257
|
return true;
|
|
264
258
|
}
|
|
265
259
|
/**
|
|
@@ -294,16 +288,9 @@ const SLASHABLE_BLOCK_PROPOSAL_VALIDATION_RESULT = [
|
|
|
294
288
|
txHashes: proposal.txHashes.map((t)=>t.toString()),
|
|
295
289
|
fishermanMode: this.config.fishermanMode || false
|
|
296
290
|
});
|
|
297
|
-
// TODO(palla/mbps): Remove this once checkpoint validation is stable.
|
|
298
|
-
// Check that we have successfully validated a block for this slot before attesting to the checkpoint.
|
|
299
|
-
if (!this.validatedBlockSlots.has(slotNumber)) {
|
|
300
|
-
this.log.warn(`No validated block found for slot ${slotNumber}, refusing to attest to checkpoint`, proposalInfo);
|
|
301
|
-
return undefined;
|
|
302
|
-
}
|
|
303
291
|
// Validate the checkpoint proposal before attesting (unless skipCheckpointProposalValidation is set)
|
|
304
|
-
|
|
305
|
-
|
|
306
|
-
this.log.verbose(`Skipping checkpoint proposal validation for slot ${slotNumber}`, proposalInfo);
|
|
292
|
+
if (this.config.skipCheckpointProposalValidation) {
|
|
293
|
+
this.log.warn(`Skipping checkpoint proposal validation for slot ${slotNumber}`, proposalInfo);
|
|
307
294
|
} else {
|
|
308
295
|
const validationResult = await this.validateCheckpointProposal(proposal, proposalInfo);
|
|
309
296
|
if (!validationResult.isValid) {
|
|
@@ -362,7 +349,7 @@ const SLASHABLE_BLOCK_PROPOSAL_VALIDATION_RESULT = [
|
|
|
362
349
|
* @returns Validation result with isValid flag and reason if invalid.
|
|
363
350
|
*/ async validateCheckpointProposal(proposal, proposalInfo) {
|
|
364
351
|
const slot = proposal.slotNumber;
|
|
365
|
-
const timeoutSeconds = 10;
|
|
352
|
+
const timeoutSeconds = 10; // TODO(palla/mbps): This should map to the timetable settings
|
|
366
353
|
// Wait for last block to sync by archive
|
|
367
354
|
let lastBlockHeader;
|
|
368
355
|
try {
|
|
@@ -421,7 +408,7 @@ const SLASHABLE_BLOCK_PROPOSAL_VALIDATION_RESULT = [
|
|
|
421
408
|
const fork = await this.worldState.fork(parentBlockNumber);
|
|
422
409
|
try {
|
|
423
410
|
// Create checkpoint builder with all existing blocks
|
|
424
|
-
const checkpointBuilder = await this.checkpointsBuilder.openCheckpoint(checkpointNumber, constants, l1ToL2Messages, previousCheckpointOutHashes, fork, blocks);
|
|
411
|
+
const checkpointBuilder = await this.checkpointsBuilder.openCheckpoint(checkpointNumber, constants, l1ToL2Messages, previousCheckpointOutHashes, fork, blocks, this.log.getBindings());
|
|
425
412
|
// Complete the checkpoint to get computed values
|
|
426
413
|
const computedCheckpoint = await checkpointBuilder.completeCheckpoint();
|
|
427
414
|
// Compare checkpoint header with proposal
|
|
@@ -448,13 +435,20 @@ const SLASHABLE_BLOCK_PROPOSAL_VALIDATION_RESULT = [
|
|
|
448
435
|
reason: 'archive_mismatch'
|
|
449
436
|
};
|
|
450
437
|
}
|
|
451
|
-
// Check that the accumulated out hash matches the value in the proposal.
|
|
452
|
-
|
|
453
|
-
const
|
|
454
|
-
|
|
438
|
+
// Check that the accumulated epoch out hash matches the value in the proposal.
|
|
439
|
+
// The epoch out hash is the accumulated hash of all checkpoint out hashes in the epoch.
|
|
440
|
+
const checkpointOutHash = computedCheckpoint.getCheckpointOutHash();
|
|
441
|
+
const computedEpochOutHash = accumulateCheckpointOutHashes([
|
|
442
|
+
...previousCheckpointOutHashes,
|
|
443
|
+
checkpointOutHash
|
|
444
|
+
]);
|
|
445
|
+
const proposalEpochOutHash = proposal.checkpointHeader.epochOutHash;
|
|
446
|
+
if (!computedEpochOutHash.equals(proposalEpochOutHash)) {
|
|
455
447
|
this.log.warn(`Epoch out hash mismatch`, {
|
|
456
|
-
|
|
457
|
-
|
|
448
|
+
proposalEpochOutHash: proposalEpochOutHash.toString(),
|
|
449
|
+
computedEpochOutHash: computedEpochOutHash.toString(),
|
|
450
|
+
checkpointOutHash: checkpointOutHash.toString(),
|
|
451
|
+
previousCheckpointOutHashes: previousCheckpointOutHashes.map((h)=>h.toString()),
|
|
458
452
|
...proposalInfo
|
|
459
453
|
});
|
|
460
454
|
return {
|
|
@@ -530,7 +524,7 @@ const SLASHABLE_BLOCK_PROPOSAL_VALIDATION_RESULT = [
|
|
|
530
524
|
}
|
|
531
525
|
]);
|
|
532
526
|
}
|
|
533
|
-
async createBlockProposal(blockHeader, indexWithinCheckpoint, inHash, archive, txs, proposerAddress, options) {
|
|
527
|
+
async createBlockProposal(blockHeader, indexWithinCheckpoint, inHash, archive, txs, proposerAddress, options = {}) {
|
|
534
528
|
// TODO(palla/mbps): Prevent double proposals properly
|
|
535
529
|
// if (this.previousProposal?.slotNumber === blockHeader.globalVariables.slotNumber) {
|
|
536
530
|
// this.log.verbose(`Already made a proposal for the same slot, skipping proposal`);
|
|
@@ -544,7 +538,7 @@ const SLASHABLE_BLOCK_PROPOSAL_VALIDATION_RESULT = [
|
|
|
544
538
|
this.previousProposal = newProposal;
|
|
545
539
|
return newProposal;
|
|
546
540
|
}
|
|
547
|
-
async createCheckpointProposal(checkpointHeader, archive, lastBlockInfo, proposerAddress, options) {
|
|
541
|
+
async createCheckpointProposal(checkpointHeader, archive, lastBlockInfo, proposerAddress, options = {}) {
|
|
548
542
|
this.log.info(`Assembling checkpoint proposal for slot ${checkpointHeader.slotNumber}`);
|
|
549
543
|
return await this.validationService.createCheckpointProposal(checkpointHeader, archive, lastBlockInfo, proposerAddress, options);
|
|
550
544
|
}
|
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.54489865",
|
|
4
4
|
"main": "dest/index.js",
|
|
5
5
|
"type": "module",
|
|
6
6
|
"exports": {
|
|
@@ -64,28 +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.54489865",
|
|
68
|
+
"@aztec/blob-lib": "0.0.1-commit.54489865",
|
|
69
|
+
"@aztec/constants": "0.0.1-commit.54489865",
|
|
70
|
+
"@aztec/epoch-cache": "0.0.1-commit.54489865",
|
|
71
|
+
"@aztec/ethereum": "0.0.1-commit.54489865",
|
|
72
|
+
"@aztec/foundation": "0.0.1-commit.54489865",
|
|
73
|
+
"@aztec/node-keystore": "0.0.1-commit.54489865",
|
|
74
|
+
"@aztec/noir-protocol-circuits-types": "0.0.1-commit.54489865",
|
|
75
|
+
"@aztec/p2p": "0.0.1-commit.54489865",
|
|
76
|
+
"@aztec/protocol-contracts": "0.0.1-commit.54489865",
|
|
77
|
+
"@aztec/prover-client": "0.0.1-commit.54489865",
|
|
78
|
+
"@aztec/simulator": "0.0.1-commit.54489865",
|
|
79
|
+
"@aztec/slasher": "0.0.1-commit.54489865",
|
|
80
|
+
"@aztec/stdlib": "0.0.1-commit.54489865",
|
|
81
|
+
"@aztec/telemetry-client": "0.0.1-commit.54489865",
|
|
82
|
+
"@aztec/validator-ha-signer": "0.0.1-commit.54489865",
|
|
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.54489865",
|
|
90
|
+
"@aztec/world-state": "0.0.1-commit.54489865",
|
|
89
91
|
"@electric-sql/pglite": "^0.3.14",
|
|
90
92
|
"@jest/globals": "^30.0.0",
|
|
91
93
|
"@types/jest": "^30.0.0",
|
|
@@ -8,11 +8,10 @@ import { createLogger } from '@aztec/foundation/log';
|
|
|
8
8
|
import { retryUntil } from '@aztec/foundation/retry';
|
|
9
9
|
import { DateProvider, Timer } from '@aztec/foundation/timer';
|
|
10
10
|
import type { P2P, PeerId } from '@aztec/p2p';
|
|
11
|
-
import { TxProvider } from '@aztec/p2p';
|
|
12
11
|
import { BlockProposalValidator } from '@aztec/p2p/msg_validators';
|
|
13
12
|
import type { L2Block, L2BlockSink, L2BlockSource } from '@aztec/stdlib/block';
|
|
14
13
|
import { getEpochAtSlot, getTimestampForSlot } from '@aztec/stdlib/epoch-helpers';
|
|
15
|
-
import type { ValidatorClientFullConfig, WorldStateSynchronizer } from '@aztec/stdlib/interfaces/server';
|
|
14
|
+
import type { ITxProvider, ValidatorClientFullConfig, WorldStateSynchronizer } from '@aztec/stdlib/interfaces/server';
|
|
16
15
|
import {
|
|
17
16
|
type L1ToL2MessageSource,
|
|
18
17
|
computeCheckpointOutHash,
|
|
@@ -78,7 +77,7 @@ export class BlockProposalHandler {
|
|
|
78
77
|
private worldState: WorldStateSynchronizer,
|
|
79
78
|
private blockSource: L2BlockSource & L2BlockSink,
|
|
80
79
|
private l1ToL2MessageSource: L1ToL2MessageSource,
|
|
81
|
-
private txProvider:
|
|
80
|
+
private txProvider: ITxProvider,
|
|
82
81
|
private blockProposalValidator: BlockProposalValidator,
|
|
83
82
|
private epochCache: EpochCache,
|
|
84
83
|
private config: ValidatorClientFullConfig,
|
|
@@ -160,9 +159,9 @@ export class BlockProposalHandler {
|
|
|
160
159
|
return { isValid: false, reason: 'parent_block_not_found' };
|
|
161
160
|
}
|
|
162
161
|
|
|
163
|
-
// Check that the parent block's slot is
|
|
164
|
-
if (parentBlockHeader !== 'genesis' && parentBlockHeader.getSlot()
|
|
165
|
-
this.log.warn(`Parent block slot is greater than
|
|
162
|
+
// Check that the parent block's slot is not greater than the proposal's slot.
|
|
163
|
+
if (parentBlockHeader !== 'genesis' && parentBlockHeader.getSlot() > slotNumber) {
|
|
164
|
+
this.log.warn(`Parent block slot is greater than proposal slot, skipping processing`, {
|
|
166
165
|
parentBlockSlot: parentBlockHeader.getSlot().toString(),
|
|
167
166
|
proposalSlot: slotNumber.toString(),
|
|
168
167
|
...proposalInfo,
|
|
@@ -475,6 +474,7 @@ export class BlockProposalHandler {
|
|
|
475
474
|
|
|
476
475
|
// Fork before the block to be built
|
|
477
476
|
const parentBlockNumber = BlockNumber(blockNumber - 1);
|
|
477
|
+
await this.worldState.syncImmediate(parentBlockNumber);
|
|
478
478
|
using fork = await this.worldState.fork(parentBlockNumber);
|
|
479
479
|
|
|
480
480
|
// Build checkpoint constants from proposal (excludes blockNumber and timestamp which are per-block)
|
|
@@ -495,6 +495,7 @@ export class BlockProposalHandler {
|
|
|
495
495
|
previousCheckpointOutHashes,
|
|
496
496
|
fork,
|
|
497
497
|
priorBlocks,
|
|
498
|
+
this.log.getBindings(),
|
|
498
499
|
);
|
|
499
500
|
|
|
500
501
|
// Build the new block
|
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
import { BlockNumber, CheckpointNumber } from '@aztec/foundation/branded-types';
|
|
2
2
|
import { merge, pick } from '@aztec/foundation/collection';
|
|
3
3
|
import { Fr } from '@aztec/foundation/curves/bn254';
|
|
4
|
-
import { createLogger } from '@aztec/foundation/log';
|
|
4
|
+
import { type Logger, type LoggerBindings, createLogger } from '@aztec/foundation/log';
|
|
5
5
|
import { bufferToHex } from '@aztec/foundation/string';
|
|
6
6
|
import { DateProvider, Timer, elapsed } from '@aztec/foundation/timer';
|
|
7
7
|
import { getDefaultAllowedSetupFunctions } from '@aztec/p2p/msg_validators';
|
|
@@ -36,8 +36,6 @@ import { createValidatorForBlockBuilding } from './tx_validator/tx_validator_fac
|
|
|
36
36
|
// Re-export for backward compatibility
|
|
37
37
|
export type { BuildBlockInCheckpointResult } from '@aztec/stdlib/interfaces/server';
|
|
38
38
|
|
|
39
|
-
const log = createLogger('checkpoint-builder');
|
|
40
|
-
|
|
41
39
|
/** Result of building a block within a checkpoint. Extends the base interface with timer. */
|
|
42
40
|
export interface BuildBlockInCheckpointResultWithTimer extends BuildBlockInCheckpointResult {
|
|
43
41
|
blockBuildingTimer: Timer;
|
|
@@ -48,6 +46,8 @@ export interface BuildBlockInCheckpointResultWithTimer extends BuildBlockInCheck
|
|
|
48
46
|
* and completing it.
|
|
49
47
|
*/
|
|
50
48
|
export class CheckpointBuilder implements ICheckpointBlockBuilder {
|
|
49
|
+
private log: Logger;
|
|
50
|
+
|
|
51
51
|
constructor(
|
|
52
52
|
private checkpointBuilder: LightweightCheckpointBuilder,
|
|
53
53
|
private fork: MerkleTreeWriteOperations,
|
|
@@ -55,7 +55,13 @@ export class CheckpointBuilder implements ICheckpointBlockBuilder {
|
|
|
55
55
|
private contractDataSource: ContractDataSource,
|
|
56
56
|
private dateProvider: DateProvider,
|
|
57
57
|
private telemetryClient: TelemetryClient,
|
|
58
|
-
|
|
58
|
+
bindings?: LoggerBindings,
|
|
59
|
+
) {
|
|
60
|
+
this.log = createLogger('checkpoint-builder', {
|
|
61
|
+
...bindings,
|
|
62
|
+
instanceId: `checkpoint-${checkpointBuilder.checkpointNumber}`,
|
|
63
|
+
});
|
|
64
|
+
}
|
|
59
65
|
|
|
60
66
|
getConstantData(): CheckpointGlobalVariables {
|
|
61
67
|
return this.checkpointBuilder.constants;
|
|
@@ -68,12 +74,12 @@ export class CheckpointBuilder implements ICheckpointBlockBuilder {
|
|
|
68
74
|
pendingTxs: Iterable<Tx> | AsyncIterable<Tx>,
|
|
69
75
|
blockNumber: BlockNumber,
|
|
70
76
|
timestamp: bigint,
|
|
71
|
-
opts: PublicProcessorLimits & { expectedEndState?: StateReference },
|
|
77
|
+
opts: PublicProcessorLimits & { expectedEndState?: StateReference } = {},
|
|
72
78
|
): Promise<BuildBlockInCheckpointResultWithTimer> {
|
|
73
79
|
const blockBuildingTimer = new Timer();
|
|
74
80
|
const slot = this.checkpointBuilder.constants.slotNumber;
|
|
75
81
|
|
|
76
|
-
log.verbose(`Building block ${blockNumber} for slot ${slot} within checkpoint`, {
|
|
82
|
+
this.log.verbose(`Building block ${blockNumber} for slot ${slot} within checkpoint`, {
|
|
77
83
|
slot,
|
|
78
84
|
blockNumber,
|
|
79
85
|
...opts,
|
|
@@ -115,7 +121,7 @@ export class CheckpointBuilder implements ICheckpointBlockBuilder {
|
|
|
115
121
|
usedTxs,
|
|
116
122
|
usedTxBlobFields,
|
|
117
123
|
};
|
|
118
|
-
log.debug('Built block within checkpoint', res.block.header);
|
|
124
|
+
this.log.debug('Built block within checkpoint', res.block.header);
|
|
119
125
|
return res;
|
|
120
126
|
}
|
|
121
127
|
|
|
@@ -123,7 +129,7 @@ export class CheckpointBuilder implements ICheckpointBlockBuilder {
|
|
|
123
129
|
async completeCheckpoint(): Promise<Checkpoint> {
|
|
124
130
|
const checkpoint = await this.checkpointBuilder.completeCheckpoint();
|
|
125
131
|
|
|
126
|
-
log.verbose(`Completed checkpoint ${checkpoint.number}`, {
|
|
132
|
+
this.log.verbose(`Completed checkpoint ${checkpoint.number}`, {
|
|
127
133
|
checkpointNumber: checkpoint.number,
|
|
128
134
|
numBlocks: checkpoint.blocks.length,
|
|
129
135
|
archiveRoot: checkpoint.archive.root.toString(),
|
|
@@ -139,14 +145,16 @@ export class CheckpointBuilder implements ICheckpointBlockBuilder {
|
|
|
139
145
|
|
|
140
146
|
protected async makeBlockBuilderDeps(globalVariables: GlobalVariables, fork: MerkleTreeWriteOperations) {
|
|
141
147
|
const txPublicSetupAllowList = this.config.txPublicSetupAllowList ?? (await getDefaultAllowedSetupFunctions());
|
|
142
|
-
const contractsDB = new PublicContractsDB(this.contractDataSource);
|
|
148
|
+
const contractsDB = new PublicContractsDB(this.contractDataSource, this.log.getBindings());
|
|
143
149
|
const guardedFork = new GuardedMerkleTreeOperations(fork);
|
|
144
150
|
|
|
151
|
+
const bindings = this.log.getBindings();
|
|
145
152
|
const publicTxSimulator = createPublicTxSimulatorForBlockBuilding(
|
|
146
153
|
guardedFork,
|
|
147
154
|
contractsDB,
|
|
148
155
|
globalVariables,
|
|
149
156
|
this.telemetryClient,
|
|
157
|
+
bindings,
|
|
150
158
|
);
|
|
151
159
|
|
|
152
160
|
const processor = new PublicProcessor(
|
|
@@ -156,7 +164,7 @@ export class CheckpointBuilder implements ICheckpointBlockBuilder {
|
|
|
156
164
|
publicTxSimulator,
|
|
157
165
|
this.dateProvider,
|
|
158
166
|
this.telemetryClient,
|
|
159
|
-
|
|
167
|
+
createLogger('simulator:public-processor', bindings),
|
|
160
168
|
this.config,
|
|
161
169
|
);
|
|
162
170
|
|
|
@@ -165,6 +173,7 @@ export class CheckpointBuilder implements ICheckpointBlockBuilder {
|
|
|
165
173
|
this.contractDataSource,
|
|
166
174
|
globalVariables,
|
|
167
175
|
txPublicSetupAllowList,
|
|
176
|
+
this.log.getBindings(),
|
|
168
177
|
);
|
|
169
178
|
|
|
170
179
|
return {
|
|
@@ -176,13 +185,17 @@ export class CheckpointBuilder implements ICheckpointBlockBuilder {
|
|
|
176
185
|
|
|
177
186
|
/** Factory for creating checkpoint builders. */
|
|
178
187
|
export class FullNodeCheckpointsBuilder implements ICheckpointsBuilder {
|
|
188
|
+
private log: Logger;
|
|
189
|
+
|
|
179
190
|
constructor(
|
|
180
191
|
private config: FullNodeBlockBuilderConfig & Pick<L1RollupConstants, 'l1GenesisTime' | 'slotDuration'>,
|
|
181
192
|
private worldState: WorldStateSynchronizer,
|
|
182
193
|
private contractDataSource: ContractDataSource,
|
|
183
194
|
private dateProvider: DateProvider,
|
|
184
195
|
private telemetryClient: TelemetryClient = getTelemetryClient(),
|
|
185
|
-
) {
|
|
196
|
+
) {
|
|
197
|
+
this.log = createLogger('checkpoint-builder');
|
|
198
|
+
}
|
|
186
199
|
|
|
187
200
|
public getConfig(): FullNodeBlockBuilderConfig {
|
|
188
201
|
return this.config;
|
|
@@ -201,11 +214,12 @@ export class FullNodeCheckpointsBuilder implements ICheckpointsBuilder {
|
|
|
201
214
|
l1ToL2Messages: Fr[],
|
|
202
215
|
previousCheckpointOutHashes: Fr[],
|
|
203
216
|
fork: MerkleTreeWriteOperations,
|
|
217
|
+
bindings?: LoggerBindings,
|
|
204
218
|
): Promise<CheckpointBuilder> {
|
|
205
219
|
const stateReference = await fork.getStateReference();
|
|
206
220
|
const archiveTree = await fork.getTreeInfo(MerkleTreeId.ARCHIVE);
|
|
207
221
|
|
|
208
|
-
log.verbose(`Building new checkpoint ${checkpointNumber}`, {
|
|
222
|
+
this.log.verbose(`Building new checkpoint ${checkpointNumber}`, {
|
|
209
223
|
checkpointNumber,
|
|
210
224
|
msgCount: l1ToL2Messages.length,
|
|
211
225
|
initialStateReference: stateReference.toInspect(),
|
|
@@ -219,6 +233,7 @@ export class FullNodeCheckpointsBuilder implements ICheckpointsBuilder {
|
|
|
219
233
|
l1ToL2Messages,
|
|
220
234
|
previousCheckpointOutHashes,
|
|
221
235
|
fork,
|
|
236
|
+
bindings,
|
|
222
237
|
);
|
|
223
238
|
|
|
224
239
|
return new CheckpointBuilder(
|
|
@@ -228,6 +243,7 @@ export class FullNodeCheckpointsBuilder implements ICheckpointsBuilder {
|
|
|
228
243
|
this.contractDataSource,
|
|
229
244
|
this.dateProvider,
|
|
230
245
|
this.telemetryClient,
|
|
246
|
+
bindings,
|
|
231
247
|
);
|
|
232
248
|
}
|
|
233
249
|
|
|
@@ -241,15 +257,23 @@ export class FullNodeCheckpointsBuilder implements ICheckpointsBuilder {
|
|
|
241
257
|
previousCheckpointOutHashes: Fr[],
|
|
242
258
|
fork: MerkleTreeWriteOperations,
|
|
243
259
|
existingBlocks: L2Block[] = [],
|
|
260
|
+
bindings?: LoggerBindings,
|
|
244
261
|
): Promise<CheckpointBuilder> {
|
|
245
262
|
const stateReference = await fork.getStateReference();
|
|
246
263
|
const archiveTree = await fork.getTreeInfo(MerkleTreeId.ARCHIVE);
|
|
247
264
|
|
|
248
265
|
if (existingBlocks.length === 0) {
|
|
249
|
-
return this.startCheckpoint(
|
|
266
|
+
return this.startCheckpoint(
|
|
267
|
+
checkpointNumber,
|
|
268
|
+
constants,
|
|
269
|
+
l1ToL2Messages,
|
|
270
|
+
previousCheckpointOutHashes,
|
|
271
|
+
fork,
|
|
272
|
+
bindings,
|
|
273
|
+
);
|
|
250
274
|
}
|
|
251
275
|
|
|
252
|
-
log.verbose(`Resuming checkpoint ${checkpointNumber} with ${existingBlocks.length} existing blocks`, {
|
|
276
|
+
this.log.verbose(`Resuming checkpoint ${checkpointNumber} with ${existingBlocks.length} existing blocks`, {
|
|
253
277
|
checkpointNumber,
|
|
254
278
|
msgCount: l1ToL2Messages.length,
|
|
255
279
|
existingBlockCount: existingBlocks.length,
|
|
@@ -265,6 +289,7 @@ export class FullNodeCheckpointsBuilder implements ICheckpointsBuilder {
|
|
|
265
289
|
previousCheckpointOutHashes,
|
|
266
290
|
fork,
|
|
267
291
|
existingBlocks,
|
|
292
|
+
bindings,
|
|
268
293
|
);
|
|
269
294
|
|
|
270
295
|
return new CheckpointBuilder(
|
|
@@ -274,6 +299,7 @@ export class FullNodeCheckpointsBuilder implements ICheckpointsBuilder {
|
|
|
274
299
|
this.contractDataSource,
|
|
275
300
|
this.dateProvider,
|
|
276
301
|
this.telemetryClient,
|
|
302
|
+
bindings,
|
|
277
303
|
);
|
|
278
304
|
}
|
|
279
305
|
|
package/src/config.ts
CHANGED
|
@@ -65,10 +65,9 @@ export const validatorClientConfigMappings: ConfigMappingsType<ValidatorClientCo
|
|
|
65
65
|
'Whether to run in fisherman mode: validates all proposals and attestations but does not broadcast attestations or participate in consensus.',
|
|
66
66
|
...booleanConfigHelper(false),
|
|
67
67
|
},
|
|
68
|
-
// TODO(palla/mbps): Change default to false once checkpoint validation is stable
|
|
69
68
|
skipCheckpointProposalValidation: {
|
|
70
|
-
description: 'Skip checkpoint proposal validation and always attest (default:
|
|
71
|
-
defaultValue:
|
|
69
|
+
description: 'Skip checkpoint proposal validation and always attest (default: false)',
|
|
70
|
+
defaultValue: false,
|
|
72
71
|
},
|
|
73
72
|
skipPushProposedBlocksToArchiver: {
|
|
74
73
|
description: 'Skip pushing re-executed blocks to archiver (default: false)',
|
package/src/metrics.ts
CHANGED
|
@@ -6,8 +6,11 @@ import {
|
|
|
6
6
|
Metrics,
|
|
7
7
|
type TelemetryClient,
|
|
8
8
|
type UpDownCounter,
|
|
9
|
+
createUpDownCounterWithDefault,
|
|
9
10
|
} from '@aztec/telemetry-client';
|
|
10
11
|
|
|
12
|
+
import type { BlockProposalValidationFailureReason } from './block_proposal_handler.js';
|
|
13
|
+
|
|
11
14
|
export class ValidatorMetrics {
|
|
12
15
|
private failedReexecutionCounter: UpDownCounter;
|
|
13
16
|
private successfulAttestationsCount: UpDownCounter;
|
|
@@ -21,16 +24,44 @@ export class ValidatorMetrics {
|
|
|
21
24
|
constructor(telemetryClient: TelemetryClient) {
|
|
22
25
|
const meter = telemetryClient.getMeter('Validator');
|
|
23
26
|
|
|
24
|
-
this.failedReexecutionCounter = meter
|
|
27
|
+
this.failedReexecutionCounter = createUpDownCounterWithDefault(meter, Metrics.VALIDATOR_FAILED_REEXECUTION_COUNT, {
|
|
28
|
+
[Attributes.STATUS]: ['failed'],
|
|
29
|
+
});
|
|
25
30
|
|
|
26
|
-
this.successfulAttestationsCount =
|
|
31
|
+
this.successfulAttestationsCount = createUpDownCounterWithDefault(
|
|
32
|
+
meter,
|
|
33
|
+
Metrics.VALIDATOR_ATTESTATION_SUCCESS_COUNT,
|
|
34
|
+
);
|
|
27
35
|
|
|
28
|
-
this.failedAttestationsBadProposalCount =
|
|
36
|
+
this.failedAttestationsBadProposalCount = createUpDownCounterWithDefault(
|
|
37
|
+
meter,
|
|
29
38
|
Metrics.VALIDATOR_ATTESTATION_FAILED_BAD_PROPOSAL_COUNT,
|
|
39
|
+
{
|
|
40
|
+
[Attributes.ERROR_TYPE]: [
|
|
41
|
+
'invalid_proposal',
|
|
42
|
+
'state_mismatch',
|
|
43
|
+
'failed_txs',
|
|
44
|
+
'in_hash_mismatch',
|
|
45
|
+
'parent_block_wrong_slot',
|
|
46
|
+
],
|
|
47
|
+
[Attributes.IS_COMMITTEE_MEMBER]: [true, false],
|
|
48
|
+
},
|
|
30
49
|
);
|
|
31
50
|
|
|
32
|
-
this.failedAttestationsNodeIssueCount =
|
|
51
|
+
this.failedAttestationsNodeIssueCount = createUpDownCounterWithDefault(
|
|
52
|
+
meter,
|
|
33
53
|
Metrics.VALIDATOR_ATTESTATION_FAILED_NODE_ISSUE_COUNT,
|
|
54
|
+
{
|
|
55
|
+
[Attributes.ERROR_TYPE]: [
|
|
56
|
+
'parent_block_not_found',
|
|
57
|
+
'global_variables_mismatch',
|
|
58
|
+
'block_number_already_exists',
|
|
59
|
+
'txs_not_available',
|
|
60
|
+
'timeout',
|
|
61
|
+
'unknown_error',
|
|
62
|
+
],
|
|
63
|
+
[Attributes.IS_COMMITTEE_MEMBER]: [true, false],
|
|
64
|
+
},
|
|
34
65
|
);
|
|
35
66
|
|
|
36
67
|
this.reexMana = meter.createHistogram(Metrics.VALIDATOR_RE_EXECUTION_MANA);
|
|
@@ -58,14 +89,22 @@ export class ValidatorMetrics {
|
|
|
58
89
|
this.successfulAttestationsCount.add(num);
|
|
59
90
|
}
|
|
60
91
|
|
|
61
|
-
public incFailedAttestationsBadProposal(
|
|
92
|
+
public incFailedAttestationsBadProposal(
|
|
93
|
+
num: number,
|
|
94
|
+
reason: BlockProposalValidationFailureReason,
|
|
95
|
+
inCommittee: boolean,
|
|
96
|
+
) {
|
|
62
97
|
this.failedAttestationsBadProposalCount.add(num, {
|
|
63
98
|
[Attributes.ERROR_TYPE]: reason,
|
|
64
99
|
[Attributes.IS_COMMITTEE_MEMBER]: inCommittee,
|
|
65
100
|
});
|
|
66
101
|
}
|
|
67
102
|
|
|
68
|
-
public incFailedAttestationsNodeIssue(
|
|
103
|
+
public incFailedAttestationsNodeIssue(
|
|
104
|
+
num: number,
|
|
105
|
+
reason: BlockProposalValidationFailureReason,
|
|
106
|
+
inCommittee: boolean,
|
|
107
|
+
) {
|
|
69
108
|
this.failedAttestationsNodeIssueCount.add(num, {
|
|
70
109
|
[Attributes.ERROR_TYPE]: reason,
|
|
71
110
|
[Attributes.IS_COMMITTEE_MEMBER]: inCommittee,
|