@aztec/epoch-cache 0.0.1-commit.c2eed6949 → 0.0.1-commit.c52d6e7

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,14 +1,15 @@
1
1
  import { createEthereumChain } from '@aztec/ethereum/chain';
2
2
  import { makeL1HttpTransport } from '@aztec/ethereum/client';
3
3
  import { NoCommitteeError, RollupContract } from '@aztec/ethereum/contracts';
4
+ import { getFinalizedL1Block } from '@aztec/ethereum/queries';
4
5
  import { SlotNumber } from '@aztec/foundation/branded-types';
5
6
  import { EthAddress } from '@aztec/foundation/eth-address';
6
7
  import { createLogger } from '@aztec/foundation/log';
7
8
  import { DateProvider } from '@aztec/foundation/timer';
8
- import { getEpochAtSlot, getEpochNumberAtTimestamp, getNextL1SlotTimestamp, getSlotAtTimestamp, getSlotRangeForEpoch, getTimestampForSlot } from '@aztec/stdlib/epoch-helpers';
9
+ import { getEpochAtSlot, getEpochNumberAtTimestamp, getNextL1SlotTimestamp, getSlotAtNextL1Block, getSlotAtTimestamp, getSlotRangeForEpoch, getStartTimestampForEpoch, getTimestampForSlot } from '@aztec/stdlib/epoch-helpers';
9
10
  import { createPublicClient, encodeAbiParameters, keccak256 } from 'viem';
10
11
  import { getEpochCacheConfigEnvVars } from './config.js';
11
- /** When proposer pipelining is enabled, the proposer builds one slot ahead. */ export const PROPOSER_PIPELINING_SLOT_OFFSET = 1;
12
+ /** The proposer pipelines by building one slot ahead. */ export const PROPOSER_PIPELINING_SLOT_OFFSET = 1;
12
13
  /**
13
14
  * Epoch cache
14
15
  *
@@ -22,16 +23,16 @@ import { getEpochCacheConfigEnvVars } from './config.js';
22
23
  l1constants;
23
24
  dateProvider;
24
25
  config;
25
- // eslint-disable-next-line aztec-custom/no-non-primitive-in-collections
26
- cache;
26
+ /**
27
+ * Single map holding both resolved entries and in-flight promises.
28
+ * A `Promise` value means a fetch is in progress; concurrent callers await it.
29
+ */ cache;
27
30
  allValidators;
28
31
  lastValidatorRefresh;
29
32
  log;
30
- enableProposerPipelining;
31
33
  constructor(rollup, l1constants, dateProvider = new DateProvider(), config = {
32
34
  cacheSize: 12,
33
- validatorRefreshIntervalSeconds: 60,
34
- enableProposerPipelining: false
35
+ validatorRefreshIntervalSeconds: 60
35
36
  }){
36
37
  this.rollup = rollup;
37
38
  this.l1constants = l1constants;
@@ -41,10 +42,8 @@ import { getEpochCacheConfigEnvVars } from './config.js';
41
42
  this.allValidators = new Set();
42
43
  this.lastValidatorRefresh = 0;
43
44
  this.log = createLogger('epoch-cache');
44
- this.enableProposerPipelining = this.config.enableProposerPipelining;
45
45
  this.log.debug(`Initialized EpochCache`, {
46
- l1constants,
47
- enableProposerPipelining: this.enableProposerPipelining
46
+ l1constants
48
47
  });
49
48
  }
50
49
  static async create(rollupOrAddress, config, deps = {}) {
@@ -89,22 +88,26 @@ import { getEpochCacheConfigEnvVars } from './config.js';
89
88
  };
90
89
  return new EpochCache(rollup, l1RollupConstants, deps.dateProvider, {
91
90
  cacheSize: 12,
92
- validatorRefreshIntervalSeconds: 60,
93
- enableProposerPipelining: config.enableProposerPipelining
91
+ validatorRefreshIntervalSeconds: 60
94
92
  });
95
93
  }
96
94
  getL1Constants() {
97
95
  return this.l1constants;
98
96
  }
99
- isProposerPipeliningEnabled() {
100
- return this.enableProposerPipelining;
97
+ /**
98
+ * The number of epochs by which validator-set sampling lags. The committee for epoch `E` samples the
99
+ * validator set as of `lagInEpochsForValidatorSet` epochs before `E` (see
100
+ * `ValidatorSelectionLib.stableEpochToValidatorSetSampleTime` on L1), so a newly staked validator only
101
+ * becomes eligible for a committee this many epochs after staking.
102
+ */ getLagInEpochsForValidatorSet() {
103
+ return this.l1constants.lagInEpochsForValidatorSet;
101
104
  }
102
105
  getSlotNow() {
103
106
  return this.getEpochAndSlotNow().slot;
104
107
  }
105
108
  getTargetSlot() {
106
109
  const slotNow = this.getSlotNow();
107
- const offset = this.isProposerPipeliningEnabled() ? PROPOSER_PIPELINING_SLOT_OFFSET : 0;
110
+ const offset = PROPOSER_PIPELINING_SLOT_OFFSET;
108
111
  return SlotNumber(slotNow + offset);
109
112
  }
110
113
  getEpochNow() {
@@ -133,9 +136,6 @@ import { getEpochCacheConfigEnvVars } from './config.js';
133
136
  };
134
137
  }
