@aztec/aztec-node 0.0.1-commit.0c875d939 → 0.0.1-commit.0dc957cde

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.
@@ -1,10 +1,10 @@
1
1
  import type { EpochCache } from '@aztec/epoch-cache';
2
2
  import { createLogger } from '@aztec/foundation/log';
3
- import type { DataStoreConfig } from '@aztec/kv-store/config';
4
3
  import { createStore } from '@aztec/kv-store/lmdb-v2';
5
4
  import type { P2PClient } from '@aztec/p2p';
6
5
  import type { L2BlockSource } from '@aztec/stdlib/block';
7
6
  import type { SlasherConfig } from '@aztec/stdlib/interfaces/server';
7
+ import type { DataStoreConfig } from '@aztec/stdlib/kv-store';
8
8
 
9
9
  import type { SentinelConfig } from './config.js';
10
10
  import { Sentinel } from './sentinel.js';
@@ -88,7 +88,7 @@ export class Sentinel extends (EventEmitter as new () => WatcherEmitter) impleme
88
88
 
89
89
  /** Loads initial slot and initializes blockstream. We will not process anything at or before the initial slot. */
90
90
  protected async init() {
91
- this.initialSlot = this.epochCache.getEpochAndSlotNow().slot;
91
+ this.initialSlot = this.epochCache.getSlotNow();
92
92
  const startingBlock = BlockNumber(await this.archiver.getBlockNumber());
93
93
  this.logger.info(`Starting validator sentinel with initial slot ${this.initialSlot} and block ${startingBlock}`);
94
94
  this.blockStream = new L2BlockStream(this.archiver, this.l2TipsStore, this, this.logger, { startingBlock });
@@ -139,15 +139,15 @@ export class Sentinel extends (EventEmitter as new () => WatcherEmitter) impleme
139
139
  return;
140
140
  }
141
141
  const blockNumber = event.block.number;
