@aztec/epoch-cache 0.0.1-commit.1142ef1 → 0.0.1-commit.125b3452

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,5 +1,5 @@
1
1
  import { type L1ContractsConfig } from '@aztec/ethereum/config';
2
2
  import { type L1ReaderConfig } from '@aztec/ethereum/l1-reader';
3
- export type EpochCacheConfig = Pick<L1ReaderConfig & L1ContractsConfig, 'l1RpcUrls' | 'l1ChainId' | 'viemPollingIntervalMS' | 'ethereumSlotDuration'>;
3
+ export type EpochCacheConfig = Pick<L1ReaderConfig & L1ContractsConfig, 'l1RpcUrls' | 'l1ChainId' | 'viemPollingIntervalMS' | 'l1HttpTimeoutMS' | 'ethereumSlotDuration'>;
4
4
  export declare function getEpochCacheConfigEnvVars(): EpochCacheConfig;
5
- //# sourceMappingURL=data:application/json;base64,eyJ2ZXJzaW9uIjozLCJmaWxlIjoiY29uZmlnLmQudHMiLCJzb3VyY2VSb290IjoiIiwic291cmNlcyI6WyIuLi9zcmMvY29uZmlnLnRzIl0sIm5hbWVzIjpbXSwibWFwcGluZ3MiOiJBQUFBLE9BQU8sRUFBRSxLQUFLLGlCQUFpQixFQUErQixNQUFNLHdCQUF3QixDQUFDO0FBQzdGLE9BQU8sRUFBRSxLQUFLLGNBQWMsRUFBNEIsTUFBTSwyQkFBMkIsQ0FBQztBQUUxRixNQUFNLE1BQU0sZ0JBQWdCLEdBQUcsSUFBSSxDQUNqQyxjQUFjLEdBQUcsaUJBQWlCLEVBQ2xDLFdBQVcsR0FBRyxXQUFXLEdBQUcsdUJBQXVCLEdBQUcsc0JBQXNCLENBQzdFLENBQUM7QUFFRix3QkFBZ0IsMEJBQTBCLElBQUksZ0JBQWdCLENBRTdEIn0=
5
+ //# sourceMappingURL=data:application/json;base64,eyJ2ZXJzaW9uIjozLCJmaWxlIjoiY29uZmlnLmQudHMiLCJzb3VyY2VSb290IjoiIiwic291cmNlcyI6WyIuLi9zcmMvY29uZmlnLnRzIl0sIm5hbWVzIjpbXSwibWFwcGluZ3MiOiJBQUFBLE9BQU8sRUFBRSxLQUFLLGlCQUFpQixFQUErQixNQUFNLHdCQUF3QixDQUFDO0FBQzdGLE9BQU8sRUFBRSxLQUFLLGNBQWMsRUFBNEIsTUFBTSwyQkFBMkIsQ0FBQztBQUUxRixNQUFNLE1BQU0sZ0JBQWdCLEdBQUcsSUFBSSxDQUNqQyxjQUFjLEdBQUcsaUJBQWlCLEVBQ2xDLFdBQVcsR0FBRyxXQUFXLEdBQUcsdUJBQXVCLEdBQUcsaUJBQWlCLEdBQUcsc0JBQXNCLENBQ2pHLENBQUM7QUFFRix3QkFBZ0IsMEJBQTBCLElBQUksZ0JBQWdCLENBRTdEIn0=
@@ -1 +1 @@
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"}
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,iBAAiB,GAAG,sBAAsB,CACjG,CAAC;AAEF,wBAAgB,0BAA0B,IAAI,gBAAgB,CAE7D"}
@@ -13,26 +13,29 @@ 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
+ };
32
34
  getProposerAttesterAddressInSlot(slot: SlotNumber): Promise<EthAddress | undefined>;
33
35
  getRegisteredValidators(): Promise<EthAddress[]>;
34
36
  isInCommittee(slot: SlotTag, validator: EthAddress): Promise<boolean>;
35
37
  filterInCommittee(slot: SlotTag, validators: EthAddress[]): Promise<EthAddress[]>;
38
+ getL1Constants(): L1RollupConstants;
36
39
  }
37
40
  /**
38
41
  * Epoch cache
@@ -67,7 +70,7 @@ export declare class EpochCache implements EpochCacheInterface {
67
70
  }): Promise<EpochCache>;
68
71
  getL1Constants(): L1RollupConstants;
69
72
  getEpochAndSlotNow(): EpochAndSlot & {
70
- now: bigint;
73
+ nowMs: bigint;
71
74
  };
72
75
  nowInSeconds(): bigint;
73
76
  private getEpochAndSlotAtSlot;
@@ -76,6 +79,20 @@ export declare class EpochCache implements EpochCacheInterface {
76
79
  };
77
80
  private getEpochAndSlotAtTimestamp;
78
81
  getCommitteeForEpoch(epoch: EpochNumber): Promise<EpochCommitteeInfo>;
82
+ /**
83
+ * Returns whether the escape hatch is open for the given epoch.
84
+ *
85
+ * Uses the already-cached EpochCommitteeInfo when available. If not cached, it will fetch
86
+ * the epoch committee info (which includes the escape hatch flag) and return it.
87
+ */
88
+ isEscapeHatchOpen(epoch: EpochNumber): Promise<boolean>;
89
+ /**
90
+ * Returns whether the escape hatch is open for the epoch containing the given slot.
91
+ *
92
+ * This is a lightweight helper intended for callers that already have a slot number and only
93
+ * need the escape hatch flag (without pulling full committee info).
94
+ */
95
+ isEscapeHatchOpenAtSlot(slot?: SlotTag): Promise<boolean>;
79
96
  /**
80
97
  * Get the current validator set
81
98
  * @param nextSlot - If true, get the validator set for the next slot.
@@ -89,18 +106,11 @@ export declare class EpochCache implements EpochCacheInterface {
89
106
  */
90
107
  getProposerIndexEncoding(epoch: EpochNumber, slot: SlotNumber, seed: bigint): `0x${string}`;
91
108
  computeProposerIndex(slot: SlotNumber, epoch: EpochNumber, seed: bigint, size: bigint): bigint;
