@aztec/epoch-cache 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.
package/dest/config.d.ts CHANGED
@@ -1,4 +1,5 @@
1
- import { type L1ContractsConfig, type L1ReaderConfig } from '@aztec/ethereum';
2
- export type EpochCacheConfig = Pick<L1ReaderConfig & L1ContractsConfig, 'l1RpcUrls' | 'l1ChainId' | 'viemPollingIntervalMS' | 'aztecSlotDuration' | 'ethereumSlotDuration' | 'aztecEpochDuration'>;
1
+ import { type L1ContractsConfig } from '@aztec/ethereum/config';
2
+ import { type L1ReaderConfig } from '@aztec/ethereum/l1-reader';
3
+ export type EpochCacheConfig = Pick<L1ReaderConfig & L1ContractsConfig, 'l1RpcUrls' | 'l1ChainId' | 'viemPollingIntervalMS' | 'ethereumSlotDuration'>;
3
4
  export declare function getEpochCacheConfigEnvVars(): EpochCacheConfig;
4
- //# sourceMappingURL=config.d.ts.map
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,EAChC,WAAW,GACX,WAAW,GACX,uBAAuB,GACvB,mBAAmB,GACnB,sBAAsB,GACtB,oBAAoB,CACvB,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,32 +1,33 @@
1
- import { RollupContract } from '@aztec/ethereum';
1
+ import { RollupContract } from '@aztec/ethereum/contracts';
2
+ import { EpochNumber, SlotNumber } from '@aztec/foundation/branded-types';
2
3
  import { EthAddress } from '@aztec/foundation/eth-address';
3
4
  import { DateProvider } from '@aztec/foundation/timer';
4
5
  import { type L1RollupConstants } from '@aztec/stdlib/epoch-helpers';
5
6
  import { type EpochCacheConfig } from './config.js';
6
7
  export type EpochAndSlot = {
7
- epoch: bigint;
8
- slot: bigint;
8
+ epoch: EpochNumber;
9
+ slot: SlotNumber;
9
10
  ts: bigint;
10
11
  };
11
12
  export type EpochCommitteeInfo = {
12
13
  committee: EthAddress[] | undefined;
13
14
  seed: bigint;
14
- epoch: bigint;
15
+ epoch: EpochNumber;
15
16
  };