135
138
  getTargetEpochAndSlotInNextL1Slot() {
136
- if (!this.isProposerPipeliningEnabled()) {
137
- return this.getEpochAndSlotInNextL1Slot();
138
- }
139
139
  const result = this.getEpochAndSlotInNextL1Slot();
140
140
  const offset = PROPOSER_PIPELINING_SLOT_OFFSET;
141
141
  const targetSlot = SlotNumber(result.slot + offset);
@@ -158,16 +158,7 @@ import { getEpochCacheConfigEnvVars } from './config.js';
158
158
  const [startSlot] = getSlotRangeForEpoch(epoch, this.l1constants);
159
159
  return this.getCommittee(startSlot);
160
160
  }
161
- /**
162
- * Returns whether the escape hatch is open for the given epoch.
163
- *
164
- * Uses the already-cached EpochCommitteeInfo when available. If not cached, it will fetch
165
- * the epoch committee info (which includes the escape hatch flag) and return it.
166
- */ async isEscapeHatchOpen(epoch) {
167
- const cached = this.cache.get(epoch);
168
- if (cached) {
169
- return cached.isEscapeHatchOpen;
170
- }
161
+ /** Returns whether the escape hatch is open for the given epoch. */ async isEscapeHatchOpen(epoch) {
171
162
  const info = await this.getCommitteeForEpoch(epoch);
172
163
  return info.isEscapeHatchOpen;
173
164
  }
@@ -181,26 +172,43 @@ import { getEpochCacheConfigEnvVars } from './config.js';
181
172
  return await this.isEscapeHatchOpen(epoch);
182
173
  }