92
- /**
93
- * Returns the current and next proposer's attester address
94
- *
95
- * We return the next proposer's attester address as the node will check if it is the proposer at the next ethereum block,
96
- * which can be the next slot. If this is the case, then it will send proposals early.
97
- */
98
- getProposerAttesterAddressInCurrentOrNextSlot(): Promise<{
109
+ /** Returns the current and next L2 slot numbers. */
110
+ getCurrentAndNextSlot(): {
99
111
  currentSlot: SlotNumber;
100
112
  nextSlot: SlotNumber;
101
- currentProposer: EthAddress | undefined;
102
- nextProposer: EthAddress | undefined;
103
- }>;
113
+ };
104
114
  /**
105
115
  * Get the proposer attester address in the given L2 slot
106
116
  * @returns The proposer attester address. If the committee does not exist, we throw a NoCommitteeError.
@@ -121,4 +131,4 @@ export declare class EpochCache implements EpochCacheInterface {
121
131
  filterInCommittee(slot: SlotTag, validators: EthAddress[]): Promise<EthAddress[]>;
122
132
  getRegisteredValidators(): Promise<EthAddress[]>;
123
133
  }
124
- //# sourceMappingURL=data:application/json;base64,eyJ2ZXJzaW9uIjozLCJmaWxlIjoiZXBvY2hfY2FjaGUuZC50cyIsInNvdXJjZVJvb3QiOiIiLCJzb3VyY2VzIjpbIi4uL3NyYy9lcG9jaF9jYWNoZS50cyJdLCJuYW1lcyI6W10sIm1hcHBpbmdzIjoiQUFDQSxPQUFPLEVBQW9CLGNBQWMsRUFBRSxNQUFNLDJCQUEyQixDQUFDO0FBQzdFLE9BQU8sRUFBRSxXQUFXLEVBQUUsVUFBVSxFQUFFLE1BQU0saUNBQWlDLENBQUM7QUFDMUUsT0FBTyxFQUFFLFVBQVUsRUFBRSxNQUFNLCtCQUErQixDQUFDO0FBRTNELE9BQU8sRUFBRSxZQUFZLEVBQUUsTUFBTSx5QkFBeUIsQ0FBQztBQUN2RCxPQUFPLEVBQ0wsS0FBSyxpQkFBaUIsRUFPdkIsTUFBTSw2QkFBNkIsQ0FBQztBQUlyQyxPQUFPLEVBQUUsS0FBSyxnQkFBZ0IsRUFBOEIsTUFBTSxhQUFhLENBQUM7QUFFaEYsTUFBTSxNQUFNLFlBQVksR0FBRztJQUN6QixLQUFLLEVBQUUsV0FBVyxDQUFDO0lBQ25CLElBQUksRUFBRSxVQUFVLENBQUM7SUFDakIsRUFBRSxFQUFFLE1BQU0sQ0FBQztDQUNaLENBQUM7QUFFRixNQUFNLE1BQU0sa0JBQWtCLEdBQUc7SUFDL0IsU0FBUyxFQUFFLFVBQVUsRUFBRSxHQUFHLFNBQVMsQ0FBQztJQUNwQyxJQUFJLEVBQUUsTUFBTSxDQUFDO0lBQ2IsS0FBSyxFQUFFLFdBQVcsQ0FBQztDQUNwQixDQUFDO0FBRUYsTUFBTSxNQUFNLE9BQU8sR0FBRyxLQUFLLEdBQUcsTUFBTSxHQUFHLFVBQVUsQ0FBQztBQUVsRCxNQUFNLFdBQVcsbUJBQW1CO0lBQ2xDLFlBQVksQ0FBQyxJQUFJLEVBQUUsT0FBTyxHQUFHLFNBQVMsR0FBRyxPQUFPLENBQUMsa0JBQWtCLENBQUMsQ0FBQztJQUNyRSxrQkFBa0IsSUFBSSxZQUFZLENBQUM7SUFDbkMsMkJBQTJCLElBQUksWUFBWSxHQUFHO1FBQUUsR0FBRyxFQUFFLE1BQU0sQ0FBQTtLQUFFLENBQUM7SUFDOUQsd0JBQXdCLENBQUMs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
134
+ //# sourceMappingURL=data:application/json;base64,eyJ2ZXJzaW9uIjozLCJmaWxlIjoiZXBvY2hfY2FjaGUuZC50cyIsInNvdXJjZVJvb3QiOiIiLCJzb3VyY2VzIjpbIi4uL3NyYy9lcG9jaF9jYWNoZS50cyJdLCJuYW1lcyI6W10sIm1hcHBpbmdzIjoiQUFFQSxPQUFPLEVBQW9CLGNBQWMsRUFBRSxNQUFNLDJCQUEyQixDQUFDO0FBQzdFLE9BQU8sRUFBRSxXQUFXLEVBQUUsVUFBVSxFQUFFLE1BQU0saUNBQWlDLENBQUM7QUFDMUUsT0FBTyxFQUFFLFVBQVUsRUFBRSxNQUFNLCtCQUErQixDQUFDO0FBRTNELE9BQU8sRUFBRSxZQUFZLEVBQUUsTUFBTSx5QkFBeUIsQ0FBQztBQUN2RCxPQUFPLEVBQ0wsS0FBSyxpQkFBaUIsRUFPdkIsTUFBTSw2QkFBNkIsQ0FBQztBQUlyQyxPQUFPLEVBQUUsS0FBSyxnQkFBZ0IsRUFBOEIsTUFBTSxhQUFhLENBQUM7QUFFaEYsTUFBTSxNQUFNLFlBQVksR0FBRztJQUN6QixLQUFLLEVBQUUsV0FBVyxDQUFDO0lBQ25CLElBQUksRUFBRSxVQUFVLENBQUM7SUFDakIsRUFBRSxFQUFFLE1BQU0sQ0FBQztDQUNaLENBQUM7QUFFRixNQUFNLE1BQU0sa0JBQWtCLEdBQUc7SUFDL0IsU0FBUyxFQUFFLFVBQVUsRUFBRSxHQUFHLFNBQVMsQ0FBQztJQUNwQyxJQUFJLEVBQUUsTUFBTSxDQUFDO0lBQ2IsS0FBSyxFQUFFLFdBQVcsQ0FBQztJQUNuQiwrREFBK0Q7SUFDL0QsaUJBQWlCLEVBQUUsT0FBTyxDQUFDO0NBQzVCLENBQUM7QUFFRixNQUFNLE1BQU0sT0FBTyxHQUFHLEtBQUssR0FBRyxNQUFNLEdBQUcsVUFBVSxDQUFDO0FBRWxELE1BQU0sV0FBVyxtQkFBbUI7SUFDbEMsWUFBWSxDQUFDLElBQUksRUFBRSxPQUFPLEdBQUcsU0FBUyxHQUFHLE9BQU8sQ0FBQyxrQkFBa0IsQ0FBQyxDQUFDO0lBQ3JFLGtCQUFrQixJQUFJLFlBQVksR0FBRztRQUFFLEtBQUssRUFBRSxNQUFNLENBQUE7S0FBRSxDQUFDO0lBQ3ZELDJCQUEyQixJQUFJLFlBQVksR0FBRztRQUFFLEdBQUcsRUFBRSxNQUFNLENBQUE7S0FBRSxDQUFDO0lBQzlELHdCQUF3QixDQUFDLEtBQUssRUFBRSxXQUFXLEVBQUUsSUFBSSxFQUFFLFVBQVUsRUFBRSxJQUFJLEVBQUUsTUFBTSxHQUFHLEtBQUssTUFBTSxFQUFFLENBQUM7SUFDNUYsb0JBQW9CLENBQUMsSUFBSSxFQUFFLFVBQVUsRUFBRSxLQUFLLEVBQUUsV0FBVyxFQUFFLElBQUksRUFBRSxNQUFNLEVBQUUsSUFBSSxFQUFFLE1BQU0sR0FBRyxNQUFNLENBQUM7SUFDL0YscUJBQXFCLElBQUk7UUFBRSxXQUFXLEVBQUUsVUFBVSxDQUFDO1FBQUMsUUFBUSxFQUFFLFVBQVUsQ0FBQTtLQUFFLENBQUM7SUFDM0UsZ0NBQWdDLENBQUMsSUFBSSxFQUFFLFVBQVUsR0FBRyxPQUFPLENBQUMsVUFBVSxHQUFHLFNBQVMsQ0FBQyxDQUFDO0lBQ3BGLHVCQUF1QixJQUFJLE9BQU8sQ0FBQyxVQUFVLEVBQUUsQ0FBQyxDQUFDO0lBQ2pELGFBQWEsQ0FBQyxJQUFJLEVBQUUsT0FBTyxFQUFFLFNBQVMsRUFBRSxVQUFVLEdBQUcsT0FBTyxDQUFDLE9BQU8sQ0FBQyxDQUFDO0lBQ3RFLGlCQUFpQixDQUFDLElBQUksRUFBRSxPQUFPLEVBQUUsVUFBVSxFQUFFLFVBQVUsRUFBRSxHQUFHLE9BQU8sQ0FBQyxVQUFVLEVBQUUsQ0FBQyxDQUFDO0lBQ2xGLGNBQWMsSUFBSSxpQkFBaUIsQ0FBQztDQUNyQztBQUVEOzs7Ozs7OztHQVFHO0FBQ0gscUJBQWEsVUFBVyxZQUFXLG1CQUFtQjtJQVFsRCxPQUFPLENBQUMsTUFBTTtJQUNkLE9BQU8sQ0FBQyxRQUFRLENBQUMsV0FBVztJQUk1QixPQUFPLENBQUMsUUFBUSxDQUFDLFlBQVk7SUFDN0IsU0FBUyxDQUFDLFFBQVEsQ0FBQyxNQUFNOzs7O0lBWjNCLFNBQVMsQ0FBQyxLQUFLLEVBQUUsR0FBRyxDQUFDLFdBQVcsRUFBRSxrQkFBa0IsQ0FBQyxDQUFhO0lBQ2xFLE9BQU8sQ0FBQyxhQUFhLENBQTBCO0lBQy9DLE9BQU8sQ0FBQyxvQkFBb0IsQ0FBSztJQUNqQyxPQUFPLENBQUMsUUFBUSxDQUFDLEdBQUcsQ0FBdUM7SUFFM0QsWUFDVSxNQUFNLEVBQUUsY0FBYyxFQUNiLFdBQVcsRUFBRSxpQkFBaUIsR0FBRztRQUNoRCwwQkFBMEIsRUFBRSxNQUFNLENBQUM7UUFDbkMsb0JBQW9CLEVBQUUsTUFBTSxDQUFDO0tBQzlCLEVBQ2dCLFlBQVksR0FBRSxZQUFpQyxFQUM3QyxNQUFNOzs7S0FBeUQsRUFLbkY7SUFFRCxPQUFhLE1BQU0sQ0FDakIsZUFBZSxFQUFFLFVBQVUsR0FBRyxjQUFjLEVBQzVDLE1BQU0sQ0FBQyxFQUFFLGdCQUFnQixFQUN6QixJQUFJLEdBQUU7UUFBRSxZQUFZLENBQUMsRUFBRSxZQUFZLENBQUE7S0FBTyx1QkFzRDNDO0lBRU0sY0FBYyxJQUFJLGlCQUFpQixDQUV6QztJQUVNLGtCQUFrQixJQUFJLFlBQVksR0FBRztRQUFFLEtBQUssRUFBRSxNQUFNLENBQUE7S0FBRSxDQUk1RDtJQUVNLFlBQVksSUFBSSxNQUFNLENBRTVCO0lBRUQsT0FBTyxDQUFDLHFCQUFxQjtJQU10QiwyQkFBMkIsSUFBSSxZQUFZLEdBQUc7UUFBRSxHQUFHLEVBQUUsTUFBTSxDQUFBO0tBQUUsQ0FJbkU7SUFFRCxPQUFPLENBQUMsMEJBQTBCO0lBUzNCLG9CQUFvQixDQUFDLEtBQUssRUFBRSxXQUFXLEdBQUcsT0FBTyxDQUFDLGtCQUFrQixDQUFDLENBRzNFO0lBRUQ7Ozs7O09BS0c7SUFDVSxpQkFBaUIsQ0FBQyxLQUFLLEVBQUUsV0FBVyxHQUFHLE9BQU8sQ0FBQyxPQUFPLENBQUMsQ0FPbkU7SUFFRDs7Ozs7T0FLRztJQUNVLHVCQUF1QixDQUFDLElBQUksR0FBRSxPQUFlLEdBQUcsT0FBTyxDQUFDLE9BQU8sQ0FBQyxDQVM1RTtJQUVEOzs7O09BSUc7SUFDVSxZQUFZLENBQUMsSUFBSSxHQUFFLE9BQWUsR0FBRyxPQUFPLENBQUMsa0JBQWtCLENBQUMsQ0FvQjVFO0lBRUQsT0FBTyxDQUFDLG9CQUFvQjtZQVVkLGdCQUFnQjtJQWtCOUI7O09BRUc7SUFDSCx3QkFBd0IsQ0FBQyxLQUFLLEVBQUUsV0FBVyxFQUFFLElBQUksRUFBRSxVQUFVLEVBQUUsSUFBSSxFQUFFLE1BQU0sR0FBRyxLQUFLLE1BQU0sRUFBRSxDQVMxRjtJQUVNLG9CQUFvQixDQUFDLElBQUksRUFBRSxVQUFVLEVBQUUsS0FBSyxFQUFFLFdBQVcsRUFBRSxJQUFJLEVBQUUsTUFBTSxFQUFFLElBQUksRUFBRSxNQUFNLEdBQUcsTUFBTSxDQU1wRztJQUVELG9EQUFvRDtJQUM3QyxxQkFBcUIsSUFBSTtRQUFFLFdBQVcsRUFBRSxVQUFVLENBQUM7UUFBQyxRQUFRLEVBQUUsVUFBVSxDQUFBO0tBQUUsQ0FRaEY7SUFFRDs7OztPQUlHO0lBQ0ksZ0NBQWdDLENBQUMsSUFBSSxFQUFFLFVBQVUsR0FBRyxPQUFPLENBQUMsVUFBVSxHQUFHLFNBQVMsQ0FBQyxDQUd6RjtJQUVEOzs7O09BSUc7SUFDSSxvQ0FBb0MsSUFBSSxPQUFPLENBQUMsVUFBVSxHQUFHLFNBQVMsQ0FBQyxDQUc3RTtZQVFhLDRCQUE0QjtJQWFuQyw2QkFBNkIsQ0FDbEMsa0JBQWtCLEVBQUUsa0JBQWtCLEVBQ3RDLElBQUksRUFBRSxVQUFVLEdBQ2YsVUFBVSxHQUFHLFNBQVMsQ0FZeEI7SUFFRCw0REFBNEQ7SUFDdEQsYUFBYSxDQUFDLElBQUksRUFBRSxPQUFPLEVBQUUsU0FBUyxFQUFFLFVBQVUsR0FBRyxPQUFPLENBQUMsT0FBTyxDQUFDLENBTTFFO0lBRUQsK0ZBQStGO0lBQ3pGLGlCQUFpQixDQUFDLElBQUksRUFBRSxPQUFPLEVBQUUsVUFBVSxFQUFFLFVBQVUsRUFBRSxHQUFHLE9BQU8sQ0FBQyxVQUFVLEVBQUUsQ0FBQyxDQU90RjtJQUVLLHVCQUF1QixJQUFJLE9BQU8sQ0FBQyxVQUFVLEVBQUUsQ0FBQyxDQVNyRDtDQUNGIn0=
@@ -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":"AAEA,OAAO,EAAoB,cAAc,EAAE,MAAM,2BAA2B,CAAC;AAC7E,OAAO,EAAE,WAAW,EAAE,UAAU,EAAE,MAAM,iCAAiC,CAAC;AAC1E,OAAO,EAAE,UAAU,EAAE,MAAM,+BAA+B,CAAC;AAE3D,OAAO,EAAE,YAAY,EAAE,MAAM,yBAAyB,CAAC;AACvD,OAAO,EACL,KAAK,iBAAiB,EAOvB,MAAM,6BAA6B,CAAC;AAIrC,OAAO,EAAE,KAAK,gBAAgB,EAA8B,MAAM,aAAa,CAAC;AAEhF,MAAM,MAAM,YAAY,GAAG;IACzB,KAAK,EAAE,WAAW,CAAC;IACnB,IAAI,EAAE,UAAU,CAAC;IACjB,EAAE,EAAE,MAAM,CAAC;CACZ,CAAC;AAEF,MAAM,MAAM,kBAAkB,GAAG;IAC/B,SAAS,EAAE,UAAU,EAAE,GAAG,SAAS,CAAC;IACpC,IAAI,EAAE,MAAM,CAAC;IACb,KAAK,EAAE,WAAW,CAAC;IACnB,+DAA+D;IAC/D,iBAAiB,EAAE,OAAO,CAAC;CAC5B,CAAC;AAEF,MAAM,MAAM,OAAO,GAAG,KAAK,GAAG,MAAM,GAAG,UAAU,CAAC;AAElD,MAAM,WAAW,mBAAmB;IAClC,YAAY,CAAC,IAAI,EAAE,OAAO,GAAG,SAAS,GAAG,OAAO,CAAC,kBAAkB,CAAC,CAAC;IACrE,kBAAkB,IAAI,YAAY,GAAG;QAAE,KAAK,EAAE,MAAM,CAAA;KAAE,CAAC;IACvD,2BAA2B,IAAI,YAAY,GAAG;QAAE,GAAG,EAAE,MAAM,CAAA;KAAE,CAAC;IAC9D,wBAAwB,CAAC,KAAK,EAAE,WAAW,EAAE,IAAI,EAAE,UAAU,EAAE,IAAI,EAAE,MAAM,GAAG,KAAK,MAAM,EAAE,CAAC;IAC5F,oBAAoB,CAAC,IAAI,EAAE,UAAU,EAAE,KAAK,EAAE,WAAW,EAAE,IAAI,EAAE,MAAM,EAAE,IAAI,EAAE,MAAM,GAAG,MAAM,CAAC;IAC/F,qBAAqB,IAAI;QAAE,WAAW,EAAE,UAAU,CAAC;QAAC,QAAQ,EAAE,UAAU,CAAA;KAAE,CAAC;IAC3E,gCAAgC,CAAC,IAAI,EAAE,UAAU,GAAG,OAAO,CAAC,UAAU,GAAG,SAAS,CAAC,CAAC;IACpF,uBAAuB,IAAI,OAAO,CAAC,UAAU,EAAE,CAAC,CAAC;IACjD,aAAa,CAAC,IAAI,EAAE,OAAO,EAAE,SAAS,EAAE,UAAU,GAAG,OAAO,CAAC,OAAO,CAAC,CAAC;IACtE,iBAAiB,CAAC,IAAI,EAAE,OAAO,EAAE,UAAU,EAAE,UAAU,EAAE,GAAG,OAAO,CAAC,UAAU,EAAE,CAAC,CAAC;IAClF,cAAc,IAAI,iBAAiB,CAAC;CACrC;AAED;;;;;;;;GAQG;AACH,qBAAa,UAAW,YAAW,mBAAmB;IAQlD,OAAO,CAAC,MAAM;IACd,OAAO,CAAC,QAAQ,CAAC,WAAW;IAI5B,OAAO,CAAC,QAAQ,CAAC,YAAY;IAC7B,SAAS,CAAC,QAAQ,CAAC,MAAM;;;;IAZ3B,SAAS,CAAC,KAAK,EAAE,GAAG,CAAC,WAAW,EAAE,kBAAkB,CAAC,CAAa;IAClE,OAAO,CAAC,aAAa,CAA0B;IAC/C,OAAO,CAAC,oBAAoB,CAAK;IACjC,OAAO,CAAC,QAAQ,CAAC,GAAG,CAAuC;IAE3D,YACU,MAAM,EAAE,cAAc,EACb,WAAW,EAAE,iBAAiB,GAAG;QAChD,0BAA0B,EAAE,MAAM,CAAC;QACnC,oBAAoB,EAAE,MAAM,CAAC;KAC9B,EACgB,YAAY,GAAE,YAAiC,EAC7C,MAAM;;;KAAyD,EAKnF;IAED,OAAa,MAAM,CACjB,eAAe,EAAE,UAAU,GAAG,cAAc,EAC5C,MAAM,CAAC,EAAE,gBAAgB,EACzB,IAAI,GAAE;QAAE,YAAY,CAAC,EAAE,YAAY,CAAA;KAAO,uBAsD3C;IAEM,cAAc,IAAI,iBAAiB,CAEzC;IAEM,kBAAkB,IAAI,YAAY,GAAG;QAAE,KAAK,EAAE,MAAM,CAAA;KAAE,CAI5D;IAEM,YAAY,IAAI,MAAM,CAE5B;IAED,OAAO,CAAC,qBAAqB;IAMtB,2BAA2B,IAAI,YAAY,GAAG;QAAE,GAAG,EAAE,MAAM,CAAA;KAAE,CAInE;IAED,OAAO,CAAC,0BAA0B;IAS3B,oBAAoB,CAAC,KAAK,EAAE,WAAW,GAAG,OAAO,CAAC,kBAAkB,CAAC,CAG3E;IAED;;;;;OAKG;IACU,iBAAiB,CAAC,KAAK,EAAE,WAAW,GAAG,OAAO,CAAC,OAAO,CAAC,CAOnE;IAED;;;;;OAKG;IACU,uBAAuB,CAAC,IAAI,GAAE,OAAe,GAAG,OAAO,CAAC,OAAO,CAAC,CAS5E;IAED;;;;OAIG;IACU,YAAY,CAAC,IAAI,GAAE,OAAe,GAAG,OAAO,CAAC,kBAAkB,CAAC,CAoB5E;IAED,OAAO,CAAC,oBAAoB;YAUd,gBAAgB;IAkB9B;;OAEG;IACH,wBAAwB,CAAC,KAAK,EAAE,WAAW,EAAE,IAAI,EAAE,UAAU,EAAE,IAAI,EAAE,MAAM,GAAG,KAAK,MAAM,EAAE,CAS1F;IAEM,oBAAoB,CAAC,IAAI,EAAE,UAAU,EAAE,KAAK,EAAE,WAAW,EAAE,IAAI,EAAE,MAAM,EAAE,IAAI,EAAE,MAAM,GAAG,MAAM,CAMpG;IAED,oDAAoD;IAC7C,qBAAqB,IAAI;QAAE,WAAW,EAAE,UAAU,CAAC;QAAC,QAAQ,EAAE,UAAU,CAAA;KAAE,CAQhF;IAED;;;;OAIG;IACI,gCAAgC,CAAC,IAAI,EAAE,UAAU,GAAG,OAAO,CAAC,UAAU,GAAG,SAAS,CAAC,CAGzF;IAED;;;;OAIG;IACI,oCAAoC,IAAI,OAAO,CAAC,UAAU,GAAG,SAAS,CAAC,CAG7E;YAQa,4BAA4B;IAanC,6BAA6B,CAClC,kBAAkB,EAAE,kBAAkB,EACtC,IAAI,EAAE,UAAU,GACf,UAAU,GAAG,SAAS,CAYxB;IAED,4DAA4D;IACtD,aAAa,CAAC,IAAI,EAAE,OAAO,EAAE,SAAS,EAAE,UAAU,GAAG,OAAO,CAAC,OAAO,CAAC,CAM1E;IAED,+FAA+F;IACzF,iBAAiB,CAAC,IAAI,EAAE,OAAO,EAAE,UAAU,EAAE,UAAU,EAAE,GAAG,OAAO,CAAC,UAAU,EAAE,CAAC,CAOtF;IAEK,uBAAuB,IAAI,OAAO,CAAC,UAAU,EAAE,CAAC,CASrD;CACF"}
@@ -1,10 +1,11 @@
1
1
  import { createEthereumChain } from '@aztec/ethereum/chain';
2
+ import { makeL1HttpTransport } from '@aztec/ethereum/client';
2
3
  import { NoCommitteeError, RollupContract } from '@aztec/ethereum/contracts';
3
4
  import { EthAddress } from '@aztec/foundation/eth-address';
4
5
  import { createLogger } from '@aztec/foundation/log';
5
6
  import { DateProvider } from '@aztec/foundation/timer';
6
7
  import { getEpochAtSlot, getEpochNumberAtTimestamp, getSlotAtTimestamp, getSlotRangeForEpoch, getTimestampForSlot, getTimestampRangeForEpoch } from '@aztec/stdlib/epoch-helpers';
7
- import { createPublicClient, encodeAbiParameters, fallback, http, keccak256 } from 'viem';
8
+ import { createPublicClient, encodeAbiParameters, keccak256 } from 'viem';
8
9
  import { getEpochCacheConfigEnvVars } from './config.js';
9
10
  /**
10
11
  * Epoch cache
@@ -50,21 +51,23 @@ import { getEpochCacheConfigEnvVars } from './config.js';
50
51
  const chain = createEthereumChain(config.l1RpcUrls, config.l1ChainId);
51
52
  const publicClient = createPublicClient({
52
53
  chain: chain.chainInfo,
53
- transport: fallback(config.l1RpcUrls.map((url)=>http(url, {
54
- batch: false
55
- }))),
54
+ transport: makeL1HttpTransport(config.l1RpcUrls, {
55
+ timeout: config.l1HttpTimeoutMS
56
+ }),
56
57
  pollingInterval: config.viemPollingIntervalMS
57
58
  });
58
59
  rollup = new RollupContract(publicClient, rollupOrAddress.toString());
59
60
  }
60
- const [l1StartBlock, l1GenesisTime, proofSubmissionEpochs, slotDuration, epochDuration, lagInEpochsForValidatorSet, lagInEpochsForRandao] = await Promise.all([
61
+ const [l1StartBlock, l1GenesisTime, proofSubmissionEpochs, slotDuration, epochDuration, lagInEpochsForValidatorSet, lagInEpochsForRandao, targetCommitteeSize, rollupManaLimit] = await Promise.all([
61
62
  rollup.getL1StartBlock(),
62
63
  rollup.getL1GenesisTime(),
63
64
  rollup.getProofSubmissionEpochs(),
64
65
  rollup.getSlotDuration(),
65
66
  rollup.getEpochDuration(),
66
67
  rollup.getLagInEpochsForValidatorSet(),
67
- rollup.getLagInEpochsForRandao()
68
+ rollup.getLagInEpochsForRandao(),
69
+ rollup.getTargetCommitteeSize(),
70
+ rollup.getManaLimit()
68
71
  ]);
69
72
  const l1RollupConstants = {
70
73
  l1StartBlock,
@@ -74,7 +77,9 @@ import { getEpochCacheConfigEnvVars } from './config.js';
74
77
  epochDuration: Number(epochDuration),
75
78
  ethereumSlotDuration: config.ethereumSlotDuration,
76
79
  lagInEpochsForValidatorSet: Number(lagInEpochsForValidatorSet),
77
- lagInEpochsForRandao: Number(lagInEpochsForRandao)
80
+ lagInEpochsForRandao: Number(lagInEpochsForRandao),
81
+ targetCommitteeSize: Number(targetCommitteeSize),
82
+ rollupManaLimit: Number(rollupManaLimit)
78
83
  };
79
84
  return new EpochCache(rollup, l1RollupConstants, deps.dateProvider);
80
85
  }
@@ -82,10 +87,11 @@ import { getEpochCacheConfigEnvVars } from './config.js';
82
87
  return this.l1constants;
83
88
  }
84
89
  getEpochAndSlotNow() {
85
- const now = this.nowInSeconds();
90
+ const nowMs = BigInt(this.dateProvider.now());
91
+ const nowSeconds = nowMs / 1000n;
86
92
  return {
87
- ...this.getEpochAndSlotAtTimestamp(now),
88
- now
93
+ ...this.getEpochAndSlotAtTimestamp(nowSeconds),
94
+ nowMs
89
95
  };
90
96
  }
91
97
  nowInSeconds() {
@@ -121,6 +127,28 @@ import { getEpochCacheConfigEnvVars } from './config.js';
121
127
  return this.getCommittee(startSlot);
122
128
  }
123
129
  /**
130
+ * Returns whether the escape hatch is open for the given epoch.
131
+ *
132
+ * Uses the already-cached EpochCommitteeInfo when available. If not cached, it will fetch
133
+ * the epoch committee info (which includes the escape hatch flag) and return it.
134
+ */ async isEscapeHatchOpen(epoch) {
135
+ const cached = this.cache.get(epoch);
136
+ if (cached) {
137
+ return cached.isEscapeHatchOpen;
138
+ }
139
+ const info = await this.getCommitteeForEpoch(epoch);
140
+ return info.isEscapeHatchOpen;
141
+ }
142
+ /**
143
+ * Returns whether the escape hatch is open for the epoch containing the given slot.
144
+ *
145
+ * This is a lightweight helper intended for callers that already have a slot number and only
146
+ * need the escape hatch flag (without pulling full committee info).
147
+ */ async isEscapeHatchOpenAtSlot(slot = 'now') {
148
+ const epoch = slot === 'now' ? this.getEpochAndSlotNow().epoch : slot === 'next' ? this.getEpochAndSlotInNextL1Slot().epoch : getEpochAtSlot(slot, this.l1constants);
149
+ return await this.isEscapeHatchOpen(epoch);
150
+ }
151
+ /**
124
152
  * Get the current validator set
125
153
  * @param nextSlot - If true, get the validator set for the next slot.
126
154
  * @returns The current validator set.
@@ -153,12 +181,13 @@ import { getEpochCacheConfigEnvVars } from './config.js';
153
181
  }
154
182
  async computeCommittee(when) {
155
183
  const { ts, epoch } = when;
156
- const [committee, seedBuffer, l1Timestamp] = await Promise.all([
184
+ const [committee, seedBuffer, l1Timestamp, isEscapeHatchOpen] = await Promise.all([
157
185
  this.rollup.getCommitteeAt(ts),
158
186
  this.rollup.getSampleSeedAt(ts),
159
187
  this.rollup.client.getBlock({
160
188
  includeTransactions: false
161
- }).then((b)=>b.timestamp)
189
+ }).then((b)=>b.timestamp),
190
+ this.rollup.isEscapeHatchOpen(epoch)
162
191
  ]);
163
192
  const { lagInEpochsForValidatorSet, epochDuration, slotDuration } = this.l1constants;
164
193
  const sub = BigInt(lagInEpochsForValidatorSet) * BigInt(epochDuration) * BigInt(slotDuration);
@@ -168,7 +197,8 @@ import { getEpochCacheConfigEnvVars } from './config.js';
168
197
  return {
169
198
  committee,
170
199
  seed: seedBuffer.toBigInt(),
171
- epoch
200
+ epoch,
201
+ isEscapeHatchOpen
172
202
  };
173
203
  }
174
204
  /**
@@ -200,17 +230,10 @@ import { getEpochCacheConfigEnvVars } from './config.js';
200
230
  }
201
231
  return BigInt(keccak256(this.getProposerIndexEncoding(epoch, slot, seed))) % size;
202
232
  }
203
- /**
204
- * Returns the current and next proposer's attester address
205
- *
206
- * We return the next proposer's attester address as the node will check if it is the proposer at the next ethereum block,
207
- * which can be the next slot. If this is the case, then it will send proposals early.
208
- */ async getProposerAttesterAddressInCurrentOrNextSlot() {
233
+ /** Returns the current and next L2 slot numbers. */ getCurrentAndNextSlot() {
209
234
  const current = this.getEpochAndSlotNow();
210
235
  const next = this.getEpochAndSlotInNextL1Slot();
211
236
  return {
212
- currentProposer: await this.getProposerAttesterAddressAt(current),
213
- nextProposer: await this.getProposerAttesterAddressAt(next),
214
237
  currentSlot: current.slot,
215
238
  nextSlot: next.slot
216
239
  };
@@ -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,eyJ2ZXJzaW9uIjozLCJmaWxlIjoidGVzdF9lcG9jaF9jYWNoZS5kLnRzIiwic291cmNlUm9vdCI6IiIsInNvdXJjZXMiOlsiLi4vLi4vc3JjL3Rlc3QvdGVzdF9lcG9jaF9jYWNoZS50cyJdLCJuYW1lcyI6W10sIm1hcHBpbmdzIjoiQUFBQSxPQUFPLEVBQUUsV0FBVyxFQUFFLFVBQVUsRUFBRSxNQUFNLGlDQUFpQyxDQUFDO0FBQzFFLE9BQU8sRUFBRSxVQUFVLEVBQUUsTUFBTSwrQkFBK0IsQ0FBQztBQUMzRCxPQUFPLEtBQUssRUFBRSxpQkFBaUIsRUFBRSxNQUFNLDZCQUE2QixDQUFDO0FBR3JFLE9BQU8sS0FBSyxFQUFFLFlBQVksRUFBRSxtQkFBbUIsRUFBRSxrQkFBa0IsRUFBRSxPQUFPLEVBQUUsTUFBTSxtQkFBbUIsQ0FBQztBQWN4Rzs7Ozs7O0dBTUc7QUFDSCxxQkFBYSxjQUFlLFlBQVcsbUJBQW1CO0lBQ3hELE9BQU8sQ0FBQyxTQUFTLENBQW9CO0lBQ3JDLE9BQU8sQ0FBQyxlQUFlLENBQXlCO0lBQ2hELE9BQU8sQ0FBQyxXQUFXLENBQTZCO0lBQ2hELE9BQU8sQ0FBQyxlQUFlLENBQWtCO0lBQ3pDLE9BQU8sQ0FBQyxJQUFJLENBQWM7SUFDMUIsT0FBTyxDQUFDLG9CQUFvQixDQUFvQjtJQUNoRCxPQUFPLENBQUMsV0FBVyxDQUFvQjtJQUV2QyxZQUFZLFdBQVcsR0FBRSxPQUFPLENBQUMsaUJBQWlCLENBQU0sRUFFdkQ7SUFFRDs7O09BR0c7SUFDSCxZQUFZLENBQUMsU0FBUyxFQUFFLFVBQVUsRUFBRSxHQUFHLElBQUksQ0FHMUM7SUFFRDs7O09BR0c7SUFDSCxXQUFXLENBQUMsUUFBUSxFQUFFLFVBQVUsR0FBRyxTQUFTLEdBQUcsSUFBSSxDQUdsRDtJQUVEOzs7T0FHRztJQUNILGNBQWMsQ0FBQyxJQUFJLEVBQUUsVUFBVSxHQUFHLElBQUksQ0FHckM7SUFFRDs7O09BR0c7SUFDSCxrQkFBa0IsQ0FBQyxJQUFJLEVBQUUsT0FBTyxHQUFHLElBQUksQ0FHdEM7SUFFRDs7O09BR0c7SUFDSCxPQUFPLENBQUMsSUFBSSxFQUFFLE1BQU0sR0FBRyxJQUFJLENBRzFCO0lBRUQ7OztPQUdHO0lBQ0gsdUJBQXVCLENBQUMsVUFBVSxFQUFFLFVBQVUsRUFBRSxHQUFHLElBQUksQ0FHdEQ7SUFFRDs7O09BR0c7SUFDSCxjQUFjLENBQUMsU0FBUyxFQUFFLE9BQU8sQ0FBQyxpQkFBaUIsQ0FBQyxHQUFHLElBQUksQ0FHMUQ7SUFFRCxjQUFjLElBQUksaUJBQWlCLENBRWxDO0lBRUQsWUFBWSxDQUFDLEtBQUssQ0FBQyxFQUFFLE9BQU8sR0FBRyxPQUFPLENBQUMsa0JBQWtCLENBQUMsQ0FRekQ7SUFFRCxrQkFBa0IsSUFBSSxZQUFZLEdBQUc7UUFBRSxLQUFLLEVBQUUsTUFBTSxDQUFBO0tBQUUsQ0FJckQ7SUFFRCwyQkFBMkIsSUFBSSxZQUFZLEdBQUc7UUFBRSxHQUFHLEVBQUUsTUFBTSxDQUFBO0tBQUUsQ0FPNUQ7SUFFRCx3QkFBd0IsQ0FBQyxLQUFLLEVBQUUsV0FBVyxFQUFFLElBQUksRUFBRSxVQUFVLEVBQUUsSUFBSSxFQUFFLE1BQU0sR0FBRyxLQUFLLE1BQU0sRUFBRSxDQUcxRjtJQUVELG9CQUFvQixDQUFDLElBQUksRUFBRSxVQUFVLEVBQUUsTUFBTSxFQUFFLFdBQVcsRUFBRSxLQUFLLEVBQUUsTUFBTSxFQUFFLElBQUksRUFBRSxNQUFNLEdBQUcsTUFBTSxDQUsvRjtJQUVELHFCQUFxQixJQUFJO1FBQUUsV0FBVyxFQUFFLFVBQVUsQ0FBQztRQUFDLFFBQVEsRUFBRSxVQUFVLENBQUE7S0FBRSxDQUt6RTtJQUVELGdDQUFnQyxDQUFDLEtBQUssRUFBRSxVQUFVLEdBQUcsT0FBTyxDQUFDLFVBQVUsR0FBRyxTQUFTLENBQUMsQ0FFbkY7SUFFRCx1QkFBdUIsSUFBSSxPQUFPLENBQUMsVUFBVSxFQUFFLENBQUMsQ0FFL0M7SUFFRCxhQUFhLENBQUMsS0FBSyxFQUFFLE9BQU8sRUFBRSxTQUFTLEVBQUUsVUFBVSxHQUFHLE9BQU8sQ0FBQyxPQUFPLENBQUMsQ0FFckU7SUFFRCxpQkFBaUIsQ0FBQyxLQUFLLEVBQUUsT0FBTyxFQUFFLFVBQVUsRUFBRSxVQUFVLEVBQUUsR0FBRyxPQUFPLENBQUMsVUFBVSxFQUFFLENBQUMsQ0FHakY7SUFFRCx1QkFBdUIsQ0FBQyxLQUFLLENBQUMsRUFBRSxPQUFPLEdBQUcsT0FBTyxDQUFDLE9BQU8sQ0FBQyxDQUV6RDtDQUNGIn0=
@@ -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;AAcxG;;;;;;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,152 @@
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
+ targetCommitteeSize: 48,
11
+ rollupManaLimit: Number.MAX_SAFE_INTEGER
12
+ };
13
+ /**
14
+ * A test implementation of EpochCacheInterface that allows manual configuration
15
+ * of committee, proposer, slot, and escape hatch state for use in tests.
16
+ *
17
+ * Unlike the real EpochCache, this class doesn't require any RPC connections
18
+ * or mock setup. Simply use the setter methods to configure the test state.
19
+ */ export class TestEpochCache {
20
+ committee = [];
21
+ proposerAddress;
22
+ currentSlot = SlotNumber(0);
23
+ escapeHatchOpen = false;
24
+ seed = 0n;
25
+ registeredValidators = [];
26
+ l1Constants;
27
+ constructor(l1Constants = {}){
28
+ this.l1Constants = {
29
+ ...DEFAULT_L1_CONSTANTS,
30
+ ...l1Constants
31
+ };
32
+ }
33
+ /**
34
+ * Sets the committee members. Used in validation and attestation flows.
35
+ * @param committee - Array of committee member addresses.
36
+ */ setCommittee(committee) {
37
+ this.committee = committee;
38
+ return this;
39
+ }
40
+ /**
41
+ * Sets the proposer address returned by getProposerAttesterAddressInSlot.
42
+ * @param proposer - The address of the current proposer.
43
+ */ setProposer(proposer) {
44
+ this.proposerAddress = proposer;
45
+ return this;
46
+ }
47
+ /**
48
+ * Sets the current slot number.
49
+ * @param slot - The slot number to set.
50
+ */ setCurrentSlot(slot) {
51
+ this.currentSlot = slot;
52
+ return this;
53
+ }
54
+ /**
55
+ * Sets whether the escape hatch is open.
56
+ * @param open - True if escape hatch should be open.
57
+ */ setEscapeHatchOpen(open) {
58
+ this.escapeHatchOpen = open;
59
+ return this;
60
+ }
61
+ /**
62
+ * Sets the randomness seed used for proposer selection.
63
+ * @param seed - The seed value.
64
+ */ setSeed(seed) {
65
+ this.seed = seed;
66
+ return this;
67
+ }
68
+ /**
69
+ * Sets the list of registered validators (all validators, not just committee).
70
+ * @param validators - Array of validator addresses.
71
+ */ setRegisteredValidators(validators) {
72
+ this.registeredValidators = validators;
73
+ return this;
74
+ }
75
+ /**
76
+ * Sets the L1 constants used for epoch/slot calculations.
77
+ * @param constants - Partial constants to override defaults.
78
+ */ setL1Constants(constants) {
79
+ this.l1Constants = {
80
+ ...this.l1Constants,
81
+ ...constants
82
+ };
83
+ return this;
84
+ }
85
+ getL1Constants() {
86
+ return this.l1Constants;
87
+ }
88
+ getCommittee(_slot) {
89
+ const epoch = getEpochAtSlot(this.currentSlot, this.l1Constants);
90
+ return Promise.resolve({
91
+ committee: this.committee,
92
+ epoch,
93
+ seed: this.seed,
94
+ isEscapeHatchOpen: this.escapeHatchOpen
95
+ });
96
+ }
97
+ getEpochAndSlotNow() {
98
+ const epoch = getEpochAtSlot(this.currentSlot, this.l1Constants);
99
+ const ts = getTimestampRangeForEpoch(epoch, this.l1Constants)[0];
100
+ return {
101
+ epoch,
102
+ slot: this.currentSlot,
103
+ ts,
104
+ nowMs: ts * 1000n
105
+ };
106
+ }
107
+ getEpochAndSlotInNextL1Slot() {
108
+ const now = getTimestampRangeForEpoch(getEpochAtSlot(this.currentSlot, this.l1Constants), this.l1Constants)[0];
109
+ const nextSlotTs = now + BigInt(this.l1Constants.ethereumSlotDuration);
110
+ const nextSlot = getSlotAtTimestamp(nextSlotTs, this.l1Constants);
111
+ const epoch = getEpochAtSlot(nextSlot, this.l1Constants);
112
+ const ts = getTimestampRangeForEpoch(epoch, this.l1Constants)[0];
113
+ return {
114
+ epoch,
115
+ slot: nextSlot,
116
+ ts,
117
+ now
118
+ };
119
+ }
120
+ getProposerIndexEncoding(epoch, slot, seed) {
121
+ // Simple encoding for testing purposes
122
+ return `0x${epoch.toString(16).padStart(64, '0')}${slot.toString(16).padStart(64, '0')}${seed.toString(16).padStart(64, '0')}`;
123
+ }
124
+ computeProposerIndex(slot, _epoch, _seed, size) {
125
+ if (size === 0n) {
126
+ return 0n;
127
+ }
128
+ return BigInt(slot) % size;
129
+ }
130
+ getCurrentAndNextSlot() {
131
+ return {
132
+ currentSlot: this.currentSlot,
133
+ nextSlot: SlotNumber(this.currentSlot + 1)
134
+ };
135
+ }
136
+ getProposerAttesterAddressInSlot(_slot) {
137
+ return Promise.resolve(this.proposerAddress);
138
+ }
139
+ getRegisteredValidators() {
140
+ return Promise.resolve(this.registeredValidators);
141
+ }
142
+ isInCommittee(_slot, validator) {
143
+ return Promise.resolve(this.committee.some((v)=>v.equals(validator)));
144
+ }
145
+ filterInCommittee(_slot, validators) {
146
+ const committeeSet = new Set(this.committee.map((v)=>v.toString()));
147
+ return Promise.resolve(validators.filter((v)=>committeeSet.has(v.toString())));
148
+ }
149
+ isEscapeHatchOpenAtSlot(_slot) {
150
+ return Promise.resolve(this.escapeHatchOpen);
151
+ }
152
+ }
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@aztec/epoch-cache",
3
- "version": "0.0.1-commit.1142ef1",
3
+ "version": "0.0.1-commit.125b3452",
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,11 +26,10 @@
26
26
  "../package.common.json"
27
27
  ],
