@aztec/aztec-node 3.0.0-canary.a9708bd → 3.0.0-devnet.2-patch.1

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,4 +1,5 @@
1
1
  import type { EpochCache } from '@aztec/epoch-cache';
2
+ import { BlockNumber, EpochNumber, SlotNumber } from '@aztec/foundation/branded-types';
2
3
  import { EthAddress } from '@aztec/foundation/eth-address';
3
4
  import { RunningPromise } from '@aztec/foundation/running-promise';
4
5
  import { type L2TipsStore } from '@aztec/kv-store/stores';
@@ -19,10 +20,10 @@ export declare class Sentinel extends Sentinel_base implements L2BlockStreamEven
19
20
  protected runningPromise: RunningPromise;
20
21
  protected blockStream: L2BlockStream;
21
22
  protected l2TipsStore: L2TipsStore;
22
- protected initialSlot: bigint | undefined;
23
- protected lastProcessedSlot: bigint | undefined;
24
- protected slotNumberToBlock: Map<bigint, {
25
- blockNumber: number;
23
+ protected initialSlot: SlotNumber | undefined;
24
+ protected lastProcessedSlot: SlotNumber | undefined;
25
+ protected slotNumberToBlock: Map<SlotNumber, {
26
+ blockNumber: BlockNumber;
26
27
  archive: string;
27
28
  attestors: EthAddress[];
28
29
  }>;
@@ -34,16 +35,15 @@ export declare class Sentinel extends Sentinel_base implements L2BlockStreamEven
34
35
  stop(): Promise<void>;
35
36
  handleBlockStreamEvent(event: L2BlockStreamEvent): Promise<void>;
36
37
  protected handleChainProven(event: L2BlockStreamEvent): Promise<void>;
37
- protected computeProvenPerformance(epoch: bigint): Promise<ValidatorsEpochPerformance>;
38
- protected updateProvenPerformance(epoch: bigint, performance: ValidatorsEpochPerformance): Promise<void>;
38
+ protected computeProvenPerformance(epoch: EpochNumber): Promise<ValidatorsEpochPerformance>;
39
39
  /**
40
40
  * Checks if a validator has been inactive for the specified number of consecutive epochs for which we have data on it.
41
41
  * @param validator The validator address to check
42
42
  * @param currentEpoch Epochs strictly before the current one are evaluated only
43
43
  * @param requiredConsecutiveEpochs Number of consecutive epochs required for slashing
44
44
  */
45
- protected checkPastInactivity(validator: EthAddress, currentEpoch: bigint, requiredConsecutiveEpochs: number): Promise<boolean>;
46
- protected handleProvenPerformance(epoch: bigint, performance: ValidatorsEpochPerformance): Promise<void>;
45
+ protected checkPastInactivity(validator: EthAddress, currentEpoch: EpochNumber, requiredConsecutiveEpochs: number): Promise<boolean>;
46
+ protected handleProvenPerformance(epoch: EpochNumber, performance: ValidatorsEpochPerformance): Promise<void>;
47
47
  /**
48
48
  * Process data for two L2 slots ago.
49
49
  * Note that we do not process historical data, since we rely on p2p data for processing,
@@ -55,36 +55,38 @@ export declare class Sentinel extends Sentinel_base implements L2BlockStreamEven
55
55
  * We also don't move past the archiver last synced L2 slot, as we don't want to process data that is not yet available.
56
56
  * Last, we check the p2p is synced with the archiver, so it has pulled all attestations from it.
57
57
  */
58
- protected isReadyToProcess(currentSlot: bigint): Promise<bigint | false>;
58
+ protected isReadyToProcess(currentSlot: SlotNumber): Promise<SlotNumber | false>;
59
59
  /**
60
60
  * Gathers committee and proposer data for a given slot, computes slot stats,
61
61
  * and updates overall stats.
62
62
  */
63
- protected processSlot(slot: bigint): Promise<void>;
63
+ protected processSlot(slot: SlotNumber): Promise<void>;
64
64
  /** Computes activity for a given slot. */
65
- protected getSlotActivity(slot: bigint, epoch: bigint, proposer: EthAddress, committee: EthAddress[]): Promise<{
65
+ protected getSlotActivity(slot: SlotNumber, epoch: EpochNumber, proposer: EthAddress, committee: EthAddress[]): Promise<{
66
66
  [k: string]: ValidatorStatusInSlot | undefined;
67
67
  }>;
68
68
  /** Push the status for each slot for each validator. */
69
- protected updateValidators(slot: bigint, stats: Record<`0x${string}`, ValidatorStatusInSlot | undefined>): Promise<void>;
69
+ protected updateValidators(slot: SlotNumber, stats: Record<`0x${string}`, ValidatorStatusInSlot | undefined>): Promise<void>;
70
70
  /** Computes stats to be returned based on stored data. */
71
- computeStats({ fromSlot: _fromSlot, toSlot: _toSlot, }?: {
72
- fromSlot?: bigint;
73
- toSlot?: bigint;
71
+ computeStats({ fromSlot, toSlot, validators }?: {
72
+ fromSlot?: SlotNumber;
73
+ toSlot?: SlotNumber;
74
+ validators?: EthAddress[];
74
75
  }): Promise<ValidatorsStats>;
75
76
  /** Computes stats for a single validator. */
76
- getValidatorStats(validatorAddress: EthAddress, fromSlot?: bigint, toSlot?: bigint): Promise<SingleValidatorStats | undefined>;
77
- protected computeStatsForValidator(address: `0x${string}`, allHistory: ValidatorStatusHistory, fromSlot?: bigint, toSlot?: bigint): ValidatorStats;
78
- protected computeMissed(history: ValidatorStatusHistory, computeOverPrefix: ValidatorStatusType, filter: ValidatorStatusInSlot): {
77
+ getValidatorStats(validatorAddress: EthAddress, fromSlot?: SlotNumber, toSlot?: SlotNumber): Promise<SingleValidatorStats | undefined>;
78
+ protected computeStatsForValidator(address: `0x${string}`, allHistory: ValidatorStatusHistory, fromSlot?: SlotNumber, toSlot?: SlotNumber): ValidatorStats;
79
+ protected computeMissed(history: ValidatorStatusHistory, computeOverPrefix: ValidatorStatusType | undefined, filter: ValidatorStatusInSlot[]): {
79
80
  currentStreak: number;
80
81
  rate: number | undefined;
81
82
  count: number;
83
+ total: number;
82
84
  };
83
- protected computeFromSlot(slot: bigint | undefined): {
85
+ protected computeFromSlot(slot: SlotNumber | undefined): {
84
86
  timestamp: bigint;
85
- slot: bigint;
87
+ slot: SlotNumber;
86
88
  date: string;
87
89
  } | undefined;
88
90
  }
89
91
  export {};
90
- //# sourceMappingURL=sentinel.d.ts.map
92
+ //# sourceMappingURL=data:application/json;base64,eyJ2ZXJzaW9uIjozLCJmaWxlIjoic2VudGluZWwuZC50cyIsInNvdXJjZVJvb3QiOiIiLCJzb3VyY2VzIjpbIi4uLy4uL3NyYy9zZW50aW5lbC9zZW50aW5lbC50cyJdLCJuYW1lcyI6W10sIm1hcHBpbmdzIjoiQUFBQSxPQUFPLEtBQUssRUFBRSxVQUFVLEVBQUUsTUFBTSxvQkFBb0IsQ0FBQztBQUNyRCxPQUFPLEVBQUUsV0FBVyxFQUFFLFdBQVcsRUFBRSxVQUFVLEVBQUUsTUFBTSxpQ0FBaUMsQ0FBQztBQUV2RixPQUFPLEVBQUUsVUFBVSxFQUFFLE1BQU0sK0JBQStCLENBQUM7QUFFM0QsT0FBTyxFQUFFLGNBQWMsRUFBRSxNQUFNLG1DQUFtQyxDQUFDO0FBQ25FLE9BQU8sRUFBcUIsS0FBSyxXQUFXLEVBQUUsTUFBTSx3QkFBd0IsQ0FBQztBQUM3RSxPQUFPLEtBQUssRUFBRSxTQUFTLEVBQUUsTUFBTSxZQUFZLENBQUM7QUFDNUMsT0FBTyxFQUlMLEtBQUssT0FBTyxFQUNaLEtBQUssY0FBYyxFQUNwQixNQUFNLGdCQUFnQixDQUFDO0FBQ3hCLE9BQU8sS0FBSyxFQUFFLGFBQWEsRUFBRSxNQUFNLHVCQUF1QixDQUFDO0FBQzNELE9BQU8sRUFDTCxLQUFLLGFBQWEsRUFDbEIsYUFBYSxFQUNiLEtBQUssa0JBQWtCLEVBQ3ZCLEtBQUsseUJBQXlCLEVBRS9CLE1BQU0scUJBQXFCLENBQUM7QUFFN0IsT0FBTyxLQUFLLEVBQ1Ysb0JBQW9CLEVBQ3BCLGNBQWMsRUFDZCxzQkFBc0IsRUFDdEIscUJBQXFCLEVBQ3JCLG1CQUFtQixFQUNuQiwwQkFBMEIsRUFDMUIsZUFBZSxFQUNoQixNQUFNLDBCQUEwQixDQUFDO0FBSWxDLE9BQU8sRUFBRSxhQUFhLEVBQUUsTUFBTSxZQUFZLENBQUM7O0FBRTNDLHFCQUFhLFFBQVMsU0FBUSxhQUEyQyxZQUFXLHlCQUF5QixFQUFFLE9BQU87SUFZbEgsU0FBUyxDQUFDLFVBQVUsRUFBRSxVQUFVO0lBQ2hDLFNBQVMsQ0FBQyxRQUFRLEVBQUUsYUFBYTtJQUNq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
@@ -1 +1 @@
1
- {"version":3,"file":"sentinel.d.ts","sourceRoot":"","sources":["../../src/sentinel/sentinel.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,UAAU,EAAE,MAAM,oBAAoB,CAAC;AAErD,OAAO,EAAE,UAAU,EAAE,MAAM,+BAA+B,CAAC;AAE3D,OAAO,EAAE,cAAc,EAAE,MAAM,mCAAmC,CAAC;AACnE,OAAO,EAAqB,KAAK,WAAW,EAAE,MAAM,wBAAwB,CAAC;AAC7E,OAAO,KAAK,EAAE,SAAS,EAAE,MAAM,YAAY,CAAC;AAC5C,OAAO,EAAoC,KAAK,OAAO,EAAE,KAAK,cAAc,EAAE,MAAM,gBAAgB,CAAC;AACrG,OAAO,KAAK,EAAE,aAAa,EAAE,MAAM,uBAAuB,CAAC;AAC3D,OAAO,EACL,KAAK,aAAa,EAClB,aAAa,EACb,KAAK,kBAAkB,EACvB,KAAK,yBAAyB,EAE/B,MAAM,qBAAqB,CAAC;AAE7B,OAAO,KAAK,EACV,oBAAoB,EACpB,cAAc,EACd,sBAAsB,EACtB,qBAAqB,EACrB,mBAAmB,EACnB,0BAA0B,EAC1B,eAAe,EAChB,MAAM,0BAA0B,CAAC;AAIlC,OAAO,EAAE,aAAa,EAAE,MAAM,YAAY,CAAC;6BAEI,UAAU,cAAc;AAAvE,qBAAa,QAAS,SAAQ,aAA2C,YAAW,yBAAyB,EAAE,OAAO;IAWlH,SAAS,CAAC,UAAU,EAAE,UAAU;IAChC,SAAS,CAAC,QAAQ,EAAE,aAAa;IACjC,SAAS,CAAC,GAAG,EAAE,SAAS;IACxB,SAAS,CAAC,KAAK,EAAE,aAAa;IAC9B,SAAS,CAAC,MAAM,EAAE,IAAI,CACpB,aAAa,EACb,iCAAiC,GAAG,wBAAwB,GAAG,0CAA0C,CAC1G;IACD,SAAS,CAAC,MAAM;IAlBlB,SAAS,CAAC,cAAc,EAAE,cAAc,CAAC;IACzC,SAAS,CAAC,WAAW,EAAG,aAAa,CAAC;IACtC,SAAS,CAAC,WAAW,EAAE,WAAW,CAAC;IAEnC,SAAS,CAAC,WAAW,EAAE,MAAM,GAAG,SAAS,CAAC;IAC1C,SAAS,CAAC,iBAAiB,EAAE,MAAM,GAAG,SAAS,CAAC;IAChD,SAAS,CAAC,iBAAiB,EAAE,GAAG,CAAC,MAAM,EAAE;QAAE,WAAW,EAAE,MAAM,CAAC;QAAC,OAAO,EAAE,MAAM,CAAC;QAAC,SAAS,EAAE,UAAU,EAAE,CAAA;KAAE,CAAC,CAC/F;gBAGA,UAAU,EAAE,UAAU,EACtB,QAAQ,EAAE,aAAa,EACvB,GAAG,EAAE,SAAS,EACd,KAAK,EAAE,aAAa,EACpB,MAAM,EAAE,IAAI,CACpB,aAAa,EACb,iCAAiC,GAAG,wBAAwB,GAAG,0CAA0C,CAC1G,EACS,MAAM,yCAAgC;IAQ3C,YAAY,CAAC,MAAM,EAAE,OAAO,CAAC,aAAa,CAAC;IAIrC,KAAK;IAKlB,kHAAkH;cAClG,IAAI;IAOb,IAAI;IAIE,sBAAsB,CAAC,KAAK,EAAE,kBAAkB,GAAG,OAAO,CAAC,IAAI,CAAC;cA2B7D,iBAAiB,CAAC,KAAK,EAAE,kBAAkB;cAoB3C,wBAAwB,CAAC,KAAK,EAAE,MAAM;IAoCtD,SAAS,CAAC,uBAAuB,CAAC,KAAK,EAAE,MAAM,EAAE,WAAW,EAAE,0BAA0B;IAIxF;;;;;OAKG;cACa,mBAAmB,CACjC,SAAS,EAAE,UAAU,EACrB,YAAY,EAAE,MAAM,EACpB,yBAAyB,EAAE,MAAM,GAChC,OAAO,CAAC,OAAO,CAAC;cAwBH,uBAAuB,CAAC,KAAK,EAAE,MAAM,EAAE,WAAW,EAAE,0BAA0B;IAkC9F;;;;OAIG;IACU,IAAI;IAmBjB;;;;OAIG;cACa,gBAAgB,CAAC,WAAW,EAAE,MAAM;IAkCpD;;;OAGG;cACa,WAAW,CAAC,IAAI,EAAE,MAAM;IAexC,0CAA0C;cAC1B,eAAe,CAAC,IAAI,EAAE,MAAM,EAAE,KAAK,EAAE,MAAM,EAAE,QAAQ,EAAE,UAAU,EAAE,SAAS,EAAE,UAAU,EAAE;;;IAwD1G,wDAAwD;IACxD,SAAS,CAAC,gBAAgB,CAAC,IAAI,EAAE,MAAM,EAAE,KAAK,EAAE,MAAM,CAAC,KAAK,MAAM,EAAE,EAAE,qBAAqB,GAAG,SAAS,CAAC;IAIxG,0DAA0D;IAC7C,YAAY,CAAC,EACxB,QAAQ,EAAE,SAAS,EACnB,MAAM,EAAE,OAAO,GAChB,GAAE;QAAE,QAAQ,CAAC,EAAE,MAAM,CAAC;QAAC,MAAM,CAAC,EAAE,MAAM,CAAA;KAAO,GAAG,OAAO,CAAC,eAAe,CAAC;IAkBzE,6CAA6C;IAChC,iBAAiB,CAC5B,gBAAgB,EAAE,UAAU,EAC5B,QAAQ,CAAC,EAAE,MAAM,EACjB,MAAM,CAAC,EAAE,MAAM,GACd,OAAO,CAAC,oBAAoB,GAAG,SAAS,CAAC;IAoC5C,SAAS,CAAC,wBAAwB,CAChC,OAAO,EAAE,KAAK,MAAM,EAAE,EACtB,UAAU,EAAE,sBAAsB,EAClC,QAAQ,CAAC,EAAE,MAAM,EACjB,MAAM,CAAC,EAAE,MAAM,GACd,cAAc;IAgBjB,SAAS,CAAC,aAAa,CACrB,OAAO,EAAE,sBAAsB,EAC/B,iBAAiB,EAAE,mBAAmB,EACtC,MAAM,EAAE,qBAAqB;;;;;IAW/B,SAAS,CAAC,eAAe,CAAC,IAAI,EAAE,MAAM,GAAG,SAAS;;;;;CAOnD"}
1
+ {"version":3,"file":"sentinel.d.ts","sourceRoot":"","sources":["../../src/sentinel/sentinel.ts"],"names":[],"mappings":"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"}
@@ -1,11 +1,12 @@
1
- import { countWhile, filterAsync } from '@aztec/foundation/collection';
1
+ import { BlockNumber, SlotNumber } from '@aztec/foundation/branded-types';
2
+ import { countWhile, filterAsync, fromEntries, getEntries, mapValues } from '@aztec/foundation/collection';
2
3
  import { EthAddress } from '@aztec/foundation/eth-address';
3
4
  import { createLogger } from '@aztec/foundation/log';
4
5
  import { RunningPromise } from '@aztec/foundation/running-promise';
5
6
  import { L2TipsMemoryStore } from '@aztec/kv-store/stores';
6
7
  import { OffenseType, WANT_TO_SLASH_EVENT } from '@aztec/slasher';
7
- import { L2BlockStream, getAttestationsFromPublishedL2Block } from '@aztec/stdlib/block';
8
- import { getEpochAtSlot, getTimestampForSlot } from '@aztec/stdlib/epoch-helpers';
8
+ import { L2BlockStream, getAttestationInfoFromPublishedL2Block } from '@aztec/stdlib/block';
9
+ import { getEpochAtSlot, getSlotRangeForEpoch, getTimestampForSlot } from '@aztec/stdlib/epoch-helpers';
9
10
  import EventEmitter from 'node:events';
10
11
  export class Sentinel extends EventEmitter {
11
12
  epochCache;
@@ -19,6 +20,7 @@ export class Sentinel extends EventEmitter {
19
20
  l2TipsStore;
20
21
  initialSlot;
21
22
  lastProcessedSlot;
23
+ // eslint-disable-next-line aztec-custom/no-non-primitive-in-collections
22
24
  slotNumberToBlock;
23
25
  constructor(epochCache, archiver, p2p, store, config, logger = createLogger('node:sentinel')){
24
26
  super(), this.epochCache = epochCache, this.archiver = archiver, this.p2p = p2p, this.store = store, this.config = config, this.logger = logger, this.slotNumberToBlock = new Map();
@@ -38,7 +40,7 @@ export class Sentinel extends EventEmitter {
38
40
  }
39
41
  /** Loads initial slot and initializes blockstream. We will not process anything at or before the initial slot. */ async init() {
40
42
  this.initialSlot = this.epochCache.getEpochAndSlotNow().slot;
41
- const startingBlock = await this.archiver.getBlockNumber();
43
+ const startingBlock = BlockNumber(await this.archiver.getBlockNumber());
42
44
  this.logger.info(`Starting validator sentinel with initial slot ${this.initialSlot} and block ${startingBlock}`);
43
45
  this.blockStream = new L2BlockStream(this.archiver, this.l2TipsStore, this, this.logger, {
44
46
  startingBlock
@@ -53,9 +55,9 @@ export class Sentinel extends EventEmitter {
53
55
  // Store mapping from slot to archive, block number, and attestors
54
56
  for (const block of event.blocks){
55
57
  this.slotNumberToBlock.set(block.block.header.getSlot(), {
56
- blockNumber: block.block.number,
58
+ blockNumber: BlockNumber(block.block.number),
57
59
  archive: block.block.archive.root.toString(),
58
- attestors: getAttestationsFromPublishedL2Block(block).map((att)=>att.getSender())
60
+ attestors: getAttestationInfoFromPublishedL2Block(block).filter((a)=>a.status === 'recovered-from-signature').map((a)=>a.address)
59
61
  });
60
62
  }
61
63
  // Prune the archive map to only keep at most N entries
@@ -74,7 +76,7 @@ export class Sentinel extends EventEmitter {
74
76
  if (event.type !== 'chain-proven') {
75
77
  return;
76
78
  }
77
- const blockNumber = event.block.number;
79
+ const blockNumber = BlockNumber(event.block.number);
78
80
  const block = await this.archiver.getBlock(blockNumber);
79
81
  if (!block) {
80
82
  this.logger.error(`Failed to get block ${blockNumber}`, {
@@ -82,18 +84,17 @@ export class Sentinel extends EventEmitter {
82
84
  });
83
85
  return;
84
86
  }
85
- const epoch = getEpochAtSlot(block.header.getSlot(), await this.archiver.getL1Constants());
87
+ // TODO(palla/slash): We should only be computing proven performance if this is
88
+ // a full proof epoch and not a partial one, otherwise we'll end up with skewed stats.
89
+ const epoch = getEpochAtSlot(block.header.getSlot(), this.epochCache.getL1Constants());
86
90
  this.logger.debug(`Computing proven performance for epoch ${epoch}`);
87
91
  const performance = await this.computeProvenPerformance(epoch);
88
92
  this.logger.info(`Computed proven performance for epoch ${epoch}`, performance);
89
- await this.updateProvenPerformance(epoch, performance);
93
+ await this.store.updateProvenPerformance(epoch, performance);
90
94
  await this.handleProvenPerformance(epoch, performance);
91
95
  }
92
96
  async computeProvenPerformance(epoch) {
93
- const headers = await this.archiver.getBlockHeadersForEpoch(epoch);
94
- const provenSlots = headers.map((h)=>h.getSlot());
95
- const fromSlot = provenSlots[0];
96
- const toSlot = provenSlots[provenSlots.length - 1];
97
+ const [fromSlot, toSlot] = getSlotRangeForEpoch(epoch, this.epochCache.getL1Constants());
97
98
  const { committee } = await this.epochCache.getCommittee(fromSlot);
98
99
  if (!committee) {
99
100
  this.logger.trace(`No committee found for slot ${fromSlot}`);
@@ -101,36 +102,25 @@ export class Sentinel extends EventEmitter {
101
102
  }
102
103
  const stats = await this.computeStats({
103
104
  fromSlot,
104
- toSlot
105
+ toSlot,
106
+ validators: committee
105
107
  });
106
- this.logger.debug(`Stats for epoch ${epoch}`, stats);
107
- const performance = {};
108
- for (const validator of Object.keys(stats.stats)){
109
- let address;
110
- try {
111
- address = EthAddress.fromString(validator);
112
- } catch (e) {
113
- this.logger.error(`Invalid validator address ${validator}`, e);
114
- continue;
115
- }
116
- if (!committee.find((v)=>v.equals(address))) {
117
- continue;
118
- }
119
- let missed = 0;
120
- for (const history of stats.stats[validator].history){
121
- if (provenSlots.includes(history.slot) && history.status === 'attestation-missed') {
122
- missed++;
123
- }
124
- }
125
- performance[address.toString()] = {
126
- missed,
127
- total: provenSlots.length
128
- };
129
- }
130
- return performance;
131
- }
132
- updateProvenPerformance(epoch, performance) {
133
- return this.store.updateProvenPerformance(epoch, performance);
108
+ this.logger.debug(`Stats for epoch ${epoch}`, {
109
+ ...stats,
110
+ fromSlot,
111
+ toSlot,
112
+ epoch
113
+ });
114
+ // Note that we are NOT using the total slots in the epoch as `total` here, since we only
115
+ // compute missed attestations over the blocks that had a proposal in them. So, let's say
116
+ // we have an epoch with 10 slots, but only 5 had a block proposal. A validator that was
117
+ // offline, assuming they were not picked as proposer, will then be reported as having missed
118
+ // 5/5 attestations. If we used the total, they'd be reported as 5/10, which would probably
119
+ // allow them to avoid being slashed.
120
+ return mapValues(stats.stats, (stat)=>({
121
+ missed: stat.missedAttestations.count + stat.missedProposals.count,
122
+ total: stat.missedAttestations.total + stat.missedProposals.total
123
+ }));
134
124
  }
135
125
  /**
136
126
  * Checks if a validator has been inactive for the specified number of consecutive epochs for which we have data on it.
@@ -143,18 +133,21 @@ export class Sentinel extends EventEmitter {
143
133
  }
144
134
  // Get all historical performance for this validator
145
135
  const allPerformance = await this.store.getProvenPerformance(validator);
136
+ // Sort by epoch descending to get most recent first, keep only epochs strictly before the current one, and get the first N
137
+ const pastEpochs = allPerformance.sort((a, b)=>Number(b.epoch - a.epoch)).filter((p)=>p.epoch < currentEpoch);
146
138
  // If we don't have enough historical data, don't slash
147
- if (allPerformance.length < requiredConsecutiveEpochs) {
139
+ if (pastEpochs.length < requiredConsecutiveEpochs) {
148
140
  this.logger.debug(`Not enough historical data for slashing ${validator} for inactivity (${allPerformance.length} epochs < ${requiredConsecutiveEpochs} required)`);
149
141
  return false;
150
142
  }
151
- // Sort by epoch descending to get most recent first, keep only epochs strictly before the current one, and get the first N
152
- return allPerformance.sort((a, b)=>Number(b.epoch - a.epoch)).filter((p)=>p.epoch < currentEpoch).slice(0, requiredConsecutiveEpochs).every((p)=>p.missed / p.total >= this.config.slashInactivityTargetPercentage);
143
+ // Check that we have at least requiredConsecutiveEpochs and that all of them are above the inactivity threshold
144
+ return pastEpochs.slice(0, requiredConsecutiveEpochs).every((p)=>p.missed / p.total >= this.config.slashInactivityTargetPercentage);
153
145
  }
154
146
  async handleProvenPerformance(epoch, performance) {
155
- const inactiveValidators = Object.entries(performance).filter(([_, { missed, total }])=>{
156
- return missed / total >= this.config.slashInactivityTargetPercentage;
157
- }).map(([address])=>address);
147
+ if (this.config.slashInactivityPenalty === 0n) {
148
+ return;
149
+ }
150
+ const inactiveValidators = getEntries(performance).filter(([_, { missed, total }])=>missed / total >= this.config.slashInactivityTargetPercentage).map(([address])=>address);
158
151
  this.logger.debug(`Found ${inactiveValidators.length} inactive validators in epoch ${epoch}`, {
159
152
  inactiveValidators,
160
153
  epoch,
@@ -166,10 +159,10 @@ export class Sentinel extends EventEmitter {
166
159
  validator: EthAddress.fromString(address),
167
160
  amount: this.config.slashInactivityPenalty,
168
161
  offenseType: OffenseType.INACTIVITY,
169
- epochOrSlot: epoch
162
+ epochOrSlot: BigInt(epoch)
170
163
  }));
171
164
  if (criminals.length > 0) {
172
- this.logger.info(`Identified ${criminals.length} validators to slash due to inactivity in at least ${epochThreshold} consecutive epochs`, {
165
+ this.logger.verbose(`Identified ${criminals.length} validators to slash due to inactivity in at least ${epochThreshold} consecutive epochs`, {
173
166
  ...args,
174
167
  epochThreshold
175
168
  });
@@ -201,7 +194,11 @@ export class Sentinel extends EventEmitter {
201
194
  * We also don't move past the archiver last synced L2 slot, as we don't want to process data that is not yet available.
202
195
  * Last, we check the p2p is synced with the archiver, so it has pulled all attestations from it.
203
196
  */ async isReadyToProcess(currentSlot) {
204
- const targetSlot = currentSlot - 2n;
197
+ if (currentSlot < 2) {
198
+ this.logger.trace(`Current slot ${currentSlot} too early.`);
199
+ return false;
200
+ }
201
+ const targetSlot = SlotNumber(currentSlot - 2);
205
202
  if (this.lastProcessedSlot && this.lastProcessedSlot >= targetSlot) {
206
203
  this.logger.trace(`Already processed slot ${targetSlot}`, {
207
204
  lastProcessedSlot: this.lastProcessedSlot
@@ -217,7 +214,7 @@ export class Sentinel extends EventEmitter {
217
214
  return false;
218
215
  }
219
216
  const archiverSlot = await this.archiver.getL2SlotNumber();
220
- if (archiverSlot < targetSlot) {
217
+ if (archiverSlot === undefined || archiverSlot < targetSlot) {
221
218
  this.logger.debug(`Waiting for archiver to sync with L2 slot ${targetSlot}`, {
222
219
  archiverSlot,
223
220
  targetSlot
@@ -267,14 +264,18 @@ export class Sentinel extends EventEmitter {
267
264
  // (contains the ones synced from mined blocks, which we may have missed from p2p).
268
265
  const block = this.slotNumberToBlock.get(slot);
269
266
  const p2pAttested = await this.p2p.getAttestationsForSlot(slot, block?.archive);
267
+ // Filter out attestations with invalid signatures
268
+ const p2pAttestors = p2pAttested.map((a)=>a.getSender()).filter((s)=>s !== undefined);
270
269
  const attestors = new Set([
271
- ...p2pAttested.map((a)=>a.getSender().toString()),
270
+ ...p2pAttestors.map((a)=>a.toString()),
272
271
  ...block?.attestors.map((a)=>a.toString()) ?? []
273
- ]);
274
- // We assume that there was a block proposal if at least one of the validators attested to it.
272
+ ].filter((addr)=>proposer.toString() !== addr));
273
+ // We assume that there was a block proposal if at least one of the validators (other than the proposer) attested to it.
275
274
  // It could be the case that every single validator failed, and we could differentiate it by having
276
275
  // this node re-execute every block proposal it sees and storing it in the attestation pool.
277
276
  // But we'll leave that corner case out to reduce pressure on the node.
277
+ // TODO(palla/slash): This breaks if a given node has more than one validator in the current committee,
278
+ // since they will attest to their own proposal it even if it's not re-executable.
278
279
  const blockStatus = block ? 'mined' : attestors.size > 0 ? 'proposed' : 'missed';
279
280
  this.logger.debug(`Block for slot ${slot} was ${blockStatus}`, {
280
281
  ...block,
@@ -315,18 +316,17 @@ export class Sentinel extends EventEmitter {
315
316
  /** Push the status for each slot for each validator. */ updateValidators(slot, stats) {
316
317
  return this.store.updateValidators(slot, stats);
317
318
  }
318
- /** Computes stats to be returned based on stored data. */ async computeStats({ fromSlot: _fromSlot, toSlot: _toSlot } = {}) {
319
- const histories = await this.store.getHistories();
319
+ /** Computes stats to be returned based on stored data. */ async computeStats({ fromSlot, toSlot, validators } = {}) {
320
+ const histories = validators ? fromEntries(await Promise.all(validators.map(async (v)=>[
321
+ v.toString(),
322
+ await this.store.getHistory(v)
323
+ ]))) : await this.store.getHistories();
320
324
  const slotNow = this.epochCache.getEpochAndSlotNow().slot;
321
- const fromSlot = _fromSlot ?? (this.lastProcessedSlot ?? slotNow) - BigInt(this.store.getHistoryLength());
322
- const toSlot = _toSlot ?? this.lastProcessedSlot ?? slotNow;
323
- const result = {};
324
- for (const [address, history] of Object.entries(histories)){
325
- const validatorAddress = address;
326
- result[validatorAddress] = this.computeStatsForValidator(validatorAddress, history, fromSlot, toSlot);
327
- }
325
+ fromSlot ??= SlotNumber(Math.max((this.lastProcessedSlot ?? slotNow) - this.store.getHistoryLength(), 0));
326
+ toSlot ??= this.lastProcessedSlot ?? slotNow;
327
+ const stats = mapValues(histories, (history, address)=>this.computeStatsForValidator(address, history ?? [], fromSlot, toSlot));
328
328
  return {
329
- stats: result,
329
+ stats,
330
330
  lastProcessedSlot: this.lastProcessedSlot,
331
331
  initialSlot: this.initialSlot,
332
332
  slotWindow: this.store.getHistoryLength()
@@ -338,44 +338,50 @@ export class Sentinel extends EventEmitter {
338
338
  return undefined;
339
339
  }
340
340
  const slotNow = this.epochCache.getEpochAndSlotNow().slot;
341
- const effectiveFromSlot = fromSlot ?? (this.lastProcessedSlot ?? slotNow) - BigInt(this.store.getHistoryLength());
341
+ const effectiveFromSlot = fromSlot ?? SlotNumber(Math.max((this.lastProcessedSlot ?? slotNow) - this.store.getHistoryLength(), 0));
342
342
  const effectiveToSlot = toSlot ?? this.lastProcessedSlot ?? slotNow;
343
343
  const historyLength = BigInt(this.store.getHistoryLength());
344
- if (effectiveToSlot - effectiveFromSlot > historyLength) {
345
- throw new Error(`Slot range (${effectiveToSlot - effectiveFromSlot}) exceeds history length (${historyLength}). ` + `Requested range: ${effectiveFromSlot} to ${effectiveToSlot}.`);
344
+ if (BigInt(effectiveToSlot) - BigInt(effectiveFromSlot) > historyLength) {
345
+ throw new Error(`Slot range (${BigInt(effectiveToSlot) - BigInt(effectiveFromSlot)}) exceeds history length (${historyLength}). ` + `Requested range: ${effectiveFromSlot} to ${effectiveToSlot}.`);
346
346
  }
347
347
  const validator = this.computeStatsForValidator(validatorAddress.toString(), history, effectiveFromSlot, effectiveToSlot);
348
- const allTimeProvenPerformance = await this.store.getProvenPerformance(validatorAddress);
349
348
  return {
350
349
  validator,
351
- allTimeProvenPerformance,
350
+ allTimeProvenPerformance: await this.store.getProvenPerformance(validatorAddress),
352
351
  lastProcessedSlot: this.lastProcessedSlot,
353
352
  initialSlot: this.initialSlot,
354
353
  slotWindow: this.store.getHistoryLength()
355
354
  };
356
355
  }
357
356
  computeStatsForValidator(address, allHistory, fromSlot, toSlot) {
358
- let history = fromSlot ? allHistory.filter((h)=>h.slot >= fromSlot) : allHistory;
359
- history = toSlot ? history.filter((h)=>h.slot <= toSlot) : history;
357
+ let history = fromSlot ? allHistory.filter((h)=>BigInt(h.slot) >= fromSlot) : allHistory;
358
+ history = toSlot ? history.filter((h)=>BigInt(h.slot) <= toSlot) : history;
359
+ const lastProposal = history.filter((h)=>h.status === 'block-proposed' || h.status === 'block-mined').at(-1);
360
+ const lastAttestation = history.filter((h)=>h.status === 'attestation-sent').at(-1);
360
361
  return {
361
362
  address: EthAddress.fromString(address),
362
- lastProposal: this.computeFromSlot(history.filter((h)=>h.status === 'block-proposed' || h.status === 'block-mined').at(-1)?.slot),
363
- lastAttestation: this.computeFromSlot(history.filter((h)=>h.status === 'attestation-sent').at(-1)?.slot),
363
+ lastProposal: this.computeFromSlot(lastProposal?.slot),
364
+ lastAttestation: this.computeFromSlot(lastAttestation?.slot),
364
365
  totalSlots: history.length,
365
- missedProposals: this.computeMissed(history, 'block', 'block-missed'),
366
- missedAttestations: this.computeMissed(history, 'attestation', 'attestation-missed'),
366
+ missedProposals: this.computeMissed(history, 'block', [
367
+ 'block-missed'
368
+ ]),
369
+ missedAttestations: this.computeMissed(history, 'attestation', [
370
+ 'attestation-missed'
371
+ ]),
367
372
  history
368
373
  };
369
374
  }
370
375
  computeMissed(history, computeOverPrefix, filter) {
371
- const relevantHistory = history.filter((h)=>h.status.startsWith(computeOverPrefix));
372
- const filteredHistory = relevantHistory.filter((h)=>h.status === filter);
376
+ const relevantHistory = history.filter((h)=>!computeOverPrefix || h.status.startsWith(computeOverPrefix));
377
+ const filteredHistory = relevantHistory.filter((h)=>filter.includes(h.status));
373
378
  return {
374
379
  currentStreak: countWhile([
375
380
  ...relevantHistory
376
- ].reverse(), (h)=>h.status === filter),
381
+ ].reverse(), (h)=>filter.includes(h.status)),
377
382
  rate: relevantHistory.length === 0 ? undefined : filteredHistory.length / relevantHistory.length,
378
- count: filteredHistory.length
383
+ count: filteredHistory.length,
384
+ total: relevantHistory.length
379
385
  };
380
386
  }
381
387
  computeFromSlot(slot) {
@@ -1,24 +1,27 @@
1
+ import { EpochNumber, SlotNumber } from '@aztec/foundation/branded-types';
1
2
  import { EthAddress } from '@aztec/foundation/eth-address';
2
3
  import type { AztecAsyncKVStore } from '@aztec/kv-store';
3
4
  import type { ValidatorStatusHistory, ValidatorStatusInSlot, ValidatorsEpochPerformance } from '@aztec/stdlib/validators';
4
5
  export declare class SentinelStore {
5
6
  private store;
6
7
  private config;
7
- static readonly SCHEMA_VERSION = 2;
8
+ static readonly SCHEMA_VERSION: number;
8
9
  private readonly historyMap;
9
10
  private readonly provenMap;
10
11
  constructor(store: AztecAsyncKVStore, config: {
11
12
  historyLength: number;
13
+ historicProvenPerformanceLength: number;
12
14
  });
13
15
  getHistoryLength(): number;
14
- updateProvenPerformance(epoch: bigint, performance: ValidatorsEpochPerformance): Promise<void>;
16
+ getHistoricProvenPerformanceLength(): number;
17
+ updateProvenPerformance(epoch: EpochNumber, performance: ValidatorsEpochPerformance): Promise<void>;
15
18
  getProvenPerformance(who: EthAddress): Promise<{
16
19
  missed: number;
17
20
  total: number;
18
- epoch: bigint;
21
+ epoch: EpochNumber;
19
22
  }[]>;
20
23
  private pushValidatorProvenPerformanceForEpoch;
21
- updateValidators(slot: bigint, statuses: Record<`0x${string}`, ValidatorStatusInSlot | undefined>): Promise<void>;
24
+ updateValidators(slot: SlotNumber, statuses: Record<`0x${string}`, ValidatorStatusInSlot | undefined>): Promise<void>;
22
25
  private pushValidatorStatusForSlot;
23
26
  getHistories(): Promise<Record<`0x${string}`, ValidatorStatusHistory>>;
24
27
  getHistory(address: EthAddress): Promise<ValidatorStatusHistory | undefined>;
@@ -29,4 +32,4 @@ export declare class SentinelStore {
29
32
  private statusToNumber;
30
33
  private statusFromNumber;
31
34
  }
32
- //# sourceMappingURL=store.d.ts.map
35
+ //# sourceMappingURL=data:application/json;base64,eyJ2ZXJzaW9uIjozLCJmaWxlIjoic3RvcmUuZC50cyIsInNvdXJjZVJvb3QiOiIiLCJzb3VyY2VzIjpbIi4uLy4uL3NyYy9zZW50aW5lbC9zdG9yZS50cyJdLCJuYW1lcyI6W10sIm1hcHBpbmdzIjoiQUFBQSxPQUFPLEVBQUUsV0FBVyxFQUFFLFVBQVUsRUFBRSxNQUFNLGlDQUFpQyxDQUFDO0FBQzFFLE9BQU8sRUFBRSxVQUFVLEVBQUUsTUFBTSwrQkFBK0IsQ0FBQztBQUUzRCxPQUFPLEtBQUssRUFBRSxpQkFBaUIsRUFBaUIsTUFBTSxpQkFBaUIsQ0FBQztBQUN4RSxPQUFPLEtBQUssRUFDVixzQkFBc0IsRUFDdEIscUJBQXFCLEVBQ3JCLDBCQUEwQixFQUMzQixNQUFNLDBCQUEwQixDQUFDO0FBRWxDLHFCQUFhLGFBQWE7SUFXdEIsT0FBTyxDQUFDLEtBQUs7SUFDYixPQUFPLENBQUMsTUFBTTtJQVhoQixnQkFBdUIsY0FBYyxTQUFLO0lBRzFDLE9BQU8sQ0FBQyxRQUFRLENBQUMsVUFBVSxDQUF1QztJQUlsRSxPQUFPLENBQUMsUUFBUSxDQUFDLFNBQVMsQ0FBdUM7SUFFakUsWUFDVSxLQUFLLEVBQUUsaUJBQWlCLEVBQ3hCLE1BQU0sRUFBRTtRQUFFLGFBQWEsRUFBRSxNQUFNLENBQUM7UUFBQywrQkFBK0IsRUFBRSxNQUFNLENBQUE7S0FBRSxFQUluRjtJQUVNLGdCQUFnQixXQUV0QjtJQUVNLGtDQUFrQyxXQUV4QztJQUVZLHVCQUF1QixDQUFDLEtBQUssRUFBRSxXQUFXLEVBQUUsV0FBVyxFQUFFLDBCQUEwQixpQkFNL0Y7SUFFWSxvQkFBb0IsQ0FBQyxHQUFHLEVBQUUsVUFBVSxHQUFHLE9BQU8sQ0FBQztRQUFFLE1BQU0sRUFBRSxNQUFNLENBQUM7UUFBQyxLQUFLLEVBQUUsTUFBTSxDQUFDO1FBQUMsS0FBSyxFQUFFLFdBQVcsQ0FBQTtLQUFFLEVBQUUsQ0FBQyxDQUduSDtZQUVhLHNDQUFzQztJQTZCdkMsZ0JBQWdCLENBQUMsSUFBSSxFQUFFLFVBQVUsRUFBRSxRQUFRLEVBQUUsTUFBTSxDQUFDLEtBQUssTUFBTSxFQUFFLEVBQUUscUJBQXFCLEdBQUcsU0FBUyxDQUFDLGlCQVFqSDtZQUVhLDBCQUEwQjtJQVkzQixZQUFZLElBQUksT0FBTyxDQUFDLE1BQU0sQ0FBQyxLQUFLLE1BQU0sRUFBRSxFQUFFLHNCQUFzQixDQUFDLENBQUMsQ0FNbEY7SUFFWSxVQUFVLENBQUMsT0FBTyxFQUFFLFVBQVUsR0FBRyxPQUFPLENBQUMsc0JBQXNCLEdBQUcsU0FBUyxDQUFDLENBR3hGO0lBRUQsT0FBTyxDQUFDLG9CQUFvQjtJQU01QixPQUFPLENBQUMsc0JBQXNCO0lBYTlCLE9BQU8sQ0FBQyxnQkFBZ0I7SUFNeEIsT0FBTyxDQUFDLGtCQUFrQjtJQVcxQixPQUFPLENBQUMsY0FBYztJQW1CdEIsT0FBTyxDQUFDLGdCQUFnQjtDQWdCekIifQ==
@@ -1 +1 @@
1
- {"version":3,"file":"store.d.ts","sourceRoot":"","sources":["../../src/sentinel/store.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,UAAU,EAAE,MAAM,+BAA+B,CAAC;AAE3D,OAAO,KAAK,EAAE,iBAAiB,EAAiB,MAAM,iBAAiB,CAAC;AACxE,OAAO,KAAK,EACV,sBAAsB,EACtB,qBAAqB,EACrB,0BAA0B,EAC3B,MAAM,0BAA0B,CAAC;AAElC,qBAAa,aAAa;IAWtB,OAAO,CAAC,KAAK;IACb,OAAO,CAAC,MAAM;IAXhB,gBAAuB,cAAc,KAAK;IAG1C,OAAO,CAAC,QAAQ,CAAC,UAAU,CAAuC;IAIlE,OAAO,CAAC,QAAQ,CAAC,SAAS,CAAuC;gBAGvD,KAAK,EAAE,iBAAiB,EACxB,MAAM,EAAE;QAAE,aAAa,EAAE,MAAM,CAAA;KAAE;IAMpC,gBAAgB;IAIV,uBAAuB,CAAC,KAAK,EAAE,MAAM,EAAE,WAAW,EAAE,0BAA0B;IAQ9E,oBAAoB,CAAC,GAAG,EAAE,UAAU,GAAG,OAAO,CAAC;QAAE,MAAM,EAAE,MAAM,CAAC;QAAC,KAAK,EAAE,MAAM,CAAC;QAAC,KAAK,EAAE,MAAM,CAAA;KAAE,EAAE,CAAC;YAKjG,sCAAsC;IA6BvC,gBAAgB,CAAC,IAAI,EAAE,MAAM,EAAE,QAAQ,EAAE,MAAM,CAAC,KAAK,MAAM,EAAE,EAAE,qBAAqB,GAAG,SAAS,CAAC;YAUhG,0BAA0B;IAY3B,YAAY,IAAI,OAAO,CAAC,MAAM,CAAC,KAAK,MAAM,EAAE,EAAE,sBAAsB,CAAC,CAAC;IAQtE,UAAU,CAAC,OAAO,EAAE,UAAU,GAAG,OAAO,CAAC,sBAAsB,GAAG,SAAS,CAAC;IAKzF,OAAO,CAAC,oBAAoB;IAM5B,OAAO,CAAC,sBAAsB;IAa9B,OAAO,CAAC,gBAAgB;IAMxB,OAAO,CAAC,kBAAkB;IAW1B,OAAO,CAAC,cAAc;IAmBtB,OAAO,CAAC,gBAAgB;CAgBzB"}
1
+ {"version":3,"file":"store.d.ts","sourceRoot":"","sources":["../../src/sentinel/store.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,WAAW,EAAE,UAAU,EAAE,MAAM,iCAAiC,CAAC;AAC1E,OAAO,EAAE,UAAU,EAAE,MAAM,+BAA+B,CAAC;AAE3D,OAAO,KAAK,EAAE,iBAAiB,EAAiB,MAAM,iBAAiB,CAAC;AACxE,OAAO,KAAK,EACV,sBAAsB,EACtB,qBAAqB,EACrB,0BAA0B,EAC3B,MAAM,0BAA0B,CAAC;AAElC,qBAAa,aAAa;IAWtB,OAAO,CAAC,KAAK;IACb,OAAO,CAAC,MAAM;IAXhB,gBAAuB,cAAc,SAAK;IAG1C,OAAO,CAAC,QAAQ,CAAC,UAAU,CAAuC;IAIlE,OAAO,CAAC,QAAQ,CAAC,SAAS,CAAuC;IAEjE,YACU,KAAK,EAAE,iBAAiB,EACxB,MAAM,EAAE;QAAE,aAAa,EAAE,MAAM,CAAC;QAAC,+BAA+B,EAAE,MAAM,CAAA;KAAE,EAInF;IAEM,gBAAgB,WAEtB;IAEM,kCAAkC,WAExC;IAEY,uBAAuB,CAAC,KAAK,EAAE,WAAW,EAAE,WAAW,EAAE,0BAA0B,iBAM/F;IAEY,oBAAoB,CAAC,GAAG,EAAE,UAAU,GAAG,OAAO,CAAC;QAAE,MAAM,EAAE,MAAM,CAAC;QAAC,KAAK,EAAE,MAAM,CAAC;QAAC,KAAK,EAAE,WAAW,CAAA;KAAE,EAAE,CAAC,CAGnH;YAEa,sCAAsC;IA6BvC,gBAAgB,CAAC,IAAI,EAAE,UAAU,EAAE,QAAQ,EAAE,MAAM,CAAC,KAAK,MAAM,EAAE,EAAE,qBAAqB,GAAG,SAAS,CAAC,iBAQjH;YAEa,0BAA0B;IAY3B,YAAY,IAAI,OAAO,CAAC,MAAM,CAAC,KAAK,MAAM,EAAE,EAAE,sBAAsB,CAAC,CAAC,CAMlF;IAEY,UAAU,CAAC,OAAO,EAAE,UAAU,GAAG,OAAO,CAAC,sBAAsB,GAAG,SAAS,CAAC,CAGxF;IAED,OAAO,CAAC,oBAAoB;IAM5B,OAAO,CAAC,sBAAsB;IAa9B,OAAO,CAAC,gBAAgB;IAMxB,OAAO,CAAC,kBAAkB;IAW1B,OAAO,CAAC,cAAc;IAmBtB,OAAO,CAAC,gBAAgB;CAgBzB"}
@@ -1,3 +1,4 @@
1
+ import { EpochNumber, SlotNumber } from '@aztec/foundation/branded-types';
1
2
  import { EthAddress } from '@aztec/foundation/eth-address';
2
3
  import { BufferReader, numToUInt8, numToUInt32BE, serializeToBuffer } from '@aztec/foundation/serialize';
3
4
  export class SentinelStore {
@@ -18,6 +19,9 @@ export class SentinelStore {
18
19
  getHistoryLength() {
19
20
  return this.config.historyLength;
20
21
  }
22
+ getHistoricProvenPerformanceLength() {
23
+ return this.config.historicProvenPerformanceLength;
24
+ }
21
25
  async updateProvenPerformance(epoch, performance) {
22
26
  await this.store.transactionAsync(async ()=>{
23
27
  for (const [who, { missed, total }] of Object.entries(performance)){
@@ -53,8 +57,8 @@ export class SentinelStore {
53
57
  // This should be sorted by epoch, but just in case.
54
58
  // Since we keep the size small, this is not a big deal.
55
59
  currentPerformance.sort((a, b)=>Number(a.epoch - b.epoch));
56
- // keep the most recent `historyLength` entries.
57
- const performanceToKeep = currentPerformance.slice(-this.config.historyLength);
60
+ // keep the most recent `historicProvenPerformanceLength` entries.
61
+ const performanceToKeep = currentPerformance.slice(-this.config.historicProvenPerformanceLength);
58
62
  await this.provenMap.set(who.toString(), this.serializePerformance(performanceToKeep));
59
63
  }
60
64
  async updateValidators(slot, statuses) {
@@ -102,7 +106,7 @@ export class SentinelStore {
102
106
  const performance = [];
103
107
  while(!reader.isEmpty()){
104
108
  performance.push({
105
- epoch: BigInt(reader.readNumber()),
109
+ epoch: EpochNumber(reader.readNumber()),
106
110
  missed: reader.readNumber(),
107
111
  total: reader.readNumber()
108
112
  });
@@ -119,7 +123,7 @@ export class SentinelStore {
119
123
  const reader = new BufferReader(buffer);
120
124
  const history = [];
121
125
  while(!reader.isEmpty()){
122
- const slot = BigInt(reader.readNumber());
126
+ const slot = SlotNumber(reader.readNumber());
123
127
  const status = this.statusFromNumber(reader.readUInt8());
124
128
  history.push({
125
129
  slot,
@@ -28,4 +28,4 @@ export declare class TestAztecNodeService extends AztecNodeService {
28
28
  epochCache: EpochCacheInterface;
29
29
  packageVersion: string;
30
30
  }
31
- //# sourceMappingURL=index.d.ts.map
31
+ //# sourceMappingURL=data:application/json;base64,eyJ2ZXJzaW9uIjozLCJmaWxlIjoiaW5kZXguZC50cyIsInNvdXJjZVJvb3QiOiIiLCJzb3VyY2VzIjpbIi4uLy4uL3NyYy90ZXN0L2luZGV4LnRzIl0sIm5hbWVzIjpbXSwibWFwcGluZ3MiOiJBQUFBLE9BQU8sS0FBSyxFQUFFLG1CQUFtQixFQUFFLE1BQU0sb0JBQW9CLENBQUM7QUFDOUQsT0FBTyxLQUFLLEVBQUUsR0FBRyxFQUFFLE1BQU0sWUFBWSxDQUFDO0FBQ3RDLE9BQU8sRUFBRSxlQUFlLEVBQUUsTUFBTSx5QkFBeUIsQ0FBQztBQUMxRCxPQUFPLEVBQUUsaUJBQWlCLEVBQUUsS0FBSyxzQkFBc0IsRUFBRSxNQUFNLGdCQUFnQixDQUFDO0FBQ2hGLE9BQU8sS0FBSyxFQUFFLGFBQWEsRUFBRSxNQUFNLHFCQUFxQixDQUFDO0FBQ3pELE9BQU8sS0FBSyxFQUFFLGtCQUFrQixFQUFFLE1BQU0sd0JBQXdCLENBQUM7QUFDakUsT0FBTyxLQUFLLEVBQUUsWUFBWSxFQUFFLE9BQU8sRUFBRSxzQkFBc0IsRUFBRSxNQUFNLGlDQUFpQyxDQUFDO0FBQ3JHLE9BQU8sS0FBSyxFQUFFLG1CQUFtQixFQUFFLE1BQU0seUJBQXlCLENBQUM7QUFDbkUsT0FBTyxLQUFLLEVBQUUscUJBQXFCLElBQUksOEJBQThCLEVBQUUsTUFBTSxrQkFBa0IsQ0FBQztBQUVoRyxPQUFPLEtBQUssRUFBRSxlQUFlLEVBQUUsTUFBTSx5QkFBeUIsQ0FBQztBQUMvRCxPQUFPLEVBQUUsZ0JBQWdCLEVBQUUsTUFBTSx5QkFBeUIsQ0FBQztBQUMzRCxPQUFPLEVBQUUsUUFBUSxFQUFFLE1BQU0seUJBQXlCLENBQUM7QUFFbkQsTUFBTSxDQUFDLE9BQU8sT0FBTyxvQkFBcUIsU0FBUSxnQkFBZ0I7SUFDakQsTUFBTSxFQUFFLGVBQWUsQ0FBQztJQUN4QixTQUFTLEVBQUUsR0FBRyxDQUFDO0lBQ2YsV0FBVyxFQUFFLGFBQWEsR0FBRyxPQUFPLENBQUMsT0FBTyxDQUFDLENBQUM7SUFDOUMsVUFBVSxFQUFFLFlBQVksQ0FBQztJQUN6QixrQkFBa0IsRUFBRSxrQkFBa0IsQ0FBQztJQUN2QyxtQkFBbUIsRUFBRSxtQkFBbUIsQ0FBQztJQUN6QyxzQkFBc0IsRUFBRSxzQkFBc0IsQ0FBQztJQUMvQyxTQUFTLEVBQUUsZUFBZSxHQUFHLFNBQVMsQ0FBQztJQUN2QyxhQUFhLEVBQUUsc0JBQXNCLEdBQUcsU0FBUyxDQUFDO0lBQ2xELGtCQUFrQixFQUFFLFFBQVEsR0FBRyxTQUFTLENBQUM7SUFDekMsaUJBQWlCLEVBQUUsaUJBQWlCLEdBQUcsU0FBUyxDQUFDO0lBQ2pELFNBQVMsRUFBRSxNQUFNLENBQUM7SUFDbEIsT0FBTyxFQUFFLE1BQU0sQ0FBQztJQUNoQixxQkFBcUIsRUFBRSw4QkFBOEIsQ0FBQztJQUN0RCxVQUFVLEVBQUUsbUJBQW1CLENBQUM7SUFDaEMsY0FBYyxFQUFFLE1BQU0sQ0FBQztDQUN2QyJ9
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@aztec/aztec-node",
3
- "version": "3.0.0-canary.a9708bd",
3
+ "version": "3.0.0-devnet.2-patch.1",
4
4
  "main": "dest/index.js",
5
5
  "type": "module",
6
6
  "exports": {
@@ -20,8 +20,8 @@
20
20
  "scripts": {
21
21
  "start": "node --no-warnings ./dest/bin",
22
22
  "start:debug": "node --no-warnings --inspect ./dest/bin",
23
- "build": "yarn clean && tsc -b",
24
- "build:dev": "tsc -b --watch",
23
+ "build": "yarn clean && ../scripts/tsc.sh",
24
+ "build:dev": "../scripts/tsc.sh --watch",
25
25
  "clean": "rm -rf ./dest .tsbuildinfo",
26
26
  "test": "NODE_NO_WARNINGS=1 node --experimental-vm-modules ../node_modules/.bin/jest --passWithNoTests --maxWorkers=${JEST_MAX_WORKERS:-8}"
27
27
  },
@@ -66,38 +66,39 @@
66
66
  ]
67
67
  },
68
68
  "dependencies": {
69
- "@aztec/archiver": "3.0.0-canary.a9708bd",
70
- "@aztec/bb-prover": "3.0.0-canary.a9708bd",
71
- "@aztec/blob-sink": "3.0.0-canary.a9708bd",
72
- "@aztec/constants": "3.0.0-canary.a9708bd",
73
- "@aztec/epoch-cache": "3.0.0-canary.a9708bd",
74
- "@aztec/ethereum": "3.0.0-canary.a9708bd",
75
- "@aztec/foundation": "3.0.0-canary.a9708bd",
76
- "@aztec/kv-store": "3.0.0-canary.a9708bd",
77
- "@aztec/l1-artifacts": "3.0.0-canary.a9708bd",
78
- "@aztec/merkle-tree": "3.0.0-canary.a9708bd",
79
- "@aztec/node-keystore": "3.0.0-canary.a9708bd",
80
- "@aztec/node-lib": "3.0.0-canary.a9708bd",
81
- "@aztec/noir-protocol-circuits-types": "3.0.0-canary.a9708bd",
82
- "@aztec/p2p": "3.0.0-canary.a9708bd",
83
- "@aztec/protocol-contracts": "3.0.0-canary.a9708bd",
84
- "@aztec/prover-client": "3.0.0-canary.a9708bd",
85
- "@aztec/sequencer-client": "3.0.0-canary.a9708bd",
86
- "@aztec/simulator": "3.0.0-canary.a9708bd",
87
- "@aztec/slasher": "3.0.0-canary.a9708bd",
88
- "@aztec/stdlib": "3.0.0-canary.a9708bd",
89
- "@aztec/telemetry-client": "3.0.0-canary.a9708bd",
90
- "@aztec/validator-client": "3.0.0-canary.a9708bd",
91
- "@aztec/world-state": "3.0.0-canary.a9708bd",
69
+ "@aztec/archiver": "3.0.0-devnet.2-patch.1",
70
+ "@aztec/bb-prover": "3.0.0-devnet.2-patch.1",
71
+ "@aztec/blob-sink": "3.0.0-devnet.2-patch.1",
72
+ "@aztec/constants": "3.0.0-devnet.2-patch.1",
73
+ "@aztec/epoch-cache": "3.0.0-devnet.2-patch.1",
74
+ "@aztec/ethereum": "3.0.0-devnet.2-patch.1",
75
+ "@aztec/foundation": "3.0.0-devnet.2-patch.1",
76
+ "@aztec/kv-store": "3.0.0-devnet.2-patch.1",
77
+ "@aztec/l1-artifacts": "3.0.0-devnet.2-patch.1",
78
+ "@aztec/merkle-tree": "3.0.0-devnet.2-patch.1",
79
+ "@aztec/node-keystore": "3.0.0-devnet.2-patch.1",
80
+ "@aztec/node-lib": "3.0.0-devnet.2-patch.1",
81
+ "@aztec/noir-protocol-circuits-types": "3.0.0-devnet.2-patch.1",
82
+ "@aztec/p2p": "3.0.0-devnet.2-patch.1",
83
+ "@aztec/protocol-contracts": "3.0.0-devnet.2-patch.1",
84
+ "@aztec/prover-client": "3.0.0-devnet.2-patch.1",
85
+ "@aztec/sequencer-client": "3.0.0-devnet.2-patch.1",
86
+ "@aztec/simulator": "3.0.0-devnet.2-patch.1",
87
+ "@aztec/slasher": "3.0.0-devnet.2-patch.1",
88
+ "@aztec/stdlib": "3.0.0-devnet.2-patch.1",
89
+ "@aztec/telemetry-client": "3.0.0-devnet.2-patch.1",
90
+ "@aztec/validator-client": "3.0.0-devnet.2-patch.1",
91
+ "@aztec/world-state": "3.0.0-devnet.2-patch.1",
92
92
  "koa": "^2.16.1",
93
- "koa-router": "^12.0.0",
93
+ "koa-router": "^13.1.1",
94
94
  "tslib": "^2.4.0",
95
- "viem": "2.23.7"
95
+ "viem": "npm:@aztec/viem@2.38.2"
96
96
  },
97
97
  "devDependencies": {
98
98
  "@jest/globals": "^30.0.0",
99
99
  "@types/jest": "^30.0.0",
100
100
  "@types/node": "^22.15.17",
101
+ "@typescript/native-preview": "7.0.0-dev.20251126.1",
101
102
  "jest": "^30.0.0",
102
103
  "jest-mock-extended": "^4.0.0",
103
104
  "ts-node": "^10.9.1",