142
- const block = await this.archiver.getL2Block(blockNumber);
143
- if (!block) {
144
- this.logger.error(`Failed to get block ${blockNumber}`, { block });
142
+ const header = await this.archiver.getBlockHeader(blockNumber);
143
+ if (!header) {
144
+ this.logger.error(`Failed to get block header ${blockNumber}`);
145
145
  return;
146
146
  }
147
147
 
148
148
  // TODO(palla/slash): We should only be computing proven performance if this is
149
149
  // a full proof epoch and not a partial one, otherwise we'll end up with skewed stats.
150
- const epoch = getEpochAtSlot(block.header.getSlot(), this.epochCache.getL1Constants());
150
+ const epoch = getEpochAtSlot(header.getSlot(), this.epochCache.getL1Constants());
151
151
  this.logger.debug(`Computing proven performance for epoch ${epoch}`);
152
152
  const performance = await this.computeProvenPerformance(epoch);
153
153
  this.logger.info(`Computed proven performance for epoch ${epoch}`, performance);
@@ -158,7 +158,11 @@ export class Sentinel extends (EventEmitter as new () => WatcherEmitter) impleme
158
158
 
159
159
  protected async computeProvenPerformance(epoch: EpochNumber): Promise<ValidatorsEpochPerformance> {
160
160
  const [fromSlot, toSlot] = getSlotRangeForEpoch(epoch, this.epochCache.getL1Constants());
161
- const { committee } = await this.epochCache.getCommittee(fromSlot);
161
+ const { committee, isEscapeHatchOpen } = await this.epochCache.getCommittee(fromSlot);
162
+ if (isEscapeHatchOpen) {
163
+ this.logger.info(`Skipping proven performance for epoch ${epoch} - escape hatch is open`);
164
+ return {};
165
+ }
162
166
  if (!committee) {
163
167
  this.logger.trace(`No committee found for slot ${fromSlot}`);
164
168
  return {};
@@ -215,7 +219,7 @@ export class Sentinel extends (EventEmitter as new () => WatcherEmitter) impleme
215
219
  // Check that we have at least requiredConsecutiveEpochs and that all of them are above the inactivity threshold
216
220
  return pastEpochs
217
221
  .slice(0, requiredConsecutiveEpochs)
218
- .every(p => p.missed / p.total >= this.config.slashInactivityTargetPercentage);
222
+ .every(p => (p.total === 0 ? false : p.missed / p.total >= this.config.slashInactivityTargetPercentage));
219
223
  }
220
224
 
221
225
  protected async handleProvenPerformance(epoch: EpochNumber, performance: ValidatorsEpochPerformance) {
@@ -224,7 +228,7 @@ export class Sentinel extends (EventEmitter as new () => WatcherEmitter) impleme
224
228
  }
225
229
 
226
230
  const inactiveValidators = getEntries(performance)
227
- .filter(([_, { missed, total }]) => missed / total >= this.config.slashInactivityTargetPercentage)
231
+ .filter(([_, { missed, total }]) => total > 0 && missed / total >= this.config.slashInactivityTargetPercentage)
228
232
  .map(([address]) => address);
229
233
 
230
234
  this.logger.debug(`Found ${inactiveValidators.length} inactive validators in epoch ${epoch}`, {
@@ -260,7 +264,7 @@ export class Sentinel extends (EventEmitter as new () => WatcherEmitter) impleme
260
264
  * and we don't have that data if we were offline during the period.
261
265
  */
262
266
  public async work() {
263
- const { slot: currentSlot } = this.epochCache.getEpochAndSlotNow();
267
+ const currentSlot = this.epochCache.getSlotNow();
264
268
  try {
265
269
  // Manually sync the block stream to ensure we have the latest data.
266
270
  // Note we never `start` the blockstream, so it loops at the same pace as we do.
@@ -305,9 +309,9 @@ export class Sentinel extends (EventEmitter as new () => WatcherEmitter) impleme
305
309
  return false;
306
310
  }
307
311
 
308
- const archiverSlot = await this.archiver.getL2SlotNumber();
309
- if (archiverSlot === undefined || archiverSlot < targetSlot) {
310
- this.logger.debug(`Waiting for archiver to sync with L2 slot ${targetSlot}`, { archiverSlot, targetSlot });
312
+ const syncedSlot = await this.archiver.getSyncedL2SlotNumber();
313
+ if (syncedSlot === undefined || syncedSlot < targetSlot) {
314
+ this.logger.debug(`Waiting for archiver to sync with L2 slot ${targetSlot}`, { syncedSlot, targetSlot });
311
315
  return false;
312
316
  }
313
317
 
@@ -327,7 +331,12 @@ export class Sentinel extends (EventEmitter as new () => WatcherEmitter) impleme
327
331
  * and updates overall stats.
328
332
  */
329
333
  protected async processSlot(slot: SlotNumber) {
330
- const { epoch, seed, committee } = await this.epochCache.getCommittee(slot);
334
+ const { epoch, seed, committee, isEscapeHatchOpen } = await this.epochCache.getCommittee(slot);
335
+ if (isEscapeHatchOpen) {
336
+ this.logger.info(`Skipping slot ${slot} at epoch ${epoch} - escape hatch is open`);
337
+ this.lastProcessedSlot = slot;
338
+ return;
339
+ }
331
340
  if (!committee || committee.length === 0) {
332
341
  this.logger.trace(`No committee found for slot ${slot} at epoch ${epoch}`);
333
342
  this.lastProcessedSlot = slot;
@@ -427,7 +436,7 @@ export class Sentinel extends (EventEmitter as new () => WatcherEmitter) impleme
427
436
  ? fromEntries(await Promise.all(validators.map(async v => [v.toString(), await this.store.getHistory(v)])))
428
437
  : await this.store.getHistories();
429
438
 
430
- const slotNow = this.epochCache.getEpochAndSlotNow().slot;
439
+ const slotNow = this.epochCache.getSlotNow();
431
440
  fromSlot ??= SlotNumber(Math.max((this.lastProcessedSlot ?? slotNow) - this.store.getHistoryLength(), 0));
432
441
  toSlot ??= this.lastProcessedSlot ?? slotNow;
433
442
 
@@ -455,7 +464,7 @@ export class Sentinel extends (EventEmitter as new () => WatcherEmitter) impleme
455
464
  return undefined;
456
465
  }
457
466
 
458
- const slotNow = this.epochCache.getEpochAndSlotNow().slot;
467
+ const slotNow = this.epochCache.getSlotNow();
459
468
  const effectiveFromSlot =
460
469
  fromSlot ?? SlotNumber(Math.max((this.lastProcessedSlot ?? slotNow) - this.store.getHistoryLength(), 0));
461
470
  const effectiveToSlot = toSlot ?? this.lastProcessedSlot ?? slotNow;