28
28
  "dependencies": {
29
- "@aztec/ethereum": "0.0.1-commit.1142ef1",
30
- "@aztec/foundation": "0.0.1-commit.1142ef1",
31
- "@aztec/l1-artifacts": "0.0.1-commit.1142ef1",
32
- "@aztec/stdlib": "0.0.1-commit.1142ef1",
33
- "@viem/anvil": "^0.0.10",
29
+ "@aztec/ethereum": "0.0.1-commit.125b3452",
30
+ "@aztec/foundation": "0.0.1-commit.125b3452",
31
+ "@aztec/l1-artifacts": "0.0.1-commit.125b3452",
32
+ "@aztec/stdlib": "0.0.1-commit.125b3452",
34
33
  "dotenv": "^16.0.3",
35
34
  "get-port": "^7.1.0",
36
35
  "jest-mock-extended": "^4.0.0",
@@ -42,7 +41,7 @@
42
41
  "@jest/globals": "^30.0.0",
43
42
  "@types/jest": "^30.0.0",
44
43
  "@types/node": "^22.15.17",
45
- "@typescript/native-preview": "7.0.0-dev.20251126.1",
44
+ "@typescript/native-preview": "7.0.0-dev.20260113.1",
46
45
  "jest": "^30.0.0",
47
46
  "ts-node": "^10.9.1",
48
47
  "typescript": "^5.3.3"
package/src/config.ts CHANGED
@@ -3,7 +3,7 @@ import { type L1ReaderConfig, getL1ReaderConfigFromEnv } from '@aztec/ethereum/l
3
3
 
4
4
  export type EpochCacheConfig = Pick<
5
5
  L1ReaderConfig & L1ContractsConfig,
6
- 'l1RpcUrls' | 'l1ChainId' | 'viemPollingIntervalMS' | 'ethereumSlotDuration'
6
+ 'l1RpcUrls' | 'l1ChainId' | 'viemPollingIntervalMS' | 'l1HttpTimeoutMS' | 'ethereumSlotDuration'
7
7
  >;
8
8
 
9
9
  export function getEpochCacheConfigEnvVars(): EpochCacheConfig {
@@ -1,4 +1,5 @@
1
1
  import { createEthereumChain } from '@aztec/ethereum/chain';
2
+ import { makeL1HttpTransport } from '@aztec/ethereum/client';
2
3
  import { NoCommitteeError, RollupContract } from '@aztec/ethereum/contracts';
3
4
  import { EpochNumber, SlotNumber } from '@aztec/foundation/branded-types';
4
5
  import { EthAddress } from '@aztec/foundation/eth-address';
@@ -14,7 +15,7 @@ import {
14
15
  getTimestampRangeForEpoch,
15
16
  } from '@aztec/stdlib/epoch-helpers';
16
17
 
17
- import { createPublicClient, encodeAbiParameters, fallback, http, keccak256 } from 'viem';
18
+ import { createPublicClient, encodeAbiParameters, keccak256 } from 'viem';
18
19
 
19
20
  import { type EpochCacheConfig, getEpochCacheConfigEnvVars } from './config.js';
20
21
 
@@ -28,26 +29,24 @@ export type EpochCommitteeInfo = {
28
29
  committee: EthAddress[] | undefined;
29
30
  seed: bigint;
30
31
  epoch: EpochNumber;
32
+ /** True if the epoch is within an open escape hatch window. */
33
+ isEscapeHatchOpen: boolean;
31
34
  };
32
35
 
33
36
  export type SlotTag = 'now' | 'next' | SlotNumber;
34
37
 
35
38
  export interface EpochCacheInterface {
36
39
  getCommittee(slot: SlotTag | undefined): Promise<EpochCommitteeInfo>;
37
- getEpochAndSlotNow(): EpochAndSlot;
40
+ getEpochAndSlotNow(): EpochAndSlot & { nowMs: bigint };
38
41
  getEpochAndSlotInNextL1Slot(): EpochAndSlot & { now: bigint };
39
42
  getProposerIndexEncoding(epoch: EpochNumber, slot: SlotNumber, seed: bigint): `0x${string}`;
40
43
  computeProposerIndex(slot: SlotNumber, epoch: EpochNumber, seed: bigint, size: bigint): bigint;
41
- getProposerAttesterAddressInCurrentOrNextSlot(): Promise<{
42
- currentProposer: EthAddress | undefined;
43
- nextProposer: EthAddress | undefined;
44
- currentSlot: SlotNumber;
45
- nextSlot: SlotNumber;
46
- }>;
44
+ getCurrentAndNextSlot(): { currentSlot: SlotNumber; nextSlot: SlotNumber };
47
45
  getProposerAttesterAddressInSlot(slot: SlotNumber): Promise<EthAddress | undefined>;
48
46
  getRegisteredValidators(): Promise<EthAddress[]>;
49
47
  isInCommittee(slot: SlotTag, validator: EthAddress): Promise<boolean>;
50
48
  filterInCommittee(slot: SlotTag, validators: EthAddress[]): Promise<EthAddress[]>;
49
+ getL1Constants(): L1RollupConstants;
51
50
  }
52
51
 
53
52
  /**
@@ -95,7 +94,7 @@ export class EpochCache implements EpochCacheInterface {
95
94
  const chain = createEthereumChain(config.l1RpcUrls, config.l1ChainId);
96
95
  const publicClient = createPublicClient({
97
96
  chain: chain.chainInfo,
98
- transport: fallback(config.l1RpcUrls.map(url => http(url, { batch: false }))),
97
+ transport: makeL1HttpTransport(config.l1RpcUrls, { timeout: config.l1HttpTimeoutMS }),
99
98
  pollingInterval: config.viemPollingIntervalMS,
100
99
  });
101
100
  rollup = new RollupContract(publicClient, rollupOrAddress.toString());
@@ -109,6 +108,8 @@ export class EpochCache implements EpochCacheInterface {
109
108
  epochDuration,
110
109
  lagInEpochsForValidatorSet,
111
110
  lagInEpochsForRandao,
111
+ targetCommitteeSize,
112
+ rollupManaLimit,
112
113
  ] = await Promise.all([
113
114
  rollup.getL1StartBlock(),
114
115
  rollup.getL1GenesisTime(),
@@ -117,6 +118,8 @@ export class EpochCache implements EpochCacheInterface {
117
118
  rollup.getEpochDuration(),
118
119
  rollup.getLagInEpochsForValidatorSet(),
119
120
  rollup.getLagInEpochsForRandao(),
121
+ rollup.getTargetCommitteeSize(),
122
+ rollup.getManaLimit(),
120
123
  ] as const);
121
124
 
122
125
  const l1RollupConstants = {
@@ -128,6 +131,8 @@ export class EpochCache implements EpochCacheInterface {
128
131
  ethereumSlotDuration: config.ethereumSlotDuration,
129
132
  lagInEpochsForValidatorSet: Number(lagInEpochsForValidatorSet),
130
133
  lagInEpochsForRandao: Number(lagInEpochsForRandao),
134
+ targetCommitteeSize: Number(targetCommitteeSize),
135
+ rollupManaLimit: Number(rollupManaLimit),
131
136
  };
132
137
 
133
138
  return new EpochCache(rollup, l1RollupConstants, deps.dateProvider);
@@ -137,9 +142,10 @@ export class EpochCache implements EpochCacheInterface {
137
142
  return this.l1constants;
138
143
  }
139
144
 
140
- public getEpochAndSlotNow(): EpochAndSlot & { now: bigint } {
141
- const now = this.nowInSeconds();
142
- return { ...this.getEpochAndSlotAtTimestamp(now), now };
145
+ public getEpochAndSlotNow(): EpochAndSlot & { nowMs: bigint } {
146
+ const nowMs = BigInt(this.dateProvider.now());
147
+ const nowSeconds = nowMs / 1000n;
148
+ return { ...this.getEpochAndSlotAtTimestamp(nowSeconds), nowMs };
143
149
  }
144
150
 
145
151
  public nowInSeconds(): bigint {
@@ -172,6 +178,38 @@ export class EpochCache implements EpochCacheInterface {
172
178
  return this.getCommittee(startSlot);
173
179
  }
174
180
 
181
+ /**
182
+ * Returns whether the escape hatch is open for the given epoch.
183
+ *
184
+ * Uses the already-cached EpochCommitteeInfo when available. If not cached, it will fetch
185
+ * the epoch committee info (which includes the escape hatch flag) and return it.
186
+ */
187
+ public async isEscapeHatchOpen(epoch: EpochNumber): Promise<boolean> {
188
+ const cached = this.cache.get(epoch);
189
+ if (cached) {
190
+ return cached.isEscapeHatchOpen;
191
+ }
192
+ const info = await this.getCommitteeForEpoch(epoch);
193
+ return info.isEscapeHatchOpen;
194
+ }
195
+
196
+ /**
197
+ * Returns whether the escape hatch is open for the epoch containing the given slot.
198
+ *
199
+ * This is a lightweight helper intended for callers that already have a slot number and only
200
+ * need the escape hatch flag (without pulling full committee info).
201
+ */
202
+ public async isEscapeHatchOpenAtSlot(slot: SlotTag = 'now'): Promise<boolean> {
203
+ const epoch =
204
+ slot === 'now'
205
+ ? this.getEpochAndSlotNow().epoch
206
+ : slot === 'next'
207
+ ? this.getEpochAndSlotInNextL1Slot().epoch
208
+ : getEpochAtSlot(slot, this.l1constants);
209
+
210
+ return await this.isEscapeHatchOpen(epoch);
211
+ }
212
+
175
213
  /**
176
214
  * Get the current validator set
177
215
  * @param nextSlot - If true, get the validator set for the next slot.
@@ -211,10 +249,11 @@ export class EpochCache implements EpochCacheInterface {
211
249
 
212
250
  private async computeCommittee(when: { epoch: EpochNumber; ts: bigint }): Promise<EpochCommitteeInfo> {
213
251
  const { ts, epoch } = when;
214
- const [committee, seedBuffer, l1Timestamp] = await Promise.all([
252
+ const [committee, seedBuffer, l1Timestamp, isEscapeHatchOpen] = await Promise.all([
215
253
  this.rollup.getCommitteeAt(ts),
216
254
  this.rollup.getSampleSeedAt(ts),
217
255
  this.rollup.client.getBlock({ includeTransactions: false }).then(b => b.timestamp),
256
+ this.rollup.isEscapeHatchOpen(epoch),
218
257
  ]);
219
258
  const { lagInEpochsForValidatorSet, epochDuration, slotDuration } = this.l1constants;
220
259
  const sub = BigInt(lagInEpochsForValidatorSet) * BigInt(epochDuration) * BigInt(slotDuration);
@@ -223,7 +262,7 @@ export class EpochCache implements EpochCacheInterface {
223
262
  `Cannot query committee for future epoch ${epoch} with timestamp ${ts} (current L1 time is ${l1Timestamp}). Check your Ethereum node is synced.`,
224
263
  );
225
264
  }
226
- return { committee, seed: seedBuffer.toBigInt(), epoch };
265
+ return { committee, seed: seedBuffer.toBigInt(), epoch, isEscapeHatchOpen };
227
266
  }
228
267
 
229
268
  /**
@@ -248,24 +287,12 @@ export class EpochCache implements EpochCacheInterface {
248
287
  return BigInt(keccak256(this.getProposerIndexEncoding(epoch, slot, seed))) % size;
249
288
  }
250
289
 
251
- /**
252
- * Returns the current and next proposer's attester address
253
- *
254
- * We return the next proposer's attester address as the node will check if it is the proposer at the next ethereum block,
255
- * which can be the next slot. If this is the case, then it will send proposals early.
256
- */
257
- public async getProposerAttesterAddressInCurrentOrNextSlot(): Promise<{
258
- currentSlot: SlotNumber;
259
- nextSlot: SlotNumber;
260
- currentProposer: EthAddress | undefined;
261
- nextProposer: EthAddress | undefined;
262
- }> {
290
+ /** Returns the current and next L2 slot numbers. */
291
+ public getCurrentAndNextSlot(): { currentSlot: SlotNumber; nextSlot: SlotNumber } {
263
292
  const current = this.getEpochAndSlotNow();
264
293
  const next = this.getEpochAndSlotInNextL1Slot();
265
294
 
266
295
  return {
267
- currentProposer: await this.getProposerAttesterAddressAt(current),
268
- nextProposer: await this.getProposerAttesterAddressAt(next),
269
296
  currentSlot: current.slot,
270
297
  nextSlot: next.slot,
271
298
  };
@@ -0,0 +1 @@
1
+ export * from './test_epoch_cache.js';
@@ -0,0 +1,171 @@
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
+ targetCommitteeSize: 48,
17
+ rollupManaLimit: Number.MAX_SAFE_INTEGER,
18
+ };
19
+
20
+ /**
21
+ * A test implementation of EpochCacheInterface that allows manual configuration
22
+ * of committee, proposer, slot, and escape hatch state for use in tests.
23
+ *
24
+ * Unlike the real EpochCache, this class doesn't require any RPC connections
25
+ * or mock setup. Simply use the setter methods to configure the test state.
26
+ */
27
+ export class TestEpochCache implements EpochCacheInterface {
28
+ private committee: EthAddress[] = [];
29
+ private proposerAddress: EthAddress | undefined;
30
+ private currentSlot: SlotNumber = SlotNumber(0);
31
+ private escapeHatchOpen: boolean = false;
32
+ private seed: bigint = 0n;
33
+ private registeredValidators: EthAddress[] = [];
34
+ private l1Constants: L1RollupConstants;
35
+
36
+ constructor(l1Constants: Partial<L1RollupConstants> = {}) {
37
+ this.l1Constants = { ...DEFAULT_L1_CONSTANTS, ...l1Constants };
38
+ }
39
+
40
+ /**
41
+ * Sets the committee members. Used in validation and attestation flows.
42
+ * @param committee - Array of committee member addresses.
43
+ */
44
+ setCommittee(committee: EthAddress[]): this {
45
+ this.committee = committee;
46
+ return this;
47
+ }
48
+
49
+ /**
50
+ * Sets the proposer address returned by getProposerAttesterAddressInSlot.
51
+ * @param proposer - The address of the current proposer.
52
+ */
53
+ setProposer(proposer: EthAddress | undefined): this {
54
+ this.proposerAddress = proposer;
55
+ return this;
56
+ }
57
+
58
+ /**
59
+ * Sets the current slot number.
60
+ * @param slot - The slot number to set.
61
+ */
62
+ setCurrentSlot(slot: SlotNumber): this {
63
+ this.currentSlot = slot;
64
+ return this;
65
+ }
66
+
67
+ /**
68
+ * Sets whether the escape hatch is open.
69
+ * @param open - True if escape hatch should be open.
70
+ */
71
+ setEscapeHatchOpen(open: boolean): this {
72
+ this.escapeHatchOpen = open;
73
+ return this;
74
+ }
75
+
76
+ /**
77
+ * Sets the randomness seed used for proposer selection.
78
+ * @param seed - The seed value.
79
+ */
80
+ setSeed(seed: bigint): this {
81
+ this.seed = seed;
82
+ return this;
83
+ }
84
+
85
+ /**
86
+ * Sets the list of registered validators (all validators, not just committee).
87
+ * @param validators - Array of validator addresses.
88
+ */
89
+ setRegisteredValidators(validators: EthAddress[]): this {
90
+ this.registeredValidators = validators;
91
+ return this;
92
+ }
93
+
94
+ /**
95
+ * Sets the L1 constants used for epoch/slot calculations.
96
+ * @param constants - Partial constants to override defaults.
97
+ */
98
+ setL1Constants(constants: Partial<L1RollupConstants>): this {
99
+ this.l1Constants = { ...this.l1Constants, ...constants };
100
+ return this;
101
+ }
102
+
103
+ getL1Constants(): L1RollupConstants {
104
+ return this.l1Constants;
105
+ }
106
+
107
+ getCommittee(_slot?: SlotTag): Promise<EpochCommitteeInfo> {
108
+ const epoch = getEpochAtSlot(this.currentSlot, this.l1Constants);
109
+ return Promise.resolve({
110
+ committee: this.committee,
111
+ epoch,
112
+ seed: this.seed,
113
+ isEscapeHatchOpen: this.escapeHatchOpen,
114
+ });
115
+ }
116
+
117
+ getEpochAndSlotNow(): EpochAndSlot & { nowMs: bigint } {
118
+ const epoch = getEpochAtSlot(this.currentSlot, this.l1Constants);
119
+ const ts = getTimestampRangeForEpoch(epoch, this.l1Constants)[0];
120
+ return { epoch, slot: this.currentSlot, ts, nowMs: ts * 1000n };
121
+ }
122
+
123
+ getEpochAndSlotInNextL1Slot(): EpochAndSlot & { now: bigint } {
124
+ const now = getTimestampRangeForEpoch(getEpochAtSlot(this.currentSlot, this.l1Constants), this.l1Constants)[0];
125
+ const nextSlotTs = now + BigInt(this.l1Constants.ethereumSlotDuration);
126
+ const nextSlot = getSlotAtTimestamp(nextSlotTs, this.l1Constants);
127
+ const epoch = getEpochAtSlot(nextSlot, this.l1Constants);
128
+ const ts = getTimestampRangeForEpoch(epoch, this.l1Constants)[0];
129
+ return { epoch, slot: nextSlot, ts, now };
130
+ }
131
+
132
+ getProposerIndexEncoding(epoch: EpochNumber, slot: SlotNumber, seed: bigint): `0x${string}` {
133
+ // Simple encoding for testing purposes
134
+ return `0x${epoch.toString(16).padStart(64, '0')}${slot.toString(16).padStart(64, '0')}${seed.toString(16).padStart(64, '0')}`;
135
+ }
136
+
137
+ computeProposerIndex(slot: SlotNumber, _epoch: EpochNumber, _seed: bigint, size: bigint): bigint {
138
+ if (size === 0n) {
139
+ return 0n;
140
+ }
141
+ return BigInt(slot) % size;
142
+ }
143
+
144
+ getCurrentAndNextSlot(): { currentSlot: SlotNumber; nextSlot: SlotNumber } {
145
+ return {
146
+ currentSlot: this.currentSlot,
147
+ nextSlot: SlotNumber(this.currentSlot + 1),
148
+ };
149
+ }
150
+
151
+ getProposerAttesterAddressInSlot(_slot: SlotNumber): Promise<EthAddress | undefined> {
152
+ return Promise.resolve(this.proposerAddress);
153
+ }
154
+
155
+ getRegisteredValidators(): Promise<EthAddress[]> {
156
+ return Promise.resolve(this.registeredValidators);
157
+ }
158
+
159
+ isInCommittee(_slot: SlotTag, validator: EthAddress): Promise<boolean> {
160
+ return Promise.resolve(this.committee.some(v => v.equals(validator)));
161
+ }
162
+
163
+ filterInCommittee(_slot: SlotTag, validators: EthAddress[]): Promise<EthAddress[]> {
164
+ const committeeSet = new Set(this.committee.map(v => v.toString()));
165
+ return Promise.resolve(validators.filter(v => committeeSet.has(v.toString())));
166
+ }
167
+
168
+ isEscapeHatchOpenAtSlot(_slot?: SlotTag): Promise<boolean> {
169
+ return Promise.resolve(this.escapeHatchOpen);
170
+ }
171
+ }