16
- export type SlotTag = 'now' | 'next' | bigint;
17
+ export type SlotTag = 'now' | 'next' | SlotNumber;
17
18
  export interface EpochCacheInterface {
18
19
  getCommittee(slot: SlotTag | undefined): Promise<EpochCommitteeInfo>;
19
20
  getEpochAndSlotNow(): EpochAndSlot;
20
21
  getEpochAndSlotInNextL1Slot(): EpochAndSlot & {
21
22
  now: bigint;
22
23
  };
23
- getProposerIndexEncoding(epoch: bigint, slot: bigint, seed: bigint): `0x${string}`;
24
- computeProposerIndex(slot: bigint, epoch: bigint, seed: bigint, size: bigint): bigint;
24
+ getProposerIndexEncoding(epoch: EpochNumber, slot: SlotNumber, seed: bigint): `0x${string}`;
25
+ computeProposerIndex(slot: SlotNumber, epoch: EpochNumber, seed: bigint, size: bigint): bigint;
25
26
  getProposerAttesterAddressInCurrentOrNextSlot(): Promise<{
26
27
  currentProposer: EthAddress | undefined;
27
28
  nextProposer: EthAddress | undefined;
28
- currentSlot: bigint;
29
- nextSlot: bigint;
29
+ currentSlot: SlotNumber;
30
+ nextSlot: SlotNumber;
30
31
  }>;
31
32
  getRegisteredValidators(): Promise<EthAddress[]>;
32
33
  isInCommittee(slot: SlotTag, validator: EthAddress): Promise<boolean>;
@@ -45,16 +46,22 @@ export declare class EpochCache implements EpochCacheInterface {
45
46
  private rollup;
46
47
  private readonly l1constants;
47
48
  private readonly dateProvider;
48
- private readonly config;
49
- private cache;
49
+ protected readonly config: {
50
+ cacheSize: number;
51
+ validatorRefreshIntervalSeconds: number;
52
+ };
53
+ protected cache: Map<EpochNumber, EpochCommitteeInfo>;
50
54
  private allValidators;
51
55
  private lastValidatorRefresh;
52
56
  private readonly log;
53
- constructor(rollup: RollupContract, initialEpoch?: bigint, initialValidators?: EthAddress[] | undefined, initialSampleSeed?: bigint, l1constants?: L1RollupConstants, dateProvider?: DateProvider, config?: {
57
+ constructor(rollup: RollupContract, l1constants: L1RollupConstants & {
58
+ lagInEpochsForValidatorSet: number;
59
+ lagInEpochsForRandao: number;
60
+ }, dateProvider?: DateProvider, config?: {
54
61
  cacheSize: number;
55
62
  validatorRefreshIntervalSeconds: number;
56
63
  });
57
- static create(rollupAddress: EthAddress, config?: EpochCacheConfig, deps?: {
64
+ static create(rollupOrAddress: EthAddress | RollupContract, config?: EpochCacheConfig, deps?: {
58
65
  dateProvider?: DateProvider;
59
66
  }): Promise<EpochCache>;
60
67
  getL1Constants(): L1RollupConstants;
@@ -67,7 +74,7 @@ export declare class EpochCache implements EpochCacheInterface {
67
74
  now: bigint;
68
75
  };
69
76
  private getEpochAndSlotAtTimestamp;
70
- getCommitteeForEpoch(epoch: bigint): Promise<EpochCommitteeInfo>;
77
+ getCommitteeForEpoch(epoch: EpochNumber): Promise<EpochCommitteeInfo>;
71
78
  /**
72
79
  * Get the current validator set
73
80
  * @param nextSlot - If true, get the validator set for the next slot.
@@ -79,8 +86,8 @@ export declare class EpochCache implements EpochCacheInterface {
79
86
  /**
80
87
  * Get the ABI encoding of the proposer index - see ValidatorSelectionLib.sol computeProposerIndex
81
88
  */
82
- getProposerIndexEncoding(epoch: bigint, slot: bigint, seed: bigint): `0x${string}`;
83
- computeProposerIndex(slot: bigint, epoch: bigint, seed: bigint, size: bigint): bigint;
89
+ getProposerIndexEncoding(epoch: EpochNumber, slot: SlotNumber, seed: bigint): `0x${string}`;
90
+ computeProposerIndex(slot: SlotNumber, epoch: EpochNumber, seed: bigint, size: bigint): bigint;
84
91
  /**
85
92
  * Returns the current and next proposer's attester address
86
93
  *
@@ -88,29 +95,29 @@ export declare class EpochCache implements EpochCacheInterface {
88
95
  * which can be the next slot. If this is the case, then it will send proposals early.
89
96
  */
90
97
  getProposerAttesterAddressInCurrentOrNextSlot(): Promise<{
91
- currentSlot: bigint;
92
- nextSlot: bigint;
98
+ currentSlot: SlotNumber;
99
+ nextSlot: SlotNumber;
93
100
  currentProposer: EthAddress | undefined;
94
101
  nextProposer: EthAddress | undefined;
95
102
  }>;
96
103
  /**
97
- * Get the proposer attester address in the next slot
104
+ * Get the proposer attester address in the given L2 slot
98
105
  * @returns The proposer attester address. If the committee does not exist, we throw a NoCommitteeError.
99
106
  * If the committee is empty (i.e. target committee size is 0, and anyone can propose), we return undefined.
100
107
  */
101
- getProposerAttesterAddressInNextSlot(): Promise<EthAddress | undefined>;
108
+ getProposerAttesterAddressInSlot(slot: SlotNumber): Promise<EthAddress | undefined>;
102
109
  /**
103
- * Get the proposer attester address at a given epoch and slot
104
- * @param when - The epoch and slot to get the proposer attester address at
110
+ * Get the proposer attester address in the next slot
105
111
  * @returns The proposer attester address. If the committee does not exist, we throw a NoCommitteeError.
106
112
  * If the committee is empty (i.e. target committee size is 0, and anyone can propose), we return undefined.
107
113
  */
114
+ getProposerAttesterAddressInNextSlot(): Promise<EthAddress | undefined>;
108
115
  private getProposerAttesterAddressAt;
109
- getProposerFromEpochCommittee(epochCommitteeInfo: EpochCommitteeInfo, slot: bigint): EthAddress | undefined;
116
+ getProposerFromEpochCommittee(epochCommitteeInfo: EpochCommitteeInfo, slot: SlotNumber): EthAddress | undefined;
110
117
  /** Check if a validator is in the given slot's committee */
111
118
  isInCommittee(slot: SlotTag, validator: EthAddress): Promise<boolean>;
112
119
  /** From the set of given addresses, return all that are on the committee for the given slot */
113
120
  filterInCommittee(slot: SlotTag, validators: EthAddress[]): Promise<EthAddress[]>;
114
121
  getRegisteredValidators(): Promise<EthAddress[]>;
115
122
  }
116
- //# sourceMappingURL=epoch_cache.d.ts.map
123
+ //# sourceMappingURL=data:application/json;base64,eyJ2ZXJzaW9uIjozLCJmaWxlIjoiZXBvY2hfY2FjaGUuZC50cyIsInNvdXJjZVJvb3QiOiIiLCJzb3VyY2VzIjpbIi4uL3NyYy9lcG9jaF9jYWNoZS50cyJdLCJuYW1lcyI6W10sIm1hcHBpbmdzIjoiQUFDQSxPQUFPLEVBQW9CLGNBQWMsRUFBRSxNQUFNLDJCQUEyQixDQUFDO0FBQzdFLE9BQU8sRUFBRSxXQUFXLEVBQUUsVUFBVSxFQUFFLE1BQU0saUNBQWlDLENBQUM7QUFDMUUsT0FBTyxFQUFFLFVBQVUsRUFBRSxNQUFNLCtCQUErQixDQUFDO0FBRTNELE9BQU8sRUFBRSxZQUFZLEVBQUUsTUFBTSx5QkFBeUIsQ0FBQztBQUN2RCxPQUFPLEVBQ0wsS0FBSyxpQkFBaUIsRUFPdkIsTUFBTSw2QkFBNkIsQ0FBQztBQUlyQyxPQUFPLEVBQUUsS0FBSyxnQkFBZ0IsRUFBOEIsTUFBTSxhQUFhLENBQUM7QUFFaEYsTUFBTSxNQUFNLFlBQVksR0FBRztJQUN6QixLQUFLLEVBQUUsV0FBVyxDQUFDO0lBQ25CLElBQUksRUFBRSxVQUFVLENBQUM7SUFDakIsRUFBRSxFQUFFLE1BQU0sQ0FBQztDQUNaLENBQUM7QUFFRixNQUFNLE1BQU0sa0JBQWtCLEdBQUc7SUFDL0IsU0FBUyxFQUFFLFVBQVUsRUFBRSxHQUFHLFNBQVMsQ0FBQztJQUNwQyxJQUFJLEVBQUUsTUFBTSxDQUFDO0lBQ2IsS0FBSyxFQUFFLFdBQVcsQ0FBQztDQUNwQixDQUFDO0FBRUYsTUFBTSxNQUFNLE9BQU8sR0FBRyxLQUFLLEdBQUcsTUFBTSxHQUFHLFVBQVUsQ0FBQztBQUVsRCxNQUFNLFdBQVcsbUJBQW1CO0lBQ2xDLFlBQVksQ0FBQyxJQUFJLEVBQUUsT0FBTyxHQUFHLFNBQVMsR0FBRyxPQUFPLENBQUMsa0JBQWtCLENBQUMsQ0FBQztJQUNyRSxrQkFBa0IsSUFBSSxZQUFZLENBQUM7SUFDbkMsMkJBQTJCLElBQUksWUFBWSxHQUFHO1FBQUUsR0FBRyxFQUFFLE1BQU0sQ0FBQTtLQUFFLENBQUM7SUFDOUQsd0JBQXdCLENBQUMs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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,8 +1,9 @@
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';
5
- import { EmptyL1RollupConstants, getEpochAtSlot, getEpochNumberAtTimestamp, getSlotAtTimestamp, getSlotRangeForEpoch, getTimestampForSlot, getTimestampRangeForEpoch } from '@aztec/stdlib/epoch-helpers';
6
+ import { getEpochAtSlot, getEpochNumberAtTimestamp, getSlotAtTimestamp, getSlotRangeForEpoch, getTimestampForSlot, getTimestampRangeForEpoch } from '@aztec/stdlib/epoch-helpers';
6
7
  import { createPublicClient, encodeAbiParameters, fallback, http, keccak256 } from 'viem';
7
8
  import { getEpochCacheConfigEnvVars } from './config.js';
8
9
  /**
@@ -18,11 +19,12 @@ import { getEpochCacheConfigEnvVars } from './config.js';
18
19
  l1constants;
19
20
  dateProvider;
20
21
  config;
22
+ // eslint-disable-next-line aztec-custom/no-non-primitive-in-collections
21
23
  cache;
22
24
  allValidators;
23
25
  lastValidatorRefresh;
24
26
  log;
25
- constructor(rollup, initialEpoch = 0n, initialValidators = undefined, initialSampleSeed = 0n, l1constants = EmptyL1RollupConstants, dateProvider = new DateProvider(), config = {
27
+ constructor(rollup, l1constants, dateProvider = new DateProvider(), config = {
26
28
  cacheSize: 12,
27
29
  validatorRefreshIntervalSeconds: 60
28
30
  }){
@@ -34,44 +36,45 @@ import { getEpochCacheConfigEnvVars } from './config.js';
34
36
  this.allValidators = new Set();
35
37
  this.lastValidatorRefresh = 0;
36
38
  this.log = createLogger('epoch-cache');
37
- this.cache.set(initialEpoch, {
38
- epoch: initialEpoch,
39
- committee: initialValidators,
40
- seed: initialSampleSeed
41
- });
42
- this.log.debug(`Initialized EpochCache with ${initialValidators?.length ?? 'no'} validators`, {
43
- l1constants,
44
- initialValidators,
45
- initialSampleSeed,
46
- initialEpoch
39
+ this.log.debug(`Initialized EpochCache`, {
40
+ l1constants
47
41
  });
48
42
  }
49
- static async create(rollupAddress, config, deps = {}) {
43
+ static async create(rollupOrAddress, config, deps = {}) {
50
44
  config = config ?? getEpochCacheConfigEnvVars();
51
- const chain = createEthereumChain(config.l1RpcUrls, config.l1ChainId);
52
- const publicClient = createPublicClient({
53
- chain: chain.chainInfo,
54
- transport: fallback(config.l1RpcUrls.map((url)=>http(url))),
55
- pollingInterval: config.viemPollingIntervalMS
56
- });
57
- const rollup = new RollupContract(publicClient, rollupAddress.toString());
58
- const [l1StartBlock, l1GenesisTime, initialValidators, sampleSeed, epochNumber, proofSubmissionEpochs] = await Promise.all([
45
+ // Load the rollup contract if we were given an address
46
+ let rollup;
47
+ if ('address' in rollupOrAddress) {
48
+ rollup = rollupOrAddress;
49
+ } else {
50
+ const chain = createEthereumChain(config.l1RpcUrls, config.l1ChainId);
51
+ const publicClient = createPublicClient({
52
+ chain: chain.chainInfo,
53
+ transport: fallback(config.l1RpcUrls.map((url)=>http(url))),
54
+ pollingInterval: config.viemPollingIntervalMS
55
+ });
56
+ rollup = new RollupContract(publicClient, rollupOrAddress.toString());
57
+ }
58
+ const [l1StartBlock, l1GenesisTime, proofSubmissionEpochs, slotDuration, epochDuration, lagInEpochsForValidatorSet, lagInEpochsForRandao] = await Promise.all([
59
59
  rollup.getL1StartBlock(),
60
60
  rollup.getL1GenesisTime(),
61
- rollup.getCurrentEpochCommittee(),
62
- rollup.getCurrentSampleSeed(),
63
- rollup.getEpochNumber(),
64
- rollup.getProofSubmissionEpochs()
61
+ rollup.getProofSubmissionEpochs(),
62
+ rollup.getSlotDuration(),
63
+ rollup.getEpochDuration(),
64
+ rollup.getLagInEpochsForValidatorSet(),
65
+ rollup.getLagInEpochsForRandao()
65
66
  ]);
66
67
  const l1RollupConstants = {
67
68
  l1StartBlock,
68
69
  l1GenesisTime,
69
70
  proofSubmissionEpochs: Number(proofSubmissionEpochs),
70
- slotDuration: config.aztecSlotDuration,
71
- epochDuration: config.aztecEpochDuration,
72
- ethereumSlotDuration: config.ethereumSlotDuration
71
+ slotDuration: Number(slotDuration),
72
+ epochDuration: Number(epochDuration),
73
+ ethereumSlotDuration: config.ethereumSlotDuration,
74
+ lagInEpochsForValidatorSet: Number(lagInEpochsForValidatorSet),
75
+ lagInEpochsForRandao: Number(lagInEpochsForRandao)
73
76
  };
74
- return new EpochCache(rollup, epochNumber, initialValidators?.map((v)=>EthAddress.fromString(v)), sampleSeed, l1RollupConstants, deps.dateProvider);
77
+ return new EpochCache(rollup, l1RollupConstants, deps.dateProvider);
75
78
  }
76
79
  getL1Constants() {
77
80
  return this.l1constants;
@@ -148,10 +151,18 @@ import { getEpochCacheConfigEnvVars } from './config.js';
148
151
  }
149
152
  async computeCommittee(when) {
150
153
  const { ts, epoch } = when;
151
- const [committeeHex, seed] = await Promise.all([
154
+ const [committeeHex, seed, l1Timestamp] = await Promise.all([
152
155
  this.rollup.getCommitteeAt(ts),
153
- this.rollup.getSampleSeedAt(ts)
156
+ this.rollup.getSampleSeedAt(ts),
157
+ this.rollup.client.getBlock({
158
+ includeTransactions: false
159
+ }).then((b)=>b.timestamp)
154
160
  ]);
161
+ const { lagInEpochsForValidatorSet, epochDuration, slotDuration } = this.l1constants;
162
+ const sub = BigInt(lagInEpochsForValidatorSet) * BigInt(epochDuration) * BigInt(slotDuration);
163
+ if (ts - sub > l1Timestamp) {
164
+ throw new Error(`Cannot query committee for future epoch ${epoch} with timestamp ${ts} (current L1 time is ${l1Timestamp}). Check your Ethereum node is synced.`);
165
+ }
155
166
  const committee = committeeHex?.map((v)=>EthAddress.fromString(v));
156
167
  return {
157
168
  committee,
@@ -176,8 +187,8 @@ import { getEpochCacheConfigEnvVars } from './config.js';
176
187
  name: 'seed'
177
188
  }
178
189
  ], [
179
- epoch,
180
- slot,
190
+ BigInt(epoch),
191
+ BigInt(slot),
181
192
  seed
182
193
  ]);
183
194
  }
@@ -204,6 +215,14 @@ import { getEpochCacheConfigEnvVars } from './config.js';
204
215
  };
205
216
  }
206
217
  /**
218
+ * Get the proposer attester address in the given L2 slot
219
+ * @returns The proposer attester address. If the committee does not exist, we throw a NoCommitteeError.
220
+ * If the committee is empty (i.e. target committee size is 0, and anyone can propose), we return undefined.
221
+ */ getProposerAttesterAddressInSlot(slot) {
222
+ const epochAndSlot = this.getEpochAndSlotAtSlot(slot);
223
+ return this.getProposerAttesterAddressAt(epochAndSlot);
224
+ }
225
+ /**
207
226
  * Get the proposer attester address in the next slot
208
227
  * @returns The proposer attester address. If the committee does not exist, we throw a NoCommitteeError.
209
228
  * If the committee is empty (i.e. target committee size is 0, and anyone can propose), we return undefined.
package/dest/index.d.ts CHANGED
@@ -1,3 +1,3 @@
1
1
  export * from './epoch_cache.js';
2
2
  export * from './config.js';
3
- //# sourceMappingURL=index.d.ts.map
3
+ //# sourceMappingURL=data:application/json;base64,eyJ2ZXJzaW9uIjozLCJmaWxlIjoiaW5kZXguZC50cyIsInNvdXJjZVJvb3QiOiIiLCJzb3VyY2VzIjpbIi4uL3NyYy9pbmRleC50cyJdLCJuYW1lcyI6W10sIm1hcHBpbmdzIjoiQUFBQSxjQUFjLGtCQUFrQixDQUFDO0FBQ2pDLGNBQWMsYUFBYSxDQUFDIn0=
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@aztec/epoch-cache",
3
- "version": "3.0.0-canary.a9708bd",
3
+ "version": "3.0.0-devnet.2-patch.1",
4
4
  "type": "module",
5
5
  "exports": {
6
6
  ".": "./dest/index.js",
@@ -15,10 +15,10 @@
15
15
  "tsconfig": "./tsconfig.json"
16
16
  },
17
17
  "scripts": {
18
- "build": "yarn clean && tsc -b",
19
- "build:dev": "tsc -b --watch",
18
+ "build": "yarn clean && ../scripts/tsc.sh",
19
+ "build:dev": "../scripts/tsc.sh --watch",
20
20
  "clean": "rm -rf ./dest .tsbuildinfo",
21
- "start:dev": "tsc-watch -p tsconfig.json --onSuccess 'yarn start'",
21
+ "start:dev": "concurrently -k \"tsgo -b -w\" \"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,22 +26,23 @@
26
26
  "../package.common.json"
27
27
  ],
28
28
  "dependencies": {
29
- "@aztec/ethereum": "3.0.0-canary.a9708bd",
30
- "@aztec/foundation": "3.0.0-canary.a9708bd",
31
- "@aztec/l1-artifacts": "3.0.0-canary.a9708bd",
32
- "@aztec/stdlib": "3.0.0-canary.a9708bd",
29
+ "@aztec/ethereum": "3.0.0-devnet.2-patch.1",
30
+ "@aztec/foundation": "3.0.0-devnet.2-patch.1",
31
+ "@aztec/l1-artifacts": "3.0.0-devnet.2-patch.1",
32
+ "@aztec/stdlib": "3.0.0-devnet.2-patch.1",
33
33
  "@viem/anvil": "^0.0.10",
34
34
  "dotenv": "^16.0.3",
35
35
  "get-port": "^7.1.0",
36
36
  "jest-mock-extended": "^4.0.0",
37
37
  "tslib": "^2.4.0",
38
- "viem": "2.23.7",
38
+ "viem": "npm:@aztec/viem@2.38.2",
39
39
  "zod": "^3.23.8"
40
40
  },
41
41
  "devDependencies": {
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
46
  "jest": "^30.0.0",
46
47
  "ts-node": "^10.9.1",
47
48
  "typescript": "^5.3.3"
package/src/config.ts CHANGED
@@ -1,18 +1,9 @@
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,
10
- | 'l1RpcUrls'
11
- | 'l1ChainId'
12
- | 'viemPollingIntervalMS'
13
- | 'aztecSlotDuration'
14
- | 'ethereumSlotDuration'
15
- | 'aztecEpochDuration'
6
+ 'l1RpcUrls' | 'l1ChainId' | 'viemPollingIntervalMS' | 'ethereumSlotDuration'
16
7
  >;
17
8
 
18
9
  export function getEpochCacheConfigEnvVars(): EpochCacheConfig {
@@ -1,9 +1,10 @@
1
- import { NoCommitteeError, RollupContract, createEthereumChain } from '@aztec/ethereum';
1
+ import { createEthereumChain } from '@aztec/ethereum/chain';
2
+ import { NoCommitteeError, RollupContract } from '@aztec/ethereum/contracts';
3
+ import { EpochNumber, SlotNumber } from '@aztec/foundation/branded-types';
2
4
  import { EthAddress } from '@aztec/foundation/eth-address';
3
5
  import { type Logger, createLogger } from '@aztec/foundation/log';
4
6
  import { DateProvider } from '@aztec/foundation/timer';
5
7
  import {
6
- EmptyL1RollupConstants,
7
8
  type L1RollupConstants,
8
9
  getEpochAtSlot,
9
10
  getEpochNumberAtTimestamp,
@@ -18,30 +19,30 @@ import { createPublicClient, encodeAbiParameters, fallback, http, keccak256 } fr
18
19
  import { type EpochCacheConfig, getEpochCacheConfigEnvVars } from './config.js';
19
20
 
20
21
  export type EpochAndSlot = {
21
- epoch: bigint;
22
- slot: bigint;
22
+ epoch: EpochNumber;
23
+ slot: SlotNumber;
23
24
  ts: bigint;
24
25
  };
25
26
 
26
27
  export type EpochCommitteeInfo = {
27
28
  committee: EthAddress[] | undefined;
28
29
  seed: bigint;
29
- epoch: bigint;
30
+ epoch: EpochNumber;
30
31
  };
31
32
 
32
- export type SlotTag = 'now' | 'next' | bigint;
33
+ export type SlotTag = 'now' | 'next' | SlotNumber;
33
34
 
34
35
  export interface EpochCacheInterface {
35
36
  getCommittee(slot: SlotTag | undefined): Promise<EpochCommitteeInfo>;
36
37
  getEpochAndSlotNow(): EpochAndSlot;
37
38
  getEpochAndSlotInNextL1Slot(): EpochAndSlot & { now: bigint };
38
- getProposerIndexEncoding(epoch: bigint, slot: bigint, seed: bigint): `0x${string}`;
39
- computeProposerIndex(slot: bigint, epoch: bigint, seed: bigint, size: bigint): bigint;
39
+ getProposerIndexEncoding(epoch: EpochNumber, slot: SlotNumber, seed: bigint): `0x${string}`;
40
+ computeProposerIndex(slot: SlotNumber, epoch: EpochNumber, seed: bigint, size: bigint): bigint;
40
41
  getProposerAttesterAddressInCurrentOrNextSlot(): Promise<{
41
42
  currentProposer: EthAddress | undefined;
42
43
  nextProposer: EthAddress | undefined;
43
- currentSlot: bigint;
44
- nextSlot: bigint;
44
+ currentSlot: SlotNumber;
45
+ nextSlot: SlotNumber;
45
46
  }>;
46
47
  getRegisteredValidators(): Promise<EthAddress[]>;
47
48
  isInCommittee(slot: SlotTag, validator: EthAddress): Promise<boolean>;
@@ -58,71 +59,77 @@ export interface EpochCacheInterface {
58
59
  * Note: This class is very dependent on the system clock being in sync.
59
60
  */
60
61
  export class EpochCache implements EpochCacheInterface {
61
- private cache: Map<bigint, EpochCommitteeInfo> = new Map();
62
+ // eslint-disable-next-line aztec-custom/no-non-primitive-in-collections
63
+ protected cache: Map<EpochNumber, EpochCommitteeInfo> = new Map();
62
64
  private allValidators: Set<string> = new Set();
63
65
  private lastValidatorRefresh = 0;
64
66
  private readonly log: Logger = createLogger('epoch-cache');
65
67
 
66
68
  constructor(
67
69
  private rollup: RollupContract,
68
- initialEpoch: bigint = 0n,
69
- initialValidators: EthAddress[] | undefined = undefined,
70
- initialSampleSeed: bigint = 0n,
71
- private readonly l1constants: L1RollupConstants = EmptyL1RollupConstants,
70
+ private readonly l1constants: L1RollupConstants & {
71
+ lagInEpochsForValidatorSet: number;
72
+ lagInEpochsForRandao: number;
73
+ },
72
74
  private readonly dateProvider: DateProvider = new DateProvider(),
73
- private readonly config = { cacheSize: 12, validatorRefreshIntervalSeconds: 60 },
75
+ protected readonly config = { cacheSize: 12, validatorRefreshIntervalSeconds: 60 },
74
76
  ) {
75
- this.cache.set(initialEpoch, { epoch: initialEpoch, committee: initialValidators, seed: initialSampleSeed });
76
- this.log.debug(`Initialized EpochCache with ${initialValidators?.length ?? 'no'} validators`, {
77
+ this.log.debug(`Initialized EpochCache`, {
77
78
  l1constants,
78
- initialValidators,
79
- initialSampleSeed,
80
- initialEpoch,
81
79
  });
82
80
  }
83
81
 
84
82
  static async create(
85
- rollupAddress: EthAddress,
83
+ rollupOrAddress: EthAddress | RollupContract,
86
84
  config?: EpochCacheConfig,
87
85
  deps: { dateProvider?: DateProvider } = {},
88
86
  ) {
89
87
  config = config ?? getEpochCacheConfigEnvVars();
90
88
 
91
- const chain = createEthereumChain(config.l1RpcUrls, config.l1ChainId);
92
- const publicClient = createPublicClient({
93
- chain: chain.chainInfo,
94
- transport: fallback(config.l1RpcUrls.map(url => http(url))),
95
- pollingInterval: config.viemPollingIntervalMS,
96
- });
89
+ // Load the rollup contract if we were given an address
90
+ let rollup: RollupContract;
91
+ if ('address' in rollupOrAddress) {
92
+ rollup = rollupOrAddress;
93
+ } else {
94
+ const chain = createEthereumChain(config.l1RpcUrls, config.l1ChainId);
95
+ const publicClient = createPublicClient({
96
+ chain: chain.chainInfo,
97
+ transport: fallback(config.l1RpcUrls.map(url => http(url))),
98
+ pollingInterval: config.viemPollingIntervalMS,
99
+ });
100
+ rollup = new RollupContract(publicClient, rollupOrAddress.toString());
101
+ }
97
102
 
98
- const rollup = new RollupContract(publicClient, rollupAddress.toString());
99
- const [l1StartBlock, l1GenesisTime, initialValidators, sampleSeed, epochNumber, proofSubmissionEpochs] =
100
- await Promise.all([
101
- rollup.getL1StartBlock(),
102
- rollup.getL1GenesisTime(),
103
- rollup.getCurrentEpochCommittee(),
104
- rollup.getCurrentSampleSeed(),
105
- rollup.getEpochNumber(),
106
- rollup.getProofSubmissionEpochs(),
107
- ] as const);
108
-
109
- const l1RollupConstants: L1RollupConstants = {
103
+ const [
104
+ l1StartBlock,
105
+ l1GenesisTime,
106
+ proofSubmissionEpochs,
107
+ slotDuration,
108
+ epochDuration,
109
+ lagInEpochsForValidatorSet,
110
+ lagInEpochsForRandao,
111
+ ] = await Promise.all([
112
+ rollup.getL1StartBlock(),
113
+ rollup.getL1GenesisTime(),
114
+ rollup.getProofSubmissionEpochs(),
115
+ rollup.getSlotDuration(),
116
+ rollup.getEpochDuration(),
117
+ rollup.getLagInEpochsForValidatorSet(),
118
+ rollup.getLagInEpochsForRandao(),
119
+ ] as const);
120
+
121
+ const l1RollupConstants = {
110
122
  l1StartBlock,
111
123
  l1GenesisTime,
112
124
  proofSubmissionEpochs: Number(proofSubmissionEpochs),
113
- slotDuration: config.aztecSlotDuration,
114
- epochDuration: config.aztecEpochDuration,
125
+ slotDuration: Number(slotDuration),
126
+ epochDuration: Number(epochDuration),
115
127
  ethereumSlotDuration: config.ethereumSlotDuration,
128
+ lagInEpochsForValidatorSet: Number(lagInEpochsForValidatorSet),
129
+ lagInEpochsForRandao: Number(lagInEpochsForRandao),
116
130
  };
117
131
 
118
- return new EpochCache(
119
- rollup,
120
- epochNumber,
121
- initialValidators?.map(v => EthAddress.fromString(v)),
122
- sampleSeed,
123
- l1RollupConstants,
124
- deps.dateProvider,
125
- );
132
+ return new EpochCache(rollup, l1RollupConstants, deps.dateProvider);
126
133
  }
127
134
 
128
135
  public getL1Constants(): L1RollupConstants {
@@ -138,7 +145,7 @@ export class EpochCache implements EpochCacheInterface {
138
145
  return BigInt(Math.floor(this.dateProvider.now() / 1000));
139
146
  }
140
147
 
141
- private getEpochAndSlotAtSlot(slot: bigint): EpochAndSlot {
148
+ private getEpochAndSlotAtSlot(slot: SlotNumber): EpochAndSlot {
142
149
  const epoch = getEpochAtSlot(slot, this.l1constants);
143
150
  const ts = getTimestampRangeForEpoch(epoch, this.l1constants)[0];
144
151
  return { epoch, ts, slot };
@@ -159,7 +166,7 @@ export class EpochCache implements EpochCacheInterface {
159
166
  };
160
167
  }
161
168
 
162
- public getCommitteeForEpoch(epoch: bigint): Promise<EpochCommitteeInfo> {
169
+ public getCommitteeForEpoch(epoch: EpochNumber): Promise<EpochCommitteeInfo> {
163
170
  const [startSlot] = getSlotRangeForEpoch(epoch, this.l1constants);
164
171
  return this.getCommittee(startSlot);
165
172
  }
@@ -201,9 +208,20 @@ export class EpochCache implements EpochCacheInterface {
201
208
  }
202
209
  }
203
210
 
204
- private async computeCommittee(when: { epoch: bigint; ts: bigint }): Promise<EpochCommitteeInfo> {
211
+ private async computeCommittee(when: { epoch: EpochNumber; ts: bigint }): Promise<EpochCommitteeInfo> {
205
212
  const { ts, epoch } = when;
206
- const [committeeHex, seed] = await Promise.all([this.rollup.getCommitteeAt(ts), this.rollup.getSampleSeedAt(ts)]);
213
+ const [committeeHex, seed, l1Timestamp] = await Promise.all([
214
+ this.rollup.getCommitteeAt(ts),
215
+ this.rollup.getSampleSeedAt(ts),
216
+ this.rollup.client.getBlock({ includeTransactions: false }).then(b => b.timestamp),
217
+ ]);
218
+ const { lagInEpochsForValidatorSet, epochDuration, slotDuration } = this.l1constants;
219
+ const sub = BigInt(lagInEpochsForValidatorSet) * BigInt(epochDuration) * BigInt(slotDuration);
220
+ if (ts - sub > l1Timestamp) {
221
+ throw new Error(
222
+ `Cannot query committee for future epoch ${epoch} with timestamp ${ts} (current L1 time is ${l1Timestamp}). Check your Ethereum node is synced.`,
223
+ );
224
+ }
207
225
  const committee = committeeHex?.map((v: `0x${string}`) => EthAddress.fromString(v));
208
226
  return { committee, seed, epoch };
209
227
  }
@@ -211,18 +229,18 @@ export class EpochCache implements EpochCacheInterface {
211
229
  /**
212
230
  * Get the ABI encoding of the proposer index - see ValidatorSelectionLib.sol computeProposerIndex
213
231
  */
214
- getProposerIndexEncoding(epoch: bigint, slot: bigint, seed: bigint): `0x${string}` {
232
+ getProposerIndexEncoding(epoch: EpochNumber, slot: SlotNumber, seed: bigint): `0x${string}` {
215
233
  return encodeAbiParameters(
216
234
  [
217
235
  { type: 'uint256', name: 'epoch' },
218
236
  { type: 'uint256', name: 'slot' },
219
237
  { type: 'uint256', name: 'seed' },
220
238
  ],
221
- [epoch, slot, seed],
239
+ [BigInt(epoch), BigInt(slot), seed],
222
240
  );
223
241
  }
224
242
 
225
- public computeProposerIndex(slot: bigint, epoch: bigint, seed: bigint, size: bigint): bigint {
243
+ public computeProposerIndex(slot: SlotNumber, epoch: EpochNumber, seed: bigint, size: bigint): bigint {
226
244
  // if committe size is 0, then mod 1 is 0
227
245
  if (size === 0n) {
228
246
  return 0n;
@@ -236,9 +254,9 @@ export class EpochCache implements EpochCacheInterface {
236
254
  * We return the next proposer's attester address as the node will check if it is the proposer at the next ethereum block,
237
255
  * which can be the next slot. If this is the case, then it will send proposals early.
238
256
  */
239
- async getProposerAttesterAddressInCurrentOrNextSlot(): Promise<{
240
- currentSlot: bigint;
241
- nextSlot: bigint;
257
+ public async getProposerAttesterAddressInCurrentOrNextSlot(): Promise<{
258
+ currentSlot: SlotNumber;
259
+ nextSlot: SlotNumber;
242
260
  currentProposer: EthAddress | undefined;
243
261
  nextProposer: EthAddress | undefined;
244
262
  }> {
@@ -253,14 +271,23 @@ export class EpochCache implements EpochCacheInterface {
253
271
  };
254
272
  }
255
273
 
274
+ /**
275
+ * Get the proposer attester address in the given L2 slot
276
+ * @returns The proposer attester address. If the committee does not exist, we throw a NoCommitteeError.
277
+ * If the committee is empty (i.e. target committee size is 0, and anyone can propose), we return undefined.
278
+ */
279
+ public getProposerAttesterAddressInSlot(slot: SlotNumber): Promise<EthAddress | undefined> {
280
+ const epochAndSlot = this.getEpochAndSlotAtSlot(slot);
281
+ return this.getProposerAttesterAddressAt(epochAndSlot);
282
+ }
283
+
256
284
  /**
257
285
  * Get the proposer attester address in the next slot
258
286
  * @returns The proposer attester address. If the committee does not exist, we throw a NoCommitteeError.
259
287
  * If the committee is empty (i.e. target committee size is 0, and anyone can propose), we return undefined.
260
288
  */
261
- getProposerAttesterAddressInNextSlot(): Promise<EthAddress | undefined> {
289
+ public getProposerAttesterAddressInNextSlot(): Promise<EthAddress | undefined> {
262
290
  const epochAndSlot = this.getEpochAndSlotInNextL1Slot();
263
-
264
291
  return this.getProposerAttesterAddressAt(epochAndSlot);
265
292
  }
266
293
 
@@ -283,7 +310,10 @@ export class EpochCache implements EpochCacheInterface {
283
310
  return committee[Number(proposerIndex)];
284
311
  }
285
312
 
286
- public getProposerFromEpochCommittee(epochCommitteeInfo: EpochCommitteeInfo, slot: bigint): EthAddress | undefined {
313
+ public getProposerFromEpochCommittee(
314
+ epochCommitteeInfo: EpochCommitteeInfo,
315
+ slot: SlotNumber,
316
+ ): EthAddress | undefined {
287
317
  if (!epochCommitteeInfo.committee || epochCommitteeInfo.committee.length === 0) {
288
318
  return undefined;
289
319
  }