@aztec/epoch-cache 0.0.1-commit.d3ec352c → 0.0.1-commit.e3c1de76

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
package/dest/config.d.ts CHANGED
@@ -1,4 +1,5 @@
1
- import { type L1ContractsConfig, type L1ReaderConfig } from '@aztec/ethereum';
1
+ import { type L1ContractsConfig } from '@aztec/ethereum/config';
2
+ import { type L1ReaderConfig } from '@aztec/ethereum/l1-reader';
2
3
  export type EpochCacheConfig = Pick<L1ReaderConfig & L1ContractsConfig, 'l1RpcUrls' | 'l1ChainId' | 'viemPollingIntervalMS' | 'ethereumSlotDuration'>;
3
4
  export declare function getEpochCacheConfigEnvVars(): EpochCacheConfig;
4
- //# sourceMappingURL=data:application/json;base64,eyJ2ZXJzaW9uIjozLCJmaWxlIjoiY29uZmlnLmQudHMiLCJzb3VyY2VSb290IjoiIiwic291cmNlcyI6WyIuLi9zcmMvY29uZmlnLnRzIl0sIm5hbWVzIjpbXSwibWFwcGluZ3MiOiJBQUFBLE9BQU8sRUFDTCxLQUFLLGlCQUFpQixFQUN0QixLQUFLLGNBQWMsRUFHcEIsTUFBTSxpQkFBaUIsQ0FBQztBQUV6QixNQUFNLE1BQU0sZ0JBQWdCLEdBQUcsSUFBSSxDQUNqQyxjQUFjLEdBQUcsaUJBQWlCLEVBQ2xDLFdBQVcsR0FBRyxXQUFXLEdBQUcsdUJBQXVCLEdBQUcsc0JBQXNCLENBQzdFLENBQUM7QUFFRix3QkFBZ0IsMEJBQTBCLElBQUksZ0JBQWdCLENBRTdEIn0=
5
+ //# sourceMappingURL=data:application/json;base64,eyJ2ZXJzaW9uIjozLCJmaWxlIjoiY29uZmlnLmQudHMiLCJzb3VyY2VSb290IjoiIiwic291cmNlcyI6WyIuLi9zcmMvY29uZmlnLnRzIl0sIm5hbWVzIjpbXSwibWFwcGluZ3MiOiJBQUFBLE9BQU8sRUFBRSxLQUFLLGlCQUFpQixFQUErQixNQUFNLHdCQUF3QixDQUFDO0FBQzdGLE9BQU8sRUFBRSxLQUFLLGNBQWMsRUFBNEIsTUFBTSwyQkFBMkIsQ0FBQztBQUUxRixNQUFNLE1BQU0sZ0JBQWdCLEdBQUcsSUFBSSxDQUNqQyxjQUFjLEdBQUcsaUJBQWlCLEVBQ2xDLFdBQVcsR0FBRyxXQUFXLEdBQUcsdUJBQXVCLEdBQUcsc0JBQXNCLENBQzdFLENBQUM7QUFFRix3QkFBZ0IsMEJBQTBCLElBQUksZ0JBQWdCLENBRTdEIn0=
@@ -1 +1 @@
1
- {"version":3,"file":"config.d.ts","sourceRoot":"","sources":["../src/config.ts"],"names":[],"mappings":"AAAA,OAAO,EACL,KAAK,iBAAiB,EACtB,KAAK,cAAc,EAGpB,MAAM,iBAAiB,CAAC;AAEzB,MAAM,MAAM,gBAAgB,GAAG,IAAI,CACjC,cAAc,GAAG,iBAAiB,EAClC,WAAW,GAAG,WAAW,GAAG,uBAAuB,GAAG,sBAAsB,CAC7E,CAAC;AAEF,wBAAgB,0BAA0B,IAAI,gBAAgB,CAE7D"}
1
+ {"version":3,"file":"config.d.ts","sourceRoot":"","sources":["../src/config.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,KAAK,iBAAiB,EAA+B,MAAM,wBAAwB,CAAC;AAC7F,OAAO,EAAE,KAAK,cAAc,EAA4B,MAAM,2BAA2B,CAAC;AAE1F,MAAM,MAAM,gBAAgB,GAAG,IAAI,CACjC,cAAc,GAAG,iBAAiB,EAClC,WAAW,GAAG,WAAW,GAAG,uBAAuB,GAAG,sBAAsB,CAC7E,CAAC;AAEF,wBAAgB,0BAA0B,IAAI,gBAAgB,CAE7D"}
package/dest/config.js CHANGED
@@ -1,4 +1,5 @@
1
- import { getL1ContractsConfigEnvVars, getL1ReaderConfigFromEnv } from '@aztec/ethereum';
1
+ import { getL1ContractsConfigEnvVars } from '@aztec/ethereum/config';
2
+ import { getL1ReaderConfigFromEnv } from '@aztec/ethereum/l1-reader';
2
3
  export function getEpochCacheConfigEnvVars() {
3
4
  return {
4
5
  ...getL1ReaderConfigFromEnv(),
@@ -1,4 +1,4 @@
1
- import { RollupContract } from '@aztec/ethereum';
1
+ import { RollupContract } from '@aztec/ethereum/contracts';
2
2
  import { EpochNumber, SlotNumber } from '@aztec/foundation/branded-types';
3
3
  import { EthAddress } from '@aztec/foundation/eth-address';
4
4
  import { DateProvider } from '@aztec/foundation/timer';
@@ -13,22 +13,25 @@ export type EpochCommitteeInfo = {
13
13
  committee: EthAddress[] | undefined;
14
14
  seed: bigint;
15
15
  epoch: EpochNumber;
16
+ /** True if the epoch is within an open escape hatch window. */
17
+ isEscapeHatchOpen: boolean;
16
18
  };
17
19
  export type SlotTag = 'now' | 'next' | SlotNumber;
18
20
  export interface EpochCacheInterface {
19
21
  getCommittee(slot: SlotTag | undefined): Promise<EpochCommitteeInfo>;
20
- getEpochAndSlotNow(): EpochAndSlot;
22
+ getEpochAndSlotNow(): EpochAndSlot & {
23
+ nowMs: bigint;
24
+ };
21
25
  getEpochAndSlotInNextL1Slot(): EpochAndSlot & {
22
26
  now: bigint;
23
27
  };
24
28
  getProposerIndexEncoding(epoch: EpochNumber, slot: SlotNumber, seed: bigint): `0x${string}`;
25
29
  computeProposerIndex(slot: SlotNumber, epoch: EpochNumber, seed: bigint, size: bigint): bigint;
26
- getProposerAttesterAddressInCurrentOrNextSlot(): Promise<{
27
- currentProposer: EthAddress | undefined;
28
- nextProposer: EthAddress | undefined;
30
+ getCurrentAndNextSlot(): {
29
31
  currentSlot: SlotNumber;
30
32
  nextSlot: SlotNumber;
31
- }>;
33
+ };
34
+ getProposerAttesterAddressInSlot(slot: SlotNumber): Promise<EthAddress | undefined>;
32
35
  getRegisteredValidators(): Promise<EthAddress[]>;
33
36
  isInCommittee(slot: SlotTag, validator: EthAddress): Promise<boolean>;
34
37
  filterInCommittee(slot: SlotTag, validators: EthAddress[]): Promise<EthAddress[]>;
@@ -66,7 +69,7 @@ export declare class EpochCache implements EpochCacheInterface {
66
69
  }): Promise<EpochCache>;
67
70
  getL1Constants(): L1RollupConstants;
68
71
  getEpochAndSlotNow(): EpochAndSlot & {
69
- now: bigint;
72
+ nowMs: bigint;
70
73
  };
71
74
  nowInSeconds(): bigint;
72
75
  private getEpochAndSlotAtSlot;
@@ -75,6 +78,20 @@ export declare class EpochCache implements EpochCacheInterface {
75
78
  };
76
79
  private getEpochAndSlotAtTimestamp;
77
80
  getCommitteeForEpoch(epoch: EpochNumber): Promise<EpochCommitteeInfo>;
81
+ /**
82
+ * Returns whether the escape hatch is open for the given epoch.
83
+ *
84
+ * Uses the already-cached EpochCommitteeInfo when available. If not cached, it will fetch
85
+ * the epoch committee info (which includes the escape hatch flag) and return it.
86
+ */
87
+ isEscapeHatchOpen(epoch: EpochNumber): Promise<boolean>;
88
+ /**
89
+ * Returns whether the escape hatch is open for the epoch containing the given slot.
90
+ *
91
+ * This is a lightweight helper intended for callers that already have a slot number and only
92
+ * need the escape hatch flag (without pulling full committee info).
93
+ */
94
+ isEscapeHatchOpenAtSlot(slot?: SlotTag): Promise<boolean>;
78
95
  /**
79
96
  * Get the current validator set
80
97
  * @param nextSlot - If true, get the validator set for the next slot.
@@ -88,18 +105,11 @@ export declare class EpochCache implements EpochCacheInterface {
88
105
  */
89
106
  getProposerIndexEncoding(epoch: EpochNumber, slot: SlotNumber, seed: bigint): `0x${string}`;
90
107
  computeProposerIndex(slot: SlotNumber, epoch: EpochNumber, seed: bigint, size: bigint): bigint;
91
- /**
92
- * Returns the current and next proposer's attester address
93
- *
94
- * We return the next proposer's attester address as the node will check if it is the proposer at the next ethereum block,
95
- * which can be the next slot. If this is the case, then it will send proposals early.
96
- */
97
- getProposerAttesterAddressInCurrentOrNextSlot(): Promise<{
108
+ /** Returns the current and next L2 slot numbers. */
109
+ getCurrentAndNextSlot(): {
98
110
  currentSlot: SlotNumber;
99
111
  nextSlot: SlotNumber;
100
- currentProposer: EthAddress | undefined;
101
- nextProposer: EthAddress | undefined;
102
- }>;
112
+ };
103
113
  /**
104
114
  * Get the proposer attester address in the given L2 slot
105
115
  * @returns The proposer attester address. If the committee does not exist, we throw a NoCommitteeError.
@@ -120,4 +130,4 @@ export declare class EpochCache implements EpochCacheInterface {
120
130
  filterInCommittee(slot: SlotTag, validators: EthAddress[]): Promise<EthAddress[]>;
121
131
  getRegisteredValidators(): Promise<EthAddress[]>;
122
132
  }
123
- //# sourceMappingURL=data:application/json;base64,eyJ2ZXJzaW9uIjozLCJmaWxlIjoiZXBvY2hfY2FjaGUuZC50cyIsInNvdXJjZVJvb3QiOiIiLCJzb3VyY2VzIjpbIi4uL3NyYy9lcG9jaF9jYWNoZS50cyJdLCJuYW1lcyI6W10sIm1hcHBpbmdzIjoiQUFBQSxPQUFPLEVBQW9CLGNBQWMsRUFBdUIsTUFBTSxpQkFBaUIsQ0FBQztBQUN4RixPQUFPLEVBQUUsV0FBVyxFQUFFLFVBQVUsRUFBRSxNQUFNLGlDQUFpQyxDQUFDO0FBQzFFLE9BQU8sRUFBRSxVQUFVLEVBQUUsTUFBTSwrQkFBK0IsQ0FBQztBQUUzRCxPQUFPLEVBQUUsWUFBWSxFQUFFLE1BQU0seUJBQXlCLENBQUM7QUFDdkQsT0FBTyxFQUNMLEtBQUssaUJBQWlCLEVBT3ZCLE1BQU0sNkJBQTZCLENBQUM7QUFJckMsT0FBTyxFQUFFLEtBQUssZ0JBQWdCLEVBQThCLE1BQU0sYUFBYSxDQUFDO0FBRWhGLE1BQU0sTUFBTSxZQUFZLEdBQUc7SUFDekIsS0FBSyxFQUFFLFdBQVcsQ0FBQztJQUNuQixJQUFJLEVBQUUsVUFBVSxDQUFDO0lBQ2pCLEVBQUUsRUFBRSxNQUFNLENBQUM7Q0FDWixDQUFDO0FBRUYsTUFBTSxNQUFNLGtCQUFrQixHQUFHO0lBQy9CLFNBQVMsRUFBRSxVQUFVLEVBQUUsR0FBRyxTQUFTLENBQUM7SUFDcEMsSUFBSSxFQUFFLE1BQU0sQ0FBQztJQUNiLEtBQUssRUFBRSxXQUFXLENBQUM7Q0FDcEIsQ0FBQztBQUVGLE1BQU0sTUFBTSxPQUFPLEdBQUcsS0FBSyxHQUFHLE1BQU0sR0FBRyxVQUFVLENBQUM7QUFFbEQsTUFBTSxXQUFXLG1CQUFtQjtJQUNsQyxZQUFZLENBQUMsSUFBSSxFQUFFLE9BQU8sR0FBRyxTQUFTLEdBQUcsT0FBTyxDQUFDLGtCQUFrQixDQUFDLENBQUM7SUFDckUsa0JBQWtCLElBQUksWUFBWSxDQUFDO0lBQ25DLDJCQUEyQixJQUFJLFlBQVksR0FBRztRQUFFLEdBQUcsRUFBRSxNQUFNLENBQUE7S0FBRSxDQUFDO0lBQzlELHdCQUF3QixDQUFD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
133
+ //# sourceMappingURL=data:application/json;base64,eyJ2ZXJzaW9uIjozLCJmaWxlIjoiZXBvY2hfY2FjaGUuZC50cyIsInNvdXJjZVJvb3QiOiIiLCJzb3VyY2VzIjpbIi4uL3NyYy9lcG9jaF9jYWNoZS50cyJdLCJuYW1lcyI6W10sIm1hcHBpbmdzIjoiQUFDQSxPQUFPLEVBQW9CLGNBQWMsRUFBRSxNQUFNLDJCQUEyQixDQUFDO0FBQzdFLE9BQU8sRUFBRSxXQUFXLEVBQUUsVUFBVSxFQUFFLE1BQU0saUNBQWlDLENBQUM7QUFDMUUsT0FBTyxFQUFFLFVBQVUsRUFBRSxNQUFNLCtCQUErQixDQUFDO0FBRTNELE9BQU8sRUFBRSxZQUFZLEVBQUUsTUFBTSx5QkFBeUIsQ0FBQztBQUN2RCxPQUFPLEVBQ0wsS0FBSyxpQkFBaUIsRUFPdkIsTUFBTSw2QkFBNkIsQ0FBQztBQUlyQyxPQUFPLEVBQUUsS0FBSyxnQkFBZ0IsRUFBOEIsTUFBTSxhQUFhLENBQUM7QUFFaEYsTUFBTSxNQUFNLFlBQVksR0FBRztJQUN6QixLQUFLLEVBQUUsV0FBVyxDQUFDO0lBQ25CLElBQUksRUFBRSxVQUFVLENBQUM7SUFDakIsRUFBRSxFQUFFLE1BQU0sQ0FBQztDQUNaLENBQUM7QUFFRixNQUFNLE1BQU0sa0JBQWtCLEdBQUc7SUFDL0IsU0FBUyxFQUFFLFVBQVUsRUFBRSxHQUFHLFNBQVMsQ0FBQztJQUNwQyxJQUFJLEVBQUUsTUFBTSxDQUFDO0lBQ2IsS0FBSyxFQUFFLFdBQVcsQ0FBQztJQUNuQiwrREFBK0Q7SUFDL0QsaUJBQWlCLEVBQUUsT0FBTyxDQUFDO0NBQzVCLENBQUM7QUFFRixNQUFNLE1BQU0sT0FBTyxHQUFHLEtBQUssR0FBRyxNQUFNLEdBQUcsVUFBVSxDQUFDO0FBRWxELE1BQU0sV0FBVyxtQkFBbUI7SUFDbEMsWUFBWSxDQUFDLElBQUksRUFBRSxPQUFPLEdBQUcsU0FBUyxHQUFHLE9BQU8sQ0FBQyxrQkFBa0IsQ0FBQyxDQUFDO0lBQ3JFLGtCQUFrQixJQUFJLFlBQVksR0FBRztRQUFFLEtBQUssRUFBRSxNQUFNLENBQUE7S0FBRSxDQUFDO0lBQ3ZE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
@@ -1 +1 @@
1
- {"version":3,"file":"epoch_cache.d.ts","sourceRoot":"","sources":["../src/epoch_cache.ts"],"names":[],"mappings":"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"}
1
+ {"version":3,"file":"epoch_cache.d.ts","sourceRoot":"","sources":["../src/epoch_cache.ts"],"names":[],"mappings":"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"}
@@ -1,4 +1,5 @@
1
- import { NoCommitteeError, RollupContract, createEthereumChain } from '@aztec/ethereum';
1
+ import { createEthereumChain } from '@aztec/ethereum/chain';
2
+ import { NoCommitteeError, RollupContract } from '@aztec/ethereum/contracts';
2
3
  import { EthAddress } from '@aztec/foundation/eth-address';
3
4
  import { createLogger } from '@aztec/foundation/log';
4
5
  import { DateProvider } from '@aztec/foundation/timer';
@@ -49,7 +50,9 @@ import { getEpochCacheConfigEnvVars } from './config.js';
49
50
  const chain = createEthereumChain(config.l1RpcUrls, config.l1ChainId);
50
51
  const publicClient = createPublicClient({
51
52
  chain: chain.chainInfo,
52
- transport: fallback(config.l1RpcUrls.map((url)=>http(url))),
53
+ transport: fallback(config.l1RpcUrls.map((url)=>http(url, {
54
+ batch: false
55
+ }))),
53
56
  pollingInterval: config.viemPollingIntervalMS
54
57
  });
55
58
  rollup = new RollupContract(publicClient, rollupOrAddress.toString());
@@ -79,10 +82,11 @@ import { getEpochCacheConfigEnvVars } from './config.js';
79
82
  return this.l1constants;
80
83
  }
81
84
  getEpochAndSlotNow() {
82
- const now = this.nowInSeconds();
85
+ const nowMs = BigInt(this.dateProvider.now());
86
+ const nowSeconds = nowMs / 1000n;
83
87
  return {
84
- ...this.getEpochAndSlotAtTimestamp(now),
85
- now
88
+ ...this.getEpochAndSlotAtTimestamp(nowSeconds),
89
+ nowMs
86
90
  };
87
91
  }
88
92
  nowInSeconds() {
@@ -118,6 +122,28 @@ import { getEpochCacheConfigEnvVars } from './config.js';
118
122
  return this.getCommittee(startSlot);
119
123
  }
120
124
  /**
125
+ * Returns whether the escape hatch is open for the given epoch.
126
+ *
127
+ * Uses the already-cached EpochCommitteeInfo when available. If not cached, it will fetch
128
+ * the epoch committee info (which includes the escape hatch flag) and return it.
129
+ */ async isEscapeHatchOpen(epoch) {
130
+ const cached = this.cache.get(epoch);
131
+ if (cached) {
132
+ return cached.isEscapeHatchOpen;
133
+ }
134
+ const info = await this.getCommitteeForEpoch(epoch);
135
+ return info.isEscapeHatchOpen;
136
+ }
137
+ /**
138
+ * Returns whether the escape hatch is open for the epoch containing the given slot.
139
+ *
140
+ * This is a lightweight helper intended for callers that already have a slot number and only
141
+ * need the escape hatch flag (without pulling full committee info).
142
+ */ async isEscapeHatchOpenAtSlot(slot = 'now') {
143
+ const epoch = slot === 'now' ? this.getEpochAndSlotNow().epoch : slot === 'next' ? this.getEpochAndSlotInNextL1Slot().epoch : getEpochAtSlot(slot, this.l1constants);
144
+ return await this.isEscapeHatchOpen(epoch);
145
+ }
146
+ /**
121
147
  * Get the current validator set
122
148
  * @param nextSlot - If true, get the validator set for the next slot.
123
149
  * @returns The current validator set.
@@ -150,23 +176,24 @@ import { getEpochCacheConfigEnvVars } from './config.js';
150
176
  }
151
177
  async computeCommittee(when) {
152
178
  const { ts, epoch } = when;
153
- const [committeeHex, seed, l1Timestamp] = await Promise.all([
179
+ const [committee, seedBuffer, l1Timestamp, isEscapeHatchOpen] = await Promise.all([
154
180
  this.rollup.getCommitteeAt(ts),
155
181
  this.rollup.getSampleSeedAt(ts),
156
182
  this.rollup.client.getBlock({
157
183
  includeTransactions: false
158
- }).then((b)=>b.timestamp)
184
+ }).then((b)=>b.timestamp),
185
+ this.rollup.isEscapeHatchOpen(epoch)
159
186
  ]);
160
187
  const { lagInEpochsForValidatorSet, epochDuration, slotDuration } = this.l1constants;
161
188
  const sub = BigInt(lagInEpochsForValidatorSet) * BigInt(epochDuration) * BigInt(slotDuration);
162
189
  if (ts - sub > l1Timestamp) {
163
190
  throw new Error(`Cannot query committee for future epoch ${epoch} with timestamp ${ts} (current L1 time is ${l1Timestamp}). Check your Ethereum node is synced.`);
164
191
  }
165
- const committee = committeeHex?.map((v)=>EthAddress.fromString(v));
166
192
  return {
167
193
  committee,
168
- seed,
169
- epoch
194
+ seed: seedBuffer.toBigInt(),
195
+ epoch,
196
+ isEscapeHatchOpen
170
197
  };
171
198
  }
172
199
  /**
@@ -198,17 +225,10 @@ import { getEpochCacheConfigEnvVars } from './config.js';
198
225
  }
199
226
  return BigInt(keccak256(this.getProposerIndexEncoding(epoch, slot, seed))) % size;
200
227
  }
201
- /**
202
- * Returns the current and next proposer's attester address
203
- *
204
- * We return the next proposer's attester address as the node will check if it is the proposer at the next ethereum block,
205
- * which can be the next slot. If this is the case, then it will send proposals early.
206
- */ async getProposerAttesterAddressInCurrentOrNextSlot() {
228
+ /** Returns the current and next L2 slot numbers. */ getCurrentAndNextSlot() {
207
229
  const current = this.getEpochAndSlotNow();
208
230
  const next = this.getEpochAndSlotInNextL1Slot();
209
231
  return {
210
- currentProposer: await this.getProposerAttesterAddressAt(current),
211
- nextProposer: await this.getProposerAttesterAddressAt(next),
212
232
  currentSlot: current.slot,
213
233
  nextSlot: next.slot
214
234
  };
@@ -272,9 +292,9 @@ import { getEpochCacheConfigEnvVars } from './config.js';
272
292
  const validatorRefreshTime = this.lastValidatorRefresh + validatorRefreshIntervalMs;
273
293
  if (validatorRefreshTime < this.dateProvider.now()) {
274
294
  const currentSet = await this.rollup.getAttesters();
275
- this.allValidators = new Set(currentSet);
295
+ this.allValidators = new Set(currentSet.map((v)=>v.toString()));
276
296
  this.lastValidatorRefresh = this.dateProvider.now();
277
297
  }
278
- return Array.from(this.allValidators.keys().map((v)=>EthAddress.fromString(v)));
298
+ return Array.from(this.allValidators.keys()).map((v)=>EthAddress.fromString(v));
279
299
  }
280
300
  }
@@ -0,0 +1,2 @@
1
+ export * from './test_epoch_cache.js';
2
+ //# sourceMappingURL=data:application/json;base64,eyJ2ZXJzaW9uIjozLCJmaWxlIjoiaW5kZXguZC50cyIsInNvdXJjZVJvb3QiOiIiLCJzb3VyY2VzIjpbIi4uLy4uL3NyYy90ZXN0L2luZGV4LnRzIl0sIm5hbWVzIjpbXSwibWFwcGluZ3MiOiJBQUFBLGNBQWMsdUJBQXVCLENBQUMifQ==
@@ -0,0 +1 @@
1
+ {"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../../src/test/index.ts"],"names":[],"mappings":"AAAA,cAAc,uBAAuB,CAAC"}
@@ -0,0 +1 @@
1
+ export * from './test_epoch_cache.js';
@@ -0,0 +1,76 @@
1
+ import { EpochNumber, SlotNumber } from '@aztec/foundation/branded-types';
2
+ import { EthAddress } from '@aztec/foundation/eth-address';
3
+ import type { L1RollupConstants } from '@aztec/stdlib/epoch-helpers';
4
+ import type { EpochAndSlot, EpochCacheInterface, EpochCommitteeInfo, SlotTag } from '../epoch_cache.js';
5
+ /**
6
+ * A test implementation of EpochCacheInterface that allows manual configuration
7
+ * of committee, proposer, slot, and escape hatch state for use in tests.
8
+ *
9
+ * Unlike the real EpochCache, this class doesn't require any RPC connections
10
+ * or mock setup. Simply use the setter methods to configure the test state.
11
+ */
12
+ export declare class TestEpochCache implements EpochCacheInterface {
13
+ private committee;
14
+ private proposerAddress;
15
+ private currentSlot;
16
+ private escapeHatchOpen;
17
+ private seed;
18
+ private registeredValidators;
19
+ private l1Constants;
20
+ constructor(l1Constants?: Partial<L1RollupConstants>);
21
+ /**
22
+ * Sets the committee members. Used in validation and attestation flows.
23
+ * @param committee - Array of committee member addresses.
24
+ */
25
+ setCommittee(committee: EthAddress[]): this;
26
+ /**
27
+ * Sets the proposer address returned by getProposerAttesterAddressInSlot.
28
+ * @param proposer - The address of the current proposer.
29
+ */
30
+ setProposer(proposer: EthAddress | undefined): this;
31
+ /**
32
+ * Sets the current slot number.
33
+ * @param slot - The slot number to set.
34
+ */
35
+ setCurrentSlot(slot: SlotNumber): this;
36
+ /**
37
+ * Sets whether the escape hatch is open.
38
+ * @param open - True if escape hatch should be open.
39
+ */
40
+ setEscapeHatchOpen(open: boolean): this;
41
+ /**
42
+ * Sets the randomness seed used for proposer selection.
43
+ * @param seed - The seed value.
44
+ */
45
+ setSeed(seed: bigint): this;
46
+ /**
47
+ * Sets the list of registered validators (all validators, not just committee).
48
+ * @param validators - Array of validator addresses.
49
+ */
50
+ setRegisteredValidators(validators: EthAddress[]): this;
51
+ /**
52
+ * Sets the L1 constants used for epoch/slot calculations.
53
+ * @param constants - Partial constants to override defaults.
54
+ */
55
+ setL1Constants(constants: Partial<L1RollupConstants>): this;
56
+ getL1Constants(): L1RollupConstants;
57
+ getCommittee(_slot?: SlotTag): Promise<EpochCommitteeInfo>;
58
+ getEpochAndSlotNow(): EpochAndSlot & {
59
+ nowMs: bigint;
60
+ };
61
+ getEpochAndSlotInNextL1Slot(): EpochAndSlot & {
62
+ now: bigint;
63
+ };
64
+ getProposerIndexEncoding(epoch: EpochNumber, slot: SlotNumber, seed: bigint): `0x${string}`;
65
+ computeProposerIndex(slot: SlotNumber, _epoch: EpochNumber, _seed: bigint, size: bigint): bigint;
66
+ getCurrentAndNextSlot(): {
67
+ currentSlot: SlotNumber;
68
+ nextSlot: SlotNumber;
69
+ };
70
+ getProposerAttesterAddressInSlot(_slot: SlotNumber): Promise<EthAddress | undefined>;
71
+ getRegisteredValidators(): Promise<EthAddress[]>;
72
+ isInCommittee(_slot: SlotTag, validator: EthAddress): Promise<boolean>;
73
+ filterInCommittee(_slot: SlotTag, validators: EthAddress[]): Promise<EthAddress[]>;
74
+ isEscapeHatchOpenAtSlot(_slot?: SlotTag): Promise<boolean>;
75
+ }
76
+ //# sourceMappingURL=data:application/json;base64,eyJ2ZXJzaW9uIjozLCJmaWxlIjoidGVzdF9lcG9jaF9jYWNoZS5kLnRzIiwic291cmNlUm9vdCI6IiIsInNvdXJjZXMiOlsiLi4vLi4vc3JjL3Rlc3QvdGVzdF9lcG9jaF9jYWNoZS50cyJdLCJuYW1lcyI6W10sIm1hcHBpbmdzIjoiQUFBQSxPQUFPLEVBQUUsV0FBVyxFQUFFLFVBQVUsRUFBRSxNQUFNLGlDQUFpQyxDQUFDO0FBQzFFLE9BQU8sRUFBRSxVQUFVLEVBQUUsTUFBTSwrQkFBK0IsQ0FBQztBQUMzRCxPQUFPLEtBQUssRUFBRSxpQkFBaUIsRUFBRSxNQUFNLDZCQUE2QixDQUFDO0FBR3JFLE9BQU8sS0FBSyxFQUFFLFlBQVksRUFBRSxtQkFBbUIsRUFBRSxrQkFBa0IsRUFBRSxPQUFPLEVBQUUsTUFBTSxtQkFBbUIsQ0FBQztBQVl4Rzs7Ozs7O0dBTUc7QUFDSCxxQkFBYSxjQUFlLFlBQVcsbUJBQW1CO0lBQ3hELE9BQU8sQ0FBQyxTQUFTLENBQW9CO0lBQ3JDLE9BQU8sQ0FBQyxlQUFlLENBQXlCO0lBQ2hELE9BQU8sQ0FBQyxXQUFXLENBQTZCO0lBQ2hELE9BQU8sQ0FBQyxlQUFlLENBQWtCO0lBQ3pDLE9BQU8sQ0FBQyxJQUFJLENBQWM7SUFDMUIsT0FBTyxDQUFDLG9CQUFvQixDQUFvQjtJQUNoRCxPQUFPLENBQUMsV0FBVyxDQUFvQjtJQUV2QyxZQUFZLFdBQVcsR0FBRSxPQUFPLENBQUMsaUJBQWlCLENBQU0sRUFFdkQ7SUFFRDs7O09BR0c7SUFDSCxZQUFZLENBQUMsU0FBUyxFQUFFLFVBQVUsRUFBRSxHQUFHLElBQUksQ0FHMUM7SUFFRDs7O09BR0c7SUFDSCxXQUFXLENBQUMsUUFBUSxFQUFFLFVBQVUsR0FBRyxTQUFTLEdBQUcsSUFBSSxDQUdsRDtJQUVEOzs7T0FHRztJQUNILGNBQWMsQ0FBQyxJQUFJLEVBQUUsVUFBVSxHQUFHLElBQUksQ0FHckM7SUFFRDs7O09BR0c7SUFDSCxrQkFBa0IsQ0FBQyxJQUFJLEVBQUUsT0FBTyxHQUFHLElBQUksQ0FHdEM7SUFFRDs7O09BR0c7SUFDSCxPQUFPLENBQUMsSUFBSSxFQUFFLE1BQU0sR0FBRyxJQUFJLENBRzFCO0lBRUQ7OztPQUdHO0lBQ0gsdUJBQXVCLENBQUMsVUFBVSxFQUFFLFVBQVUsRUFBRSxHQUFHLElBQUksQ0FHdEQ7SUFFRDs7O09BR0c7SUFDSCxjQUFjLENBQUMsU0FBUyxFQUFFLE9BQU8sQ0FBQyxpQkFBaUIsQ0FBQyxHQUFHLElBQUksQ0FHMUQ7SUFFRCxjQUFjLElBQUksaUJBQWlCLENBRWxDO0lBRUQsWUFBWSxDQUFDLEtBQUssQ0FBQyxFQUFFLE9BQU8sR0FBRyxPQUFPLENBQUMsa0JBQWtCLENBQUMsQ0FRekQ7SUFFRCxrQkFBa0IsSUFBSSxZQUFZLEdBQUc7UUFBRSxLQUFLLEVBQUUsTUFBTSxDQUFBO0tBQUUsQ0FJckQ7SUFFRCwyQkFBMkIsSUFBSSxZQUFZLEdBQUc7UUFBRSxHQUFHLEVBQUUsTUFBTSxDQUFBO0tBQUUsQ0FPNUQ7SUFFRCx3QkFBd0IsQ0FBQyxLQUFLLEVBQUUsV0FBVyxFQUFFLElBQUksRUFBRSxVQUFVLEVBQUUsSUFBSSxFQUFFLE1BQU0sR0FBRyxLQUFLLE1BQU0sRUFBRSxDQUcxRjtJQUVELG9CQUFvQixDQUFDLElBQUksRUFBRSxVQUFVLEVBQUUsTUFBTSxFQUFFLFdBQVcsRUFBRSxLQUFLLEVBQUUsTUFBTSxFQUFFLElBQUksRUFBRSxNQUFNLEdBQUcsTUFBTSxDQUsvRjtJQUVELHFCQUFxQixJQUFJO1FBQUUsV0FBVyxFQUFFLFVBQVUsQ0FBQztRQUFDLFFBQVEsRUFBRSxVQUFVLENBQUE7S0FBRSxDQUt6RTtJQUVELGdDQUFnQyxDQUFDLEtBQUssRUFBRSxVQUFVLEdBQUcsT0FBTyxDQUFDLFVBQVUsR0FBRyxTQUFTLENBQUMsQ0FFbkY7SUFFRCx1QkFBdUIsSUFBSSxPQUFPLENBQUMsVUFBVSxFQUFFLENBQUMsQ0FFL0M7SUFFRCxhQUFhLENBQUMsS0FBSyxFQUFFLE9BQU8sRUFBRSxTQUFTLEVBQUUsVUFBVSxHQUFHLE9BQU8sQ0FBQyxPQUFPLENBQUMsQ0FFckU7SUFFRCxpQkFBaUIsQ0FBQyxLQUFLLEVBQUUsT0FBTyxFQUFFLFVBQVUsRUFBRSxVQUFVLEVBQUUsR0FBRyxPQUFPLENBQUMsVUFBVSxFQUFFLENBQUMsQ0FHakY7SUFFRCx1QkFBdUIsQ0FBQyxLQUFLLENBQUMsRUFBRSxPQUFPLEdBQUcsT0FBTyxDQUFDLE9BQU8sQ0FBQyxDQUV6RDtDQUNGIn0=
@@ -0,0 +1 @@
1
+ {"version":3,"file":"test_epoch_cache.d.ts","sourceRoot":"","sources":["../../src/test/test_epoch_cache.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,WAAW,EAAE,UAAU,EAAE,MAAM,iCAAiC,CAAC;AAC1E,OAAO,EAAE,UAAU,EAAE,MAAM,+BAA+B,CAAC;AAC3D,OAAO,KAAK,EAAE,iBAAiB,EAAE,MAAM,6BAA6B,CAAC;AAGrE,OAAO,KAAK,EAAE,YAAY,EAAE,mBAAmB,EAAE,kBAAkB,EAAE,OAAO,EAAE,MAAM,mBAAmB,CAAC;AAYxG;;;;;;GAMG;AACH,qBAAa,cAAe,YAAW,mBAAmB;IACxD,OAAO,CAAC,SAAS,CAAoB;IACrC,OAAO,CAAC,eAAe,CAAyB;IAChD,OAAO,CAAC,WAAW,CAA6B;IAChD,OAAO,CAAC,eAAe,CAAkB;IACzC,OAAO,CAAC,IAAI,CAAc;IAC1B,OAAO,CAAC,oBAAoB,CAAoB;IAChD,OAAO,CAAC,WAAW,CAAoB;IAEvC,YAAY,WAAW,GAAE,OAAO,CAAC,iBAAiB,CAAM,EAEvD;IAED;;;OAGG;IACH,YAAY,CAAC,SAAS,EAAE,UAAU,EAAE,GAAG,IAAI,CAG1C;IAED;;;OAGG;IACH,WAAW,CAAC,QAAQ,EAAE,UAAU,GAAG,SAAS,GAAG,IAAI,CAGlD;IAED;;;OAGG;IACH,cAAc,CAAC,IAAI,EAAE,UAAU,GAAG,IAAI,CAGrC;IAED;;;OAGG;IACH,kBAAkB,CAAC,IAAI,EAAE,OAAO,GAAG,IAAI,CAGtC;IAED;;;OAGG;IACH,OAAO,CAAC,IAAI,EAAE,MAAM,GAAG,IAAI,CAG1B;IAED;;;OAGG;IACH,uBAAuB,CAAC,UAAU,EAAE,UAAU,EAAE,GAAG,IAAI,CAGtD;IAED;;;OAGG;IACH,cAAc,CAAC,SAAS,EAAE,OAAO,CAAC,iBAAiB,CAAC,GAAG,IAAI,CAG1D;IAED,cAAc,IAAI,iBAAiB,CAElC;IAED,YAAY,CAAC,KAAK,CAAC,EAAE,OAAO,GAAG,OAAO,CAAC,kBAAkB,CAAC,CAQzD;IAED,kBAAkB,IAAI,YAAY,GAAG;QAAE,KAAK,EAAE,MAAM,CAAA;KAAE,CAIrD;IAED,2BAA2B,IAAI,YAAY,GAAG;QAAE,GAAG,EAAE,MAAM,CAAA;KAAE,CAO5D;IAED,wBAAwB,CAAC,KAAK,EAAE,WAAW,EAAE,IAAI,EAAE,UAAU,EAAE,IAAI,EAAE,MAAM,GAAG,KAAK,MAAM,EAAE,CAG1F;IAED,oBAAoB,CAAC,IAAI,EAAE,UAAU,EAAE,MAAM,EAAE,WAAW,EAAE,KAAK,EAAE,MAAM,EAAE,IAAI,EAAE,MAAM,GAAG,MAAM,CAK/F;IAED,qBAAqB,IAAI;QAAE,WAAW,EAAE,UAAU,CAAC;QAAC,QAAQ,EAAE,UAAU,CAAA;KAAE,CAKzE;IAED,gCAAgC,CAAC,KAAK,EAAE,UAAU,GAAG,OAAO,CAAC,UAAU,GAAG,SAAS,CAAC,CAEnF;IAED,uBAAuB,IAAI,OAAO,CAAC,UAAU,EAAE,CAAC,CAE/C;IAED,aAAa,CAAC,KAAK,EAAE,OAAO,EAAE,SAAS,EAAE,UAAU,GAAG,OAAO,CAAC,OAAO,CAAC,CAErE;IAED,iBAAiB,CAAC,KAAK,EAAE,OAAO,EAAE,UAAU,EAAE,UAAU,EAAE,GAAG,OAAO,CAAC,UAAU,EAAE,CAAC,CAGjF;IAED,uBAAuB,CAAC,KAAK,CAAC,EAAE,OAAO,GAAG,OAAO,CAAC,OAAO,CAAC,CAEzD;CACF"}
@@ -0,0 +1,150 @@
1
+ import { SlotNumber } from '@aztec/foundation/branded-types';
2
+ import { getEpochAtSlot, getSlotAtTimestamp, getTimestampRangeForEpoch } from '@aztec/stdlib/epoch-helpers';
3
+ /** Default L1 constants for testing. */ const DEFAULT_L1_CONSTANTS = {
4
+ l1StartBlock: 0n,
5
+ l1GenesisTime: 0n,
6
+ slotDuration: 24,
7
+ epochDuration: 16,
8
+ ethereumSlotDuration: 12,
9
+ proofSubmissionEpochs: 2
10
+ };
11
+ /**
12
+ * A test implementation of EpochCacheInterface that allows manual configuration
13
+ * of committee, proposer, slot, and escape hatch state for use in tests.
14
+ *
15
+ * Unlike the real EpochCache, this class doesn't require any RPC connections
16
+ * or mock setup. Simply use the setter methods to configure the test state.
17
+ */ export class TestEpochCache {
18
+ committee = [];
19
+ proposerAddress;
20
+ currentSlot = SlotNumber(0);
21
+ escapeHatchOpen = false;
22
+ seed = 0n;
23
+ registeredValidators = [];
24
+ l1Constants;
25
+ constructor(l1Constants = {}){
26
+ this.l1Constants = {
27
+ ...DEFAULT_L1_CONSTANTS,
28
+ ...l1Constants
29
+ };
30
+ }
31
+ /**
32
+ * Sets the committee members. Used in validation and attestation flows.
33
+ * @param committee - Array of committee member addresses.
34
+ */ setCommittee(committee) {
35
+ this.committee = committee;
36
+ return this;
37
+ }
38
+ /**
39
+ * Sets the proposer address returned by getProposerAttesterAddressInSlot.
40
+ * @param proposer - The address of the current proposer.
41
+ */ setProposer(proposer) {
42
+ this.proposerAddress = proposer;
43
+ return this;
44
+ }
45
+ /**
46
+ * Sets the current slot number.
47
+ * @param slot - The slot number to set.
48
+ */ setCurrentSlot(slot) {
49
+ this.currentSlot = slot;
50
+ return this;
51
+ }
52
+ /**
53
+ * Sets whether the escape hatch is open.
54
+ * @param open - True if escape hatch should be open.
55
+ */ setEscapeHatchOpen(open) {
56
+ this.escapeHatchOpen = open;
57
+ return this;
58
+ }
59
+ /**
60
+ * Sets the randomness seed used for proposer selection.
61
+ * @param seed - The seed value.
62
+ */ setSeed(seed) {
63
+ this.seed = seed;
64
+ return this;
65
+ }
66
+ /**
67
+ * Sets the list of registered validators (all validators, not just committee).
68
+ * @param validators - Array of validator addresses.
69
+ */ setRegisteredValidators(validators) {
70
+ this.registeredValidators = validators;
71
+ return this;
72
+ }
73
+ /**
74
+ * Sets the L1 constants used for epoch/slot calculations.
75
+ * @param constants - Partial constants to override defaults.
76
+ */ setL1Constants(constants) {
77
+ this.l1Constants = {
78
+ ...this.l1Constants,
79
+ ...constants
80
+ };
81
+ return this;
82
+ }
83
+ getL1Constants() {
84
+ return this.l1Constants;
85
+ }
86
+ getCommittee(_slot) {
87
+ const epoch = getEpochAtSlot(this.currentSlot, this.l1Constants);
88
+ return Promise.resolve({
89
+ committee: this.committee,
90
+ epoch,
91
+ seed: this.seed,
92
+ isEscapeHatchOpen: this.escapeHatchOpen
93
+ });
94
+ }
95
+ getEpochAndSlotNow() {
96
+ const epoch = getEpochAtSlot(this.currentSlot, this.l1Constants);
97
+ const ts = getTimestampRangeForEpoch(epoch, this.l1Constants)[0];
98
+ return {
99
+ epoch,
100
+ slot: this.currentSlot,
101
+ ts,
102
+ nowMs: ts * 1000n
103
+ };
104
+ }
105
+ getEpochAndSlotInNextL1Slot() {
106
+ const now = getTimestampRangeForEpoch(getEpochAtSlot(this.currentSlot, this.l1Constants), this.l1Constants)[0];
107
+ const nextSlotTs = now + BigInt(this.l1Constants.ethereumSlotDuration);
108
+ const nextSlot = getSlotAtTimestamp(nextSlotTs, this.l1Constants);
109
+ const epoch = getEpochAtSlot(nextSlot, this.l1Constants);
110
+ const ts = getTimestampRangeForEpoch(epoch, this.l1Constants)[0];
111
+ return {
112
+ epoch,
113
+ slot: nextSlot,
114
+ ts,
115
+ now
116
+ };
117
+ }
118
+ getProposerIndexEncoding(epoch, slot, seed) {
119
+ // Simple encoding for testing purposes
120
+ return `0x${epoch.toString(16).padStart(64, '0')}${slot.toString(16).padStart(64, '0')}${seed.toString(16).padStart(64, '0')}`;
121
+ }
122
+ computeProposerIndex(slot, _epoch, _seed, size) {
123
+ if (size === 0n) {
124
+ return 0n;
125
+ }
126
+ return BigInt(slot) % size;
127
+ }
128
+ getCurrentAndNextSlot() {
129
+ return {
130
+ currentSlot: this.currentSlot,
131
+ nextSlot: SlotNumber(this.currentSlot + 1)
132
+ };
133
+ }
134
+ getProposerAttesterAddressInSlot(_slot) {
135
+ return Promise.resolve(this.proposerAddress);
136
+ }
137
+ getRegisteredValidators() {
138
+ return Promise.resolve(this.registeredValidators);
139
+ }
140
+ isInCommittee(_slot, validator) {
141
+ return Promise.resolve(this.committee.some((v)=>v.equals(validator)));
142
+ }
143
+ filterInCommittee(_slot, validators) {
144
+ const committeeSet = new Set(this.committee.map((v)=>v.toString()));
145
+ return Promise.resolve(validators.filter((v)=>committeeSet.has(v.toString())));
146
+ }
147
+ isEscapeHatchOpenAtSlot(_slot) {
148
+ return Promise.resolve(this.escapeHatchOpen);
149
+ }
150
+ }
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@aztec/epoch-cache",
3
- "version": "0.0.1-commit.d3ec352c",
3
+ "version": "0.0.1-commit.e3c1de76",
4
4
  "type": "module",
5
5
  "exports": {
6
6
  ".": "./dest/index.js",
@@ -18,7 +18,7 @@
18
18
  "build": "yarn clean && ../scripts/tsc.sh",
19
19
  "build:dev": "../scripts/tsc.sh --watch",
20
20
  "clean": "rm -rf ./dest .tsbuildinfo",
21
- "start:dev": "concurrently -k \"tsgo -b -w\" \"nodemon --watch dest --exec yarn start\"",
21
+ "start:dev": "concurrently -k \"../scripts/tsc.sh --watch\" \"nodemon --watch dest --exec yarn start\"",
22
22
  "start": "node ./dest/index.js",
23
23
  "test": "NODE_NO_WARNINGS=1 node --experimental-vm-modules ../node_modules/.bin/jest --passWithNoTests --maxWorkers=${JEST_MAX_WORKERS:-8}"
24
24
  },
@@ -26,10 +26,10 @@
26
26
  "../package.common.json"
27
27
  ],
28
28
  "dependencies": {
29
- "@aztec/ethereum": "0.0.1-commit.d3ec352c",
30
- "@aztec/foundation": "0.0.1-commit.d3ec352c",
31
- "@aztec/l1-artifacts": "0.0.1-commit.d3ec352c",
32
- "@aztec/stdlib": "0.0.1-commit.d3ec352c",
29
+ "@aztec/ethereum": "0.0.1-commit.e3c1de76",
30
+ "@aztec/foundation": "0.0.1-commit.e3c1de76",
31
+ "@aztec/l1-artifacts": "0.0.1-commit.e3c1de76",
32
+ "@aztec/stdlib": "0.0.1-commit.e3c1de76",
33
33
  "@viem/anvil": "^0.0.10",
34
34
  "dotenv": "^16.0.3",
35
35
  "get-port": "^7.1.0",
@@ -42,7 +42,7 @@
42
42
  "@jest/globals": "^30.0.0",
43
43
  "@types/jest": "^30.0.0",
44
44
  "@types/node": "^22.15.17",
45
- "@typescript/native-preview": "7.0.0-dev.20251126.1",
45
+ "@typescript/native-preview": "7.0.0-dev.20260113.1",
46
46
  "jest": "^30.0.0",
47
47
  "ts-node": "^10.9.1",
48
48
  "typescript": "^5.3.3"
package/src/config.ts CHANGED
@@ -1,9 +1,5 @@
1
- import {
2
- type L1ContractsConfig,
3
- type L1ReaderConfig,
4
- getL1ContractsConfigEnvVars,
5
- getL1ReaderConfigFromEnv,
6
- } from '@aztec/ethereum';
1
+ import { type L1ContractsConfig, getL1ContractsConfigEnvVars } from '@aztec/ethereum/config';
2
+ import { type L1ReaderConfig, getL1ReaderConfigFromEnv } from '@aztec/ethereum/l1-reader';
7
3
 
8
4
  export type EpochCacheConfig = Pick<
9
5
  L1ReaderConfig & L1ContractsConfig,
@@ -1,4 +1,5 @@
1
- import { NoCommitteeError, RollupContract, createEthereumChain } from '@aztec/ethereum';
1
+ import { createEthereumChain } from '@aztec/ethereum/chain';
2
+ import { NoCommitteeError, RollupContract } from '@aztec/ethereum/contracts';
2
3
  import { EpochNumber, SlotNumber } from '@aztec/foundation/branded-types';
3
4
  import { EthAddress } from '@aztec/foundation/eth-address';
4
5
  import { type Logger, createLogger } from '@aztec/foundation/log';
@@ -27,22 +28,20 @@ export type EpochCommitteeInfo = {
27
28
  committee: EthAddress[] | undefined;
28
29
  seed: bigint;
29
30
  epoch: EpochNumber;
31
+ /** True if the epoch is within an open escape hatch window. */
32
+ isEscapeHatchOpen: boolean;
30
33
  };
31
34
 
32
35
  export type SlotTag = 'now' | 'next' | SlotNumber;
33
36
 
34
37
  export interface EpochCacheInterface {
35
38
  getCommittee(slot: SlotTag | undefined): Promise<EpochCommitteeInfo>;
36
- getEpochAndSlotNow(): EpochAndSlot;
39
+ getEpochAndSlotNow(): EpochAndSlot & { nowMs: bigint };
37
40
  getEpochAndSlotInNextL1Slot(): EpochAndSlot & { now: bigint };
38
41
  getProposerIndexEncoding(epoch: EpochNumber, slot: SlotNumber, seed: bigint): `0x${string}`;
39
42
  computeProposerIndex(slot: SlotNumber, epoch: EpochNumber, seed: bigint, size: bigint): bigint;
40
- getProposerAttesterAddressInCurrentOrNextSlot(): Promise<{
41
- currentProposer: EthAddress | undefined;
42
- nextProposer: EthAddress | undefined;
43
- currentSlot: SlotNumber;
44
- nextSlot: SlotNumber;
45
- }>;
43
+ getCurrentAndNextSlot(): { currentSlot: SlotNumber; nextSlot: SlotNumber };
44
+ getProposerAttesterAddressInSlot(slot: SlotNumber): Promise<EthAddress | undefined>;
46
45
  getRegisteredValidators(): Promise<EthAddress[]>;
47
46
  isInCommittee(slot: SlotTag, validator: EthAddress): Promise<boolean>;
48
47
  filterInCommittee(slot: SlotTag, validators: EthAddress[]): Promise<EthAddress[]>;
@@ -93,7 +92,7 @@ export class EpochCache implements EpochCacheInterface {
93
92
  const chain = createEthereumChain(config.l1RpcUrls, config.l1ChainId);
94
93
  const publicClient = createPublicClient({
95
94
  chain: chain.chainInfo,
96
- transport: fallback(config.l1RpcUrls.map(url => http(url))),
95
+ transport: fallback(config.l1RpcUrls.map(url => http(url, { batch: false }))),
97
96
  pollingInterval: config.viemPollingIntervalMS,
98
97
  });
99
98
  rollup = new RollupContract(publicClient, rollupOrAddress.toString());
@@ -135,9 +134,10 @@ export class EpochCache implements EpochCacheInterface {
135
134
  return this.l1constants;
136
135
  }
137
136
 
138
- public getEpochAndSlotNow(): EpochAndSlot & { now: bigint } {
139
- const now = this.nowInSeconds();
140
- return { ...this.getEpochAndSlotAtTimestamp(now), now };
137
+ public getEpochAndSlotNow(): EpochAndSlot & { nowMs: bigint } {
138
+ const nowMs = BigInt(this.dateProvider.now());
139
+ const nowSeconds = nowMs / 1000n;
140
+ return { ...this.getEpochAndSlotAtTimestamp(nowSeconds), nowMs };
141
141
  }
142
142
 
143
143
  public nowInSeconds(): bigint {
@@ -170,6 +170,38 @@ export class EpochCache implements EpochCacheInterface {
170
170
  return this.getCommittee(startSlot);
171
171
  }
172
172
 
173
+ /**
174
+ * Returns whether the escape hatch is open for the given epoch.
175
+ *
176
+ * Uses the already-cached EpochCommitteeInfo when available. If not cached, it will fetch
177
+ * the epoch committee info (which includes the escape hatch flag) and return it.
178
+ */
179
+ public async isEscapeHatchOpen(epoch: EpochNumber): Promise<boolean> {
180
+ const cached = this.cache.get(epoch);
181
+ if (cached) {
182
+ return cached.isEscapeHatchOpen;
183
+ }
184
+ const info = await this.getCommitteeForEpoch(epoch);
185
+ return info.isEscapeHatchOpen;
186
+ }
187
+
188
+ /**
189
+ * Returns whether the escape hatch is open for the epoch containing the given slot.
190
+ *
191
+ * This is a lightweight helper intended for callers that already have a slot number and only
192
+ * need the escape hatch flag (without pulling full committee info).
193
+ */
194
+ public async isEscapeHatchOpenAtSlot(slot: SlotTag = 'now'): Promise<boolean> {
195
+ const epoch =
196
+ slot === 'now'
197
+ ? this.getEpochAndSlotNow().epoch
198
+ : slot === 'next'
199
+ ? this.getEpochAndSlotInNextL1Slot().epoch
200
+ : getEpochAtSlot(slot, this.l1constants);
201
+
202
+ return await this.isEscapeHatchOpen(epoch);
203
+ }
204
+
173
205
  /**
174
206
  * Get the current validator set
175
207
  * @param nextSlot - If true, get the validator set for the next slot.
@@ -209,10 +241,11 @@ export class EpochCache implements EpochCacheInterface {
209
241
 
210
242
  private async computeCommittee(when: { epoch: EpochNumber; ts: bigint }): Promise<EpochCommitteeInfo> {
211
243
  const { ts, epoch } = when;
212
- const [committeeHex, seed, l1Timestamp] = await Promise.all([
244
+ const [committee, seedBuffer, l1Timestamp, isEscapeHatchOpen] = await Promise.all([
213
245
  this.rollup.getCommitteeAt(ts),
214
246
  this.rollup.getSampleSeedAt(ts),
215
247
  this.rollup.client.getBlock({ includeTransactions: false }).then(b => b.timestamp),
248
+ this.rollup.isEscapeHatchOpen(epoch),
216
249
  ]);
217
250
  const { lagInEpochsForValidatorSet, epochDuration, slotDuration } = this.l1constants;
218
251
  const sub = BigInt(lagInEpochsForValidatorSet) * BigInt(epochDuration) * BigInt(slotDuration);
@@ -221,8 +254,7 @@ export class EpochCache implements EpochCacheInterface {
221
254
  `Cannot query committee for future epoch ${epoch} with timestamp ${ts} (current L1 time is ${l1Timestamp}). Check your Ethereum node is synced.`,
222
255
  );
223
256
  }
224
- const committee = committeeHex?.map((v: `0x${string}`) => EthAddress.fromString(v));
225
- return { committee, seed, epoch };
257
+ return { committee, seed: seedBuffer.toBigInt(), epoch, isEscapeHatchOpen };
226
258
  }
227
259
 
228
260
  /**
@@ -247,24 +279,12 @@ export class EpochCache implements EpochCacheInterface {
247
279
  return BigInt(keccak256(this.getProposerIndexEncoding(epoch, slot, seed))) % size;
248
280
  }
249
281
 
250
- /**
251
- * Returns the current and next proposer's attester address
252
- *
253
- * We return the next proposer's attester address as the node will check if it is the proposer at the next ethereum block,
254
- * which can be the next slot. If this is the case, then it will send proposals early.
255
- */
256
- public async getProposerAttesterAddressInCurrentOrNextSlot(): Promise<{
257
- currentSlot: SlotNumber;
258
- nextSlot: SlotNumber;
259
- currentProposer: EthAddress | undefined;
260
- nextProposer: EthAddress | undefined;
261
- }> {
282
+ /** Returns the current and next L2 slot numbers. */
283
+ public getCurrentAndNextSlot(): { currentSlot: SlotNumber; nextSlot: SlotNumber } {
262
284
  const current = this.getEpochAndSlotNow();
263
285
  const next = this.getEpochAndSlotInNextL1Slot();
264
286
 
265
287
  return {
266
- currentProposer: await this.getProposerAttesterAddressAt(current),
267
- nextProposer: await this.getProposerAttesterAddressAt(next),
268
288
  currentSlot: current.slot,
269
289
  nextSlot: next.slot,
270
290
  };
@@ -350,9 +370,9 @@ export class EpochCache implements EpochCacheInterface {
350
370
  const validatorRefreshTime = this.lastValidatorRefresh + validatorRefreshIntervalMs;
351
371
  if (validatorRefreshTime < this.dateProvider.now()) {
352
372
  const currentSet = await this.rollup.getAttesters();
353
- this.allValidators = new Set(currentSet);
373
+ this.allValidators = new Set(currentSet.map(v => v.toString()));
354
374
  this.lastValidatorRefresh = this.dateProvider.now();
355
375
  }
356
- return Array.from(this.allValidators.keys().map(v => EthAddress.fromString(v)));
376
+ return Array.from(this.allValidators.keys()).map(v => EthAddress.fromString(v));
357
377
  }
358
378
  }
@@ -0,0 +1 @@
1
+ export * from './test_epoch_cache.js';
@@ -0,0 +1,169 @@
1
+ import { EpochNumber, SlotNumber } from '@aztec/foundation/branded-types';
2
+ import { EthAddress } from '@aztec/foundation/eth-address';
3
+ import type { L1RollupConstants } from '@aztec/stdlib/epoch-helpers';
4
+ import { getEpochAtSlot, getSlotAtTimestamp, getTimestampRangeForEpoch } from '@aztec/stdlib/epoch-helpers';
5
+
6
+ import type { EpochAndSlot, EpochCacheInterface, EpochCommitteeInfo, SlotTag } from '../epoch_cache.js';
7
+
8
+ /** Default L1 constants for testing. */
9
+ const DEFAULT_L1_CONSTANTS: L1RollupConstants = {
10
+ l1StartBlock: 0n,
11
+ l1GenesisTime: 0n,
12
+ slotDuration: 24,
13
+ epochDuration: 16,
14
+ ethereumSlotDuration: 12,
15
+ proofSubmissionEpochs: 2,
16
+ };
17
+
18
+ /**
19
+ * A test implementation of EpochCacheInterface that allows manual configuration
20
+ * of committee, proposer, slot, and escape hatch state for use in tests.
21
+ *
22
+ * Unlike the real EpochCache, this class doesn't require any RPC connections
23
+ * or mock setup. Simply use the setter methods to configure the test state.
24
+ */
25
+ export class TestEpochCache implements EpochCacheInterface {
26
+ private committee: EthAddress[] = [];
27
+ private proposerAddress: EthAddress | undefined;
28
+ private currentSlot: SlotNumber = SlotNumber(0);
29
+ private escapeHatchOpen: boolean = false;
30
+ private seed: bigint = 0n;
31
+ private registeredValidators: EthAddress[] = [];
32
+ private l1Constants: L1RollupConstants;
33
+
34
+ constructor(l1Constants: Partial<L1RollupConstants> = {}) {
35
+ this.l1Constants = { ...DEFAULT_L1_CONSTANTS, ...l1Constants };
36
+ }
37
+
38
+ /**
39
+ * Sets the committee members. Used in validation and attestation flows.
40
+ * @param committee - Array of committee member addresses.
41
+ */
42
+ setCommittee(committee: EthAddress[]): this {
43
+ this.committee = committee;
44
+ return this;
45
+ }
46
+
47
+ /**
48
+ * Sets the proposer address returned by getProposerAttesterAddressInSlot.
49
+ * @param proposer - The address of the current proposer.
50
+ */
51
+ setProposer(proposer: EthAddress | undefined): this {
52
+ this.proposerAddress = proposer;
53
+ return this;
54
+ }
55
+
56
+ /**
57
+ * Sets the current slot number.
58
+ * @param slot - The slot number to set.
59
+ */
60
+ setCurrentSlot(slot: SlotNumber): this {
61
+ this.currentSlot = slot;
62
+ return this;
63
+ }
64
+
65
+ /**
66
+ * Sets whether the escape hatch is open.
67
+ * @param open - True if escape hatch should be open.
68
+ */
69
+ setEscapeHatchOpen(open: boolean): this {
70
+ this.escapeHatchOpen = open;
71
+ return this;
72
+ }
73
+
74
+ /**
75
+ * Sets the randomness seed used for proposer selection.
76
+ * @param seed - The seed value.
77
+ */
78
+ setSeed(seed: bigint): this {
79
+ this.seed = seed;
80
+ return this;
81
+ }
82
+
83
+ /**
84
+ * Sets the list of registered validators (all validators, not just committee).
85
+ * @param validators - Array of validator addresses.
86
+ */
87
+ setRegisteredValidators(validators: EthAddress[]): this {
88
+ this.registeredValidators = validators;
89
+ return this;
90
+ }
91
+
92
+ /**
93
+ * Sets the L1 constants used for epoch/slot calculations.
94
+ * @param constants - Partial constants to override defaults.
95
+ */
96
+ setL1Constants(constants: Partial<L1RollupConstants>): this {
97
+ this.l1Constants = { ...this.l1Constants, ...constants };
98
+ return this;
99
+ }
100
+
101
+ getL1Constants(): L1RollupConstants {
102
+ return this.l1Constants;
103
+ }
104
+
105
+ getCommittee(_slot?: SlotTag): Promise<EpochCommitteeInfo> {
106
+ const epoch = getEpochAtSlot(this.currentSlot, this.l1Constants);
107
+ return Promise.resolve({
108
+ committee: this.committee,
109
+ epoch,
110
+ seed: this.seed,
111
+ isEscapeHatchOpen: this.escapeHatchOpen,
112
+ });
113
+ }
114
+
115
+ getEpochAndSlotNow(): EpochAndSlot & { nowMs: bigint } {
116
+ const epoch = getEpochAtSlot(this.currentSlot, this.l1Constants);
117
+ const ts = getTimestampRangeForEpoch(epoch, this.l1Constants)[0];
118
+ return { epoch, slot: this.currentSlot, ts, nowMs: ts * 1000n };
119
+ }
120
+
121
+ getEpochAndSlotInNextL1Slot(): EpochAndSlot & { now: bigint } {
122
+ const now = getTimestampRangeForEpoch(getEpochAtSlot(this.currentSlot, this.l1Constants), this.l1Constants)[0];
123
+ const nextSlotTs = now + BigInt(this.l1Constants.ethereumSlotDuration);
124
+ const nextSlot = getSlotAtTimestamp(nextSlotTs, this.l1Constants);
125
+ const epoch = getEpochAtSlot(nextSlot, this.l1Constants);
126
+ const ts = getTimestampRangeForEpoch(epoch, this.l1Constants)[0];
127
+ return { epoch, slot: nextSlot, ts, now };
128
+ }
129
+
130
+ getProposerIndexEncoding(epoch: EpochNumber, slot: SlotNumber, seed: bigint): `0x${string}` {
131
+ // Simple encoding for testing purposes
132
+ return `0x${epoch.toString(16).padStart(64, '0')}${slot.toString(16).padStart(64, '0')}${seed.toString(16).padStart(64, '0')}`;
133
+ }
134
+
135
+ computeProposerIndex(slot: SlotNumber, _epoch: EpochNumber, _seed: bigint, size: bigint): bigint {
136
+ if (size === 0n) {
137
+ return 0n;
138
+ }
139
+ return BigInt(slot) % size;
140
+ }
141
+
142
+ getCurrentAndNextSlot(): { currentSlot: SlotNumber; nextSlot: SlotNumber } {
143
+ return {
144
+ currentSlot: this.currentSlot,
145
+ nextSlot: SlotNumber(this.currentSlot + 1),
146
+ };
147
+ }
148
+
149
+ getProposerAttesterAddressInSlot(_slot: SlotNumber): Promise<EthAddress | undefined> {
150
+ return Promise.resolve(this.proposerAddress);
151
+ }
152
+
153
+ getRegisteredValidators(): Promise<EthAddress[]> {
154
+ return Promise.resolve(this.registeredValidators);
155
+ }
156
+
157
+ isInCommittee(_slot: SlotTag, validator: EthAddress): Promise<boolean> {
158
+ return Promise.resolve(this.committee.some(v => v.equals(validator)));
159
+ }
160
+
161
+ filterInCommittee(_slot: SlotTag, validators: EthAddress[]): Promise<EthAddress[]> {
162
+ const committeeSet = new Set(this.committee.map(v => v.toString()));
163
+ return Promise.resolve(validators.filter(v => committeeSet.has(v.toString())));
164
+ }
165
+
166
+ isEscapeHatchOpenAtSlot(_slot?: SlotTag): Promise<boolean> {
167
+ return Promise.resolve(this.escapeHatchOpen);
168
+ }
169
+ }