@aztec/epoch-cache 0.87.7 → 1.0.0-nightly.20250605

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.
@@ -18,7 +18,7 @@ export interface EpochCacheInterface {
18
18
  getEpochAndSlotNow(): EpochAndSlot;
19
19
  getProposerIndexEncoding(epoch: bigint, slot: bigint, seed: bigint): `0x${string}`;
20
20
  computeProposerIndex(slot: bigint, epoch: bigint, seed: bigint, size: bigint): bigint;
21
- getProposerInCurrentOrNextSlot(): Promise<{
21
+ getProposerAttesterAddressInCurrentOrNextSlot(): Promise<{
22
22
  currentProposer: EthAddress;
23
23
  nextProposer: EthAddress;
24
24
  currentSlot: bigint;
@@ -52,8 +52,9 @@ export declare class EpochCache implements EpochCacheInterface {
52
52
  getEpochAndSlotNow(): EpochAndSlot;
53
53
  private nowInSeconds;
54
54
  private getEpochAndSlotAtSlot;
55
- private getEpochAndSlotInNextSlot;
55
+ getEpochAndSlotInNextSlot(): EpochAndSlot;
56
56
  private getEpochAndSlotAtTimestamp;
57
+ getCommitteeForEpoch(epoch: bigint): Promise<EpochCommitteeInfo>;
57
58
  /**
58
59
  * Get the current validator set
59
60
  * @param nextSlot - If true, get the validator set for the next slot.
@@ -68,22 +69,24 @@ export declare class EpochCache implements EpochCacheInterface {
68
69
  getProposerIndexEncoding(epoch: bigint, slot: bigint, seed: bigint): `0x${string}`;
69
70
  computeProposerIndex(slot: bigint, epoch: bigint, seed: bigint, size: bigint): bigint;
70
71
  /**
71
- * Returns the current and next proposer
72
+ * Returns the current and next proposer's attester address
72
73
  *
73
- * We return the next proposer as the node will check if it is the proposer at the next ethereum block, which
74
- * can be the next slot. If this is the case, then it will send proposals early.
74
+ * We return the next proposer's attester address as the node will check if it is the proposer at the next ethereum block,
75
+ * which can be the next slot. If this is the case, then it will send proposals early.
75
76
  */
76
- getProposerInCurrentOrNextSlot(): Promise<{
77
- currentProposer: EthAddress;
78
- nextProposer: EthAddress;
77
+ getProposerAttesterAddressInCurrentOrNextSlot(): Promise<{
79
78
  currentSlot: bigint;
80
79
  nextSlot: bigint;
80
+ currentProposer: EthAddress;
81
+ nextProposer: EthAddress;
81
82
  }>;
82
- private getProposerAt;
83
+ getProposerAttesterAddressInNextSlot(): Promise<EthAddress>;
84
+ private getProposerAttesterAddressAt;
83
85
  /**
84
86
  * Check if a validator is in the current epoch's committee
85
87
  */
86
88
  isInCommittee(validator: EthAddress): Promise<boolean>;
89
+ filterInCommittee(validators: EthAddress[]): Promise<EthAddress[]>;
87
90
  }
88
91
  export {};
89
92
  //# sourceMappingURL=epoch_cache.d.ts.map
@@ -1 +1 @@
1
- {"version":3,"file":"epoch_cache.d.ts","sourceRoot":"","sources":["../src/epoch_cache.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,cAAc,EAAuB,MAAM,iBAAiB,CAAC;AACtE,OAAO,EAAE,UAAU,EAAE,MAAM,+BAA+B,CAAC;AAE3D,OAAO,EAAE,YAAY,EAAE,MAAM,yBAAyB,CAAC;AACvD,OAAO,EAEL,KAAK,iBAAiB,EAKvB,MAAM,6BAA6B,CAAC;AAIrC,OAAO,EAAE,KAAK,gBAAgB,EAA8B,MAAM,aAAa,CAAC;AAEhF,KAAK,YAAY,GAAG;IAClB,KAAK,EAAE,MAAM,CAAC;IACd,IAAI,EAAE,MAAM,CAAC;IACb,EAAE,EAAE,MAAM,CAAC;CACZ,CAAC;AAEF,MAAM,MAAM,kBAAkB,GAAG;IAC/B,SAAS,EAAE,UAAU,EAAE,CAAC;IACxB,IAAI,EAAE,MAAM,CAAC;IACb,KAAK,EAAE,MAAM,CAAC;CACf,CAAC;AAEF,MAAM,WAAW,mBAAmB;IAClC,YAAY,CAAC,IAAI,EAAE,KAAK,GAAG,MAAM,GAAG,MAAM,GAAG,SAAS,GAAG,OAAO,CAAC,kBAAkB,CAAC,CAAC;IACrF,kBAAkB,IAAI,YAAY,CAAC;IACnC,wBAAwB,CAAC,KAAK,EAAE,MAAM,EAAE,IAAI,EAAE,MAAM,EAAE,IAAI,EAAE,MAAM,GAAG,KAAK,MAAM,EAAE,CAAC;IACnF,oBAAoB,CAAC,IAAI,EAAE,MAAM,EAAE,KAAK,EAAE,MAAM,EAAE,IAAI,EAAE,MAAM,EAAE,IAAI,EAAE,MAAM,GAAG,MAAM,CAAC;IACtF,8BAA8B,IAAI,OAAO,CAAC;QACxC,eAAe,EAAE,UAAU,CAAC;QAC5B,YAAY,EAAE,UAAU,CAAC;QACzB,WAAW,EAAE,MAAM,CAAC;QACpB,QAAQ,EAAE,MAAM,CAAC;KAClB,CAAC,CAAC;IACH,aAAa,CAAC,SAAS,EAAE,UAAU,GAAG,OAAO,CAAC,OAAO,CAAC,CAAC;CACxD;AAED;;;;;;;;GAQG;AACH,qBAAa,UAAW,YAAW,mBAAmB;IAKlD,OAAO,CAAC,MAAM;IAId,OAAO,CAAC,QAAQ,CAAC,WAAW;IAC5B,OAAO,CAAC,QAAQ,CAAC,YAAY;IAC7B,OAAO,CAAC,QAAQ,CAAC,MAAM;IAVzB,OAAO,CAAC,KAAK,CAA8C;IAC3D,OAAO,CAAC,QAAQ,CAAC,GAAG,CAAuC;gBAGjD,MAAM,EAAE,cAAc,EAC9B,YAAY,GAAE,MAAW,EACzB,iBAAiB,GAAE,UAAU,EAAO,EACpC,iBAAiB,GAAE,MAAW,EACb,WAAW,GAAE,iBAA0C,EACvD,YAAY,GAAE,YAAiC,EAC/C,MAAM;;KAAoB;WAWhC,MAAM,CACjB,aAAa,EAAE,UAAU,EACzB,MAAM,CAAC,EAAE,gBAAgB,EACzB,IAAI,GAAE;QAAE,YAAY,CAAC,EAAE,YAAY,CAAA;KAAO;IAuCrC,cAAc,IAAI,iBAAiB;IAInC,kBAAkB,IAAI,YAAY;IAIzC,OAAO,CAAC,YAAY;IAIpB,OAAO,CAAC,qBAAqB;IAM7B,OAAO,CAAC,yBAAyB;IAKjC,OAAO,CAAC,0BAA0B;IAQlC;;;;OAIG;IACU,YAAY,CAAC,IAAI,GAAE,KAAK,GAAG,MAAM,GAAG,MAAc,GAAG,OAAO,CAAC,kBAAkB,CAAC;IAkB7F,OAAO,CAAC,oBAAoB;YAUd,gBAAgB;IAO9B;;OAEG;IACH,wBAAwB,CAAC,KAAK,EAAE,MAAM,EAAE,IAAI,EAAE,MAAM,EAAE,IAAI,EAAE,MAAM,GAAG,KAAK,MAAM,EAAE;IAWlF,oBAAoB,CAAC,IAAI,EAAE,MAAM,EAAE,KAAK,EAAE,MAAM,EAAE,IAAI,EAAE,MAAM,EAAE,IAAI,EAAE,MAAM,GAAG,MAAM;IAIrF;;;;;OAKG;IACG,8BAA8B,IAAI,OAAO,CAAC;QAC9C,eAAe,EAAE,UAAU,CAAC;QAC5B,YAAY,EAAE,UAAU,CAAC;QACzB,WAAW,EAAE,MAAM,CAAC;QACpB,QAAQ,EAAE,MAAM,CAAC;KAClB,CAAC;YAYY,aAAa;IAO3B;;OAEG;IACG,aAAa,CAAC,SAAS,EAAE,UAAU,GAAG,OAAO,CAAC,OAAO,CAAC;CAI7D"}
1
+ {"version":3,"file":"epoch_cache.d.ts","sourceRoot":"","sources":["../src/epoch_cache.ts"],"names":[],"mappings":"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"}
@@ -2,7 +2,7 @@ import { RollupContract, createEthereumChain } from '@aztec/ethereum';
2
2
  import { EthAddress } from '@aztec/foundation/eth-address';
3
3
  import { createLogger } from '@aztec/foundation/log';
4
4
  import { DateProvider } from '@aztec/foundation/timer';
5
- import { EmptyL1RollupConstants, getEpochAtSlot, getEpochNumberAtTimestamp, getSlotAtTimestamp, getTimestampRangeForEpoch } from '@aztec/stdlib/epoch-helpers';
5
+ import { EmptyL1RollupConstants, getEpochAtSlot, getEpochNumberAtTimestamp, getSlotAtTimestamp, getSlotRangeForEpoch, getTimestampRangeForEpoch } from '@aztec/stdlib/epoch-helpers';
6
6
  import { createPublicClient, encodeAbiParameters, fallback, http, keccak256 } from 'viem';
7
7
  import { getEpochCacheConfigEnvVars } from './config.js';
8
8
  /**
@@ -86,7 +86,7 @@ import { getEpochCacheConfigEnvVars } from './config.js';
86
86
  };
87
87
  }
88
88
  getEpochAndSlotInNextSlot() {
89
- const nextSlotTs = this.nowInSeconds() + BigInt(this.l1constants.slotDuration);
89
+ const nextSlotTs = this.nowInSeconds() + BigInt(this.l1constants.ethereumSlotDuration);
90
90
  return this.getEpochAndSlotAtTimestamp(nextSlotTs);
91
91
  }
92
92
  getEpochAndSlotAtTimestamp(ts) {
@@ -96,6 +96,10 @@ import { getEpochCacheConfigEnvVars } from './config.js';
96
96
  ts
97
97
  };
98
98
  }
99
+ getCommitteeForEpoch(epoch) {
100
+ const [startSlot] = getSlotRangeForEpoch(epoch, this.l1constants);
101
+ return this.getCommittee(startSlot);
102
+ }
99
103
  /**
100
104
  * Get the current validator set
101
105
  * @param nextSlot - If true, get the validator set for the next slot.
@@ -109,6 +113,10 @@ import { getEpochCacheConfigEnvVars } from './config.js';
109
113
  epoch,
110
114
  ts
111
115
  });
116
+ // If the committee size is 0, then do not cache
117
+ if (epochData.committee.length == 0) {
118
+ return epochData;
119
+ }
112
120
  this.cache.set(epoch, epochData);
113
121
  const toPurge = Array.from(this.cache.keys()).sort((a, b)=>Number(b - a)).slice(this.config.cacheSize);
114
122
  toPurge.forEach((key)=>this.cache.delete(key));
@@ -159,24 +167,32 @@ import { getEpochCacheConfigEnvVars } from './config.js';
159
167
  ]);
160
168
  }
161
169
  computeProposerIndex(slot, epoch, seed, size) {
170
+ // if committe size is 0, then mod 1 is 0
171
+ if (size === 0n) {
172
+ return 0n;
173
+ }
162
174
  return BigInt(keccak256(this.getProposerIndexEncoding(epoch, slot, seed))) % size;
163
175
  }
164
176
  /**
165
- * Returns the current and next proposer
177
+ * Returns the current and next proposer's attester address
166
178
  *
167
- * We return the next proposer as the node will check if it is the proposer at the next ethereum block, which
168
- * can be the next slot. If this is the case, then it will send proposals early.
169
- */ async getProposerInCurrentOrNextSlot() {
179
+ * We return the next proposer's attester address as the node will check if it is the proposer at the next ethereum block,
180
+ * which can be the next slot. If this is the case, then it will send proposals early.
181
+ */ async getProposerAttesterAddressInCurrentOrNextSlot() {
170
182
  const current = this.getEpochAndSlotNow();
171
183
  const next = this.getEpochAndSlotInNextSlot();
172
184
  return {
173
- currentProposer: await this.getProposerAt(current),
174
- nextProposer: await this.getProposerAt(next),
185
+ currentProposer: await this.getProposerAttesterAddressAt(current),
186
+ nextProposer: await this.getProposerAttesterAddressAt(next),
175
187
  currentSlot: current.slot,
176
188
  nextSlot: next.slot
177
189
  };
178
190
  }
179
- async getProposerAt(when) {
191
+ getProposerAttesterAddressInNextSlot() {
192
+ const epochAndSlot = this.getEpochAndSlotInNextSlot();
193
+ return this.getProposerAttesterAddressAt(epochAndSlot);
194
+ }
195
+ async getProposerAttesterAddressAt(when) {
180
196
  const { epoch, slot } = when;
181
197
  const { seed, committee } = await this.getCommittee(slot);
182
198
  const proposerIndex = this.computeProposerIndex(slot, epoch, seed, BigInt(committee.length));
@@ -188,4 +204,9 @@ import { getEpochCacheConfigEnvVars } from './config.js';
188
204
  const { committee } = await this.getCommittee();
189
205
  return committee.some((v)=>v.equals(validator));
190
206
  }
207
+ async filterInCommittee(validators) {
208
+ const { committee } = await this.getCommittee();
209
+ const committeeSet = new Set(committee.map((v)=>v.toString()));
210
+ return validators.filter((v)=>committeeSet.has(v.toString()));
211
+ }
191
212
  }
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@aztec/epoch-cache",
3
- "version": "0.87.7",
3
+ "version": "1.0.0-nightly.20250605",
4
4
  "type": "module",
5
5
  "exports": {
6
6
  ".": "./dest/index.js",
@@ -26,10 +26,10 @@
26
26
  "../package.common.json"
27
27
  ],
28
28
  "dependencies": {
29
- "@aztec/ethereum": "0.87.7",
30
- "@aztec/foundation": "0.87.7",
31
- "@aztec/l1-artifacts": "0.87.7",
32
- "@aztec/stdlib": "0.87.7",
29
+ "@aztec/ethereum": "1.0.0-nightly.20250605",
30
+ "@aztec/foundation": "1.0.0-nightly.20250605",
31
+ "@aztec/l1-artifacts": "1.0.0-nightly.20250605",
32
+ "@aztec/stdlib": "1.0.0-nightly.20250605",
33
33
  "@viem/anvil": "^0.0.10",
34
34
  "dotenv": "^16.0.3",
35
35
  "get-port": "^7.1.0",
@@ -8,6 +8,7 @@ import {
8
8
  getEpochAtSlot,
9
9
  getEpochNumberAtTimestamp,
10
10
  getSlotAtTimestamp,
11
+ getSlotRangeForEpoch,
11
12
  getTimestampRangeForEpoch,
12
13
  } from '@aztec/stdlib/epoch-helpers';
13
14
 
@@ -32,7 +33,7 @@ export interface EpochCacheInterface {
32
33
  getEpochAndSlotNow(): EpochAndSlot;
33
34
  getProposerIndexEncoding(epoch: bigint, slot: bigint, seed: bigint): `0x${string}`;
34
35
  computeProposerIndex(slot: bigint, epoch: bigint, seed: bigint, size: bigint): bigint;
35
- getProposerInCurrentOrNextSlot(): Promise<{
36
+ getProposerAttesterAddressInCurrentOrNextSlot(): Promise<{
36
37
  currentProposer: EthAddress;
37
38
  nextProposer: EthAddress;
38
39
  currentSlot: bigint;
@@ -132,8 +133,8 @@ export class EpochCache implements EpochCacheInterface {
132
133
  return { epoch, ts, slot };
133
134
  }
134
135
 
135
- private getEpochAndSlotInNextSlot(): EpochAndSlot {
136
- const nextSlotTs = this.nowInSeconds() + BigInt(this.l1constants.slotDuration);
136
+ public getEpochAndSlotInNextSlot(): EpochAndSlot {
137
+ const nextSlotTs = this.nowInSeconds() + BigInt(this.l1constants.ethereumSlotDuration);
137
138
  return this.getEpochAndSlotAtTimestamp(nextSlotTs);
138
139
  }
139
140
 
@@ -145,6 +146,11 @@ export class EpochCache implements EpochCacheInterface {
145
146
  };
146
147
  }
147
148
 
149
+ public getCommitteeForEpoch(epoch: bigint): Promise<EpochCommitteeInfo> {
150
+ const [startSlot] = getSlotRangeForEpoch(epoch, this.l1constants);
151
+ return this.getCommittee(startSlot);
152
+ }
153
+
148
154
  /**
149
155
  * Get the current validator set
150
156
  * @param nextSlot - If true, get the validator set for the next slot.
@@ -158,6 +164,10 @@ export class EpochCache implements EpochCacheInterface {
158
164
  }
159
165
 
160
166
  const epochData = await this.computeCommittee({ epoch, ts });
167
+ // If the committee size is 0, then do not cache
168
+ if (epochData.committee.length == 0) {
169
+ return epochData;
170
+ }
161
171
  this.cache.set(epoch, epochData);
162
172
 
163
173
  const toPurge = Array.from(this.cache.keys())
@@ -200,35 +210,46 @@ export class EpochCache implements EpochCacheInterface {
200
210
  }
201
211
 
202
212
  computeProposerIndex(slot: bigint, epoch: bigint, seed: bigint, size: bigint): bigint {
213
+ // if committe size is 0, then mod 1 is 0
214
+ if (size === 0n) {
215
+ return 0n;
216
+ }
203
217
  return BigInt(keccak256(this.getProposerIndexEncoding(epoch, slot, seed))) % size;
204
218
  }
205
219
 
206
220
  /**
207
- * Returns the current and next proposer
221
+ * Returns the current and next proposer's attester address
208
222
  *
209
- * We return the next proposer as the node will check if it is the proposer at the next ethereum block, which
210
- * can be the next slot. If this is the case, then it will send proposals early.
223
+ * We return the next proposer's attester address as the node will check if it is the proposer at the next ethereum block,
224
+ * which can be the next slot. If this is the case, then it will send proposals early.
211
225
  */
212
- async getProposerInCurrentOrNextSlot(): Promise<{
213
- currentProposer: EthAddress;
214
- nextProposer: EthAddress;
226
+ async getProposerAttesterAddressInCurrentOrNextSlot(): Promise<{
215
227
  currentSlot: bigint;
216
228
  nextSlot: bigint;
229
+ currentProposer: EthAddress;
230
+ nextProposer: EthAddress;
217
231
  }> {
218
232
  const current = this.getEpochAndSlotNow();
219
233
  const next = this.getEpochAndSlotInNextSlot();
220
234
 
221
235
  return {
222
- currentProposer: await this.getProposerAt(current),
223
- nextProposer: await this.getProposerAt(next),
236
+ currentProposer: await this.getProposerAttesterAddressAt(current),
237
+ nextProposer: await this.getProposerAttesterAddressAt(next),
224
238
  currentSlot: current.slot,
225
239
  nextSlot: next.slot,
226
240
  };
227
241
  }
228
242
 
229
- private async getProposerAt(when: EpochAndSlot) {
243
+ getProposerAttesterAddressInNextSlot(): Promise<EthAddress> {
244
+ const epochAndSlot = this.getEpochAndSlotInNextSlot();
245
+
246
+ return this.getProposerAttesterAddressAt(epochAndSlot);
247
+ }
248
+
249
+ private async getProposerAttesterAddressAt(when: EpochAndSlot) {
230
250
  const { epoch, slot } = when;
231
251
  const { seed, committee } = await this.getCommittee(slot);
252
+
232
253
  const proposerIndex = this.computeProposerIndex(slot, epoch, seed, BigInt(committee.length));
233
254
  return committee[Number(proposerIndex)];
234
255
  }
@@ -240,4 +261,10 @@ export class EpochCache implements EpochCacheInterface {
240
261
  const { committee } = await this.getCommittee();
241
262
  return committee.some(v => v.equals(validator));
242
263
  }
264
+
265
+ async filterInCommittee(validators: EthAddress[]): Promise<EthAddress[]> {
266
+ const { committee } = await this.getCommittee();
267
+ const committeeSet = new Set(committee.map(v => v.toString()));
268
+ return validators.filter(v => committeeSet.has(v.toString()));
269
+ }
243
270
  }