183
174
  /**
184
- * Get the current validator set
185
- * @param nextSlot - If true, get the validator set for the next slot.
186
- * @returns The current validator set.
175
+ * Get the current validator set.
176
+ *
177
+ * Returns cached data if the entry is finalized or still fresh (queried less than one
178
+ * Ethereum slot ago). Stale non-finalized entries are re-queried, and concurrent callers
179
+ * coalesce on the same in-flight promise so the L1 query happens only once.
187
180
  */ async getCommittee(slot = 'now') {
188
181
  const { epoch, ts } = this.getEpochAndTimestamp(slot);
189
- if (this.cache.has(epoch)) {
190
- return this.cache.get(epoch);
182
+ const cached = this.cache.get(epoch);
183
+ // In-flight promise: another caller is already fetching this epoch — just await it.
184
+ if (cached instanceof Promise) {
185
+ return (await cached).data;
191
186
  }
192
- const epochData = await this.computeCommittee({
193
- epoch,
194
- ts
195
- });
196
- // If the committee size is 0 or undefined, then do not cache
197
- if (!epochData.committee || epochData.committee.length === 0) {
198
- return epochData;
187
+ // Resolved entry: return it if finalized or still fresh.
188
+ if (cached && (cached.finalized || !this.isStale(cached))) {
189
+ return cached.data;
190
+ }
191
+ // Stale non-finalized entry: do a lightweight refresh first (check block hash + finalized ts).
192
+ // Only fall back to a full re-fetch if the L1 block was reorged.
193
+ if (cached) {
194
+ const promise = this.refreshStaleEntry(cached, epoch, ts);
195
+ this.cache.set(epoch, promise);
196
+ try {
197
+ return (await promise).data;
198
+ } catch (err) {
199
+ this.cache.set(epoch, cached);
200
+ throw err;
201
+ }
202
+ }
203
+ // No entry at all: full fetch.
204
+ const promise = this.fetchAndCache(epoch, ts);
205
+ this.cache.set(epoch, promise);
206
+ try {
207
+ return (await promise).data;
208
+ } catch (err) {
209
+ this.cache.delete(epoch);
210
+ throw err;
199
211
  }
200
- this.cache.set(epoch, epochData);
201
- const toPurge = Array.from(this.cache.keys()).sort((a, b)=>Number(b - a)).slice(this.config.cacheSize);
202
- toPurge.forEach((key)=>this.cache.delete(key));
203
- return epochData;
204
212
  }
205
213
  getEpochAndTimestamp(slot = 'now') {
206
214
  if (slot === 'now') {
@@ -211,27 +219,121 @@ import { getEpochCacheConfigEnvVars } from './config.js';
211
219
  return this.getEpochAndSlotAtSlot(slot);
212
220
  }
213
221
  }
214
- async computeCommittee(when) {
215
- const { ts, epoch } = when;
216
- const [committee, seedBuffer, l1Timestamp, isEscapeHatchOpen] = await Promise.all([
222
+ /** Evicts oldest cache entries (resolved or in-flight) beyond cacheSize. */ purgeCache() {
223
+ if (this.cache.size <= this.config.cacheSize) {
224
+ return;
225
+ }
226
+ const toPurge = Array.from(this.cache.keys()).sort((a, b)=>Number(b - a)).slice(this.config.cacheSize);
227
+ toPurge.forEach((key)=>this.cache.delete(key));
228
+ }
229
+ /** Returns true if a non-finalized cache entry is older than one Ethereum slot. */ isStale(entry) {
230
+ const nowSeconds = BigInt(this.dateProvider.nowInSeconds());
231
+ return nowSeconds - entry.lastRefreshL1Timestamp >= BigInt(this.l1constants.ethereumSlotDuration);
232
+ }
233
+ /** Whether a cached epoch entry has been marked as finalized. Returns undefined if not cached or still in-flight. */ isFinalized(epoch) {
234
+ const entry = this.cache.get(epoch);
235
+ if (!entry || entry instanceof Promise) {
236
+ return undefined;
237
+ }
238
+ return entry.finalized;
239
+ }
240
+ /** Returns the latest L1 timestamp stored in the cached entry. Undefined if not cached or in-flight. */ getCachedLastRefreshL1Timestamp(epoch) {
241
+ const entry = this.cache.get(epoch);
242
+ if (!entry || entry instanceof Promise) {
243
+ return undefined;
244
+ }
245
+ return entry.lastRefreshL1Timestamp;
246
+ }
247
+ /** Computes the sampling timestamp for an epoch's committee data. */ getSamplingTimestamp(epoch) {
248
+ const { lagInEpochsForRandao, epochDuration, slotDuration } = this.l1constants;
249
+ const epochStartTs = getStartTimestampForEpoch(epoch, this.l1constants);
250
+ return epochStartTs - BigInt(lagInEpochsForRandao) * BigInt(epochDuration) * BigInt(slotDuration);
251
+ }
252
+ /**
253
+ * Lightweight refresh for a stale non-finalized entry. Queries only the block hash at
254
+ * the original block number and the finalized block timestamp — avoids the expensive
255
+ * getCommitteeAt and getSampleSeedAt calls on the rollup contract.
256
+ *
257
+ * If the block hash still matches (no L1 reorg), we keep the existing data and just
258
+ * update the provenance timestamp. If the finalized block has caught up, we promote the
259
+ * entry to finalized. If there was a reorg (hash mismatch), we fall back to a full fetch.
260
+ */ async refreshStaleEntry(stale, epoch, ts) {
261
+ const [blockAtOriginal, l1FinalizedBlock, latestBlock] = await Promise.all([
262
+ this.rollup.client.getBlock({
263
+ blockNumber: stale.lastQueryL1BlockNumber,
264
+ includeTransactions: false
265
+ }),
266
+ getFinalizedL1Block(this.rollup.client),
267
+ this.rollup.client.getBlock({
268
+ includeTransactions: false
269
+ })
270
+ ]);
271
+ if (blockAtOriginal.hash === stale.lastQueryL1BlockHash) {
272
+ // No reorg: the data is still valid. Check if we can now mark it as finalized.
273
+ const samplingTs = this.getSamplingTimestamp(epoch);
274
+ const finalized = !!(stale.data.committee && stale.data.committee.length > 0) && l1FinalizedBlock !== undefined && samplingTs <= l1FinalizedBlock.timestamp;
275
+ const refreshed = {
276
+ ...stale,
277
+ lastRefreshL1Timestamp: latestBlock.timestamp,
278
+ finalized
279
+ };
280
+ this.cache.set(epoch, refreshed);
281
+ return refreshed;
282
+ }
283
+ // Reorg detected: block hash mismatch. Do a full re-fetch.
284
+ // Pass the already-fetched block timestamps to avoid redundant queries.
285
+ this.log.warn(`L1 reorg detected for epoch ${epoch}: block ${stale.lastQueryL1BlockNumber} hash changed`, {
286
+ epoch,
287
+ expectedHash: stale.lastQueryL1BlockHash,
288
+ actualHash: blockAtOriginal.hash
289
+ });
290
+ return this.fetchAndCache(epoch, ts, {
291
+ latestBlock,
292
+ finalizedBlock: l1FinalizedBlock
293
+ });
294
+ }
295
+ /**
296
+ * Fetches committee data from L1, determines finalization status, and stores in the cache.
297
+ *
298
+ * Uses `lagInEpochsForRandao` (the binding constraint, always <= lagInEpochsForValidatorSet)
299
+ * and computes the sampling timestamp from the epoch start to match the L1 contract's logic.
300
+ *
301
+ * When called from refreshStaleEntry after a reorg, the latest and finalized blocks are
302
+ * passed in to avoid redundant L1 queries.
303
+ */ async fetchAndCache(epoch, ts, prefetched) {
304
+ const [committee, seedBuffer, latestBlock, finalizedBlock, isEscapeHatchOpen] = await Promise.all([
217
305
  this.rollup.getCommitteeAt(ts),
218
306
  this.rollup.getSampleSeedAt(ts),
219
- this.rollup.client.getBlock({
307
+ prefetched?.latestBlock ?? this.rollup.client.getBlock({
220
308
  includeTransactions: false
221
- }).then((b)=>b.timestamp),
309
+ }),
310
+ prefetched !== undefined ? prefetched.finalizedBlock : getFinalizedL1Block(this.rollup.client),
222
311
  this.rollup.isEscapeHatchOpen(epoch)
223
312
  ]);
224
- const { lagInEpochsForValidatorSet, epochDuration, slotDuration } = this.l1constants;
225
- const sub = BigInt(lagInEpochsForValidatorSet) * BigInt(epochDuration) * BigInt(slotDuration);
226
- if (ts - sub > l1Timestamp) {
227
- throw new Error(`Cannot query committee for future epoch ${epoch} with timestamp ${ts} (current L1 time is ${l1Timestamp}). Check your Ethereum node is synced.`);
313
+ const samplingTs = this.getSamplingTimestamp(epoch);
314
+ if (samplingTs > latestBlock.timestamp) {
315
+ throw new Error(`Cannot query committee for future epoch ${epoch}: ` + `sampling timestamp ${samplingTs} is beyond latest L1 block at ${latestBlock.timestamp}. ` + `Check your Ethereum node is synced.`);
228
316
  }
229
- return {
317
+ // Empty committees are never marked finalized so they always get re-queried after TTL.
318
+ // If L1 has no finalized block yet (devnet startup), entries stay unfinalized.
319
+ const hasCommittee = !!(committee && committee.length > 0);
320
+ const finalized = hasCommittee && finalizedBlock !== undefined && samplingTs <= finalizedBlock.timestamp;
321
+ const data = {
230
322
  committee,
231
323
  seed: seedBuffer.toBigInt(),
232
324
  epoch,
233
325
  isEscapeHatchOpen
234
326
  };
327
+ const entry = {
328
+ data,
329
+ lastQueryL1BlockNumber: latestBlock.number,
330
+ lastQueryL1BlockHash: latestBlock.hash,
331
+ lastRefreshL1Timestamp: latestBlock.timestamp,
332
+ finalized
333
+ };
334
+ this.cache.set(epoch, entry);
335
+ this.purgeCache();
336
+ return entry;
235
337
  }
236
338
  /**
237
339
  * Get the ABI encoding of the proposer index - see ValidatorSelectionLib.sol computeProposerIndex
@@ -270,12 +372,16 @@ import { getEpochCacheConfigEnvVars } from './config.js';
270
372
  nextSlot: next.slot
271
373
  };
272
374
  }
273
- /** Returns the taget and next L2 slot in the next L1 slot */ getTargetAndNextSlot() {
274
- const targetSlot = this.getTargetSlot();
275
- const next = this.getTargetEpochAndSlotInNextL1Slot();
375
+ /** Returns the target and next L2 slot in the next L1 slot. */ getTargetAndNextSlot() {
376
+ const nowSeconds = BigInt(this.dateProvider.nowInSeconds());
377
+ const offset = PROPOSER_PIPELINING_SLOT_OFFSET;
378
+ const currentSlot = getSlotAtTimestamp(nowSeconds, this.l1constants);
379
+ const targetSlot = SlotNumber(currentSlot + offset);
380
+ const nextL2SlotOnL1 = getSlotAtNextL1Block(nowSeconds, this.l1constants);
381
+ const nextSlot = SlotNumber(nextL2SlotOnL1 + offset);
276
382
  return {
277
383
  targetSlot,
278
- nextSlot: next.slot
384
+ nextSlot
279
385
  };
280
386
  }
281
387
  /**
@@ -17,8 +17,9 @@ export declare class TestEpochCache implements EpochCacheInterface {
17
17
  private seed;
18
18
  private registeredValidators;
19
19
  private l1Constants;
20
- private proposerPipeliningEnabled;
20
+ private lagInEpochsForValidatorSet;
21
21
  constructor(l1Constants?: Partial<L1RollupConstants>);
22
+ setLagInEpochsForValidatorSet(lag: number): this;
22
23
  /**
23
24
  * Sets the committee members. Used in validation and attestation flows.
24
25
  * @param committee - Array of committee member addresses.
@@ -55,13 +56,12 @@ export declare class TestEpochCache implements EpochCacheInterface {
55
56
  */
56
57
  setL1Constants(constants: Partial<L1RollupConstants>): this;
57
58
  getL1Constants(): L1RollupConstants;
58
- setProposerPipeliningEnabled(enabled: boolean): void;
59
+ getLagInEpochsForValidatorSet(): number;
59
60
  getCommittee(_slot?: SlotTag): Promise<EpochCommitteeInfo>;
60
61
  getSlotNow(): SlotNumber;
61
62
  getTargetSlot(): SlotNumber;
62
63
  getEpochNow(): EpochNumber;
63
64
  getTargetEpoch(): EpochNumber;
64
- isProposerPipeliningEnabled(): boolean;
65
65
  getEpochAndSlotNow(): EpochAndSlot & {
66
66
  nowMs: bigint;
67
67
  };
@@ -88,4 +88,4 @@ export declare class TestEpochCache implements EpochCacheInterface {
88
88
  isEscapeHatchOpen(_epoch: EpochNumber): Promise<boolean>;
89
89
  isEscapeHatchOpenAtSlot(_slot?: SlotTag): Promise<boolean>;
90
90
  }
91
- //# sourceMappingURL=data:application/json;base64,eyJ2ZXJzaW9uIjozLCJmaWxlIjoidGVzdF9lcG9jaF9jYWNoZS5kLnRzIiwic291cmNlUm9vdCI6IiIsInNvdXJjZXMiOlsiLi4vLi4vc3JjL3Rlc3QvdGVzdF9lcG9jaF9jYWNoZS50cyJdLCJuYW1lcyI6W10sIm1hcHBpbmdzIjoiQUFBQSxPQUFPLEVBQUUsV0FBVyxFQUFFLFVBQVUsRUFBRSxNQUFNLGlDQUFpQyxDQUFDO0FBQzFFLE9BQU8sRUFBRSxVQUFVLEVBQUUsTUFBTSwrQkFBK0IsQ0FBQztBQUMzRCxPQUFPLEtBQUssRUFBRSxpQkFBaUIsRUFBRSxNQUFNLDZCQUE2QixDQUFDO0FBR3JFLE9BQU8sRUFDTCxLQUFLLFlBQVksRUFDakIsS0FBSyxtQkFBbUIsRUFDeEIsS0FBSyxrQkFBa0IsRUFFdkIsS0FBSyxPQUFPLEVBQ2IsTUFBTSxtQkFBbUIsQ0FBQztBQWMzQjs7Ozs7O0dBTUc7QUFDSCxxQkFBYSxjQUFlLFlBQVcsbUJBQW1CO0lBQ3hELE9BQU8sQ0FBQyxTQUFTLENBQW9CO0lBQ3JDLE9BQU8sQ0FBQyxlQUFlLENBQXlCO0lBQ2hELE9BQU8sQ0FBQyxXQUFXLENBQTZCO0lBQ2hELE9BQU8sQ0FBQyxlQUFlLENBQWtCO0lBQ3pDLE9BQU8sQ0FBQyxJQUFJLENBQWM7SUFDMUIsT0FBTyxDQUFDLG9CQUFvQixDQUFvQjtJQUNoRCxPQUFPLENBQUMsV0FBVyxDQUFvQjtJQUN2QyxPQUFPLENBQUMseUJBQXlCLENBQVM7SUFFMUMsWUFBWSxXQUFXLEdBQUUsT0FBTyxDQUFDLGlCQUFpQixDQUFNLEVBRXZEO0lBRUQ7OztPQUdHO0lBQ0gsWUFBWSxDQUFDLFNBQVMsRUFBRSxVQUFVLEVBQUUsR0FBRyxJQUFJLENBRzFDO0lBRUQ7OztPQUdHO0lBQ0gsV0FBVyxDQUFDLFFBQVEsRUFBRSxVQUFVLEdBQUcsU0FBUyxHQUFHLElBQUksQ0FHbEQ7SUFFRDs7O09BR0c7SUFDSCxjQUFjLENBQUMsSUFBSSxFQUFFLFVBQVUsR0FBRyxJQUFJLENBR3JDO0lBRUQ7OztPQUdHO0lBQ0gsa0JBQWtCLENBQUMsSUFBSSxFQUFFLE9BQU8sR0FBRyxJQUFJLENBR3RDO0lBRUQ7OztPQUdHO0lBQ0gsT0FBTyxDQUFDLElBQUksRUFBRSxNQUFNLEdBQUcsSUFBSSxDQUcxQjtJQUVEOzs7T0FHRztJQUNILHVCQUF1QixDQUFDLFVBQVUsRUFBRSxVQUFVLEVBQUUsR0FBRyxJQUFJLENBR3REO0lBRUQ7OztPQUdHO0lBQ0gsY0FBYyxDQUFDLFNBQVMsRUFBRSxPQUFPLENBQUMsaUJBQWlCLENBQUMsR0FBRyxJQUFJLENBRzFEO0lBRUQsY0FBYyxJQUFJLGlCQUFpQixDQUVsQztJQUVELDRCQUE0QixDQUFDLE9BQU8sRUFBRSxPQUFPLEdBQUcsSUFBSSxDQUVuRDtJQUVELFlBQVksQ0FBQyxLQUFLLENBQUMsRUFBRSxPQUFPLEdBQUcsT0FBTyxDQUFDLGtCQUFrQixDQUFDLENBUXpEO0lBRUQsVUFBVSxJQUFJLFVBQVUsQ0FFdkI7SUFFRCxhQUFhLElBQUksVUFBVSxDQUkxQjtJQUVELFdBQVcsSUFBSSxXQUFXLENBRXpCO0lBRUQsY0FBYyxJQUFJLFdBQVcsQ0FFNUI7SUFFRCwyQkFBMkIsSUFBSSxPQUFPLENBRXJDO0lBRUQsa0JBQWtCLElBQUksWUFBWSxHQUFHO1FBQUUsS0FBSyxFQUFFLE1BQU0sQ0FBQTtLQUFFLENBU3JEO0lBRUQsMkJBQTJCLElBQUksWUFBWSxHQUFHO1FBQUUsVUFBVSxFQUFFLE1BQU0sQ0FBQTtLQUFFLENBWW5FO0lBRUQsaUNBQWlDLElBQUksWUFBWSxHQUFHO1FBQUUsVUFBVSxFQUFFLE1BQU0sQ0FBQTtLQUFFLENBS3pFO0lBRUQsd0JBQXdCLENBQUMsS0FBSyxFQUFFLFdBQVcsRUFBRSxJQUFJLEVBQUUsVUFBVSxFQUFFLElBQUksRUFBRSxNQUFNLEdBQUcsS0FBSyxNQUFNLEVBQUUsQ0FHMUY7SUFFRCxvQkFBb0IsQ0FBQyxJQUFJLEVBQUUsVUFBVSxFQUFFLE1BQU0sRUFBRSxXQUFXLEVBQUUsS0FBSyxFQUFFLE1BQU0sRUFBRSxJQUFJLEVBQUUsTUFBTSxHQUFHLE1BQU0sQ0FLL0Y7SUFFRCxxQkFBcUIsSUFBSTtRQUFFLFdBQVcsRUFBRSxVQUFVLENBQUM7UUFBQyxRQUFRLEVBQUUsVUFBVSxDQUFBO0tBQUUsQ0FRekU7SUFFRCxvQkFBb0IsSUFBSTtRQUFFLFVBQVUsRUFBRSxVQUFVLENBQUM7UUFBQyxRQUFRLEVBQUUsVUFBVSxDQUFBO0tBQUUsQ0FRdkU7SUFFRCxnQ0FBZ0MsQ0FBQyxLQUFLLEVBQUUsVUFBVSxHQUFHLE9BQU8sQ0FBQyxVQUFVLEdBQUcsU0FBUyxDQUFDLENBRW5GO0lBRUQsdUJBQXVCLElBQUksT0FBTyxDQUFDLFVBQVUsRUFBRSxDQUFDLENBRS9DO0lBRUQsYUFBYSxDQUFDLEtBQUssRUFBRSxPQUFPLEVBQUUsU0FBUyxFQUFFLFVBQVUsR0FBRyxPQUFPLENBQUMsT0FBTyxDQUFDLENBRXJFO0lBRUQsaUJBQWlCLENBQUMsS0FBSyxFQUFFLE9BQU8sRUFBRSxVQUFVLEVBQUUsVUFBVSxFQUFFLEdBQUcsT0FBTyxDQUFDLFVBQVUsRUFBRSxDQUFDLENBR2pGO0lBRUQsaUJBQWlCLENBQUMsTUFBTSxFQUFFLFdBQVcsR0FBRyxPQUFPLENBQUMsT0FBTyxDQUFDLENBRXZEO0lBRUQsdUJBQXVCLENBQUMsS0FBSyxDQUFDLEVBQUUsT0FBTyxHQUFHLE9BQU8sQ0FBQyxPQUFPLENBQUMsQ0FFekQ7Q0FDRiJ9
91
+ //# sourceMappingURL=data:application/json;base64,eyJ2ZXJzaW9uIjozLCJmaWxlIjoidGVzdF9lcG9jaF9jYWNoZS5kLnRzIiwic291cmNlUm9vdCI6IiIsInNvdXJjZXMiOlsiLi4vLi4vc3JjL3Rlc3QvdGVzdF9lcG9jaF9jYWNoZS50cyJdLCJuYW1lcyI6W10sIm1hcHBpbmdzIjoiQUFBQSxPQUFPLEVBQUUsV0FBVyxFQUFFLFVBQVUsRUFBRSxNQUFNLGlDQUFpQyxDQUFDO0FBQzFFLE9BQU8sRUFBRSxVQUFVLEVBQUUsTUFBTSwrQkFBK0IsQ0FBQztBQUMzRCxPQUFPLEtBQUssRUFBRSxpQkFBaUIsRUFBRSxNQUFNLDZCQUE2QixDQUFDO0FBUXJFLE9BQU8sRUFDTCxLQUFLLFlBQVksRUFDakIsS0FBSyxtQkFBbUIsRUFDeEIsS0FBSyxrQkFBa0IsRUFFdkIsS0FBSyxPQUFPLEVBQ2IsTUFBTSxtQkFBbUIsQ0FBQztBQWMzQjs7Ozs7O0dBTUc7QUFDSCxxQkFBYSxjQUFlLFlBQVcsbUJBQW1CO0lBQ3hELE9BQU8sQ0FBQyxTQUFTLENBQW9CO0lBQ3JDLE9BQU8sQ0FBQyxlQUFlLENBQXlCO0lBQ2hELE9BQU8sQ0FBQyxXQUFXLENBQTZCO0lBQ2hELE9BQU8sQ0FBQyxlQUFlLENBQWtCO0lBQ3pDLE9BQU8sQ0FBQyxJQUFJLENBQWM7SUFDMUIsT0FBTyxDQUFDLG9CQUFvQixDQUFvQjtJQUNoRCxPQUFPLENBQUMsV0FBVyxDQUFvQjtJQUN2QyxPQUFPLENBQUMsMEJBQTBCLENBQUs7SUFFdkMsWUFBWSxXQUFXLEdBQUUsT0FBTyxDQUFDLGlCQUFpQixDQUFNLEVBRXZEO0lBRUQsNkJBQTZCLENBQUMsR0FBRyxFQUFFLE1BQU0sR0FBRyxJQUFJLENBRy9DO0lBRUQ7OztPQUdHO0lBQ0gsWUFBWSxDQUFDLFNBQVMsRUFBRSxVQUFVLEVBQUUsR0FBRyxJQUFJLENBRzFDO0lBRUQ7OztPQUdHO0lBQ0gsV0FBVyxDQUFDLFFBQVEsRUFBRSxVQUFVLEdBQUcsU0FBUyxHQUFHLElBQUksQ0FHbEQ7SUFFRDs7O09BR0c7SUFDSCxjQUFjLENBQUMsSUFBSSxFQUFFLFVBQVUsR0FBRyxJQUFJLENBR3JDO0lBRUQ7OztPQUdHO0lBQ0gsa0JBQWtCLENBQUMsSUFBSSxFQUFFLE9BQU8sR0FBRyxJQUFJLENBR3RDO0lBRUQ7OztPQUdHO0lBQ0gsT0FBTyxDQUFDLElBQUksRUFBRSxNQUFNLEdBQUcsSUFBSSxDQUcxQjtJQUVEOzs7T0FHRztJQUNILHVCQUF1QixDQUFDLFVBQVUsRUFBRSxVQUFVLEVBQUUsR0FBRyxJQUFJLENBR3REO0lBRUQ7OztPQUdHO0lBQ0gsY0FBYyxDQUFDLFNBQVMsRUFBRSxPQUFPLENBQUMsaUJBQWlCLENBQUMsR0FBRyxJQUFJLENBRzFEO0lBRUQsY0FBYyxJQUFJLGlCQUFpQixDQUVsQztJQUVELDZCQUE2QixJQUFJLE1BQU0sQ0FFdEM7SUFFRCxZQUFZLENBQUMsS0FBSyxDQUFDLEVBQUUsT0FBTyxHQUFHLE9BQU8sQ0FBQyxrQkFBa0IsQ0FBQyxDQVF6RDtJQUVELFVBQVUsSUFBSSxVQUFVLENBRXZCO0lBRUQsYUFBYSxJQUFJLFVBQVUsQ0FFMUI7SUFFRCxXQUFXLElBQUksV0FBVyxDQUV6QjtJQUVELGNBQWMsSUFBSSxXQUFXLENBRTVCO0lBRUQsa0JBQWtCLElBQUksWUFBWSxHQUFHO1FBQUUsS0FBSyxFQUFFLE1BQU0sQ0FBQTtLQUFFLENBWXJEO0lBRUQsMkJBQTJCLElBQUksWUFBWSxHQUFHO1FBQUUsVUFBVSxFQUFFLE1BQU0sQ0FBQTtLQUFFLENBWW5FO0lBRUQsaUNBQWlDLElBQUksWUFBWSxHQUFHO1FBQUUsVUFBVSxFQUFFLE1BQU0sQ0FBQTtLQUFFLENBS3pFO0lBRUQsd0JBQXdCLENBQUMsS0FBSyxFQUFFLFdBQVcsRUFBRSxJQUFJLEVBQUUsVUFBVSxFQUFFLElBQUksRUFBRSxNQUFNLEdBQUcsS0FBSyxNQUFNLEVBQUUsQ0FHMUY7SUFFRCxvQkFBb0IsQ0FBQyxJQUFJLEVBQUUsVUFBVSxFQUFFLE1BQU0sRUFBRSxXQUFXLEVBQUUsS0FBSyxFQUFFLE1BQU0sRUFBRSxJQUFJLEVBQUUsTUFBTSxHQUFHLE1BQU0sQ0FLL0Y7SUFFRCxxQkFBcUIsSUFBSTtRQUFFLFdBQVcsRUFBRSxVQUFVLENBQUM7UUFBQyxRQUFRLEVBQUUsVUFBVSxDQUFBO0tBQUUsQ0FRekU7SUFFRCxvQkFBb0IsSUFBSTtRQUFFLFVBQVUsRUFBRSxVQUFVLENBQUM7UUFBQyxRQUFRLEVBQUUsVUFBVSxDQUFBO0tBQUUsQ0FRdkU7SUFFRCxnQ0FBZ0MsQ0FBQyxLQUFLLEVBQUUsVUFBVSxHQUFHLE9BQU8sQ0FBQyxVQUFVLEdBQUcsU0FBUyxDQUFDLENBRW5GO0lBRUQsdUJBQXVCLElBQUksT0FBTyxDQUFDLFVBQVUsRUFBRSxDQUFDLENBRS9DO0lBRUQsYUFBYSxDQUFDLEtBQUssRUFBRSxPQUFPLEVBQUUsU0FBUyxFQUFFLFVBQVUsR0FBRyxPQUFPLENBQUMsT0FBTyxDQUFDLENBRXJFO0lBRUQsaUJBQWlCLENBQUMsS0FBSyxFQUFFLE9BQU8sRUFBRSxVQUFVLEVBQUUsVUFBVSxFQUFFLEdBQUcsT0FBTyxDQUFDLFVBQVUsRUFBRSxDQUFDLENBR2pGO0lBRUQsaUJBQWlCLENBQUMsTUFBTSxFQUFFLFdBQVcsR0FBRyxPQUFPLENBQUMsT0FBTyxDQUFDLENBRXZEO0lBRUQsdUJBQXVCLENBQUMsS0FBSyxDQUFDLEVBQUUsT0FBTyxHQUFHLE9BQU8sQ0FBQyxPQUFPLENBQUMsQ0FFekQ7Q0FDRiJ9
@@ -1 +1 @@
1
- {"version":3,"file":"test_epoch_cache.d.ts","sourceRoot":"","sources":["../../src/test/test_epoch_cache.ts"],"names":[],"mappings":"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"}
1
+ {"version":3,"file":"test_epoch_cache.d.ts","sourceRoot":"","sources":["../../src/test/test_epoch_cache.ts"],"names":[],"mappings":"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"}
@@ -1,5 +1,5 @@
1
1
  import { SlotNumber } from '@aztec/foundation/branded-types';
2
- import { getEpochAtSlot, getSlotAtTimestamp, getTimestampRangeForEpoch } from '@aztec/stdlib/epoch-helpers';
2
+ import { getEpochAtSlot, getSlotAtTimestamp, getTimestampForSlot, getTimestampRangeForEpoch } from '@aztec/stdlib/epoch-helpers';
3
3
  import { PROPOSER_PIPELINING_SLOT_OFFSET } from '../epoch_cache.js';
4
4
  /** Default L1 constants for testing. */ const DEFAULT_L1_CONSTANTS = {
5
5
  l1StartBlock: 0n,
@@ -25,13 +25,17 @@ import { PROPOSER_PIPELINING_SLOT_OFFSET } from '../epoch_cache.js';
25
25
  seed = 0n;
26
26
  registeredValidators = [];
27
27
  l1Constants;
28
- proposerPipeliningEnabled = false;
28
+ lagInEpochsForValidatorSet = 2;
29
29
  constructor(l1Constants = {}){
30
30
  this.l1Constants = {
31
31
  ...DEFAULT_L1_CONSTANTS,
32
32
  ...l1Constants
33
33
  };
34
34
  }
35
+ setLagInEpochsForValidatorSet(lag) {
36
+ this.lagInEpochsForValidatorSet = lag;
37
+ return this;
38
+ }
35
39
  /**
36
40
  * Sets the committee members. Used in validation and attestation flows.
37
41
  * @param committee - Array of committee member addresses.
@@ -87,8 +91,8 @@ import { PROPOSER_PIPELINING_SLOT_OFFSET } from '../epoch_cache.js';
87
91
  getL1Constants() {
88
92
  return this.l1Constants;
89
93
  }
90
- setProposerPipeliningEnabled(enabled) {
91
- this.proposerPipeliningEnabled = enabled;
94
+ getLagInEpochsForValidatorSet() {
95
+ return this.lagInEpochsForValidatorSet;
92
96
  }
93
97
  getCommittee(_slot) {
94
98
  const epoch = getEpochAtSlot(this.currentSlot, this.l1Constants);
@@ -103,7 +107,7 @@ import { PROPOSER_PIPELINING_SLOT_OFFSET } from '../epoch_cache.js';
103
107
  return this.currentSlot;
104
108
  }
105
109
  getTargetSlot() {
106
- return this.proposerPipeliningEnabled ? SlotNumber(this.currentSlot + PROPOSER_PIPELINING_SLOT_OFFSET) : this.currentSlot;
110
+ return SlotNumber(this.currentSlot + PROPOSER_PIPELINING_SLOT_OFFSET);
107
111
  }
108
112
  getEpochNow() {
109
113
  return getEpochAtSlot(this.currentSlot, this.l1Constants);
@@ -111,12 +115,12 @@ import { PROPOSER_PIPELINING_SLOT_OFFSET } from '../epoch_cache.js';
111
115
  getTargetEpoch() {
112
116
  return getEpochAtSlot(this.getTargetSlot(), this.l1Constants);
113
117
  }
114
- isProposerPipeliningEnabled() {
115
- return this.proposerPipeliningEnabled;
116
- }
117
118
  getEpochAndSlotNow() {
119
+ // Model "now" as the start of the current slot (mirroring the real EpochCache, which derives nowMs
120
+ // from the wall clock). Using the slot start rather than the epoch start keeps nowMs consistent with
121
+ // currentSlot, which the pipelining receive-window check (clock_tolerance) relies on.
118
122
  const epochNow = getEpochAtSlot(this.currentSlot, this.l1Constants);
119
- const ts = getTimestampRangeForEpoch(epochNow, this.l1Constants)[0];
123
+ const ts = getTimestampForSlot(this.currentSlot, this.l1Constants);
120
124
  return {
121
125
  epoch: epochNow,
122
126
  slot: this.currentSlot,
@@ -139,7 +143,7 @@ import { PROPOSER_PIPELINING_SLOT_OFFSET } from '../epoch_cache.js';
139
143
  }
140
144
  getTargetEpochAndSlotInNextL1Slot() {
141
145
  const result = this.getEpochAndSlotInNextL1Slot();
142
- const offset = this.isProposerPipeliningEnabled() ? PROPOSER_PIPELINING_SLOT_OFFSET : 0;
146
+ const offset = PROPOSER_PIPELINING_SLOT_OFFSET;
143
147
  const targetSlot = SlotNumber(result.slot + offset);
144
148
  return {
145
149
  ...result,
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@aztec/epoch-cache",
3
- "version": "0.0.1-commit.c2eed6949",
3
+ "version": "0.0.1-commit.c52d6e7",
4
4
  "type": "module",
5
5
  "exports": {
6
6
  ".": "./dest/index.js",
@@ -26,16 +26,16 @@
26
26
  "../package.common.json"
27
27
  ],
28
28
  "dependencies": {
29
- "@aztec/ethereum": "0.0.1-commit.c2eed6949",
30
- "@aztec/foundation": "0.0.1-commit.c2eed6949",
31
- "@aztec/l1-artifacts": "0.0.1-commit.c2eed6949",
32
- "@aztec/stdlib": "0.0.1-commit.c2eed6949",
29
+ "@aztec/ethereum": "0.0.1-commit.c52d6e7",
30
+ "@aztec/foundation": "0.0.1-commit.c52d6e7",
31
+ "@aztec/l1-artifacts": "6.0.0-nightly.20260807",
32
+ "@aztec/stdlib": "0.0.1-commit.c52d6e7",
33
33
  "dotenv": "^16.0.3",
34
34
  "get-port": "^7.1.0",
35
35
  "jest-mock-extended": "^4.0.0",
36
36
  "tslib": "^2.4.0",
37
37
  "viem": "npm:@aztec/viem@2.38.2",
38
- "zod": "^3.23.8"
38
+ "zod": "^4"
39
39
  },
40
40
  "devDependencies": {
41
41
  "@jest/globals": "^30.0.0",
package/src/config.ts CHANGED
@@ -1,17 +1,11 @@
1
1
  import { type L1ContractsConfig, getL1ContractsConfigEnvVars } from '@aztec/ethereum/config';
2
2
  import { type L1ReaderConfig, getL1ReaderConfigFromEnv } from '@aztec/ethereum/l1-reader';
3
- import { type PipelineConfig, getPipelineConfigEnvVars } from '@aztec/stdlib/config';
4
3
 
5
4
  export type EpochCacheConfig = Pick<
6
- L1ReaderConfig & L1ContractsConfig & PipelineConfig,
7
- | 'l1RpcUrls'
8
- | 'l1ChainId'
9
- | 'viemPollingIntervalMS'
10
- | 'ethereumSlotDuration'
11
- | 'l1HttpTimeoutMS'
12
- | 'enableProposerPipelining'
5
+ L1ReaderConfig & L1ContractsConfig,
6
+ 'l1RpcUrls' | 'l1ChainId' | 'viemPollingIntervalMS' | 'ethereumSlotDuration' | 'l1HttpTimeoutMS'
13
7
  >;
14
8
 
15
9
  export function getEpochCacheConfigEnvVars(): EpochCacheConfig {
16
- return { ...getL1ReaderConfigFromEnv(), ...getL1ContractsConfigEnvVars(), ...getPipelineConfigEnvVars() };
10
+ return { ...getL1ReaderConfigFromEnv(), ...getL1ContractsConfigEnvVars() };
17
11
  }