@aztec/validator-client 0.0.1-commit.8c0b8ff → 0.0.1-commit.8cb2d04d8
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 +0 -2
- package/dest/checkpoint_builder.js +1 -1
- package/dest/config.d.ts +1 -1
- package/dest/config.d.ts.map +1 -1
- package/dest/config.js +6 -10
- package/dest/duties/validation_service.d.ts +7 -9
- package/dest/duties/validation_service.d.ts.map +1 -1
- package/dest/duties/validation_service.js +13 -25
- package/dest/factory.d.ts +1 -1
- package/dest/factory.d.ts.map +1 -1
- package/dest/factory.js +1 -1
- package/dest/metrics.d.ts +5 -1
- package/dest/metrics.d.ts.map +1 -1
- package/dest/metrics.js +12 -0
- package/dest/proposal_handler.d.ts +20 -6
- package/dest/proposal_handler.d.ts.map +1 -1
- package/dest/proposal_handler.js +230 -108
- package/dest/validator.d.ts +19 -11
- package/dest/validator.d.ts.map +1 -1
- package/dest/validator.js +90 -54
- package/package.json +19 -19
- package/src/checkpoint_builder.ts +1 -1
- package/src/config.ts +6 -10
- package/src/duties/validation_service.ts +16 -29
- package/src/factory.ts +1 -0
- package/src/metrics.ts +18 -0
- package/src/proposal_handler.ts +252 -113
- package/src/validator.ts +118 -68
package/dest/proposal_handler.js
CHANGED
|
@@ -94,6 +94,9 @@ import { getTelemetryClient } from '@aztec/telemetry-client';
|
|
|
94
94
|
dateProvider;
|
|
95
95
|
log;
|
|
96
96
|
tracer;
|
|
97
|
+
/** Cached last checkpoint validation result to avoid double-validation on validator nodes. */ lastCheckpointValidationResult;
|
|
98
|
+
/** Archiver reference for setting proposed checkpoints (pipelining). Set via register(). */ archiver;
|
|
99
|
+
/** Returns current validator addresses for own-proposal detection. Set via register(). */ getOwnValidatorAddresses;
|
|
97
100
|
constructor(checkpointsBuilder, worldState, blockSource, l1ToL2MessageSource, txProvider, blockProposalValidator, epochCache, config, blobClient, metrics, dateProvider = new DateProvider(), telemetry = getTelemetryClient(), log = createLogger('validator:proposal-handler')){
|
|
98
101
|
this.checkpointsBuilder = checkpointsBuilder;
|
|
99
102
|
this.worldState = worldState;
|
|
@@ -113,9 +116,14 @@ import { getTelemetryClient } from '@aztec/telemetry-client';
|
|
|
113
116
|
this.tracer = telemetry.getTracer('ProposalHandler');
|
|
114
117
|
}
|
|
115
118
|
/**
|
|
116
|
-
* Registers
|
|
117
|
-
* Block proposals are
|
|
118
|
-
|
|
119
|
+
* Registers handlers for block and checkpoint proposals on the p2p client.
|
|
120
|
+
* Block proposals are registered for non-validator nodes (validators register their own enhanced handler).
|
|
121
|
+
* The all-nodes checkpoint proposal handler is always registered for validation, caching, and pipelining.
|
|
122
|
+
* @param archiver - Archiver reference for setting proposed checkpoints (pipelining)
|
|
123
|
+
* @param getOwnValidatorAddresses - Returns current validator addresses for own-proposal detection
|
|
124
|
+
*/ register(p2pClient, shouldReexecute, archiver, getOwnValidatorAddresses) {
|
|
125
|
+
this.archiver = archiver;
|
|
126
|
+
this.getOwnValidatorAddresses = getOwnValidatorAddresses;
|
|
119
127
|
// Non-validator handler that processes or re-executes for monitoring but does not attest.
|
|
120
128
|
// Returns boolean indicating whether the proposal was valid.
|
|
121
129
|
const blockHandler = async (proposal, proposalSender)=>{
|
|
@@ -146,29 +154,43 @@ import { getTelemetryClient } from '@aztec/telemetry-client';
|
|
|
146
154
|
}
|
|
147
155
|
};
|
|
148
156
|
p2pClient.registerBlockProposalHandler(blockHandler);
|
|
149
|
-
//
|
|
150
|
-
|
|
151
|
-
|
|
152
|
-
|
|
153
|
-
|
|
154
|
-
|
|
155
|
-
|
|
156
|
-
|
|
157
|
-
|
|
158
|
-
|
|
159
|
-
|
|
160
|
-
|
|
161
|
-
|
|
162
|
-
|
|
157
|
+
// All-nodes checkpoint proposal handler: validates, caches, and sets proposed checkpoint for pipelining.
|
|
158
|
+
// Runs for all nodes (validators and non-validators). Validators get the cached result in the
|
|
159
|
+
// validator-specific callback (attestToCheckpointProposal) which runs after this one.
|
|
160
|
+
const checkpointHandler = async (proposal, _sender)=>{
|
|
161
|
+
try {
|
|
162
|
+
const pipeliningTimer = new Timer();
|
|
163
|
+
const proposalInfo = {
|
|
164
|
+
slot: proposal.slotNumber,
|
|
165
|
+
archive: proposal.archive.toString(),
|
|
166
|
+
proposer: proposal.getSender()?.toString()
|
|
167
|
+
};
|
|
168
|
+
// For own proposals, skip validation — the proposer already built and validated the checkpoint
|
|
169
|
+
const proposer = proposal.getSender();
|
|
170
|
+
const ownAddresses = this.getOwnValidatorAddresses?.();
|
|
171
|
+
const isOwnProposal = proposer && ownAddresses?.some((addr)=>addr === proposer.toString());
|
|
172
|
+
if (isOwnProposal) {
|
|
173
|
+
this.log.debug(`Skipping validation for own checkpoint proposal at slot ${proposal.slotNumber}`);
|
|
174
|
+
if (this.archiver && this.epochCache.isProposerPipeliningEnabled()) {
|
|
175
|
+
await this.setProposedCheckpointFromBlocks(proposal);
|
|
163
176
|
}
|
|
164
|
-
|
|
165
|
-
this.log.error('Error processing checkpoint proposal in non-validator handler', error);
|
|
177
|
+
return undefined;
|
|
166
178
|
}
|
|
167
|
-
|
|
168
|
-
|
|
169
|
-
|
|
170
|
-
|
|
171
|
-
|
|
179
|
+
const result = await this.handleCheckpointProposal(proposal, proposalInfo);
|
|
180
|
+
if (result.isValid && this.archiver && this.epochCache.isProposerPipeliningEnabled()) {
|
|
181
|
+
const set = await this.setProposedCheckpointFromValidation(proposal);
|
|
182
|
+
if (set) {
|
|
183
|
+
this.metrics?.recordCheckpointProposalToPipelinedStateDuration(pipeliningTimer.ms());
|
|
184
|
+
}
|
|
185
|
+
}
|
|
186
|
+
} catch (err) {
|
|
187
|
+
this.log.warn(`Error handling checkpoint proposal for slot ${proposal.slotNumber}`, {
|
|
188
|
+
err
|
|
189
|
+
});
|
|
190
|
+
}
|
|
191
|
+
return undefined;
|
|
192
|
+
};
|
|
193
|
+
p2pClient.registerAllNodesCheckpointProposalHandler(checkpointHandler);
|
|
172
194
|
return this;
|
|
173
195
|
}
|
|
174
196
|
async handleBlockProposal(proposal, proposalSender, shouldReexecute) {
|
|
@@ -204,17 +226,21 @@ import { getTelemetryClient } from '@aztec/telemetry-client';
|
|
|
204
226
|
};
|
|
205
227
|
}
|
|
206
228
|
// Ensure the block source is synced before checking for existing blocks,
|
|
207
|
-
// since a
|
|
229
|
+
// since a proposed checkpoint prune may remove blocks we'd otherwise find.
|
|
208
230
|
// This affects mostly the block_number_already_exists check, since a pending
|
|
209
231
|
// checkpoint prune could remove a block that would conflict with this proposal.
|
|
210
|
-
//
|
|
211
|
-
|
|
212
|
-
|
|
213
|
-
|
|
214
|
-
|
|
215
|
-
|
|
216
|
-
|
|
217
|
-
|
|
232
|
+
// When pipelining is enabled, the proposer builds ahead of L1 submission, so the
|
|
233
|
+
// block source won't have synced to the proposed slot yet. Skip the sync wait to
|
|
234
|
+
// avoid eating into the attestation window.
|
|
235
|
+
if (!this.epochCache.isProposerPipeliningEnabled()) {
|
|
236
|
+
const blockSourceSync = await this.waitForBlockSourceSync(slotNumber);
|
|
237
|
+
if (!blockSourceSync) {
|
|
238
|
+
this.log.warn(`Block source is not synced, skipping processing`, proposalInfo);
|
|
239
|
+
return {
|
|
240
|
+
isValid: false,
|
|
241
|
+
reason: 'block_source_not_synced'
|
|
242
|
+
};
|
|
243
|
+
}
|
|
218
244
|
}
|
|
219
245
|
// Check that the parent proposal is a block we know, otherwise reexecution would fail.
|
|
220
246
|
// If we don't find it immediately, we keep retrying for a while; it may be we still
|
|
@@ -325,7 +351,7 @@ import { getTelemetryClient } from '@aztec/telemetry-client';
|
|
|
325
351
|
}
|
|
326
352
|
// If we succeeded, push this block into the archiver (unless disabled)
|
|
327
353
|
if (reexecutionResult?.block && this.config.skipPushProposedBlocksToArchiver === false) {
|
|
328
|
-
await this.blockSource.addBlock(reexecutionResult
|
|
354
|
+
await this.blockSource.addBlock(reexecutionResult.block);
|
|
329
355
|
}
|
|
330
356
|
this.log.info(`Successfully re-executed block ${blockNumber} proposal at index ${proposal.indexWithinCheckpoint} on slot ${slotNumber}`, {
|
|
331
357
|
...proposalInfo,
|
|
@@ -339,13 +365,12 @@ import { getTelemetryClient } from '@aztec/telemetry-client';
|
|
|
339
365
|
}
|
|
340
366
|
async getParentBlock(proposal) {
|
|
341
367
|
const parentArchive = proposal.blockHeader.lastArchive.root;
|
|
342
|
-
const slot = proposal.slotNumber;
|
|
343
368
|
const config = this.checkpointsBuilder.getConfig();
|
|
344
369
|
const { genesisArchiveRoot } = await this.blockSource.getGenesisValues();
|
|
345
370
|
if (parentArchive.equals(genesisArchiveRoot)) {
|
|
346
371
|
return 'genesis';
|
|
347
372
|
}
|
|
348
|
-
const deadline = this.getReexecutionDeadline(
|
|
373
|
+
const deadline = this.getReexecutionDeadline(proposal.slotNumber, config);
|
|
349
374
|
const currentTime = this.dateProvider.now();
|
|
350
375
|
const timeoutDurationMs = deadline.getTime() - currentTime;
|
|
351
376
|
try {
|
|
@@ -491,8 +516,11 @@ import { getTelemetryClient } from '@aztec/telemetry-client';
|
|
|
491
516
|
}
|
|
492
517
|
return undefined;
|
|
493
518
|
}
|
|
494
|
-
getReexecutionDeadline(
|
|
495
|
-
|
|
519
|
+
getReexecutionDeadline(slotNumber, config) {
|
|
520
|
+
// Under proposer pipelining, the proposal slot may be ahead of wall clock time.
|
|
521
|
+
// Reexecution budgets should still be bounded by the current slot we are in now.
|
|
522
|
+
const wallclockSlot = slotNumber - this.epochCache.pipeliningOffset();
|
|
523
|
+
const nextSlotTimestampSeconds = Number(getTimestampForSlot(SlotNumber(wallclockSlot + 1), config));
|
|
496
524
|
return new Date(nextSlotTimestampSeconds * 1000);
|
|
497
525
|
}
|
|
498
526
|
/** Waits for the block source to sync L1 data up to at least the slot before the given one. */ async waitForBlockSourceSync(slot) {
|
|
@@ -502,16 +530,17 @@ import { getTelemetryClient } from '@aztec/telemetry-client';
|
|
|
502
530
|
return true;
|
|
503
531
|
}
|
|
504
532
|
// Make a quick check before triggering an archiver sync
|
|
533
|
+
// If we are pipelining and have a pending checkpoint number stored, we will allow the block proposal to be for a slot further
|
|
505
534
|
const syncedSlot = await this.blockSource.getSyncedL2SlotNumber();
|
|
506
|
-
if (syncedSlot !== undefined && syncedSlot + 1 >= slot) {
|
|
535
|
+
if (syncedSlot !== undefined && syncedSlot + 1 + this.epochCache.pipeliningOffset() >= slot) {
|
|
507
536
|
return true;
|
|
508
537
|
}
|
|
509
538
|
try {
|
|
510
539
|
// Trigger an immediate sync of the block source, and wait until it reports being synced to the required slot
|
|
511
540
|
return await retryUntil(async ()=>{
|
|
512
541
|
await this.blockSource.syncImmediate();
|
|
513
|
-
const
|
|
514
|
-
return
|
|
542
|
+
const updatedSyncedSlot = await this.blockSource.getSyncedL2SlotNumber();
|
|
543
|
+
return updatedSyncedSlot !== undefined && updatedSyncedSlot + 1 >= slot;
|
|
515
544
|
}, 'wait for block source sync', timeoutMs / 1000, 0.5);
|
|
516
545
|
} catch (err) {
|
|
517
546
|
if (err instanceof TimeoutError) {
|
|
@@ -639,25 +668,49 @@ import { getTelemetryClient } from '@aztec/telemetry-client';
|
|
|
639
668
|
}
|
|
640
669
|
}
|
|
641
670
|
/**
|
|
642
|
-
* Validates a checkpoint proposal and uploads blobs if configured.
|
|
643
|
-
*
|
|
671
|
+
* Validates a checkpoint proposal, caches the result, and uploads blobs if configured.
|
|
672
|
+
* Returns a cached result if the same proposal (archive + slot) was already validated.
|
|
673
|
+
* Used by both the all-nodes callback (via register) and the validator client (via delegation).
|
|
644
674
|
*/ async handleCheckpointProposal(proposal, proposalInfo) {
|
|
675
|
+
const slot = proposal.slotNumber;
|
|
676
|
+
// Check cache: same archive+slot means we already validated this proposal
|
|
677
|
+
if (this.lastCheckpointValidationResult && this.lastCheckpointValidationResult.archive.equals(proposal.archive) && this.lastCheckpointValidationResult.slotNumber === slot) {
|
|
678
|
+
this.log.debug(`Returning cached validation result for checkpoint proposal at slot ${slot}`, proposalInfo);
|
|
679
|
+
return this.lastCheckpointValidationResult.result;
|
|
680
|
+
}
|
|
645
681
|
const proposer = proposal.getSender();
|
|
646
682
|
if (!proposer) {
|
|
647
683
|
this.log.warn(`Received checkpoint proposal with invalid signature for slot ${proposal.slotNumber}`);
|
|
648
|
-
|
|
684
|
+
const result = {
|
|
649
685
|
isValid: false,
|
|
650
686
|
reason: 'invalid_signature'
|
|
651
687
|
};
|
|
688
|
+
this.lastCheckpointValidationResult = {
|
|
689
|
+
archive: proposal.archive,
|
|
690
|
+
slotNumber: slot,
|
|
691
|
+
result
|
|
692
|
+
};
|
|
693
|
+
return result;
|
|
652
694
|
}
|
|
653
695
|
if (!validateFeeAssetPriceModifier(proposal.feeAssetPriceModifier)) {
|
|
654
696
|
this.log.warn(`Received checkpoint proposal with invalid feeAssetPriceModifier ${proposal.feeAssetPriceModifier} for slot ${proposal.slotNumber}`);
|
|
655
|
-
|
|
697
|
+
const result = {
|
|
656
698
|
isValid: false,
|
|
657
699
|
reason: 'invalid_fee_asset_price_modifier'
|
|
658
700
|
};
|
|
701
|
+
this.lastCheckpointValidationResult = {
|
|
702
|
+
archive: proposal.archive,
|
|
703
|
+
slotNumber: slot,
|
|
704
|
+
result
|
|
705
|
+
};
|
|
706
|
+
return result;
|
|
659
707
|
}
|
|
660
708
|
const result = await this.validateCheckpointProposal(proposal, proposalInfo);
|
|
709
|
+
this.lastCheckpointValidationResult = {
|
|
710
|
+
archive: proposal.archive,
|
|
711
|
+
slotNumber: slot,
|
|
712
|
+
result
|
|
713
|
+
};
|
|
661
714
|
// Upload blobs to filestore if validation passed (fire and forget)
|
|
662
715
|
if (result.isValid) {
|
|
663
716
|
this.tryUploadBlobsForCheckpoint(proposal, proposalInfo);
|
|
@@ -668,73 +721,78 @@ import { getTelemetryClient } from '@aztec/telemetry-client';
|
|
|
668
721
|
* Validates a checkpoint proposal by building the full checkpoint and comparing it with the proposal.
|
|
669
722
|
* @returns Validation result with isValid flag and reason if invalid.
|
|
670
723
|
*/ async validateCheckpointProposal(proposal, proposalInfo) {
|
|
671
|
-
const
|
|
672
|
-
|
|
673
|
-
|
|
674
|
-
|
|
675
|
-
|
|
676
|
-
// Wait for last block to sync by archive
|
|
677
|
-
let lastBlockHeader;
|
|
724
|
+
const env = {
|
|
725
|
+
stack: [],
|
|
726
|
+
error: void 0,
|
|
727
|
+
hasError: false
|
|
728
|
+
};
|
|
678
729
|
try {
|
|
679
|
-
|
|
680
|
-
|
|
681
|
-
|
|
682
|
-
|
|
683
|
-
|
|
684
|
-
|
|
685
|
-
|
|
730
|
+
const slot = proposal.slotNumber;
|
|
731
|
+
// Timeout block syncing at the start of the next slot
|
|
732
|
+
const config = this.checkpointsBuilder.getConfig();
|
|
733
|
+
const nextSlotTimestampSeconds = Number(getTimestampForSlot(SlotNumber(slot + 1), config));
|
|
734
|
+
const timeoutSeconds = Math.max(1, nextSlotTimestampSeconds - Math.floor(this.dateProvider.now() / 1000));
|
|
735
|
+
// Wait for last block to sync by archive
|
|
736
|
+
let lastBlockHeader;
|
|
737
|
+
try {
|
|
738
|
+
lastBlockHeader = await retryUntil(async ()=>{
|
|
739
|
+
await this.blockSource.syncImmediate();
|
|
740
|
+
return this.blockSource.getBlockHeaderByArchive(proposal.archive);
|
|
741
|
+
}, `waiting for block with archive ${proposal.archive.toString()} for slot ${slot}`, timeoutSeconds, 0.5);
|
|
742
|
+
} catch (err) {
|
|
743
|
+
if (err instanceof TimeoutError) {
|
|
744
|
+
this.log.warn(`Timed out waiting for block with archive matching checkpoint proposal`, proposalInfo);
|
|
745
|
+
return {
|
|
746
|
+
isValid: false,
|
|
747
|
+
reason: 'last_block_not_found'
|
|
748
|
+
};
|
|
749
|
+
}
|
|
750
|
+
this.log.error(`Error fetching last block for checkpoint proposal`, err, proposalInfo);
|
|
751
|
+
return {
|
|
752
|
+
isValid: false,
|
|
753
|
+
reason: 'block_fetch_error'
|
|
754
|
+
};
|
|
755
|
+
}
|
|
756
|
+
if (!lastBlockHeader) {
|
|
757
|
+
this.log.warn(`Last block not found for checkpoint proposal`, proposalInfo);
|
|
686
758
|
return {
|
|
687
759
|
isValid: false,
|
|
688
760
|
reason: 'last_block_not_found'
|
|
689
761
|
};
|
|
690
762
|
}
|
|
691
|
-
|
|
692
|
-
|
|
693
|
-
|
|
694
|
-
|
|
695
|
-
|
|
696
|
-
|
|
697
|
-
|
|
698
|
-
|
|
699
|
-
|
|
700
|
-
|
|
701
|
-
|
|
702
|
-
|
|
703
|
-
|
|
704
|
-
|
|
705
|
-
|
|
706
|
-
|
|
707
|
-
|
|
708
|
-
|
|
709
|
-
|
|
710
|
-
|
|
711
|
-
};
|
|
712
|
-
|
|
713
|
-
|
|
714
|
-
|
|
715
|
-
|
|
716
|
-
|
|
717
|
-
|
|
718
|
-
|
|
719
|
-
|
|
720
|
-
|
|
721
|
-
|
|
722
|
-
|
|
723
|
-
|
|
724
|
-
});
|
|
725
|
-
// Get checkpoint constants from first block
|
|
726
|
-
const firstBlock = blocks[0];
|
|
727
|
-
const constants = this.extractCheckpointConstants(firstBlock);
|
|
728
|
-
const checkpointNumber = firstBlock.checkpointNumber;
|
|
729
|
-
// Get L1-to-L2 messages for this checkpoint
|
|
730
|
-
const l1ToL2Messages = await this.l1ToL2MessageSource.getL1ToL2Messages(checkpointNumber);
|
|
731
|
-
// Collect the out hashes of all the checkpoints before this one in the same epoch
|
|
732
|
-
const epoch = getEpochAtSlot(slot, this.epochCache.getL1Constants());
|
|
733
|
-
const previousCheckpointOutHashes = (await this.blockSource.getCheckpointsDataForEpoch(epoch)).filter((c)=>c.checkpointNumber < checkpointNumber).map((c)=>c.checkpointOutHash);
|
|
734
|
-
// Fork world state at the block before the first block
|
|
735
|
-
const parentBlockNumber = BlockNumber(firstBlock.number - 1);
|
|
736
|
-
const fork = await this.worldState.fork(parentBlockNumber);
|
|
737
|
-
try {
|
|
763
|
+
// Get all full blocks for the slot and checkpoint
|
|
764
|
+
const blocks = await this.blockSource.getBlocksForSlot(slot);
|
|
765
|
+
if (blocks.length === 0) {
|
|
766
|
+
this.log.warn(`No blocks found for slot ${slot}`, proposalInfo);
|
|
767
|
+
return {
|
|
768
|
+
isValid: false,
|
|
769
|
+
reason: 'no_blocks_for_slot'
|
|
770
|
+
};
|
|
771
|
+
}
|
|
772
|
+
// Ensure the last block for this slot matches the archive in the checkpoint proposal
|
|
773
|
+
if (!blocks.at(-1)?.archive.root.equals(proposal.archive)) {
|
|
774
|
+
this.log.warn(`Last block archive mismatch for checkpoint proposal`, proposalInfo);
|
|
775
|
+
return {
|
|
776
|
+
isValid: false,
|
|
777
|
+
reason: 'last_block_archive_mismatch'
|
|
778
|
+
};
|
|
779
|
+
}
|
|
780
|
+
this.log.debug(`Found ${blocks.length} blocks for slot ${slot}`, {
|
|
781
|
+
...proposalInfo,
|
|
782
|
+
blockNumbers: blocks.map((b)=>b.number)
|
|
783
|
+
});
|
|
784
|
+
// Get checkpoint constants from first block
|
|
785
|
+
const firstBlock = blocks[0];
|
|
786
|
+
const constants = this.extractCheckpointConstants(firstBlock);
|
|
787
|
+
const checkpointNumber = firstBlock.checkpointNumber;
|
|
788
|
+
// Get L1-to-L2 messages for this checkpoint
|
|
789
|
+
const l1ToL2Messages = await this.l1ToL2MessageSource.getL1ToL2Messages(checkpointNumber);
|
|
790
|
+
// Collect the out hashes of all the checkpoints before this one in the same epoch
|
|
791
|
+
const epoch = getEpochAtSlot(slot, this.epochCache.getL1Constants());
|
|
792
|
+
const previousCheckpointOutHashes = (await this.blockSource.getCheckpointsDataForEpoch(epoch)).filter((c)=>c.checkpointNumber < checkpointNumber).map((c)=>c.checkpointOutHash);
|
|
793
|
+
// Fork world state at the block before the first block
|
|
794
|
+
const parentBlockNumber = BlockNumber(firstBlock.number - 1);
|
|
795
|
+
const fork = _ts_add_disposable_resource(env, await this.checkpointsBuilder.getFork(parentBlockNumber), true);
|
|
738
796
|
// Create checkpoint builder with all existing blocks
|
|
739
797
|
const checkpointBuilder = await this.checkpointsBuilder.openCheckpoint(checkpointNumber, constants, proposal.feeAssetPriceModifier, l1ToL2Messages, previousCheckpointOutHashes, fork, blocks, this.log.getBindings());
|
|
740
798
|
// Complete the checkpoint to get computed values
|
|
@@ -802,10 +860,15 @@ import { getTelemetryClient } from '@aztec/telemetry-client';
|
|
|
802
860
|
}
|
|
803
861
|
this.log.verbose(`Checkpoint proposal validation successful for slot ${slot}`, proposalInfo);
|
|
804
862
|
return {
|
|
805
|
-
isValid: true
|
|
863
|
+
isValid: true,
|
|
864
|
+
checkpointNumber
|
|
806
865
|
};
|
|
866
|
+
} catch (e) {
|
|
867
|
+
env.error = e;
|
|
868
|
+
env.hasError = true;
|
|
807
869
|
} finally{
|
|
808
|
-
|
|
870
|
+
const result = _ts_dispose_resources(env);
|
|
871
|
+
if (result) await result;
|
|
809
872
|
}
|
|
810
873
|
}
|
|
811
874
|
/** Extracts checkpoint global variables from a block. */ extractCheckpointConstants(block) {
|
|
@@ -849,4 +912,63 @@ import { getTelemetryClient } from '@aztec/telemetry-client';
|
|
|
849
912
|
this.log.warn(`Failed to upload blobs for checkpoint: ${err}`, proposalInfo);
|
|
850
913
|
}
|
|
851
914
|
}
|
|
915
|
+
/**
|
|
916
|
+
* Derives proposed checkpoint data from validated blocks and sets it on the archiver.
|
|
917
|
+
* Used after successful validation of a foreign proposal.
|
|
918
|
+
* Does not retry since we already waited for the block during validation.
|
|
919
|
+
*/ async setProposedCheckpointFromValidation(proposal) {
|
|
920
|
+
if (!this.archiver) {
|
|
921
|
+
return false;
|
|
922
|
+
}
|
|
923
|
+
const blockData = await this.blockSource.getBlockDataByArchive(proposal.archive);
|
|
924
|
+
if (!blockData) {
|
|
925
|
+
this.log.debug(`Block data not found for checkpoint proposal archive, cannot set proposed checkpoint`, {
|
|
926
|
+
archive: proposal.archive.toString()
|
|
927
|
+
});
|
|
928
|
+
return false;
|
|
929
|
+
}
|
|
930
|
+
await this.archiver.setProposedCheckpoint({
|
|
931
|
+
header: proposal.checkpointHeader,
|
|
932
|
+
checkpointNumber: blockData.checkpointNumber,
|
|
933
|
+
startBlock: BlockNumber(blockData.header.getBlockNumber() - blockData.indexWithinCheckpoint),
|
|
934
|
+
blockCount: blockData.indexWithinCheckpoint + 1,
|
|
935
|
+
totalManaUsed: proposal.checkpointHeader.totalManaUsed.toBigInt(),
|
|
936
|
+
feeAssetPriceModifier: proposal.feeAssetPriceModifier
|
|
937
|
+
});
|
|
938
|
+
return true;
|
|
939
|
+
}
|
|
940
|
+
/**
|
|
941
|
+
* Sets proposed checkpoint from blocks for own proposals (skips full validation).
|
|
942
|
+
* Retries fetching block data since the checkpoint proposal often arrives before the last block
|
|
943
|
+
* finishes re-execution.
|
|
944
|
+
*/ async setProposedCheckpointFromBlocks(proposal) {
|
|
945
|
+
if (!this.archiver) {
|
|
946
|
+
return false;
|
|
947
|
+
}
|
|
948
|
+
let blockData = await this.blockSource.getBlockDataByArchive(proposal.archive);
|
|
949
|
+
if (!blockData) {
|
|
950
|
+
// The checkpoint proposal often arrives before the last block finishes re-execution.
|
|
951
|
+
// Retry until we find the data or give up at the end of the slot.
|
|
952
|
+
const nextSlot = this.epochCache.getSlotNow() + 1;
|
|
953
|
+
const timeOfNextSlot = getTimestampForSlot(SlotNumber(nextSlot), await this.archiver.getL1Constants());
|
|
954
|
+
const timeoutSeconds = Math.max(1, Number(timeOfNextSlot) - Math.floor(this.dateProvider.now() / 1000));
|
|
955
|
+
blockData = await retryUntil(()=>this.blockSource.getBlockDataByArchive(proposal.archive), 'block data for own checkpoint proposal', timeoutSeconds, 0.25).catch(()=>undefined);
|
|
956
|
+
}
|
|
957
|
+
if (blockData) {
|
|
958
|
+
await this.archiver.setProposedCheckpoint({
|
|
959
|
+
header: proposal.checkpointHeader,
|
|
960
|
+
checkpointNumber: blockData.checkpointNumber,
|
|
961
|
+
startBlock: BlockNumber(blockData.header.getBlockNumber() - blockData.indexWithinCheckpoint),
|
|
962
|
+
blockCount: blockData.indexWithinCheckpoint + 1,
|
|
963
|
+
totalManaUsed: proposal.checkpointHeader.totalManaUsed.toBigInt(),
|
|
964
|
+
feeAssetPriceModifier: proposal.feeAssetPriceModifier
|
|
965
|
+
});
|
|
966
|
+
return true;
|
|
967
|
+
} else {
|
|
968
|
+
this.log.debug(`Block data not found for own checkpoint proposal archive, cannot set proposed checkpoint`, {
|
|
969
|
+
archive: proposal.archive.toString()
|
|
970
|
+
});
|
|
971
|
+
return false;
|
|
972
|
+
}
|
|
973
|
+
}
|
|
852
974
|
}
|
package/dest/validator.d.ts
CHANGED
|
@@ -1,17 +1,17 @@
|
|
|
1
1
|
import type { BlobClientInterface } from '@aztec/blob-client/client';
|
|
2
2
|
import type { EpochCache } from '@aztec/epoch-cache';
|
|
3
|
-
import {
|
|
3
|
+
import { CheckpointNumber, IndexWithinCheckpoint, SlotNumber } from '@aztec/foundation/branded-types';
|
|
4
4
|
import { Fr } from '@aztec/foundation/curves/bn254';
|
|
5
5
|
import type { EthAddress } from '@aztec/foundation/eth-address';
|
|
6
6
|
import type { Signature } from '@aztec/foundation/eth-signature';
|
|
7
|
-
import { type Logger } from '@aztec/foundation/log';
|
|
7
|
+
import { type LogData, type Logger } from '@aztec/foundation/log';
|
|
8
8
|
import { DateProvider } from '@aztec/foundation/timer';
|
|
9
9
|
import type { KeystoreManager } from '@aztec/node-keystore';
|
|
10
10
|
import type { P2P, PeerId } from '@aztec/p2p';
|
|
11
11
|
import { type Watcher, type WatcherEmitter } from '@aztec/slasher';
|
|
12
12
|
import type { AztecAddress } from '@aztec/stdlib/aztec-address';
|
|
13
13
|
import type { CommitteeAttestationsAndSigners, L2BlockSink, L2BlockSource } from '@aztec/stdlib/block';
|
|
14
|
-
import type {
|
|
14
|
+
import type { ITxProvider, Validator, ValidatorClientFullConfig, WorldStateSynchronizer } from '@aztec/stdlib/interfaces/server';
|
|
15
15
|
import type { L1ToL2MessageSource } from '@aztec/stdlib/messaging';
|
|
16
16
|
import { type BlockProposal, type BlockProposalOptions, type CheckpointAttestation, CheckpointProposal, type CheckpointProposalCore, type CheckpointProposalOptions } from '@aztec/stdlib/p2p';
|
|
17
17
|
import type { CheckpointHeader } from '@aztec/stdlib/rollup';
|
|
@@ -32,9 +32,13 @@ export declare class ValidatorClient extends ValidatorClient_base implements Val
|
|
|
32
32
|
private epochCache;
|
|
33
33
|
private p2pClient;
|
|
34
34
|
private proposalHandler;
|
|
35
|
+
private blockSource;
|
|
36
|
+
private checkpointsBuilder;
|
|
37
|
+
private worldState;
|
|
38
|
+
private l1ToL2MessageSource;
|
|
35
39
|
private config;
|
|
36
40
|
private blobClient;
|
|
37
|
-
private
|
|
41
|
+
private slashingProtectionSigner;
|
|
38
42
|
private dateProvider;
|
|
39
43
|
readonly tracer: Tracer;
|
|
40
44
|
private validationService;
|
|
@@ -52,7 +56,7 @@ export declare class ValidatorClient extends ValidatorClient_base implements Val
|
|
|
52
56
|
private proposersOfInvalidBlocks;
|
|
53
57
|
/** Tracks the last checkpoint proposal we attested to, to prevent equivocation. */
|
|
54
58
|
private lastAttestedProposal?;
|
|
55
|
-
protected constructor(keyStore: ExtendedValidatorKeyStore, epochCache: EpochCache, p2pClient: P2P, proposalHandler: ProposalHandler, config: ValidatorClientFullConfig, blobClient: BlobClientInterface,
|
|
59
|
+
protected constructor(keyStore: ExtendedValidatorKeyStore, epochCache: EpochCache, p2pClient: P2P, proposalHandler: ProposalHandler, blockSource: L2BlockSource, checkpointsBuilder: FullNodeCheckpointsBuilder, worldState: WorldStateSynchronizer, l1ToL2MessageSource: L1ToL2MessageSource, config: ValidatorClientFullConfig, blobClient: BlobClientInterface, slashingProtectionSigner: ValidatorHASigner, dateProvider?: DateProvider, telemetry?: TelemetryClient, log?: Logger);
|
|
56
60
|
static validateKeyStoreConfiguration(keyStoreManager: KeystoreManager, logger?: Logger): void;
|
|
57
61
|
private handleEpochCommitteeUpdate;
|
|
58
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>;
|
|
@@ -87,6 +91,10 @@ export declare class ValidatorClient extends ValidatorClient_base implements Val
|
|
|
87
91
|
*/
|
|
88
92
|
private shouldAttestToSlot;
|
|
89
93
|
private createCheckpointAttestationsFromProposal;
|
|
94
|
+
/**
|
|
95
|
+
* Uploads blobs for a checkpoint to the filestore (fire and forget).
|
|
96
|
+
*/
|
|
97
|
+
protected uploadBlobsForCheckpoint(proposal: CheckpointProposalCore, proposalInfo: LogData): Promise<void>;
|
|
90
98
|
private slashInvalidBlock;
|
|
91
99
|
/**
|
|
92
100
|
* Handle detection of a duplicate proposal (equivocation).
|
|
@@ -98,13 +106,13 @@ export declare class ValidatorClient extends ValidatorClient_base implements Val
|
|
|
98
106
|
* Emits a slash event when an attester signs attestations for different proposals at the same slot.
|
|
99
107
|
*/
|
|
100
108
|
private handleDuplicateAttestation;
|
|
101
|
-
createBlockProposal(blockHeader: BlockHeader, indexWithinCheckpoint: IndexWithinCheckpoint, inHash: Fr, archive: Fr, txs: Tx[], proposerAddress: EthAddress | undefined, options?: BlockProposalOptions): Promise<BlockProposal>;
|
|
102
|
-
createCheckpointProposal(checkpointHeader: CheckpointHeader, archive: Fr, feeAssetPriceModifier: bigint,
|
|
109
|
+
createBlockProposal(blockHeader: BlockHeader, checkpointNumber: CheckpointNumber, indexWithinCheckpoint: IndexWithinCheckpoint, inHash: Fr, archive: Fr, txs: Tx[], proposerAddress: EthAddress | undefined, options?: BlockProposalOptions): Promise<BlockProposal>;
|
|
110
|
+
createCheckpointProposal(checkpointHeader: CheckpointHeader, archive: Fr, checkpointNumber: CheckpointNumber, feeAssetPriceModifier: bigint, lastBlockProposal: BlockProposal | undefined, proposerAddress: EthAddress | undefined, options?: CheckpointProposalOptions): Promise<CheckpointProposal>;
|
|
103
111
|
broadcastBlockProposal(proposal: BlockProposal): Promise<void>;
|
|
104
|
-
signAttestationsAndSigners(attestationsAndSigners: CommitteeAttestationsAndSigners, proposer: EthAddress, slot: SlotNumber,
|
|
105
|
-
collectOwnAttestations(proposal: CheckpointProposal): Promise<CheckpointAttestation[]>;
|
|
106
|
-
collectAttestations(proposal: CheckpointProposal, required: number, deadline: Date): Promise<CheckpointAttestation[]>;
|
|
112
|
+
signAttestationsAndSigners(attestationsAndSigners: CommitteeAttestationsAndSigners, proposer: EthAddress, slot: SlotNumber, checkpointNumber: CheckpointNumber): Promise<Signature>;
|
|
113
|
+
collectOwnAttestations(proposal: CheckpointProposal, checkpointNumber: CheckpointNumber): Promise<CheckpointAttestation[]>;
|
|
114
|
+
collectAttestations(proposal: CheckpointProposal, required: number, deadline: Date, checkpointNumber: CheckpointNumber): Promise<CheckpointAttestation[]>;
|
|
107
115
|
private handleAuthRequest;
|
|
108
116
|
}
|
|
109
117
|
export {};
|
|
110
|
-
//# sourceMappingURL=data:application/json;base64,
|
|
118
|
+
//# sourceMappingURL=data:application/json;base64,eyJ2ZXJzaW9uIjozLCJmaWxlIjoidmFsaWRhdG9yLmQudHMiLCJzb3VyY2VSb290IjoiIiwic291cmNlcyI6WyIuLi9zcmMvdmFsaWRhdG9yLnRzIl0sIm5hbWVzIjpbXSwibWFwcGluZ3MiOiJBQUFBLE9BQU8sS0FBSyxFQUFFLG1CQUFtQixFQUFFLE1BQU0sMkJBQTJCLENBQUM7QUFFckUsT0FBTyxLQUFLLEVBQUUsVUFBVSxFQUFFLE1BQU0sb0JBQW9CLENBQUM7QUFDckQsT0FBTyxFQUFFLGdCQUFnQixFQUFlLHFCQUFxQixFQUFFLFVBQVUsRUFBRSxNQUFNLGlDQUFpQyxDQUFDO0FBQ25ILE9BQU8sRUFBRSxFQUFFLEVBQUUsTUFBTSxnQ0FBZ0MsQ0FBQztBQUNwRCxPQUFPLEtBQUssRUFBRSxVQUFVLEVBQUUsTUFBTSwrQkFBK0IsQ0FBQztBQUNoRSxPQUFPLEtBQUssRUFBRSxTQUFTLEVBQUUsTUFBTSxpQ0FBaUMsQ0FBQztBQUNqRSxPQUFPLEVBQUUsS0FBSyxPQUFPLEVBQUUsS0FBSyxNQUFNLEVBQWdCLE1BQU0sdUJBQXVCLENBQUM7QUFHaEYsT0FBTyxFQUFFLFlBQVksRUFBRSxNQUFNLHlCQUF5QixDQUFDO0FBQ3ZELE9BQU8sS0FBSyxFQUFFLGVBQWUsRUFBRSxNQUFNLHNCQUFzQixDQUFDO0FBQzVELE9BQU8sS0FBSyxFQUFtRCxHQUFHLEVBQUUsTUFBTSxFQUFFLE1BQU0sWUFBWSxDQUFDO0FBRS9GLE9BQU8sRUFBb0MsS0FBSyxPQUFPLEVBQUUsS0FBSyxjQUFjLEVBQUUsTUFBTSxnQkFBZ0IsQ0FBQztBQUNyRyxPQUFPLEtBQUssRUFBRSxZQUFZLEVBQUUsTUFBTSw2QkFBNkIsQ0FBQztBQUNoRSxPQUFPLEtBQUssRUFBRSwrQkFBK0IsRUFBRSxXQUFXLEVBQUUsYUFBYSxFQUFFLE1BQU0scUJBQXFCLENBQUM7QUFFdkcsT0FBTyxLQUFLLEVBQ1YsV0FBVyxFQUNYLFNBQVMsRUFDVCx5QkFBeUIsRUFDekIsc0JBQXNCLEVBQ3ZCLE1BQU0saUNBQWlDLENBQUM7QUFDekMsT0FB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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;
|
|
1
|
+
{"version":3,"file":"validator.d.ts","sourceRoot":"","sources":["../src/validator.ts"],"names":[],"mappings":"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"}
|