@aztec/epoch-cache 0.0.1-commit.88e6f9396 → 0.0.1-commit.8c0b8ff
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 +2 -3
- package/dest/config.d.ts.map +1 -1
- package/dest/config.js +1 -3
- package/dest/epoch_cache.d.ts +5 -40
- package/dest/epoch_cache.d.ts.map +1 -1
- package/dest/epoch_cache.js +25 -70
- package/dest/test/test_epoch_cache.d.ts +3 -18
- package/dest/test/test_epoch_cache.d.ts.map +1 -1
- package/dest/test/test_epoch_cache.js +11 -54
- package/package.json +6 -5
- package/src/config.ts +3 -9
- package/src/epoch_cache.ts +24 -90
- package/src/test/test_epoch_cache.ts +12 -79
package/dest/config.d.ts
CHANGED
|
@@ -1,6 +1,5 @@
|
|
|
1
1
|
import { type L1ContractsConfig } from '@aztec/ethereum/config';
|
|
2
2
|
import { type L1ReaderConfig } from '@aztec/ethereum/l1-reader';
|
|
3
|
-
|
|
4
|
-
export type EpochCacheConfig = Pick<L1ReaderConfig & L1ContractsConfig & PipelineConfig, 'l1RpcUrls' | 'l1ChainId' | 'viemPollingIntervalMS' | 'ethereumSlotDuration' | 'l1HttpTimeoutMS' | 'enableProposerPipelining'>;
|
|
3
|
+
export type EpochCacheConfig = Pick<L1ReaderConfig & L1ContractsConfig, 'l1RpcUrls' | 'l1ChainId' | 'viemPollingIntervalMS' | 'l1HttpTimeoutMS' | 'ethereumSlotDuration'>;
|
|
5
4
|
export declare function getEpochCacheConfigEnvVars(): EpochCacheConfig;
|
|
6
|
-
//# sourceMappingURL=data:application/json;base64,
|
|
5
|
+
//# sourceMappingURL=data:application/json;base64,eyJ2ZXJzaW9uIjozLCJmaWxlIjoiY29uZmlnLmQudHMiLCJzb3VyY2VSb290IjoiIiwic291cmNlcyI6WyIuLi9zcmMvY29uZmlnLnRzIl0sIm5hbWVzIjpbXSwibWFwcGluZ3MiOiJBQUFBLE9BQU8sRUFBRSxLQUFLLGlCQUFpQixFQUErQixNQUFNLHdCQUF3QixDQUFDO0FBQzdGLE9BQU8sRUFBRSxLQUFLLGNBQWMsRUFBNEIsTUFBTSwyQkFBMkIsQ0FBQztBQUUxRixNQUFNLE1BQU0sZ0JBQWdCLEdBQUcsSUFBSSxDQUNqQyxjQUFjLEdBQUcsaUJBQWlCLEVBQ2xDLFdBQVcsR0FBRyxXQUFXLEdBQUcsdUJBQXVCLEdBQUcsaUJBQWlCLEdBQUcsc0JBQXNCLENBQ2pHLENBQUM7QUFFRix3QkFBZ0IsMEJBQTBCLElBQUksZ0JBQWdCLENBRTdEIn0=
|
package/dest/config.d.ts.map
CHANGED
|
@@ -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;
|
|
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"}
|
package/dest/config.js
CHANGED
|
@@ -1,10 +1,8 @@
|
|
|
1
1
|
import { getL1ContractsConfigEnvVars } from '@aztec/ethereum/config';
|
|
2
2
|
import { getL1ReaderConfigFromEnv } from '@aztec/ethereum/l1-reader';
|
|
3
|
-
import { getPipelineConfigEnvVars } from '@aztec/stdlib/config';
|
|
4
3
|
export function getEpochCacheConfigEnvVars() {
|
|
5
4
|
return {
|
|
6
5
|
...getL1ReaderConfigFromEnv(),
|
|
7
|
-
...getL1ContractsConfigEnvVars()
|
|
8
|
-
...getPipelineConfigEnvVars()
|
|
6
|
+
...getL1ContractsConfigEnvVars()
|
|
9
7
|
};
|
|
10
8
|
}
|
package/dest/epoch_cache.d.ts
CHANGED
|
@@ -4,12 +4,9 @@ import { EthAddress } from '@aztec/foundation/eth-address';
|
|
|
4
4
|
import { DateProvider } from '@aztec/foundation/timer';
|
|
5
5
|
import { type L1RollupConstants } from '@aztec/stdlib/epoch-helpers';
|
|
6
6
|
import { type EpochCacheConfig } from './config.js';
|
|
7
|
-
/** When proposer pipelining is enabled, the proposer builds one slot ahead. */
|
|
8
|
-
export declare const PROPOSER_PIPELINING_SLOT_OFFSET = 1;
|
|
9
|
-
/** Flat return type for compound epoch/slot getters. */
|
|
10
7
|
export type EpochAndSlot = {
|
|
11
|
-
slot: SlotNumber;
|
|
12
8
|
epoch: EpochNumber;
|
|
9
|
+
slot: SlotNumber;
|
|
13
10
|
ts: bigint;
|
|
14
11
|
};
|
|
15
12
|
export type EpochCommitteeInfo = {
|
|
@@ -22,33 +19,18 @@ export type EpochCommitteeInfo = {
|
|
|
22
19
|
export type SlotTag = 'now' | 'next' | SlotNumber;
|
|
23
20
|
export interface EpochCacheInterface {
|
|
24
21
|
getCommittee(slot: SlotTag | undefined): Promise<EpochCommitteeInfo>;
|
|
25
|
-
getSlotNow(): SlotNumber;
|
|
26
|
-
getTargetSlot(): SlotNumber;
|
|
27
|
-
getEpochNow(): EpochNumber;
|
|
28
|
-
getTargetEpoch(): EpochNumber;
|
|
29
22
|
getEpochAndSlotNow(): EpochAndSlot & {
|
|
30
23
|
nowMs: bigint;
|
|
31
24
|
};
|
|
32
25
|
getEpochAndSlotInNextL1Slot(): EpochAndSlot & {
|
|
33
|
-
|
|
34
|
-
};
|
|
35
|
-
/** Returns epoch/slot info for the next L1 slot with pipeline offset applied. */
|
|
36
|
-
getTargetEpochAndSlotInNextL1Slot(): EpochAndSlot & {
|
|
37
|
-
nowSeconds: bigint;
|
|
26
|
+
now: bigint;
|
|
38
27
|
};
|
|
39
|
-
isProposerPipeliningEnabled(): boolean;
|
|
40
|
-
isEscapeHatchOpen(epoch: EpochNumber): Promise<boolean>;
|
|
41
|
-
isEscapeHatchOpenAtSlot(slot: SlotTag): Promise<boolean>;
|
|
42
28
|
getProposerIndexEncoding(epoch: EpochNumber, slot: SlotNumber, seed: bigint): `0x${string}`;
|
|
43
29
|
computeProposerIndex(slot: SlotNumber, epoch: EpochNumber, seed: bigint, size: bigint): bigint;
|
|
44
30
|
getCurrentAndNextSlot(): {
|
|
45
31
|
currentSlot: SlotNumber;
|
|
46
32
|
nextSlot: SlotNumber;
|
|
47
33
|
};
|
|
48
|
-
getTargetAndNextSlot(): {
|
|
49
|
-
targetSlot: SlotNumber;
|
|
50
|
-
nextSlot: SlotNumber;
|
|
51
|
-
};
|
|
52
34
|
getProposerAttesterAddressInSlot(slot: SlotNumber): Promise<EthAddress | undefined>;
|
|
53
35
|
getRegisteredValidators(): Promise<EthAddress[]>;
|
|
54
36
|
isInCommittee(slot: SlotTag, validator: EthAddress): Promise<boolean>;
|
|
@@ -71,40 +53,28 @@ export declare class EpochCache implements EpochCacheInterface {
|
|
|
71
53
|
protected readonly config: {
|
|
72
54
|
cacheSize: number;
|
|
73
55
|
validatorRefreshIntervalSeconds: number;
|
|
74
|
-
enableProposerPipelining: boolean;
|
|
75
56
|
};
|
|
76
57
|
protected cache: Map<EpochNumber, EpochCommitteeInfo>;
|
|
77
58
|
private allValidators;
|
|
78
59
|
private lastValidatorRefresh;
|
|
79
60
|
private readonly log;
|
|
80
|
-
protected enableProposerPipelining: boolean;
|
|
81
61
|
constructor(rollup: RollupContract, l1constants: L1RollupConstants & {
|
|
82
62
|
lagInEpochsForValidatorSet: number;
|
|
83
63
|
lagInEpochsForRandao: number;
|
|
84
64
|
}, dateProvider?: DateProvider, config?: {
|
|
85
65
|
cacheSize: number;
|
|
86
66
|
validatorRefreshIntervalSeconds: number;
|
|
87
|
-
enableProposerPipelining: boolean;
|
|
88
67
|
});
|
|
89
68
|
static create(rollupOrAddress: EthAddress | RollupContract, config?: EpochCacheConfig, deps?: {
|
|
90
69
|
dateProvider?: DateProvider;
|
|
91
70
|
}): Promise<EpochCache>;
|
|
92
71
|
getL1Constants(): L1RollupConstants;
|
|
93
|
-
isProposerPipeliningEnabled(): boolean;
|
|
94
|
-
getSlotNow(): SlotNumber;
|
|
95
|
-
getTargetSlot(): SlotNumber;
|
|
96
|
-
getEpochNow(): EpochNumber;
|
|
97
|
-
getTargetEpoch(): EpochNumber;
|
|
98
72
|
getEpochAndSlotNow(): EpochAndSlot & {
|
|
99
73
|
nowMs: bigint;
|
|
100
74
|
};
|
|
101
|
-
nowInSeconds(): bigint;
|
|
102
75
|
private getEpochAndSlotAtSlot;
|
|
103
76
|
getEpochAndSlotInNextL1Slot(): EpochAndSlot & {
|
|
104
|
-
|
|
105
|
-
};
|
|
106
|
-
getTargetEpochAndSlotInNextL1Slot(): EpochAndSlot & {
|
|
107
|
-
nowSeconds: bigint;
|
|
77
|
+
now: bigint;
|
|
108
78
|
};
|
|
109
79
|
private getEpochAndSlotAtTimestamp;
|
|
110
80
|
getCommitteeForEpoch(epoch: EpochNumber): Promise<EpochCommitteeInfo>;
|
|
@@ -135,16 +105,11 @@ export declare class EpochCache implements EpochCacheInterface {
|
|
|
135
105
|
*/
|
|
136
106
|
getProposerIndexEncoding(epoch: EpochNumber, slot: SlotNumber, seed: bigint): `0x${string}`;
|
|
137
107
|
computeProposerIndex(slot: SlotNumber, epoch: EpochNumber, seed: bigint, size: bigint): bigint;
|
|
138
|
-
/** Returns the current and next L2 slot
|
|
108
|
+
/** Returns the current and next L2 slot numbers. */
|
|
139
109
|
getCurrentAndNextSlot(): {
|
|
140
110
|
currentSlot: SlotNumber;
|
|
141
111
|
nextSlot: SlotNumber;
|
|
142
112
|
};
|
|
143
|
-
/** Returns the taget and next L2 slot in the next L1 slot */
|
|
144
|
-
getTargetAndNextSlot(): {
|
|
145
|
-
targetSlot: SlotNumber;
|
|
146
|
-
nextSlot: SlotNumber;
|
|
147
|
-
};
|
|
148
113
|
/**
|
|
149
114
|
* Get the proposer attester address in the given L2 slot
|
|
150
115
|
* @returns The proposer attester address. If the committee does not exist, we throw a NoCommitteeError.
|
|
@@ -165,4 +130,4 @@ export declare class EpochCache implements EpochCacheInterface {
|
|
|
165
130
|
filterInCommittee(slot: SlotTag, validators: EthAddress[]): Promise<EthAddress[]>;
|
|
166
131
|
getRegisteredValidators(): Promise<EthAddress[]>;
|
|
167
132
|
}
|
|
168
|
-
//# sourceMappingURL=data:application/json;base64,
|
|
133
|
+
//# sourceMappingURL=data:application/json;base64,eyJ2ZXJzaW9uIjozLCJmaWxlIjoiZXBvY2hfY2FjaGUuZC50cyIsInNvdXJjZVJvb3QiOiIiLCJzb3VyY2VzIjpbIi4uL3NyYy9lcG9jaF9jYWNoZS50cyJdLCJuYW1lcyI6W10sIm1hcHBpbmdzIjoiQUFFQSxPQUFPLEVBQW9CLGNBQWMsRUFBRSxNQUFNLDJCQUEyQixDQUFDO0FBQzdFLE9BQU8sRUFBRSxXQUFXLEVBQUUsVUFBVSxFQUFFLE1BQU0saUNBQWlDLENBQUM7QUFDMUUsT0FBTyxFQUFFLFVBQVUsRUFBRSxNQUFNLCtCQUErQixDQUFDO0FBRTNELE9BQU8sRUFBRSxZQUFZLEVBQUUsTUFBTSx5QkFBeUIsQ0FBQztBQUN2RCxPQUFPLEVBQ0wsS0FBSyxpQkFBaUIsRUFRdkIsTUFBTSw2QkFBNkIsQ0FBQztBQUlyQyxPQUFPLEVBQUUsS0FBSyxnQkFBZ0IsRUFBOEIsTUFBTSxhQUFhLENBQUM7QUFFaEYsTUFBTSxNQUFNLFlBQVksR0FBRztJQUN6QixLQUFLLEVBQUUsV0FBVyxDQUFDO0lBQ25CLElBQUksRUFBRSxVQUFVLENBQUM7SUFDakIsRUFBRSxFQUFFLE1BQU0sQ0FBQztDQUNaLENBQUM7QUFFRixNQUFNLE1BQU0sa0JBQWtCLEdBQUc7SUFDL0IsU0FBUyxFQUFFLFVBQVUsRUFBRSxHQUFHLFNBQVMsQ0FBQztJQUNwQyxJQUFJLEVBQUUsTUFBTSxDQUFDO0lBQ2IsS0FBSyxFQUFFLFdBQVcsQ0FBQztJQUNuQiwrREFBK0Q7SUFDL0QsaUJBQWlCLEVBQUUsT0FBTyxDQUFDO0NBQzVCLENBQUM7QUFFRixNQUFNLE1BQU0sT0FBTyxHQUFHLEtBQUssR0FBRyxNQUFNLEdBQUcsVUFBVSxDQUFDO0FBRWxELE1BQU0sV0FBVyxtQkFBbUI7SUFDbEMsWUFBWSxDQUFDLElBQUksRUFBRSxPQUFPLEdBQUcsU0FBUyxHQUFHLE9BQU8sQ0FBQyxrQkFBa0IsQ0FBQyxDQUFDO0lBQ3JFLGtCQUFrQixJQUFJLFlBQVksR0FBRztRQUFFLEtBQUssRUFBRSxNQUFNLENBQUE7S0FBRSxDQUFDO0lBQ3ZELDJCQUEyQixJQUFJLFlBQVksR0FBRztRQUFFLEdBQUcsRUFBRSxNQUFNLENBQUE7S0FBRSxDQUFDO0lBQzlELHdCQUF3QixDQUFDLEtBQUssRUFBRSxXQUFXLEVBQUUsSUFBSSxFQUFFLFVBQVUsRUFBRSxJQUFJLEVBQUUsTUFBTSxHQUFHLEtBQUssTUFBTSxFQUFFLENBQUM7SUFDNUYsb0JBQW9CLENBQUMsSUFBSSxFQUFFLFVBQVUsRUFBRSxLQUFLLEVBQUUsV0FBVyxFQUFFLElBQUksRUFBRSxNQUFNLEVBQUUsSUFBSSxFQUFFLE1BQU0sR0FBRyxNQUFNLENBQUM7SUFDL0YscUJBQXFCLElBQUk7UUFBRSxXQUFXLEVBQUUsVUFBVSxDQUFDO1FBQUMsUUFBUSxFQUFFLFVBQVUsQ0FBQTtLQUFFLENBQUM7SUFDM0UsZ0NBQWdDLENBQUMsSUFBSSxFQUFFLFVBQVUsR0FBRyxPQUFPLENBQUMsVUFBVSxHQUFHLFNBQVMsQ0FBQyxDQUFDO0lBQ3BGLHVCQUF1QixJQUFJLE9BQU8sQ0FBQyxVQUFVLEVBQUUsQ0FBQyxDQUFDO0lBQ2pELGFBQWEsQ0FBQyxJQUFJLEVBQUUsT0FBTyxFQUFFLFNBQVMsRUFBRSxVQUFVLEdBQUcsT0FBTyxDQUFDLE9BQU8sQ0FBQyxDQUFDO0lBQ3RFLGlCQUFpQixDQUFDLElBQUksRUFBRSxPQUFPLEVBQUUsVUFBVSxFQUFFLFVBQVUsRUFBRSxHQUFHLE9BQU8sQ0FBQyxVQUFVLEVBQUUsQ0FBQyxDQUFDO0lBQ2xGLGNBQWMsSUFBSSxpQkFBaUIsQ0FBQztDQUNyQztBQUVEOzs7Ozs7OztHQVFHO0FBQ0gscUJBQWEsVUFBVyxZQUFXLG1CQUFtQjtJQVFsRCxPQUFPLENBQUMsTUFBTTtJQUNkLE9BQU8sQ0FBQyxRQUFRLENBQUMsV0FBVztJQUk1QixPQUFPLENBQUMsUUFBUSxDQUFDLFlBQVk7SUFDN0IsU0FBUyxDQUFDLFFBQVEsQ0FBQyxNQUFNOzs7O0lBWjNCLFNBQVMsQ0FBQyxLQUFLLEVBQUUsR0FBRyxDQUFDLFdBQVcsRUFBRSxrQkFBa0IsQ0FBQyxDQUFhO0lBQ2xFLE9BQU8sQ0FBQyxhQUFhLENBQTBCO0lBQy9DLE9BQU8sQ0FBQyxvQkFBb0IsQ0FBSztJQUNqQyxPQUFPLENBQUMsUUFBUSxDQUFDLEdBQUcsQ0FBdUM7SUFFM0QsWUFDVSxNQUFNLEVBQUUsY0FBYyxFQUNiLFdBQVcsRUFBRSxpQkFBaUIsR0FBRztRQUNoRCwwQkFBMEIsRUFBRSxNQUFNLENBQUM7UUFDbkMsb0JBQW9CLEVBQUUsTUFBTSxDQUFDO0tBQzlCLEVBQ2dCLFlBQVksR0FBRSxZQUFpQyxFQUM3QyxNQUFNOzs7S0FBeUQsRUFLbkY7SUFFRCxPQUFhLE1BQU0sQ0FDakIsZUFBZSxFQUFFLFVBQVUsR0FBRyxjQUFjLEVBQzVDLE1BQU0sQ0FBQyxFQUFFLGdCQUFnQixFQUN6QixJQUFJLEdBQUU7UUFBRSxZQUFZLENBQUMsRUFBRSxZQUFZLENBQUE7S0FBTyx1QkFzRDNDO0lBRU0sY0FBYyxJQUFJLGlCQUFpQixDQUV6QztJQUVNLGtCQUFrQixJQUFJLFlBQVksR0FBRztRQUFFLEtBQUssRUFBRSxNQUFNLENBQUE7S0FBRSxDQUk1RDtJQUVELE9BQU8sQ0FBQyxxQkFBcUI7SUFNdEIsMkJBQTJCLElBQUksWUFBWSxHQUFHO1FBQUUsR0FBRyxFQUFFLE1BQU0sQ0FBQTtLQUFFLENBSW5FO0lBRUQsT0FBTyxDQUFDLDBCQUEwQjtJQVMzQixvQkFBb0IsQ0FBQyxLQUFLLEVBQUUsV0FBVyxHQUFHLE9BQU8sQ0FBQyxrQkFBa0IsQ0FBQyxDQUczRTtJQUVEOzs7OztPQUtHO0lBQ1UsaUJBQWlCLENBQUMsS0FBSyxFQUFFLFdBQVcsR0FBRyxPQUFPLENBQUMsT0FBTyxDQUFDLENBT25FO0lBRUQ7Ozs7O09BS0c7SUFDVSx1QkFBdUIsQ0FBQyxJQUFJLEdBQUUsT0FBZSxHQUFHLE9BQU8sQ0FBQyxPQUFPLENBQUMsQ0FTNUU7SUFFRDs7OztPQUlHO0lBQ1UsWUFBWSxDQUFDLElBQUksR0FBRSxPQUFlLEdBQUcsT0FBTyxDQUFDLGtCQUFrQixDQUFDLENBb0I1RTtJQUVELE9BQU8sQ0FBQyxvQkFBb0I7WUFVZCxnQkFBZ0I7SUFrQjlCOztPQUVHO0lBQ0gsd0JBQXdCLENBQUMsS0FBSyxFQUFFLFdBQVcsRUFBRSxJQUFJLEVBQUUsVUFBVSxFQUFFLElBQUksRUFBRSxNQUFNLEdBQUcsS0FBSyxNQUFNLEVBQUUsQ0FTMUY7SUFFTSxvQkFBb0IsQ0FBQyxJQUFJLEVBQUUsVUFBVSxFQUFFLEtBQUssRUFBRSxXQUFXLEVBQUUsSUFBSSxFQUFFLE1BQU0sRUFBRSxJQUFJLEVBQUUsTUFBTSxHQUFHLE1BQU0sQ0FNcEc7SUFFRCxvREFBb0Q7SUFDN0MscUJBQXFCLElBQUk7UUFBRSxXQUFXLEVBQUUsVUFBVSxDQUFDO1FBQUMsUUFBUSxFQUFFLFVBQVUsQ0FBQTtLQUFFLENBUWhGO0lBRUQ7Ozs7T0FJRztJQUNJLGdDQUFnQyxDQUFDLElBQUksRUFBRSxVQUFVLEdBQUcsT0FBTyxDQUFDLFVBQVUsR0FBRyxTQUFTLENBQUMsQ0FHekY7SUFFRDs7OztPQUlHO0lBQ0ksb0NBQW9DLElBQUksT0FBTyxDQUFDLFVBQVUsR0FBRyxTQUFTLENBQUMsQ0FHN0U7WUFRYSw0QkFBNEI7SUFhbkMsNkJBQTZCLENBQ2xDLGtCQUFrQixFQUFFLGtCQUFrQixFQUN0QyxJQUFJLEVBQUUsVUFBVSxHQUNmLFVBQVUsR0FBRyxTQUFTLENBWXhCO0lBRUQsNERBQTREO0lBQ3RELGFBQWEsQ0FBQyxJQUFJLEVBQUUsT0FBTyxFQUFFLFNBQVMsRUFBRSxVQUFVLEdBQUcsT0FBTyxDQUFDLE9BQU8sQ0FBQyxDQU0xRTtJQUVELCtGQUErRjtJQUN6RixpQkFBaUIsQ0FBQyxJQUFJLEVBQUUsT0FBTyxFQUFFLFVBQVUsRUFBRSxVQUFVLEVBQUUsR0FBRyxPQUFPLENBQUMsVUFBVSxFQUFFLENBQUMsQ0FPdEY7SUFFSyx1QkFBdUIsSUFBSSxPQUFPLENBQUMsVUFBVSxFQUFFLENBQUMsQ0FVckQ7Q0FDRiJ9
|
|
@@ -1 +1 @@
|
|
|
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,
|
|
1
|
+
{"version":3,"file":"epoch_cache.d.ts","sourceRoot":"","sources":["../src/epoch_cache.ts"],"names":[],"mappings":"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"}
|
package/dest/epoch_cache.js
CHANGED
|
@@ -1,14 +1,12 @@
|
|
|
1
1
|
import { createEthereumChain } from '@aztec/ethereum/chain';
|
|
2
2
|
import { makeL1HttpTransport } from '@aztec/ethereum/client';
|
|
3
3
|
import { NoCommitteeError, RollupContract } from '@aztec/ethereum/contracts';
|
|
4
|
-
import { SlotNumber } from '@aztec/foundation/branded-types';
|
|
5
4
|
import { EthAddress } from '@aztec/foundation/eth-address';
|
|
6
5
|
import { createLogger } from '@aztec/foundation/log';
|
|
7
6
|
import { DateProvider } from '@aztec/foundation/timer';
|
|
8
|
-
import { getEpochAtSlot, getEpochNumberAtTimestamp, getSlotAtTimestamp, getSlotRangeForEpoch, getTimestampForSlot } from '@aztec/stdlib/epoch-helpers';
|
|
7
|
+
import { getEpochAtSlot, getEpochNumberAtTimestamp, getNextL1SlotTimestamp, getSlotAtTimestamp, getSlotRangeForEpoch, getTimestampForSlot, getTimestampRangeForEpoch } from '@aztec/stdlib/epoch-helpers';
|
|
9
8
|
import { createPublicClient, encodeAbiParameters, keccak256 } from 'viem';
|
|
10
9
|
import { getEpochCacheConfigEnvVars } from './config.js';
|
|
11
|
-
/** When proposer pipelining is enabled, the proposer builds one slot ahead. */ export const PROPOSER_PIPELINING_SLOT_OFFSET = 1;
|
|
12
10
|
/**
|
|
13
11
|
* Epoch cache
|
|
14
12
|
*
|
|
@@ -27,11 +25,9 @@ import { getEpochCacheConfigEnvVars } from './config.js';
|
|
|
27
25
|
allValidators;
|
|
28
26
|
lastValidatorRefresh;
|
|
29
27
|
log;
|
|
30
|
-
enableProposerPipelining;
|
|
31
28
|
constructor(rollup, l1constants, dateProvider = new DateProvider(), config = {
|
|
32
29
|
cacheSize: 12,
|
|
33
|
-
validatorRefreshIntervalSeconds: 60
|
|
34
|
-
enableProposerPipelining: false
|
|
30
|
+
validatorRefreshIntervalSeconds: 60
|
|
35
31
|
}){
|
|
36
32
|
this.rollup = rollup;
|
|
37
33
|
this.l1constants = l1constants;
|
|
@@ -41,10 +37,8 @@ import { getEpochCacheConfigEnvVars } from './config.js';
|
|
|
41
37
|
this.allValidators = new Set();
|
|
42
38
|
this.lastValidatorRefresh = 0;
|
|
43
39
|
this.log = createLogger('epoch-cache');
|
|
44
|
-
this.enableProposerPipelining = this.config.enableProposerPipelining;
|
|
45
40
|
this.log.debug(`Initialized EpochCache`, {
|
|
46
|
-
l1constants
|
|
47
|
-
enableProposerPipelining: this.enableProposerPipelining
|
|
41
|
+
l1constants
|
|
48
42
|
});
|
|
49
43
|
}
|
|
50
44
|
static async create(rollupOrAddress, config, deps = {}) {
|
|
@@ -87,32 +81,11 @@ import { getEpochCacheConfigEnvVars } from './config.js';
|
|
|
87
81
|
targetCommitteeSize: Number(targetCommitteeSize),
|
|
88
82
|
rollupManaLimit: Number(rollupManaLimit)
|
|
89
83
|
};
|
|
90
|
-
return new EpochCache(rollup, l1RollupConstants, deps.dateProvider
|
|
91
|
-
cacheSize: 12,
|
|
92
|
-
validatorRefreshIntervalSeconds: 60,
|
|
93
|
-
enableProposerPipelining: config.enableProposerPipelining
|
|
94
|
-
});
|
|
84
|
+
return new EpochCache(rollup, l1RollupConstants, deps.dateProvider);
|
|
95
85
|
}
|
|
96
86
|
getL1Constants() {
|
|
97
87
|
return this.l1constants;
|
|
98
88
|
}
|
|
99
|
-
isProposerPipeliningEnabled() {
|
|
100
|
-
return this.enableProposerPipelining;
|
|
101
|
-
}
|
|
102
|
-
getSlotNow() {
|
|
103
|
-
return this.getEpochAndSlotNow().slot;
|
|
104
|
-
}
|
|
105
|
-
getTargetSlot() {
|
|
106
|
-
const slotNow = this.getSlotNow();
|
|
107
|
-
const offset = this.isProposerPipeliningEnabled() ? PROPOSER_PIPELINING_SLOT_OFFSET : 0;
|
|
108
|
-
return SlotNumber(slotNow + offset);
|
|
109
|
-
}
|
|
110
|
-
getEpochNow() {
|
|
111
|
-
return this.getEpochAndSlotNow().epoch;
|
|
112
|
-
}
|
|
113
|
-
getTargetEpoch() {
|
|
114
|
-
return getEpochAtSlot(this.getTargetSlot(), this.l1constants);
|
|
115
|
-
}
|
|
116
89
|
getEpochAndSlotNow() {
|
|
117
90
|
const nowMs = BigInt(this.dateProvider.now());
|
|
118
91
|
const nowSeconds = nowMs / 1000n;
|
|
@@ -121,40 +94,29 @@ import { getEpochCacheConfigEnvVars } from './config.js';
|
|
|
121
94
|
nowMs
|
|
122
95
|
};
|
|
123
96
|
}
|
|
124
|
-
nowInSeconds() {
|
|
125
|
-
return BigInt(Math.floor(this.dateProvider.now() / 1000));
|
|
126
|
-
}
|
|
127
97
|
getEpochAndSlotAtSlot(slot) {
|
|
128
|
-
|
|
129
|
-
|
|
130
|
-
getEpochAndSlotInNextL1Slot() {
|
|
131
|
-
const nowSeconds = this.nowInSeconds();
|
|
132
|
-
const nextSlotTs = nowSeconds + BigInt(this.l1constants.ethereumSlotDuration);
|
|
98
|
+
const epoch = getEpochAtSlot(slot, this.l1constants);
|
|
99
|
+
const ts = getTimestampRangeForEpoch(epoch, this.l1constants)[0];
|
|
133
100
|
return {
|
|
134
|
-
|
|
135
|
-
|
|
101
|
+
epoch,
|
|
102
|
+
ts,
|
|
103
|
+
slot
|
|
136
104
|
};
|
|
137
105
|
}
|
|
138
|
-
|
|
139
|
-
|
|
140
|
-
|
|
141
|
-
}
|
|
142
|
-
const result = this.getEpochAndSlotInNextL1Slot();
|
|
143
|
-
const offset = PROPOSER_PIPELINING_SLOT_OFFSET;
|
|
144
|
-
const targetSlot = SlotNumber(result.slot + offset);
|
|
106
|
+
getEpochAndSlotInNextL1Slot() {
|
|
107
|
+
const now = BigInt(this.dateProvider.nowInSeconds());
|
|
108
|
+
const nextSlotTs = getNextL1SlotTimestamp(Number(now), this.l1constants);
|
|
145
109
|
return {
|
|
146
|
-
...
|
|
147
|
-
|
|
148
|
-
epoch: getEpochAtSlot(targetSlot, this.l1constants)
|
|
110
|
+
...this.getEpochAndSlotAtTimestamp(nextSlotTs),
|
|
111
|
+
now
|
|
149
112
|
};
|
|
150
113
|
}
|
|
151
114
|
getEpochAndSlotAtTimestamp(ts) {
|
|
152
115
|
const slot = getSlotAtTimestamp(ts, this.l1constants);
|
|
153
|
-
const epoch = getEpochNumberAtTimestamp(ts, this.l1constants);
|
|
154
116
|
return {
|
|
155
|
-
|
|
156
|
-
|
|
157
|
-
|
|
117
|
+
epoch: getEpochNumberAtTimestamp(ts, this.l1constants),
|
|
118
|
+
ts: getTimestampForSlot(slot, this.l1constants),
|
|
119
|
+
slot
|
|
158
120
|
};
|
|
159
121
|
}
|
|
160
122
|
getCommitteeForEpoch(epoch) {
|
|
@@ -180,7 +142,7 @@ import { getEpochCacheConfigEnvVars } from './config.js';
|
|
|
180
142
|
* This is a lightweight helper intended for callers that already have a slot number and only
|
|
181
143
|
* need the escape hatch flag (without pulling full committee info).
|
|
182
144
|
*/ async isEscapeHatchOpenAtSlot(slot = 'now') {
|
|
183
|
-
const epoch = slot === 'now' ? this.
|
|
145
|
+
const epoch = slot === 'now' ? this.getEpochAndSlotNow().epoch : slot === 'next' ? this.getEpochAndSlotInNextL1Slot().epoch : getEpochAtSlot(slot, this.l1constants);
|
|
184
146
|
return await this.isEscapeHatchOpen(epoch);
|
|
185
147
|
}
|
|
186
148
|
/**
|
|
@@ -265,19 +227,11 @@ import { getEpochCacheConfigEnvVars } from './config.js';
|
|
|
265
227
|
}
|
|
266
228
|
return BigInt(keccak256(this.getProposerIndexEncoding(epoch, slot, seed))) % size;
|
|
267
229
|
}
|
|
268
|
-
/** Returns the current and next L2 slot
|
|
269
|
-
const
|
|
230
|
+
/** Returns the current and next L2 slot numbers. */ getCurrentAndNextSlot() {
|
|
231
|
+
const current = this.getEpochAndSlotNow();
|
|
270
232
|
const next = this.getEpochAndSlotInNextL1Slot();
|
|
271
233
|
return {
|
|
272
|
-
currentSlot,
|
|
273
|
-
nextSlot: next.slot
|
|
274
|
-
};
|
|
275
|
-
}
|
|
276
|
-
/** Returns the taget and next L2 slot in the next L1 slot */ getTargetAndNextSlot() {
|
|
277
|
-
const targetSlot = this.getTargetSlot();
|
|
278
|
-
const next = this.getTargetEpochAndSlotInNextL1Slot();
|
|
279
|
-
return {
|
|
280
|
-
targetSlot,
|
|
234
|
+
currentSlot: current.slot,
|
|
281
235
|
nextSlot: next.slot
|
|
282
236
|
};
|
|
283
237
|
}
|
|
@@ -338,10 +292,11 @@ import { getEpochCacheConfigEnvVars } from './config.js';
|
|
|
338
292
|
async getRegisteredValidators() {
|
|
339
293
|
const validatorRefreshIntervalMs = this.config.validatorRefreshIntervalSeconds * 1000;
|
|
340
294
|
const validatorRefreshTime = this.lastValidatorRefresh + validatorRefreshIntervalMs;
|
|
341
|
-
|
|
342
|
-
|
|
295
|
+
const now = this.dateProvider.now();
|
|
296
|
+
if (validatorRefreshTime < now) {
|
|
297
|
+
const currentSet = await this.rollup.getAttesters(BigInt(Math.floor(now / 1000)));
|
|
343
298
|
this.allValidators = new Set(currentSet.map((v)=>v.toString()));
|
|
344
|
-
this.lastValidatorRefresh =
|
|
299
|
+
this.lastValidatorRefresh = now;
|
|
345
300
|
}
|
|
346
301
|
return Array.from(this.allValidators.keys()).map((v)=>EthAddress.fromString(v));
|
|
347
302
|
}
|
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
import { EpochNumber, SlotNumber } from '@aztec/foundation/branded-types';
|
|
2
2
|
import { EthAddress } from '@aztec/foundation/eth-address';
|
|
3
3
|
import type { L1RollupConstants } from '@aztec/stdlib/epoch-helpers';
|
|
4
|
-
import {
|
|
4
|
+
import type { EpochAndSlot, EpochCacheInterface, EpochCommitteeInfo, SlotTag } from '../epoch_cache.js';
|
|
5
5
|
/**
|
|
6
6
|
* A test implementation of EpochCacheInterface that allows manual configuration
|
|
7
7
|
* of committee, proposer, slot, and escape hatch state for use in tests.
|
|
@@ -17,7 +17,6 @@ export declare class TestEpochCache implements EpochCacheInterface {
|
|
|
17
17
|
private seed;
|
|
18
18
|
private registeredValidators;
|
|
19
19
|
private l1Constants;
|
|
20
|
-
private proposerPipeliningEnabled;
|
|
21
20
|
constructor(l1Constants?: Partial<L1RollupConstants>);
|
|
22
21
|
/**
|
|
23
22
|
* Sets the committee members. Used in validation and attestation flows.
|
|
@@ -55,21 +54,12 @@ export declare class TestEpochCache implements EpochCacheInterface {
|
|
|
55
54
|
*/
|
|
56
55
|
setL1Constants(constants: Partial<L1RollupConstants>): this;
|
|
57
56
|
getL1Constants(): L1RollupConstants;
|
|
58
|
-
setProposerPipeliningEnabled(enabled: boolean): void;
|
|
59
57
|
getCommittee(_slot?: SlotTag): Promise<EpochCommitteeInfo>;
|
|
60
|
-
getSlotNow(): SlotNumber;
|
|
61
|
-
getTargetSlot(): SlotNumber;
|
|
62
|
-
getEpochNow(): EpochNumber;
|
|
63
|
-
getTargetEpoch(): EpochNumber;
|
|
64
|
-
isProposerPipeliningEnabled(): boolean;
|
|
65
58
|
getEpochAndSlotNow(): EpochAndSlot & {
|
|
66
59
|
nowMs: bigint;
|
|
67
60
|
};
|
|
68
61
|
getEpochAndSlotInNextL1Slot(): EpochAndSlot & {
|
|
69
|
-
|
|
70
|
-
};
|
|
71
|
-
getTargetEpochAndSlotInNextL1Slot(): EpochAndSlot & {
|
|
72
|
-
nowSeconds: bigint;
|
|
62
|
+
now: bigint;
|
|
73
63
|
};
|
|
74
64
|
getProposerIndexEncoding(epoch: EpochNumber, slot: SlotNumber, seed: bigint): `0x${string}`;
|
|
75
65
|
computeProposerIndex(slot: SlotNumber, _epoch: EpochNumber, _seed: bigint, size: bigint): bigint;
|
|
@@ -77,15 +67,10 @@ export declare class TestEpochCache implements EpochCacheInterface {
|
|
|
77
67
|
currentSlot: SlotNumber;
|
|
78
68
|
nextSlot: SlotNumber;
|
|
79
69
|
};
|
|
80
|
-
getTargetAndNextSlot(): {
|
|
81
|
-
targetSlot: SlotNumber;
|
|
82
|
-
nextSlot: SlotNumber;
|
|
83
|
-
};
|
|
84
70
|
getProposerAttesterAddressInSlot(_slot: SlotNumber): Promise<EthAddress | undefined>;
|
|
85
71
|
getRegisteredValidators(): Promise<EthAddress[]>;
|
|
86
72
|
isInCommittee(_slot: SlotTag, validator: EthAddress): Promise<boolean>;
|
|
87
73
|
filterInCommittee(_slot: SlotTag, validators: EthAddress[]): Promise<EthAddress[]>;
|
|
88
|
-
isEscapeHatchOpen(_epoch: EpochNumber): Promise<boolean>;
|
|
89
74
|
isEscapeHatchOpenAtSlot(_slot?: SlotTag): Promise<boolean>;
|
|
90
75
|
}
|
|
91
|
-
//# sourceMappingURL=data:application/json;base64,
|
|
76
|
+
//# sourceMappingURL=data:application/json;base64,eyJ2ZXJzaW9uIjozLCJmaWxlIjoidGVzdF9lcG9jaF9jYWNoZS5kLnRzIiwic291cmNlUm9vdCI6IiIsInNvdXJjZXMiOlsiLi4vLi4vc3JjL3Rlc3QvdGVzdF9lcG9jaF9jYWNoZS50cyJdLCJuYW1lcyI6W10sIm1hcHBpbmdzIjoiQUFBQSxPQUFPLEVBQUUsV0FBVyxFQUFFLFVBQVUsRUFBRSxNQUFNLGlDQUFpQyxDQUFDO0FBQzFFLE9BQU8sRUFBRSxVQUFVLEVBQUUsTUFBTSwrQkFBK0IsQ0FBQztBQUMzRCxPQUFPLEtBQUssRUFBRSxpQkFBaUIsRUFBRSxNQUFNLDZCQUE2QixDQUFDO0FBR3JFLE9BQU8sS0FBSyxFQUFFLFlBQVksRUFBRSxtQkFBbUIsRUFBRSxrQkFBa0IsRUFBRSxPQUFPLEVBQUUsTUFBTSxtQkFBbUIsQ0FBQztBQWN4Rzs7Ozs7O0dBTUc7QUFDSCxxQkFBYSxjQUFlLFlBQVcsbUJBQW1CO0lBQ3hELE9BQU8sQ0FBQyxTQUFTLENBQW9CO0lBQ3JDLE9BQU8sQ0FBQyxlQUFlLENBQXlCO0lBQ2hELE9BQU8sQ0FBQyxXQUFXLENBQTZCO0lBQ2hELE9BQU8sQ0FBQyxlQUFlLENBQWtCO0lBQ3pDLE9BQU8sQ0FBQyxJQUFJLENBQWM7SUFDMUIsT0FBTyxDQUFDLG9CQUFvQixDQUFvQjtJQUNoRCxPQUFPLENBQUMsV0FBVyxDQUFvQjtJQUV2QyxZQUFZLFdBQVcsR0FBRSxPQUFPLENBQUMsaUJBQWlCLENBQU0sRUFFdkQ7SUFFRDs7O09BR0c7SUFDSCxZQUFZLENBQUMsU0FBUyxFQUFFLFVBQVUsRUFBRSxHQUFHLElBQUksQ0FHMUM7SUFFRDs7O09BR0c7SUFDSCxXQUFXLENBQUMsUUFBUSxFQUFFLFVBQVUsR0FBRyxTQUFTLEdBQUcsSUFBSSxDQUdsRDtJQUVEOzs7T0FHRztJQUNILGNBQWMsQ0FBQyxJQUFJLEVBQUUsVUFBVSxHQUFHLElBQUksQ0FHckM7SUFFRDs7O09BR0c7SUFDSCxrQkFBa0IsQ0FBQyxJQUFJLEVBQUUsT0FBTyxHQUFHLElBQUksQ0FHdEM7SUFFRDs7O09BR0c7SUFDSCxPQUFPLENBQUMsSUFBSSxFQUFFLE1BQU0sR0FBRyxJQUFJLENBRzFCO0lBRUQ7OztPQUdHO0lBQ0gsdUJBQXVCLENBQUMsVUFBVSxFQUFFLFVBQVUsRUFBRSxHQUFHLElBQUksQ0FHdEQ7SUFFRDs7O09BR0c7SUFDSCxjQUFjLENBQUMsU0FBUyxFQUFFLE9BQU8sQ0FBQyxpQkFBaUIsQ0FBQyxHQUFHLElBQUksQ0FHMUQ7SUFFRCxjQUFjLElBQUksaUJBQWlCLENBRWxDO0lBRUQsWUFBWSxDQUFDLEtBQUssQ0FBQyxFQUFFLE9BQU8sR0FBRyxPQUFPLENBQUMsa0JBQWtCLENBQUMsQ0FRekQ7SUFFRCxrQkFBa0IsSUFBSSxZQUFZLEdBQUc7UUFBRSxLQUFLLEVBQUUsTUFBTSxDQUFBO0tBQUUsQ0FJckQ7SUFFRCwyQkFBMkIsSUFBSSxZQUFZLEdBQUc7UUFBRSxHQUFHLEVBQUUsTUFBTSxDQUFBO0tBQUUsQ0FPNUQ7SUFFRCx3QkFBd0IsQ0FBQyxLQUFLLEVBQUUsV0FBVyxFQUFFLElBQUksRUFBRSxVQUFVLEVBQUUsSUFBSSxFQUFFLE1BQU0sR0FBRyxLQUFLLE1BQU0sRUFBRSxDQUcxRjtJQUVELG9CQUFvQixDQUFDLElBQUksRUFBRSxVQUFVLEVBQUUsTUFBTSxFQUFFLFdBQVcsRUFBRSxLQUFLLEVBQUUsTUFBTSxFQUFFLElBQUksRUFBRSxNQUFNLEdBQUcsTUFBTSxDQUsvRjtJQUVELHFCQUFxQixJQUFJO1FBQUUsV0FBVyxFQUFFLFVBQVUsQ0FBQztRQUFDLFFBQVEsRUFBRSxVQUFVLENBQUE7S0FBRSxDQUt6RTtJQUVELGdDQUFnQyxDQUFDLEtBQUssRUFBRSxVQUFVLEdBQUcsT0FBTyxDQUFDLFVBQVUsR0FBRyxTQUFTLENBQUMsQ0FFbkY7SUFFRCx1QkFBdUIsSUFBSSxPQUFPLENBQUMsVUFBVSxFQUFFLENBQUMsQ0FFL0M7SUFFRCxhQUFhLENBQUMsS0FBSyxFQUFFLE9BQU8sRUFBRSxTQUFTLEVBQUUsVUFBVSxHQUFHLE9BQU8sQ0FBQyxPQUFPLENBQUMsQ0FFckU7SUFFRCxpQkFBaUIsQ0FBQyxLQUFLLEVBQUUsT0FBTyxFQUFFLFVBQVUsRUFBRSxVQUFVLEVBQUUsR0FBRyxPQUFPLENBQUMsVUFBVSxFQUFFLENBQUMsQ0FHakY7SUFFRCx1QkFBdUIsQ0FBQyxLQUFLLENBQUMsRUFBRSxPQUFPLEdBQUcsT0FBTyxDQUFDLE9BQU8sQ0FBQyxDQUV6RDtDQUNGIn0=
|
|
@@ -1 +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,
|
|
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"}
|
|
@@ -1,6 +1,5 @@
|
|
|
1
1
|
import { SlotNumber } from '@aztec/foundation/branded-types';
|
|
2
2
|
import { getEpochAtSlot, getSlotAtTimestamp, getTimestampRangeForEpoch } from '@aztec/stdlib/epoch-helpers';
|
|
3
|
-
import { PROPOSER_PIPELINING_SLOT_OFFSET } from '../epoch_cache.js';
|
|
4
3
|
/** Default L1 constants for testing. */ const DEFAULT_L1_CONSTANTS = {
|
|
5
4
|
l1StartBlock: 0n,
|
|
6
5
|
l1GenesisTime: 0n,
|
|
@@ -25,7 +24,6 @@ import { PROPOSER_PIPELINING_SLOT_OFFSET } from '../epoch_cache.js';
|
|
|
25
24
|
seed = 0n;
|
|
26
25
|
registeredValidators = [];
|
|
27
26
|
l1Constants;
|
|
28
|
-
proposerPipeliningEnabled = false;
|
|
29
27
|
constructor(l1Constants = {}){
|
|
30
28
|
this.l1Constants = {
|
|
31
29
|
...DEFAULT_L1_CONSTANTS,
|
|
@@ -87,9 +85,6 @@ import { PROPOSER_PIPELINING_SLOT_OFFSET } from '../epoch_cache.js';
|
|
|
87
85
|
getL1Constants() {
|
|
88
86
|
return this.l1Constants;
|
|
89
87
|
}
|
|
90
|
-
setProposerPipeliningEnabled(enabled) {
|
|
91
|
-
this.proposerPipeliningEnabled = enabled;
|
|
92
|
-
}
|
|
93
88
|
getCommittee(_slot) {
|
|
94
89
|
const epoch = getEpochAtSlot(this.currentSlot, this.l1Constants);
|
|
95
90
|
return Promise.resolve({
|
|
@@ -99,52 +94,27 @@ import { PROPOSER_PIPELINING_SLOT_OFFSET } from '../epoch_cache.js';
|
|
|
99
94
|
isEscapeHatchOpen: this.escapeHatchOpen
|
|
100
95
|
});
|
|
101
96
|
}
|
|
102
|
-
getSlotNow() {
|
|
103
|
-
return this.currentSlot;
|
|
104
|
-
}
|
|
105
|
-
getTargetSlot() {
|
|
106
|
-
return this.proposerPipeliningEnabled ? SlotNumber(this.currentSlot + PROPOSER_PIPELINING_SLOT_OFFSET) : this.currentSlot;
|
|
107
|
-
}
|
|
108
|
-
getEpochNow() {
|
|
109
|
-
return getEpochAtSlot(this.currentSlot, this.l1Constants);
|
|
110
|
-
}
|
|
111
|
-
getTargetEpoch() {
|
|
112
|
-
return getEpochAtSlot(this.getTargetSlot(), this.l1Constants);
|
|
113
|
-
}
|
|
114
|
-
isProposerPipeliningEnabled() {
|
|
115
|
-
return this.proposerPipeliningEnabled;
|
|
116
|
-
}
|
|
117
97
|
getEpochAndSlotNow() {
|
|
118
|
-
const
|
|
119
|
-
const ts = getTimestampRangeForEpoch(
|
|
98
|
+
const epoch = getEpochAtSlot(this.currentSlot, this.l1Constants);
|
|
99
|
+
const ts = getTimestampRangeForEpoch(epoch, this.l1Constants)[0];
|
|
120
100
|
return {
|
|
121
|
-
epoch
|
|
101
|
+
epoch,
|
|
122
102
|
slot: this.currentSlot,
|
|
123
103
|
ts,
|
|
124
104
|
nowMs: ts * 1000n
|
|
125
105
|
};
|
|
126
106
|
}
|
|
127
107
|
getEpochAndSlotInNextL1Slot() {
|
|
128
|
-
const
|
|
129
|
-
const nextSlotTs =
|
|
108
|
+
const now = getTimestampRangeForEpoch(getEpochAtSlot(this.currentSlot, this.l1Constants), this.l1Constants)[0];
|
|
109
|
+
const nextSlotTs = now + BigInt(this.l1Constants.ethereumSlotDuration);
|
|
130
110
|
const nextSlot = getSlotAtTimestamp(nextSlotTs, this.l1Constants);
|
|
131
|
-
const
|
|
132
|
-
const ts = getTimestampRangeForEpoch(
|
|
111
|
+
const epoch = getEpochAtSlot(nextSlot, this.l1Constants);
|
|
112
|
+
const ts = getTimestampRangeForEpoch(epoch, this.l1Constants)[0];
|
|
133
113
|
return {
|
|
134
|
-
epoch
|
|
114
|
+
epoch,
|
|
135
115
|
slot: nextSlot,
|
|
136
116
|
ts,
|
|
137
|
-
|
|
138
|
-
};
|
|
139
|
-
}
|
|
140
|
-
getTargetEpochAndSlotInNextL1Slot() {
|
|
141
|
-
const result = this.getEpochAndSlotInNextL1Slot();
|
|
142
|
-
const offset = this.isProposerPipeliningEnabled() ? PROPOSER_PIPELINING_SLOT_OFFSET : 0;
|
|
143
|
-
const targetSlot = SlotNumber(result.slot + offset);
|
|
144
|
-
return {
|
|
145
|
-
...result,
|
|
146
|
-
slot: targetSlot,
|
|
147
|
-
epoch: getEpochAtSlot(targetSlot, this.l1Constants)
|
|
117
|
+
now
|
|
148
118
|
};
|
|
149
119
|
}
|
|
150
120
|
getProposerIndexEncoding(epoch, slot, seed) {
|
|
@@ -158,19 +128,9 @@ import { PROPOSER_PIPELINING_SLOT_OFFSET } from '../epoch_cache.js';
|
|
|
158
128
|
return BigInt(slot) % size;
|
|
159
129
|
}
|
|
160
130
|
getCurrentAndNextSlot() {
|
|
161
|
-
const currentSlot = this.getSlotNow();
|
|
162
|
-
const next = this.getEpochAndSlotInNextL1Slot();
|
|
163
|
-
return {
|
|
164
|
-
currentSlot,
|
|
165
|
-
nextSlot: next.slot
|
|
166
|
-
};
|
|
167
|
-
}
|
|
168
|
-
getTargetAndNextSlot() {
|
|
169
|
-
const targetSlot = this.getTargetSlot();
|
|
170
|
-
const next = this.getTargetEpochAndSlotInNextL1Slot();
|
|
171
131
|
return {
|
|
172
|
-
|
|
173
|
-
nextSlot:
|
|
132
|
+
currentSlot: this.currentSlot,
|
|
133
|
+
nextSlot: SlotNumber(this.currentSlot + 1)
|
|
174
134
|
};
|
|
175
135
|
}
|
|
176
136
|
getProposerAttesterAddressInSlot(_slot) {
|
|
@@ -186,9 +146,6 @@ import { PROPOSER_PIPELINING_SLOT_OFFSET } from '../epoch_cache.js';
|
|
|
186
146
|
const committeeSet = new Set(this.committee.map((v)=>v.toString()));
|
|
187
147
|
return Promise.resolve(validators.filter((v)=>committeeSet.has(v.toString())));
|
|
188
148
|
}
|
|
189
|
-
isEscapeHatchOpen(_epoch) {
|
|
190
|
-
return Promise.resolve(this.escapeHatchOpen);
|
|
191
|
-
}
|
|
192
149
|
isEscapeHatchOpenAtSlot(_slot) {
|
|
193
150
|
return Promise.resolve(this.escapeHatchOpen);
|
|
194
151
|
}
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@aztec/epoch-cache",
|
|
3
|
-
"version": "0.0.1-commit.
|
|
3
|
+
"version": "0.0.1-commit.8c0b8ff",
|
|
4
4
|
"type": "module",
|
|
5
5
|
"exports": {
|
|
6
6
|
".": "./dest/index.js",
|
|
@@ -26,10 +26,11 @@
|
|
|
26
26
|
"../package.common.json"
|
|
27
27
|
],
|
|
28
28
|
"dependencies": {
|
|
29
|
-
"@aztec/ethereum": "0.0.1-commit.
|
|
30
|
-
"@aztec/foundation": "0.0.1-commit.
|
|
31
|
-
"@aztec/l1-artifacts": "0.0.1-commit.
|
|
32
|
-
"@aztec/stdlib": "0.0.1-commit.
|
|
29
|
+
"@aztec/ethereum": "0.0.1-commit.8c0b8ff",
|
|
30
|
+
"@aztec/foundation": "0.0.1-commit.8c0b8ff",
|
|
31
|
+
"@aztec/l1-artifacts": "0.0.1-commit.8c0b8ff",
|
|
32
|
+
"@aztec/stdlib": "0.0.1-commit.8c0b8ff",
|
|
33
|
+
"@viem/anvil": "^0.0.10",
|
|
33
34
|
"dotenv": "^16.0.3",
|
|
34
35
|
"get-port": "^7.1.0",
|
|
35
36
|
"jest-mock-extended": "^4.0.0",
|
package/src/config.ts
CHANGED
|
@@ -1,17 +1,11 @@
|
|
|
1
1
|
import { type L1ContractsConfig, getL1ContractsConfigEnvVars } from '@aztec/ethereum/config';
|
|
2
2
|
import { type L1ReaderConfig, getL1ReaderConfigFromEnv } from '@aztec/ethereum/l1-reader';
|
|
3
|
-
import { type PipelineConfig, getPipelineConfigEnvVars } from '@aztec/stdlib/config';
|
|
4
3
|
|
|
5
4
|
export type EpochCacheConfig = Pick<
|
|
6
|
-
L1ReaderConfig & L1ContractsConfig
|
|
7
|
-
| '
|
|
8
|
-
| 'l1ChainId'
|
|
9
|
-
| 'viemPollingIntervalMS'
|
|
10
|
-
| 'ethereumSlotDuration'
|
|
11
|
-
| 'l1HttpTimeoutMS'
|
|
12
|
-
| 'enableProposerPipelining'
|
|
5
|
+
L1ReaderConfig & L1ContractsConfig,
|
|
6
|
+
'l1RpcUrls' | 'l1ChainId' | 'viemPollingIntervalMS' | 'l1HttpTimeoutMS' | 'ethereumSlotDuration'
|
|
13
7
|
>;
|
|
14
8
|
|
|
15
9
|
export function getEpochCacheConfigEnvVars(): EpochCacheConfig {
|
|
16
|
-
return { ...getL1ReaderConfigFromEnv(), ...getL1ContractsConfigEnvVars()
|
|
10
|
+
return { ...getL1ReaderConfigFromEnv(), ...getL1ContractsConfigEnvVars() };
|
|
17
11
|
}
|
package/src/epoch_cache.ts
CHANGED
|
@@ -9,22 +9,20 @@ import {
|
|
|
9
9
|
type L1RollupConstants,
|
|
10
10
|
getEpochAtSlot,
|
|
11
11
|
getEpochNumberAtTimestamp,
|
|
12
|
+
getNextL1SlotTimestamp,
|
|
12
13
|
getSlotAtTimestamp,
|
|
13
14
|
getSlotRangeForEpoch,
|
|
14
15
|
getTimestampForSlot,
|
|
16
|
+
getTimestampRangeForEpoch,
|
|
15
17
|
} from '@aztec/stdlib/epoch-helpers';
|
|
16
18
|
|
|
17
19
|
import { createPublicClient, encodeAbiParameters, keccak256 } from 'viem';
|
|
18
20
|
|
|
19
21
|
import { type EpochCacheConfig, getEpochCacheConfigEnvVars } from './config.js';
|
|
20
22
|
|
|
21
|
-
/** When proposer pipelining is enabled, the proposer builds one slot ahead. */
|
|
22
|
-
export const PROPOSER_PIPELINING_SLOT_OFFSET = 1;
|
|
23
|
-
|
|
24
|
-
/** Flat return type for compound epoch/slot getters. */
|
|
25
23
|
export type EpochAndSlot = {
|
|
26
|
-
slot: SlotNumber;
|
|
27
24
|
epoch: EpochNumber;
|
|
25
|
+
slot: SlotNumber;
|
|
28
26
|
ts: bigint;
|
|
29
27
|
};
|
|
30
28
|
|
|
@@ -40,21 +38,11 @@ export type SlotTag = 'now' | 'next' | SlotNumber;
|
|
|
40
38
|
|
|
41
39
|
export interface EpochCacheInterface {
|
|
42
40
|
getCommittee(slot: SlotTag | undefined): Promise<EpochCommitteeInfo>;
|
|
43
|
-
getSlotNow(): SlotNumber;
|
|
44
|
-
getTargetSlot(): SlotNumber;
|
|
45
|
-
getEpochNow(): EpochNumber;
|
|
46
|
-
getTargetEpoch(): EpochNumber;
|
|
47
41
|
getEpochAndSlotNow(): EpochAndSlot & { nowMs: bigint };
|
|
48
|
-
getEpochAndSlotInNextL1Slot(): EpochAndSlot & {
|
|
49
|
-
/** Returns epoch/slot info for the next L1 slot with pipeline offset applied. */
|
|
50
|
-
getTargetEpochAndSlotInNextL1Slot(): EpochAndSlot & { nowSeconds: bigint };
|
|
51
|
-
isProposerPipeliningEnabled(): boolean;
|
|
52
|
-
isEscapeHatchOpen(epoch: EpochNumber): Promise<boolean>;
|
|
53
|
-
isEscapeHatchOpenAtSlot(slot: SlotTag): Promise<boolean>;
|
|
42
|
+
getEpochAndSlotInNextL1Slot(): EpochAndSlot & { now: bigint };
|
|
54
43
|
getProposerIndexEncoding(epoch: EpochNumber, slot: SlotNumber, seed: bigint): `0x${string}`;
|
|
55
44
|
computeProposerIndex(slot: SlotNumber, epoch: EpochNumber, seed: bigint, size: bigint): bigint;
|
|
56
45
|
getCurrentAndNextSlot(): { currentSlot: SlotNumber; nextSlot: SlotNumber };
|
|
57
|
-
getTargetAndNextSlot(): { targetSlot: SlotNumber; nextSlot: SlotNumber };
|
|
58
46
|
getProposerAttesterAddressInSlot(slot: SlotNumber): Promise<EthAddress | undefined>;
|
|
59
47
|
getRegisteredValidators(): Promise<EthAddress[]>;
|
|
60
48
|
isInCommittee(slot: SlotTag, validator: EthAddress): Promise<boolean>;
|
|
@@ -78,8 +66,6 @@ export class EpochCache implements EpochCacheInterface {
|
|
|
78
66
|
private lastValidatorRefresh = 0;
|
|
79
67
|
private readonly log: Logger = createLogger('epoch-cache');
|
|
80
68
|
|
|
81
|
-
protected enableProposerPipelining: boolean;
|
|
82
|
-
|
|
83
69
|
constructor(
|
|
84
70
|
private rollup: RollupContract,
|
|
85
71
|
private readonly l1constants: L1RollupConstants & {
|
|
@@ -87,12 +73,10 @@ export class EpochCache implements EpochCacheInterface {
|
|
|
87
73
|
lagInEpochsForRandao: number;
|
|
88
74
|
},
|
|
89
75
|
private readonly dateProvider: DateProvider = new DateProvider(),
|
|
90
|
-
protected readonly config = { cacheSize: 12, validatorRefreshIntervalSeconds: 60
|
|
76
|
+
protected readonly config = { cacheSize: 12, validatorRefreshIntervalSeconds: 60 },
|
|
91
77
|
) {
|
|
92
|
-
this.enableProposerPipelining = this.config.enableProposerPipelining;
|
|
93
78
|
this.log.debug(`Initialized EpochCache`, {
|
|
94
79
|
l1constants,
|
|
95
|
-
enableProposerPipelining: this.enableProposerPipelining,
|
|
96
80
|
});
|
|
97
81
|
}
|
|
98
82
|
|
|
@@ -152,77 +136,37 @@ export class EpochCache implements EpochCacheInterface {
|
|
|
152
136
|
rollupManaLimit: Number(rollupManaLimit),
|
|
153
137
|
};
|
|
154
138
|
|
|
155
|
-
return new EpochCache(rollup, l1RollupConstants, deps.dateProvider
|
|
156
|
-
cacheSize: 12,
|
|
157
|
-
validatorRefreshIntervalSeconds: 60,
|
|
158
|
-
enableProposerPipelining: config.enableProposerPipelining,
|
|
159
|
-
});
|
|
139
|
+
return new EpochCache(rollup, l1RollupConstants, deps.dateProvider);
|
|
160
140
|
}
|
|
161
141
|
|
|
162
142
|
public getL1Constants(): L1RollupConstants {
|
|
163
143
|
return this.l1constants;
|
|
164
144
|
}
|
|
165
145
|
|
|
166
|
-
public isProposerPipeliningEnabled(): boolean {
|
|
167
|
-
return this.enableProposerPipelining;
|
|
168
|
-
}
|
|
169
|
-
|
|
170
|
-
public getSlotNow(): SlotNumber {
|
|
171
|
-
return this.getEpochAndSlotNow().slot;
|
|
172
|
-
}
|
|
173
|
-
|
|
174
|
-
public getTargetSlot(): SlotNumber {
|
|
175
|
-
const slotNow = this.getSlotNow();
|
|
176
|
-
const offset = this.isProposerPipeliningEnabled() ? PROPOSER_PIPELINING_SLOT_OFFSET : 0;
|
|
177
|
-
return SlotNumber(slotNow + offset);
|
|
178
|
-
}
|
|
179
|
-
|
|
180
|
-
public getEpochNow(): EpochNumber {
|
|
181
|
-
return this.getEpochAndSlotNow().epoch;
|
|
182
|
-
}
|
|
183
|
-
|
|
184
|
-
public getTargetEpoch(): EpochNumber {
|
|
185
|
-
return getEpochAtSlot(this.getTargetSlot(), this.l1constants);
|
|
186
|
-
}
|
|
187
|
-
|
|
188
146
|
public getEpochAndSlotNow(): EpochAndSlot & { nowMs: bigint } {
|
|
189
147
|
const nowMs = BigInt(this.dateProvider.now());
|
|
190
148
|
const nowSeconds = nowMs / 1000n;
|
|
191
149
|
return { ...this.getEpochAndSlotAtTimestamp(nowSeconds), nowMs };
|
|
192
150
|
}
|
|
193
151
|
|
|
194
|
-
public nowInSeconds(): bigint {
|
|
195
|
-
return BigInt(Math.floor(this.dateProvider.now() / 1000));
|
|
196
|
-
}
|
|
197
|
-
|
|
198
152
|
private getEpochAndSlotAtSlot(slot: SlotNumber): EpochAndSlot {
|
|
199
|
-
|
|
200
|
-
|
|
201
|
-
|
|
202
|
-
public getEpochAndSlotInNextL1Slot(): EpochAndSlot & { nowSeconds: bigint } {
|
|
203
|
-
const nowSeconds = this.nowInSeconds();
|
|
204
|
-
const nextSlotTs = nowSeconds + BigInt(this.l1constants.ethereumSlotDuration);
|
|
205
|
-
return { ...this.getEpochAndSlotAtTimestamp(nextSlotTs), nowSeconds };
|
|
153
|
+
const epoch = getEpochAtSlot(slot, this.l1constants);
|
|
154
|
+
const ts = getTimestampRangeForEpoch(epoch, this.l1constants)[0];
|
|
155
|
+
return { epoch, ts, slot };
|
|
206
156
|
}
|
|
207
157
|
|
|
208
|
-
public
|
|
209
|
-
|
|
210
|
-
|
|
211
|
-
}
|
|
212
|
-
|
|
213
|
-
const result = this.getEpochAndSlotInNextL1Slot();
|
|
214
|
-
const offset = PROPOSER_PIPELINING_SLOT_OFFSET;
|
|
215
|
-
const targetSlot = SlotNumber(result.slot + offset);
|
|
216
|
-
return { ...result, slot: targetSlot, epoch: getEpochAtSlot(targetSlot, this.l1constants) };
|
|
158
|
+
public getEpochAndSlotInNextL1Slot(): EpochAndSlot & { now: bigint } {
|
|
159
|
+
const now = BigInt(this.dateProvider.nowInSeconds());
|
|
160
|
+
const nextSlotTs = getNextL1SlotTimestamp(Number(now), this.l1constants);
|
|
161
|
+
return { ...this.getEpochAndSlotAtTimestamp(nextSlotTs), now };
|
|
217
162
|
}
|
|
218
163
|
|
|
219
164
|
private getEpochAndSlotAtTimestamp(ts: bigint): EpochAndSlot {
|
|
220
165
|
const slot = getSlotAtTimestamp(ts, this.l1constants);
|
|
221
|
-
const epoch = getEpochNumberAtTimestamp(ts, this.l1constants);
|
|
222
166
|
return {
|
|
223
|
-
|
|
224
|
-
epoch,
|
|
167
|
+
epoch: getEpochNumberAtTimestamp(ts, this.l1constants),
|
|
225
168
|
ts: getTimestampForSlot(slot, this.l1constants),
|
|
169
|
+
slot,
|
|
226
170
|
};
|
|
227
171
|
}
|
|
228
172
|
|
|
@@ -255,7 +199,7 @@ export class EpochCache implements EpochCacheInterface {
|
|
|
255
199
|
public async isEscapeHatchOpenAtSlot(slot: SlotTag = 'now'): Promise<boolean> {
|
|
256
200
|
const epoch =
|
|
257
201
|
slot === 'now'
|
|
258
|
-
? this.
|
|
202
|
+
? this.getEpochAndSlotNow().epoch
|
|
259
203
|
: slot === 'next'
|
|
260
204
|
? this.getEpochAndSlotInNextL1Slot().epoch
|
|
261
205
|
: getEpochAtSlot(slot, this.l1constants);
|
|
@@ -290,7 +234,7 @@ export class EpochCache implements EpochCacheInterface {
|
|
|
290
234
|
return epochData;
|
|
291
235
|
}
|
|
292
236
|
|
|
293
|
-
private getEpochAndTimestamp(slot: SlotTag = 'now')
|
|
237
|
+
private getEpochAndTimestamp(slot: SlotTag = 'now') {
|
|
294
238
|
if (slot === 'now') {
|
|
295
239
|
return this.getEpochAndSlotNow();
|
|
296
240
|
} else if (slot === 'next') {
|
|
@@ -340,24 +284,13 @@ export class EpochCache implements EpochCacheInterface {
|
|
|
340
284
|
return BigInt(keccak256(this.getProposerIndexEncoding(epoch, slot, seed))) % size;
|
|
341
285
|
}
|
|
342
286
|
|
|
343
|
-
/** Returns the current and next L2 slot
|
|
287
|
+
/** Returns the current and next L2 slot numbers. */
|
|
344
288
|
public getCurrentAndNextSlot(): { currentSlot: SlotNumber; nextSlot: SlotNumber } {
|
|
345
|
-
const
|
|
289
|
+
const current = this.getEpochAndSlotNow();
|
|
346
290
|
const next = this.getEpochAndSlotInNextL1Slot();
|
|
347
291
|
|
|
348
292
|
return {
|
|
349
|
-
currentSlot,
|
|
350
|
-
nextSlot: next.slot,
|
|
351
|
-
};
|
|
352
|
-
}
|
|
353
|
-
|
|
354
|
-
/** Returns the taget and next L2 slot in the next L1 slot */
|
|
355
|
-
public getTargetAndNextSlot(): { targetSlot: SlotNumber; nextSlot: SlotNumber } {
|
|
356
|
-
const targetSlot = this.getTargetSlot();
|
|
357
|
-
const next = this.getTargetEpochAndSlotInNextL1Slot();
|
|
358
|
-
|
|
359
|
-
return {
|
|
360
|
-
targetSlot,
|
|
293
|
+
currentSlot: current.slot,
|
|
361
294
|
nextSlot: next.slot,
|
|
362
295
|
};
|
|
363
296
|
}
|
|
@@ -440,10 +373,11 @@ export class EpochCache implements EpochCacheInterface {
|
|
|
440
373
|
async getRegisteredValidators(): Promise<EthAddress[]> {
|
|
441
374
|
const validatorRefreshIntervalMs = this.config.validatorRefreshIntervalSeconds * 1000;
|
|
442
375
|
const validatorRefreshTime = this.lastValidatorRefresh + validatorRefreshIntervalMs;
|
|
443
|
-
|
|
444
|
-
|
|
376
|
+
const now = this.dateProvider.now();
|
|
377
|
+
if (validatorRefreshTime < now) {
|
|
378
|
+
const currentSet = await this.rollup.getAttesters(BigInt(Math.floor(now / 1000)));
|
|
445
379
|
this.allValidators = new Set(currentSet.map(v => v.toString()));
|
|
446
|
-
this.lastValidatorRefresh =
|
|
380
|
+
this.lastValidatorRefresh = now;
|
|
447
381
|
}
|
|
448
382
|
return Array.from(this.allValidators.keys()).map(v => EthAddress.fromString(v));
|
|
449
383
|
}
|
|
@@ -3,13 +3,7 @@ import { EthAddress } from '@aztec/foundation/eth-address';
|
|
|
3
3
|
import type { L1RollupConstants } from '@aztec/stdlib/epoch-helpers';
|
|
4
4
|
import { getEpochAtSlot, getSlotAtTimestamp, getTimestampRangeForEpoch } from '@aztec/stdlib/epoch-helpers';
|
|
5
5
|
|
|
6
|
-
import {
|
|
7
|
-
type EpochAndSlot,
|
|
8
|
-
type EpochCacheInterface,
|
|
9
|
-
type EpochCommitteeInfo,
|
|
10
|
-
PROPOSER_PIPELINING_SLOT_OFFSET,
|
|
11
|
-
type SlotTag,
|
|
12
|
-
} from '../epoch_cache.js';
|
|
6
|
+
import type { EpochAndSlot, EpochCacheInterface, EpochCommitteeInfo, SlotTag } from '../epoch_cache.js';
|
|
13
7
|
|
|
14
8
|
/** Default L1 constants for testing. */
|
|
15
9
|
const DEFAULT_L1_CONSTANTS: L1RollupConstants = {
|
|
@@ -38,7 +32,6 @@ export class TestEpochCache implements EpochCacheInterface {
|
|
|
38
32
|
private seed: bigint = 0n;
|
|
39
33
|
private registeredValidators: EthAddress[] = [];
|
|
40
34
|
private l1Constants: L1RollupConstants;
|
|
41
|
-
private proposerPipeliningEnabled = false;
|
|
42
35
|
|
|
43
36
|
constructor(l1Constants: Partial<L1RollupConstants> = {}) {
|
|
44
37
|
this.l1Constants = { ...DEFAULT_L1_CONSTANTS, ...l1Constants };
|
|
@@ -111,10 +104,6 @@ export class TestEpochCache implements EpochCacheInterface {
|
|
|
111
104
|
return this.l1Constants;
|
|
112
105
|
}
|
|
113
106
|
|
|
114
|
-
setProposerPipeliningEnabled(enabled: boolean): void {
|
|
115
|
-
this.proposerPipeliningEnabled = enabled;
|
|
116
|
-
}
|
|
117
|
-
|
|
118
107
|
getCommittee(_slot?: SlotTag): Promise<EpochCommitteeInfo> {
|
|
119
108
|
const epoch = getEpochAtSlot(this.currentSlot, this.l1Constants);
|
|
120
109
|
return Promise.resolve({
|
|
@@ -125,58 +114,19 @@ export class TestEpochCache implements EpochCacheInterface {
|
|
|
125
114
|
});
|
|
126
115
|
}
|
|
127
116
|
|
|
128
|
-
getSlotNow(): SlotNumber {
|
|
129
|
-
return this.currentSlot;
|
|
130
|
-
}
|
|
131
|
-
|
|
132
|
-
getTargetSlot(): SlotNumber {
|
|
133
|
-
return this.proposerPipeliningEnabled
|
|
134
|
-
? SlotNumber(this.currentSlot + PROPOSER_PIPELINING_SLOT_OFFSET)
|
|
135
|
-
: this.currentSlot;
|
|
136
|
-
}
|
|
137
|
-
|
|
138
|
-
getEpochNow(): EpochNumber {
|
|
139
|
-
return getEpochAtSlot(this.currentSlot, this.l1Constants);
|
|
140
|
-
}
|
|
141
|
-
|
|
142
|
-
getTargetEpoch(): EpochNumber {
|
|
143
|
-
return getEpochAtSlot(this.getTargetSlot(), this.l1Constants);
|
|
144
|
-
}
|
|
145
|
-
|
|
146
|
-
isProposerPipeliningEnabled(): boolean {
|
|
147
|
-
return this.proposerPipeliningEnabled;
|
|
148
|
-
}
|
|
149
|
-
|
|
150
117
|
getEpochAndSlotNow(): EpochAndSlot & { nowMs: bigint } {
|
|
151
|
-
const
|
|
152
|
-
const ts = getTimestampRangeForEpoch(
|
|
153
|
-
return {
|
|
154
|
-
epoch: epochNow,
|
|
155
|
-
slot: this.currentSlot,
|
|
156
|
-
ts,
|
|
157
|
-
nowMs: ts * 1000n,
|
|
158
|
-
};
|
|
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 };
|
|
159
121
|
}
|
|
160
122
|
|
|
161
|
-
getEpochAndSlotInNextL1Slot(): EpochAndSlot & {
|
|
162
|
-
const
|
|
163
|
-
const nextSlotTs =
|
|
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);
|
|
164
126
|
const nextSlot = getSlotAtTimestamp(nextSlotTs, this.l1Constants);
|
|
165
|
-
const
|
|
166
|
-
const ts = getTimestampRangeForEpoch(
|
|
167
|
-
return {
|
|
168
|
-
epoch: epochNow,
|
|
169
|
-
slot: nextSlot,
|
|
170
|
-
ts,
|
|
171
|
-
nowSeconds: nowTs,
|
|
172
|
-
};
|
|
173
|
-
}
|
|
174
|
-
|
|
175
|
-
getTargetEpochAndSlotInNextL1Slot(): EpochAndSlot & { nowSeconds: bigint } {
|
|
176
|
-
const result = this.getEpochAndSlotInNextL1Slot();
|
|
177
|
-
const offset = this.isProposerPipeliningEnabled() ? PROPOSER_PIPELINING_SLOT_OFFSET : 0;
|
|
178
|
-
const targetSlot = SlotNumber(result.slot + offset);
|
|
179
|
-
return { ...result, slot: targetSlot, epoch: getEpochAtSlot(targetSlot, this.l1Constants) };
|
|
127
|
+
const epoch = getEpochAtSlot(nextSlot, this.l1Constants);
|
|
128
|
+
const ts = getTimestampRangeForEpoch(epoch, this.l1Constants)[0];
|
|
129
|
+
return { epoch, slot: nextSlot, ts, now };
|
|
180
130
|
}
|
|
181
131
|
|
|
182
132
|
getProposerIndexEncoding(epoch: EpochNumber, slot: SlotNumber, seed: bigint): `0x${string}` {
|
|
@@ -192,22 +142,9 @@ export class TestEpochCache implements EpochCacheInterface {
|
|
|
192
142
|
}
|
|
193
143
|
|
|
194
144
|
getCurrentAndNextSlot(): { currentSlot: SlotNumber; nextSlot: SlotNumber } {
|
|
195
|
-
const currentSlot = this.getSlotNow();
|
|
196
|
-
const next = this.getEpochAndSlotInNextL1Slot();
|
|
197
|
-
|
|
198
|
-
return {
|
|
199
|
-
currentSlot,
|
|
200
|
-
nextSlot: next.slot,
|
|
201
|
-
};
|
|
202
|
-
}
|
|
203
|
-
|
|
204
|
-
getTargetAndNextSlot(): { targetSlot: SlotNumber; nextSlot: SlotNumber } {
|
|
205
|
-
const targetSlot = this.getTargetSlot();
|
|
206
|
-
const next = this.getTargetEpochAndSlotInNextL1Slot();
|
|
207
|
-
|
|
208
145
|
return {
|
|
209
|
-
|
|
210
|
-
nextSlot:
|
|
146
|
+
currentSlot: this.currentSlot,
|
|
147
|
+
nextSlot: SlotNumber(this.currentSlot + 1),
|
|
211
148
|
};
|
|
212
149
|
}
|
|
213
150
|
|
|
@@ -228,10 +165,6 @@ export class TestEpochCache implements EpochCacheInterface {
|
|
|
228
165
|
return Promise.resolve(validators.filter(v => committeeSet.has(v.toString())));
|
|
229
166
|
}
|
|
230
167
|
|
|
231
|
-
isEscapeHatchOpen(_epoch: EpochNumber): Promise<boolean> {
|
|
232
|
-
return Promise.resolve(this.escapeHatchOpen);
|
|
233
|
-
}
|
|
234
|
-
|
|
235
168
|
isEscapeHatchOpenAtSlot(_slot?: SlotTag): Promise<boolean> {
|
|
236
169
|
return Promise.resolve(this.escapeHatchOpen);
|
|
237
170
|
}
|