@aztec/epoch-cache 5.0.0-private.20260318 → 5.0.0-private.20260319
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 +3 -2
- package/dest/config.d.ts.map +1 -1
- package/dest/config.js +3 -1
- package/dest/epoch_cache.d.ts +39 -5
- package/dest/epoch_cache.d.ts.map +1 -1
- package/dest/epoch_cache.js +64 -21
- package/dest/test/test_epoch_cache.d.ts +18 -3
- package/dest/test/test_epoch_cache.d.ts.map +1 -1
- package/dest/test/test_epoch_cache.js +54 -11
- package/package.json +5 -5
- package/src/config.ts +9 -3
- package/src/epoch_cache.ts +83 -19
- package/src/test/test_epoch_cache.ts +79 -12
package/dest/config.d.ts
CHANGED
|
@@ -1,5 +1,6 @@
|
|
|
1
1
|
import { type L1ContractsConfig } from '@aztec/ethereum/config';
|
|
2
2
|
import { type L1ReaderConfig } from '@aztec/ethereum/l1-reader';
|
|
3
|
-
|
|
3
|
+
import { type PipelineConfig } from '@aztec/stdlib/config';
|
|
4
|
+
export type EpochCacheConfig = Pick<L1ReaderConfig & L1ContractsConfig & PipelineConfig, 'l1RpcUrls' | 'l1ChainId' | 'viemPollingIntervalMS' | 'ethereumSlotDuration' | 'l1HttpTimeoutMS' | 'enableProposerPipelining'>;
|
|
4
5
|
export declare function getEpochCacheConfigEnvVars(): EpochCacheConfig;
|
|
5
|
-
//# sourceMappingURL=data:application/json;base64,
|
|
6
|
+
//# sourceMappingURL=data:application/json;base64,eyJ2ZXJzaW9uIjozLCJmaWxlIjoiY29uZmlnLmQudHMiLCJzb3VyY2VSb290IjoiIiwic291cmNlcyI6WyIuLi9zcmMvY29uZmlnLnRzIl0sIm5hbWVzIjpbXSwibWFwcGluZ3MiOiJBQUFBLE9BQU8sRUFBRSxLQUFLLGlCQUFpQixFQUErQixNQUFNLHdCQUF3QixDQUFDO0FBQzdGLE9BQU8sRUFBRSxLQUFLLGNBQWMsRUFBNEIsTUFBTSwyQkFBMkIsQ0FBQztBQUMxRixPQUFPLEVBQUUsS0FBSyxjQUFjLEVBQTRCLE1BQU0sc0JBQXNCLENBQUM7QUFFckYsTUFBTSxNQUFNLGdCQUFnQixHQUFHLElBQUksQ0FDakMsY0FBYyxHQUFHLGlCQUFpQixHQUFHLGNBQWMsRUFDakQsV0FBVyxHQUNYLFdBQVcsR0FDWCx1QkFBdUIsR0FDdkIsc0JBQXNCLEdBQ3RCLGlCQUFpQixHQUNqQiwwQkFBMEIsQ0FDN0IsQ0FBQztBQUVGLHdCQUFnQiwwQkFBMEIsSUFBSSxnQkFBZ0IsQ0FFN0QifQ==
|
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;AAC1F,OAAO,EAAE,KAAK,cAAc,EAA4B,MAAM,sBAAsB,CAAC;AAErF,MAAM,MAAM,gBAAgB,GAAG,IAAI,CACjC,cAAc,GAAG,iBAAiB,GAAG,cAAc,EACjD,WAAW,GACX,WAAW,GACX,uBAAuB,GACvB,sBAAsB,GACtB,iBAAiB,GACjB,0BAA0B,CAC7B,CAAC;AAEF,wBAAgB,0BAA0B,IAAI,gBAAgB,CAE7D"}
|
package/dest/config.js
CHANGED
|
@@ -1,8 +1,10 @@
|
|
|
1
1
|
import { getL1ContractsConfigEnvVars } from '@aztec/ethereum/config';
|
|
2
2
|
import { getL1ReaderConfigFromEnv } from '@aztec/ethereum/l1-reader';
|
|
3
|
+
import { getPipelineConfigEnvVars } from '@aztec/stdlib/config';
|
|
3
4
|
export function getEpochCacheConfigEnvVars() {
|
|
4
5
|
return {
|
|
5
6
|
...getL1ReaderConfigFromEnv(),
|
|
6
|
-
...getL1ContractsConfigEnvVars()
|
|
7
|
+
...getL1ContractsConfigEnvVars(),
|
|
8
|
+
...getPipelineConfigEnvVars()
|
|
7
9
|
};
|
|
8
10
|
}
|
package/dest/epoch_cache.d.ts
CHANGED
|
@@ -4,9 +4,12 @@ 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. */
|
|
7
10
|
export type EpochAndSlot = {
|
|
8
|
-
epoch: EpochNumber;
|
|
9
11
|
slot: SlotNumber;
|
|
12
|
+
epoch: EpochNumber;
|
|
10
13
|
ts: bigint;
|
|
11
14
|
};
|
|
12
15
|
export type EpochCommitteeInfo = {
|
|
@@ -19,18 +22,33 @@ export type EpochCommitteeInfo = {
|
|
|
19
22
|
export type SlotTag = 'now' | 'next' | SlotNumber;
|
|
20
23
|
export interface EpochCacheInterface {
|
|
21
24
|
getCommittee(slot: SlotTag | undefined): Promise<EpochCommitteeInfo>;
|
|
25
|
+
getSlotNow(): SlotNumber;
|
|
26
|
+
getTargetSlot(): SlotNumber;
|
|
27
|
+
getEpochNow(): EpochNumber;
|
|
28
|
+
getTargetEpoch(): EpochNumber;
|
|
22
29
|
getEpochAndSlotNow(): EpochAndSlot & {
|
|
23
30
|
nowMs: bigint;
|
|
24
31
|
};
|
|
25
32
|
getEpochAndSlotInNextL1Slot(): EpochAndSlot & {
|
|
26
|
-
|
|
33
|
+
nowSeconds: bigint;
|
|
34
|
+
};
|
|
35
|
+
/** Returns epoch/slot info for the next L1 slot with pipeline offset applied. */
|
|
36
|
+
getTargetEpochAndSlotInNextL1Slot(): EpochAndSlot & {
|
|
37
|
+
nowSeconds: bigint;
|
|
27
38
|
};
|
|
39
|
+
isProposerPipeliningEnabled(): boolean;
|
|
40
|
+
isEscapeHatchOpen(epoch: EpochNumber): Promise<boolean>;
|
|
41
|
+
isEscapeHatchOpenAtSlot(slot: SlotTag): Promise<boolean>;
|
|
28
42
|
getProposerIndexEncoding(epoch: EpochNumber, slot: SlotNumber, seed: bigint): `0x${string}`;
|
|
29
43
|
computeProposerIndex(slot: SlotNumber, epoch: EpochNumber, seed: bigint, size: bigint): bigint;
|
|
30
44
|
getCurrentAndNextSlot(): {
|
|
31
45
|
currentSlot: SlotNumber;
|
|
32
46
|
nextSlot: SlotNumber;
|
|
33
47
|
};
|
|
48
|
+
getTargetAndNextSlot(): {
|
|
49
|
+
targetSlot: SlotNumber;
|
|
50
|
+
nextSlot: SlotNumber;
|
|
51
|
+
};
|
|
34
52
|
getProposerAttesterAddressInSlot(slot: SlotNumber): Promise<EthAddress | undefined>;
|
|
35
53
|
getRegisteredValidators(): Promise<EthAddress[]>;
|
|
36
54
|
isInCommittee(slot: SlotTag, validator: EthAddress): Promise<boolean>;
|
|
@@ -53,29 +71,40 @@ export declare class EpochCache implements EpochCacheInterface {
|
|
|
53
71
|
protected readonly config: {
|
|
54
72
|
cacheSize: number;
|
|
55
73
|
validatorRefreshIntervalSeconds: number;
|
|
74
|
+
enableProposerPipelining: boolean;
|
|
56
75
|
};
|
|
57
76
|
protected cache: Map<EpochNumber, EpochCommitteeInfo>;
|
|
58
77
|
private allValidators;
|
|
59
78
|
private lastValidatorRefresh;
|
|
60
79
|
private readonly log;
|
|
80
|
+
protected enableProposerPipelining: boolean;
|
|
61
81
|
constructor(rollup: RollupContract, l1constants: L1RollupConstants & {
|
|
62
82
|
lagInEpochsForValidatorSet: number;
|
|
63
83
|
lagInEpochsForRandao: number;
|
|
64
84
|
}, dateProvider?: DateProvider, config?: {
|
|
65
85
|
cacheSize: number;
|
|
66
86
|
validatorRefreshIntervalSeconds: number;
|
|
87
|
+
enableProposerPipelining: boolean;
|
|
67
88
|
});
|
|
68
89
|
static create(rollupOrAddress: EthAddress | RollupContract, config?: EpochCacheConfig, deps?: {
|
|
69
90
|
dateProvider?: DateProvider;
|
|
70
91
|
}): Promise<EpochCache>;
|
|
71
92
|
getL1Constants(): L1RollupConstants;
|
|
93
|
+
isProposerPipeliningEnabled(): boolean;
|
|
94
|
+
getSlotNow(): SlotNumber;
|
|
95
|
+
getTargetSlot(): SlotNumber;
|
|
96
|
+
getEpochNow(): EpochNumber;
|
|
97
|
+
getTargetEpoch(): EpochNumber;
|
|
72
98
|
getEpochAndSlotNow(): EpochAndSlot & {
|
|
73
99
|
nowMs: bigint;
|
|
74
100
|
};
|
|
75
101
|
nowInSeconds(): bigint;
|
|
76
102
|
private getEpochAndSlotAtSlot;
|
|
77
103
|
getEpochAndSlotInNextL1Slot(): EpochAndSlot & {
|
|
78
|
-
|
|
104
|
+
nowSeconds: bigint;
|
|
105
|
+
};
|
|
106
|
+
getTargetEpochAndSlotInNextL1Slot(): EpochAndSlot & {
|
|
107
|
+
nowSeconds: bigint;
|
|
79
108
|
};
|
|
80
109
|
private getEpochAndSlotAtTimestamp;
|
|
81
110
|
getCommitteeForEpoch(epoch: EpochNumber): Promise<EpochCommitteeInfo>;
|
|
@@ -106,11 +135,16 @@ export declare class EpochCache implements EpochCacheInterface {
|
|
|
106
135
|
*/
|
|
107
136
|
getProposerIndexEncoding(epoch: EpochNumber, slot: SlotNumber, seed: bigint): `0x${string}`;
|
|
108
137
|
computeProposerIndex(slot: SlotNumber, epoch: EpochNumber, seed: bigint, size: bigint): bigint;
|
|
109
|
-
/** Returns the current and next L2 slot
|
|
138
|
+
/** Returns the current and next L2 slot in next eth L1 Slot. */
|
|
110
139
|
getCurrentAndNextSlot(): {
|
|
111
140
|
currentSlot: SlotNumber;
|
|
112
141
|
nextSlot: SlotNumber;
|
|
113
142
|
};
|
|
143
|
+
/** Returns the taget and next L2 slot in the next L1 slot */
|
|
144
|
+
getTargetAndNextSlot(): {
|
|
145
|
+
targetSlot: SlotNumber;
|
|
146
|
+
nextSlot: SlotNumber;
|
|
147
|
+
};
|
|
114
148
|
/**
|
|
115
149
|
* Get the proposer attester address in the given L2 slot
|
|
116
150
|
* @returns The proposer attester address. If the committee does not exist, we throw a NoCommitteeError.
|
|
@@ -131,4 +165,4 @@ export declare class EpochCache implements EpochCacheInterface {
|
|
|
131
165
|
filterInCommittee(slot: SlotTag, validators: EthAddress[]): Promise<EthAddress[]>;
|
|
132
166
|
getRegisteredValidators(): Promise<EthAddress[]>;
|
|
133
167
|
}
|
|
134
|
-
//# sourceMappingURL=data:application/json;base64,
|
|
168
|
+
//# sourceMappingURL=data:application/json;base64,eyJ2ZXJzaW9uIjozLCJmaWxlIjoiZXBvY2hfY2FjaGUuZC50cyIsInNvdXJjZVJvb3QiOiIiLCJzb3VyY2VzIjpbIi4uL3NyYy9lcG9jaF9jYWNoZS50cyJdLCJuYW1lcyI6W10sIm1hcHBpbmdzIjoiQUFFQSxPQUFPLEVBQW9CLGNBQWMsRUFBRSxNQUFNLDJCQUEyQixDQUFDO0FBQzdFLE9BQU8sRUFBRSxXQUFXLEVBQUUsVUFBVSxFQUFFLE1BQU0saUNBQWlDLENBQUM7QUFDMUUsT0FBTyxFQUFFLFVBQVUsRUFBRSxNQUFNLCtCQUErQixDQUFDO0FBRTNELE9BQU8sRUFBRSxZQUFZLEVBQUUsTUFBTSx5QkFBeUIsQ0FBQztBQUN2RCxPQUFPLEVBQ0wsS0FBSyxpQkFBaUIsRUFNdkIsTUFBTSw2QkFBNkIsQ0FBQztBQUlyQyxPQUFPLEVBQUUsS0FBSyxnQkFBZ0IsRUFBOEIsTUFBTSxhQUFhLENBQUM7QUFFaEYsK0VBQStFO0FBQy9FLGVBQU8sTUFBTSwrQkFBK0IsSUFBSSxDQUFDO0FBRWpELHdEQUF3RDtBQUN4RCxNQUFNLE1BQU0sWUFBWSxHQUFHO0lBQ3pCLElBQUksRUFBRSxVQUFVLENBQUM7SUFDakIsS0FBSyxFQUFFLFdBQVcsQ0FBQztJQUNuQixFQUFFLEVBQUUsTUFBTSxDQUFDO0NBQ1osQ0FBQztBQUVGLE1BQU0sTUFBTSxrQkFBa0IsR0FBRztJQUMvQixTQUFTLEVBQUUsVUFBVSxFQUFFLEdBQUcsU0FBUyxDQUFDO0lBQ3BDLElBQUksRUFBRSxNQUFNLENBQUM7SUFDYixLQUFLLEVBQUUsV0FBVyxDQUFDO0lBQ25CLCtEQUErRDtJQUMvRCxpQkFBaUIsRUFBRSxPQUFPLENBQUM7Q0FDNUIsQ0FBQztBQUVGLE1BQU0sTUFBTSxPQUFPLEdBQUcsS0FBSyxHQUFHLE1BQU0sR0FBRyxVQUFVLENBQUM7QUFFbEQsTUFBTSxXQUFXLG1CQUFtQjtJQUNsQyxZQUFZLENBQUMsSUFBSSxFQUFFLE9BQU8sR0FBRyxTQUFTLEdBQUcsT0FBTyxDQUFDLGtCQUFrQixDQUFDLENBQUM7SUFDckUsVUFB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
|
|
@@ -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,12 +1,14 @@
|
|
|
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';
|
|
4
5
|
import { EthAddress } from '@aztec/foundation/eth-address';
|
|
5
6
|
import { createLogger } from '@aztec/foundation/log';
|
|
6
7
|
import { DateProvider } from '@aztec/foundation/timer';
|
|
7
|
-
import { getEpochAtSlot, getEpochNumberAtTimestamp, getSlotAtTimestamp, getSlotRangeForEpoch, getTimestampForSlot
|
|
8
|
+
import { getEpochAtSlot, getEpochNumberAtTimestamp, getSlotAtTimestamp, getSlotRangeForEpoch, getTimestampForSlot } from '@aztec/stdlib/epoch-helpers';
|
|
8
9
|
import { createPublicClient, encodeAbiParameters, keccak256 } from 'viem';
|
|
9
10
|
import { getEpochCacheConfigEnvVars } from './config.js';
|
|
11
|
+
/** When proposer pipelining is enabled, the proposer builds one slot ahead. */ export const PROPOSER_PIPELINING_SLOT_OFFSET = 1;
|
|
10
12
|
/**
|
|
11
13
|
* Epoch cache
|
|
12
14
|
*
|
|
@@ -25,9 +27,11 @@ import { getEpochCacheConfigEnvVars } from './config.js';
|
|
|
25
27
|
allValidators;
|
|
26
28
|
lastValidatorRefresh;
|
|
27
29
|
log;
|
|
30
|
+
enableProposerPipelining;
|
|
28
31
|
constructor(rollup, l1constants, dateProvider = new DateProvider(), config = {
|
|
29
32
|
cacheSize: 12,
|
|
30
|
-
validatorRefreshIntervalSeconds: 60
|
|
33
|
+
validatorRefreshIntervalSeconds: 60,
|
|
34
|
+
enableProposerPipelining: false
|
|
31
35
|
}){
|
|
32
36
|
this.rollup = rollup;
|
|
33
37
|
this.l1constants = l1constants;
|
|
@@ -37,8 +41,10 @@ import { getEpochCacheConfigEnvVars } from './config.js';
|
|
|
37
41
|
this.allValidators = new Set();
|
|
38
42
|
this.lastValidatorRefresh = 0;
|
|
39
43
|
this.log = createLogger('epoch-cache');
|
|
44
|
+
this.enableProposerPipelining = this.config.enableProposerPipelining;
|
|
40
45
|
this.log.debug(`Initialized EpochCache`, {
|
|
41
|
-
l1constants
|
|
46
|
+
l1constants,
|
|
47
|
+
enableProposerPipelining: this.enableProposerPipelining
|
|
42
48
|
});
|
|
43
49
|
}
|
|
44
50
|
static async create(rollupOrAddress, config, deps = {}) {
|
|
@@ -81,11 +87,32 @@ import { getEpochCacheConfigEnvVars } from './config.js';
|
|
|
81
87
|
targetCommitteeSize: Number(targetCommitteeSize),
|
|
82
88
|
rollupManaLimit: Number(rollupManaLimit)
|
|
83
89
|
};
|
|
84
|
-
return new EpochCache(rollup, l1RollupConstants, deps.dateProvider
|
|
90
|
+
return new EpochCache(rollup, l1RollupConstants, deps.dateProvider, {
|
|
91
|
+
cacheSize: 12,
|
|
92
|
+
validatorRefreshIntervalSeconds: 60,
|
|
93
|
+
enableProposerPipelining: config.enableProposerPipelining
|
|
94
|
+
});
|
|
85
95
|
}
|
|
86
96
|
getL1Constants() {
|
|
87
97
|
return this.l1constants;
|
|
88
98
|
}
|
|
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
|
+
}
|
|
89
116
|
getEpochAndSlotNow() {
|
|
90
117
|
const nowMs = BigInt(this.dateProvider.now());
|
|
91
118
|
const nowSeconds = nowMs / 1000n;
|
|
@@ -98,28 +125,36 @@ import { getEpochCacheConfigEnvVars } from './config.js';
|
|
|
98
125
|
return BigInt(Math.floor(this.dateProvider.now() / 1000));
|
|
99
126
|
}
|
|
100
127
|
getEpochAndSlotAtSlot(slot) {
|
|
101
|
-
|
|
102
|
-
const ts = getTimestampRangeForEpoch(epoch, this.l1constants)[0];
|
|
103
|
-
return {
|
|
104
|
-
epoch,
|
|
105
|
-
ts,
|
|
106
|
-
slot
|
|
107
|
-
};
|
|
128
|
+
return this.getEpochAndSlotAtTimestamp(getTimestampForSlot(slot, this.l1constants));
|
|
108
129
|
}
|
|
109
130
|
getEpochAndSlotInNextL1Slot() {
|
|
110
|
-
const
|
|
111
|
-
const nextSlotTs =
|
|
131
|
+
const nowSeconds = this.nowInSeconds();
|
|
132
|
+
const nextSlotTs = nowSeconds + BigInt(this.l1constants.ethereumSlotDuration);
|
|
112
133
|
return {
|
|
113
134
|
...this.getEpochAndSlotAtTimestamp(nextSlotTs),
|
|
114
|
-
|
|
135
|
+
nowSeconds
|
|
136
|
+
};
|
|
137
|
+
}
|
|
138
|
+
getTargetEpochAndSlotInNextL1Slot() {
|
|
139
|
+
if (!this.isProposerPipeliningEnabled()) {
|
|
140
|
+
return this.getEpochAndSlotInNextL1Slot();
|
|
141
|
+
}
|
|
142
|
+
const result = this.getEpochAndSlotInNextL1Slot();
|
|
143
|
+
const offset = PROPOSER_PIPELINING_SLOT_OFFSET;
|
|
144
|
+
const targetSlot = SlotNumber(result.slot + offset);
|
|
145
|
+
return {
|
|
146
|
+
...result,
|
|
147
|
+
slot: targetSlot,
|
|
148
|
+
epoch: getEpochAtSlot(targetSlot, this.l1constants)
|
|
115
149
|
};
|
|
116
150
|
}
|
|
117
151
|
getEpochAndSlotAtTimestamp(ts) {
|
|
118
152
|
const slot = getSlotAtTimestamp(ts, this.l1constants);
|
|
153
|
+
const epoch = getEpochNumberAtTimestamp(ts, this.l1constants);
|
|
119
154
|
return {
|
|
120
|
-
|
|
121
|
-
|
|
122
|
-
slot
|
|
155
|
+
slot,
|
|
156
|
+
epoch,
|
|
157
|
+
ts: getTimestampForSlot(slot, this.l1constants)
|
|
123
158
|
};
|
|
124
159
|
}
|
|
125
160
|
getCommitteeForEpoch(epoch) {
|
|
@@ -145,7 +180,7 @@ import { getEpochCacheConfigEnvVars } from './config.js';
|
|
|
145
180
|
* This is a lightweight helper intended for callers that already have a slot number and only
|
|
146
181
|
* need the escape hatch flag (without pulling full committee info).
|
|
147
182
|
*/ async isEscapeHatchOpenAtSlot(slot = 'now') {
|
|
148
|
-
const epoch = slot === 'now' ? this.
|
|
183
|
+
const epoch = slot === 'now' ? this.getEpochNow() : slot === 'next' ? this.getEpochAndSlotInNextL1Slot().epoch : getEpochAtSlot(slot, this.l1constants);
|
|
149
184
|
return await this.isEscapeHatchOpen(epoch);
|
|
150
185
|
}
|
|
151
186
|
/**
|
|
@@ -230,11 +265,19 @@ import { getEpochCacheConfigEnvVars } from './config.js';
|
|
|
230
265
|
}
|
|
231
266
|
return BigInt(keccak256(this.getProposerIndexEncoding(epoch, slot, seed))) % size;
|
|
232
267
|
}
|
|
233
|
-
/** Returns the current and next L2 slot
|
|
234
|
-
const
|
|
268
|
+
/** Returns the current and next L2 slot in next eth L1 Slot. */ getCurrentAndNextSlot() {
|
|
269
|
+
const currentSlot = this.getSlotNow();
|
|
235
270
|
const next = this.getEpochAndSlotInNextL1Slot();
|
|
236
271
|
return {
|
|
237
|
-
currentSlot
|
|
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,
|
|
238
281
|
nextSlot: next.slot
|
|
239
282
|
};
|
|
240
283
|
}
|
|
@@ -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 type
|
|
4
|
+
import { type EpochAndSlot, type EpochCacheInterface, type EpochCommitteeInfo, type 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,6 +17,7 @@ export declare class TestEpochCache implements EpochCacheInterface {
|
|
|
17
17
|
private seed;
|
|
18
18
|
private registeredValidators;
|
|
19
19
|
private l1Constants;
|
|
20
|
+
private proposerPipeliningEnabled;
|
|
20
21
|
constructor(l1Constants?: Partial<L1RollupConstants>);
|
|
21
22
|
/**
|
|
22
23
|
* Sets the committee members. Used in validation and attestation flows.
|
|
@@ -54,12 +55,21 @@ export declare class TestEpochCache implements EpochCacheInterface {
|
|
|
54
55
|
*/
|
|
55
56
|
setL1Constants(constants: Partial<L1RollupConstants>): this;
|
|
56
57
|
getL1Constants(): L1RollupConstants;
|
|
58
|
+
setProposerPipeliningEnabled(enabled: boolean): void;
|
|
57
59
|
getCommittee(_slot?: SlotTag): Promise<EpochCommitteeInfo>;
|
|
60
|
+
getSlotNow(): SlotNumber;
|
|
61
|
+
getTargetSlot(): SlotNumber;
|
|
62
|
+
getEpochNow(): EpochNumber;
|
|
63
|
+
getTargetEpoch(): EpochNumber;
|
|
64
|
+
isProposerPipeliningEnabled(): boolean;
|
|
58
65
|
getEpochAndSlotNow(): EpochAndSlot & {
|
|
59
66
|
nowMs: bigint;
|
|
60
67
|
};
|
|
61
68
|
getEpochAndSlotInNextL1Slot(): EpochAndSlot & {
|
|
62
|
-
|
|
69
|
+
nowSeconds: bigint;
|
|
70
|
+
};
|
|
71
|
+
getTargetEpochAndSlotInNextL1Slot(): EpochAndSlot & {
|
|
72
|
+
nowSeconds: bigint;
|
|
63
73
|
};
|
|
64
74
|
getProposerIndexEncoding(epoch: EpochNumber, slot: SlotNumber, seed: bigint): `0x${string}`;
|
|
65
75
|
computeProposerIndex(slot: SlotNumber, _epoch: EpochNumber, _seed: bigint, size: bigint): bigint;
|
|
@@ -67,10 +77,15 @@ export declare class TestEpochCache implements EpochCacheInterface {
|
|
|
67
77
|
currentSlot: SlotNumber;
|
|
68
78
|
nextSlot: SlotNumber;
|
|
69
79
|
};
|
|
80
|
+
getTargetAndNextSlot(): {
|
|
81
|
+
targetSlot: SlotNumber;
|
|
82
|
+
nextSlot: SlotNumber;
|
|
83
|
+
};
|
|
70
84
|
getProposerAttesterAddressInSlot(_slot: SlotNumber): Promise<EthAddress | undefined>;
|
|
71
85
|
getRegisteredValidators(): Promise<EthAddress[]>;
|
|
72
86
|
isInCommittee(_slot: SlotTag, validator: EthAddress): Promise<boolean>;
|
|
73
87
|
filterInCommittee(_slot: SlotTag, validators: EthAddress[]): Promise<EthAddress[]>;
|
|
88
|
+
isEscapeHatchOpen(_epoch: EpochNumber): Promise<boolean>;
|
|
74
89
|
isEscapeHatchOpenAtSlot(_slot?: SlotTag): Promise<boolean>;
|
|
75
90
|
}
|
|
76
|
-
//# sourceMappingURL=data:application/json;base64,
|
|
91
|
+
//# sourceMappingURL=data:application/json;base64,eyJ2ZXJzaW9uIjozLCJmaWxlIjoidGVzdF9lcG9jaF9jYWNoZS5kLnRzIiwic291cmNlUm9vdCI6IiIsInNvdXJjZXMiOlsiLi4vLi4vc3JjL3Rlc3QvdGVzdF9lcG9jaF9jYWNoZS50cyJdLCJuYW1lcyI6W10sIm1hcHBpbmdzIjoiQUFBQSxPQUFPLEVBQUUsV0FBVyxFQUFFLFVBQVUsRUFBRSxNQUFNLGlDQUFpQyxDQUFDO0FBQzFFLE9BQU8sRUFBRSxVQUFVLEVBQUUsTUFBTSwrQkFBK0IsQ0FBQztBQUMzRCxPQUFPLEtBQUssRUFBRSxpQkFBaUIsRUFBRSxNQUFNLDZCQUE2QixDQUFDO0FBR3JFLE9BQU8sRUFDTCxLQUFLLFlBQVksRUFDakIsS0FBSyxtQkFBbUIsRUFDeEIsS0FBSyxrQkFBa0IsRUFFdkIsS0FBSyxPQUFPLEVBQ2IsTUFBTSxtQkFBbUIsQ0FBQztBQWMzQjs7Ozs7O0dBTUc7QUFDSCxxQkFBYSxjQUFlLFlBQVcsbUJBQW1CO0lBQ3hELE9BQU8sQ0FBQyxTQUFTLENBQW9CO0lBQ3JDLE9BQU8sQ0FBQyxlQUFlLENBQXlCO0lBQ2hELE9BQU8sQ0FBQyxXQUFXLENBQTZCO0lBQ2hELE9BQU8sQ0FBQyxlQUFlLENBQWtCO0lBQ3pDLE9BQU8sQ0FBQyxJQUFJLENBQWM7SUFDMUIsT0FBTyxDQUFDLG9CQUFvQixDQUFvQjtJQUNoRCxPQUFPLENBQUMsV0FBVyxDQUFvQjtJQUN2QyxPQUFPLENBQUMseUJBQXlCLENBQVM7SUFFMUMsWUFBWSxXQUFXLEdBQUUsT0FBTyxDQUFDLGlCQUFpQixDQUFNLEVBRXZEO0lBRUQ7OztPQUdHO0lBQ0gsWUFBWSxDQUFDLFNBQVMsRUFBRSxVQUFVLEVBQUUsR0FBRyxJQUFJLENBRzFDO0lBRUQ7OztPQUdHO0lBQ0gsV0FBVyxDQUFDLFFBQVEsRUFBRSxVQUFVLEdBQUcsU0FBUyxHQUFHLElBQUksQ0FHbEQ7SUFFRDs7O09BR0c7SUFDSCxjQUFjLENBQUMsSUFBSSxFQUFFLFVBQVUsR0FBRyxJQUFJLENBR3JDO0lBRUQ7OztPQUdHO0lBQ0gsa0JBQWtCLENBQUMsSUFBSSxFQUFFLE9BQU8sR0FBRyxJQUFJLENBR3RDO0lBRUQ7OztPQUdHO0lBQ0gsT0FBTyxDQUFDLElBQUksRUFBRSxNQUFNLEdBQUcsSUFBSSxDQUcxQjtJQUVEOzs7T0FHRztJQUNILHVCQUF1QixDQUFDLFVBQVUsRUFBRSxVQUFVLEVBQUUsR0FBRyxJQUFJLENBR3REO0lBRUQ7OztPQUdHO0lBQ0gsY0FBYyxDQUFDLFNBQVMsRUFBRSxPQUFPLENBQUMsaUJBQWlCLENBQUMsR0FBRyxJQUFJLENBRzFEO0lBRUQsY0FBYyxJQUFJLGlCQUFpQixDQUVsQztJQUVELDRCQUE0QixDQUFDLE9BQU8sRUFBRSxPQUFPLEdBQUcsSUFBSSxDQUVuRDtJQUVELFlBQVksQ0FBQyxLQUFLLENBQUMsRUFBRSxPQUFPLEdBQUcsT0FBTyxDQUFDLGtCQUFrQixDQUFDLENBUXpEO0lBRUQsVUFBVSxJQUFJLFVBQVUsQ0FFdkI7SUFFRCxhQUFhLElBQUksVUFBVSxDQUkxQjtJQUVELFdBQVcsSUFBSSxXQUFXLENBRXpCO0lBRUQsY0FBYyxJQUFJLFdBQVcsQ0FFNUI7SUFFRCwyQkFBMkIsSUFBSSxPQUFPLENBRXJDO0lBRUQsa0JBQWtCLElBQUksWUFBWSxHQUFHO1FBQUUsS0FBSyxFQUFFLE1BQU0sQ0FBQTtLQUFFLENBU3JEO0lBRUQsMkJBQTJCLElBQUksWUFBWSxHQUFHO1FBQUUsVUFBVSxFQUFFLE1BQU0sQ0FBQTtLQUFFLENBWW5FO0lBRUQsaUNBQWlDLElBQUksWUFBWSxHQUFHO1FBQUUsVUFBVSxFQUFFLE1BQU0sQ0FBQTtLQUFFLENBS3pFO0lBRUQsd0JBQXdCLENBQUMsS0FBSyxFQUFFLFdBQVcsRUFBRSxJQUFJLEVBQUUsVUFBVSxFQUFFLElBQUksRUFBRSxNQUFNLEdBQUcsS0FBSyxNQUFNLEVBQUUsQ0FHMUY7SUFFRCxvQkFBb0IsQ0FBQyxJQUFJLEVBQUUsVUFBVSxFQUFFLE1BQU0sRUFBRSxXQUFXLEVBQUUsS0FBSyxFQUFFLE1BQU0sRUFBRSxJQUFJLEVBQUUsTUFBTSxHQUFHLE1BQU0sQ0FLL0Y7SUFFRCxxQkFBcUIsSUFBSTtRQUFFLFdBQVcsRUFBRSxVQUFVLENBQUM7UUFBQyxRQUFRLEVBQUUsVUFBVSxDQUFBO0tBQUUsQ0FRekU7SUFFRCxvQkFBb0IsSUFBSTtRQUFFLFVBQVUsRUFBRSxVQUFVLENBQUM7UUFBQyxRQUFRLEVBQUUsVUFBVSxDQUFBO0tBQUUsQ0FRdkU7SUFFRCxnQ0FBZ0MsQ0FBQyxLQUFLLEVBQUUsVUFBVSxHQUFHLE9BQU8sQ0FBQyxVQUFVLEdBQUcsU0FBUyxDQUFDLENBRW5GO0lBRUQsdUJBQXVCLElBQUksT0FBTyxDQUFDLFVBQVUsRUFBRSxDQUFDLENBRS9DO0lBRUQsYUFBYSxDQUFDLEtBQUssRUFBRSxPQUFPLEVBQUUsU0FBUyxFQUFFLFVBQVUsR0FBRyxPQUFPLENBQUMsT0FBTyxDQUFDLENBRXJFO0lBRUQsaUJBQWlCLENBQUMsS0FBSyxFQUFFLE9BQU8sRUFBRSxVQUFVLEVBQUUsVUFBVSxFQUFFLEdBQUcsT0FBTyxDQUFDLFVBQVUsRUFBRSxDQUFDLENBR2pGO0lBRUQsaUJBQWlCLENBQUMsTUFBTSxFQUFFLFdBQVcsR0FBRyxPQUFPLENBQUMsT0FBTyxDQUFDLENBRXZEO0lBRUQsdUJBQXVCLENBQUMsS0FBSyxDQUFDLEVBQUUsT0FBTyxHQUFHLE9BQU8sQ0FBQyxPQUFPLENBQUMsQ0FFekQ7Q0FDRiJ9
|
|
@@ -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,KAAK,
|
|
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,EACL,KAAK,YAAY,EACjB,KAAK,mBAAmB,EACxB,KAAK,kBAAkB,EAEvB,KAAK,OAAO,EACb,MAAM,mBAAmB,CAAC;AAc3B;;;;;;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;IACvC,OAAO,CAAC,yBAAyB,CAAS;IAE1C,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,4BAA4B,CAAC,OAAO,EAAE,OAAO,GAAG,IAAI,CAEnD;IAED,YAAY,CAAC,KAAK,CAAC,EAAE,OAAO,GAAG,OAAO,CAAC,kBAAkB,CAAC,CAQzD;IAED,UAAU,IAAI,UAAU,CAEvB;IAED,aAAa,IAAI,UAAU,CAI1B;IAED,WAAW,IAAI,WAAW,CAEzB;IAED,cAAc,IAAI,WAAW,CAE5B;IAED,2BAA2B,IAAI,OAAO,CAErC;IAED,kBAAkB,IAAI,YAAY,GAAG;QAAE,KAAK,EAAE,MAAM,CAAA;KAAE,CASrD;IAED,2BAA2B,IAAI,YAAY,GAAG;QAAE,UAAU,EAAE,MAAM,CAAA;KAAE,CAYnE;IAED,iCAAiC,IAAI,YAAY,GAAG;QAAE,UAAU,EAAE,MAAM,CAAA;KAAE,CAKzE;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,CAQzE;IAED,oBAAoB,IAAI;QAAE,UAAU,EAAE,UAAU,CAAC;QAAC,QAAQ,EAAE,UAAU,CAAA;KAAE,CAQvE;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,iBAAiB,CAAC,MAAM,EAAE,WAAW,GAAG,OAAO,CAAC,OAAO,CAAC,CAEvD;IAED,uBAAuB,CAAC,KAAK,CAAC,EAAE,OAAO,GAAG,OAAO,CAAC,OAAO,CAAC,CAEzD;CACF"}
|
|
@@ -1,5 +1,6 @@
|
|
|
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';
|
|
3
4
|
/** Default L1 constants for testing. */ const DEFAULT_L1_CONSTANTS = {
|
|
4
5
|
l1StartBlock: 0n,
|
|
5
6
|
l1GenesisTime: 0n,
|
|
@@ -24,6 +25,7 @@ import { getEpochAtSlot, getSlotAtTimestamp, getTimestampRangeForEpoch } from '@
|
|
|
24
25
|
seed = 0n;
|
|
25
26
|
registeredValidators = [];
|
|
26
27
|
l1Constants;
|
|
28
|
+
proposerPipeliningEnabled = false;
|
|
27
29
|
constructor(l1Constants = {}){
|
|
28
30
|
this.l1Constants = {
|
|
29
31
|
...DEFAULT_L1_CONSTANTS,
|
|
@@ -85,6 +87,9 @@ import { getEpochAtSlot, getSlotAtTimestamp, getTimestampRangeForEpoch } from '@
|
|
|
85
87
|
getL1Constants() {
|
|
86
88
|
return this.l1Constants;
|
|
87
89
|
}
|
|
90
|
+
setProposerPipeliningEnabled(enabled) {
|
|
91
|
+
this.proposerPipeliningEnabled = enabled;
|
|
92
|
+
}
|
|
88
93
|
getCommittee(_slot) {
|
|
89
94
|
const epoch = getEpochAtSlot(this.currentSlot, this.l1Constants);
|
|
90
95
|
return Promise.resolve({
|
|
@@ -94,27 +99,52 @@ import { getEpochAtSlot, getSlotAtTimestamp, getTimestampRangeForEpoch } from '@
|
|
|
94
99
|
isEscapeHatchOpen: this.escapeHatchOpen
|
|
95
100
|
});
|
|
96
101
|
}
|
|
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
|
+
}
|
|
97
117
|
getEpochAndSlotNow() {
|
|
98
|
-
const
|
|
99
|
-
const ts = getTimestampRangeForEpoch(
|
|
118
|
+
const epochNow = getEpochAtSlot(this.currentSlot, this.l1Constants);
|
|
119
|
+
const ts = getTimestampRangeForEpoch(epochNow, this.l1Constants)[0];
|
|
100
120
|
return {
|
|
101
|
-
epoch,
|
|
121
|
+
epoch: epochNow,
|
|
102
122
|
slot: this.currentSlot,
|
|
103
123
|
ts,
|
|
104
124
|
nowMs: ts * 1000n
|
|
105
125
|
};
|
|
106
126
|
}
|
|
107
127
|
getEpochAndSlotInNextL1Slot() {
|
|
108
|
-
const
|
|
109
|
-
const nextSlotTs =
|
|
128
|
+
const nowTs = getTimestampRangeForEpoch(getEpochAtSlot(this.currentSlot, this.l1Constants), this.l1Constants)[0];
|
|
129
|
+
const nextSlotTs = nowTs + BigInt(this.l1Constants.ethereumSlotDuration);
|
|
110
130
|
const nextSlot = getSlotAtTimestamp(nextSlotTs, this.l1Constants);
|
|
111
|
-
const
|
|
112
|
-
const ts = getTimestampRangeForEpoch(
|
|
131
|
+
const epochNow = getEpochAtSlot(nextSlot, this.l1Constants);
|
|
132
|
+
const ts = getTimestampRangeForEpoch(epochNow, this.l1Constants)[0];
|
|
113
133
|
return {
|
|
114
|
-
epoch,
|
|
134
|
+
epoch: epochNow,
|
|
115
135
|
slot: nextSlot,
|
|
116
136
|
ts,
|
|
117
|
-
|
|
137
|
+
nowSeconds: nowTs
|
|
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)
|
|
118
148
|
};
|
|
119
149
|
}
|
|
120
150
|
getProposerIndexEncoding(epoch, slot, seed) {
|
|
@@ -128,9 +158,19 @@ import { getEpochAtSlot, getSlotAtTimestamp, getTimestampRangeForEpoch } from '@
|
|
|
128
158
|
return BigInt(slot) % size;
|
|
129
159
|
}
|
|
130
160
|
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();
|
|
131
171
|
return {
|
|
132
|
-
|
|
133
|
-
nextSlot:
|
|
172
|
+
targetSlot,
|
|
173
|
+
nextSlot: next.slot
|
|
134
174
|
};
|
|
135
175
|
}
|
|
136
176
|
getProposerAttesterAddressInSlot(_slot) {
|
|
@@ -146,6 +186,9 @@ import { getEpochAtSlot, getSlotAtTimestamp, getTimestampRangeForEpoch } from '@
|
|
|
146
186
|
const committeeSet = new Set(this.committee.map((v)=>v.toString()));
|
|
147
187
|
return Promise.resolve(validators.filter((v)=>committeeSet.has(v.toString())));
|
|
148
188
|
}
|
|
189
|
+
isEscapeHatchOpen(_epoch) {
|
|
190
|
+
return Promise.resolve(this.escapeHatchOpen);
|
|
191
|
+
}
|
|
149
192
|
isEscapeHatchOpenAtSlot(_slot) {
|
|
150
193
|
return Promise.resolve(this.escapeHatchOpen);
|
|
151
194
|
}
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@aztec/epoch-cache",
|
|
3
|
-
"version": "5.0.0-private.
|
|
3
|
+
"version": "5.0.0-private.20260319",
|
|
4
4
|
"type": "module",
|
|
5
5
|
"exports": {
|
|
6
6
|
".": "./dest/index.js",
|
|
@@ -26,10 +26,10 @@
|
|
|
26
26
|
"../package.common.json"
|
|
27
27
|
],
|
|
28
28
|
"dependencies": {
|
|
29
|
-
"@aztec/ethereum": "5.0.0-private.
|
|
30
|
-
"@aztec/foundation": "5.0.0-private.
|
|
31
|
-
"@aztec/l1-artifacts": "5.0.0-private.
|
|
32
|
-
"@aztec/stdlib": "5.0.0-private.
|
|
29
|
+
"@aztec/ethereum": "5.0.0-private.20260319",
|
|
30
|
+
"@aztec/foundation": "5.0.0-private.20260319",
|
|
31
|
+
"@aztec/l1-artifacts": "5.0.0-private.20260319",
|
|
32
|
+
"@aztec/stdlib": "5.0.0-private.20260319",
|
|
33
33
|
"dotenv": "^16.0.3",
|
|
34
34
|
"get-port": "^7.1.0",
|
|
35
35
|
"jest-mock-extended": "^4.0.0",
|
package/src/config.ts
CHANGED
|
@@ -1,11 +1,17 @@
|
|
|
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';
|
|
3
4
|
|
|
4
5
|
export type EpochCacheConfig = Pick<
|
|
5
|
-
L1ReaderConfig & L1ContractsConfig,
|
|
6
|
-
|
|
6
|
+
L1ReaderConfig & L1ContractsConfig & PipelineConfig,
|
|
7
|
+
| 'l1RpcUrls'
|
|
8
|
+
| 'l1ChainId'
|
|
9
|
+
| 'viemPollingIntervalMS'
|
|
10
|
+
| 'ethereumSlotDuration'
|
|
11
|
+
| 'l1HttpTimeoutMS'
|
|
12
|
+
| 'enableProposerPipelining'
|
|
7
13
|
>;
|
|
8
14
|
|
|
9
15
|
export function getEpochCacheConfigEnvVars(): EpochCacheConfig {
|
|
10
|
-
return { ...getL1ReaderConfigFromEnv(), ...getL1ContractsConfigEnvVars() };
|
|
16
|
+
return { ...getL1ReaderConfigFromEnv(), ...getL1ContractsConfigEnvVars(), ...getPipelineConfigEnvVars() };
|
|
11
17
|
}
|
package/src/epoch_cache.ts
CHANGED
|
@@ -12,16 +12,19 @@ import {
|
|
|
12
12
|
getSlotAtTimestamp,
|
|
13
13
|
getSlotRangeForEpoch,
|
|
14
14
|
getTimestampForSlot,
|
|
15
|
-
getTimestampRangeForEpoch,
|
|
16
15
|
} from '@aztec/stdlib/epoch-helpers';
|
|
17
16
|
|
|
18
17
|
import { createPublicClient, encodeAbiParameters, keccak256 } from 'viem';
|
|
19
18
|
|
|
20
19
|
import { type EpochCacheConfig, getEpochCacheConfigEnvVars } from './config.js';
|
|
21
20
|
|
|
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. */
|
|
22
25
|
export type EpochAndSlot = {
|
|
23
|
-
epoch: EpochNumber;
|
|
24
26
|
slot: SlotNumber;
|
|
27
|
+
epoch: EpochNumber;
|
|
25
28
|
ts: bigint;
|
|
26
29
|
};
|
|
27
30
|
|
|
@@ -37,11 +40,21 @@ export type SlotTag = 'now' | 'next' | SlotNumber;
|
|
|
37
40
|
|
|
38
41
|
export interface EpochCacheInterface {
|
|
39
42
|
getCommittee(slot: SlotTag | undefined): Promise<EpochCommitteeInfo>;
|
|
43
|
+
getSlotNow(): SlotNumber;
|
|
44
|
+
getTargetSlot(): SlotNumber;
|
|
45
|
+
getEpochNow(): EpochNumber;
|
|
46
|
+
getTargetEpoch(): EpochNumber;
|
|
40
47
|
getEpochAndSlotNow(): EpochAndSlot & { nowMs: bigint };
|
|
41
|
-
getEpochAndSlotInNextL1Slot(): EpochAndSlot & {
|
|
48
|
+
getEpochAndSlotInNextL1Slot(): EpochAndSlot & { nowSeconds: bigint };
|
|
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
54
|
getProposerIndexEncoding(epoch: EpochNumber, slot: SlotNumber, seed: bigint): `0x${string}`;
|
|
43
55
|
computeProposerIndex(slot: SlotNumber, epoch: EpochNumber, seed: bigint, size: bigint): bigint;
|
|
44
56
|
getCurrentAndNextSlot(): { currentSlot: SlotNumber; nextSlot: SlotNumber };
|
|
57
|
+
getTargetAndNextSlot(): { targetSlot: SlotNumber; nextSlot: SlotNumber };
|
|
45
58
|
getProposerAttesterAddressInSlot(slot: SlotNumber): Promise<EthAddress | undefined>;
|
|
46
59
|
getRegisteredValidators(): Promise<EthAddress[]>;
|
|
47
60
|
isInCommittee(slot: SlotTag, validator: EthAddress): Promise<boolean>;
|
|
@@ -65,6 +78,8 @@ export class EpochCache implements EpochCacheInterface {
|
|
|
65
78
|
private lastValidatorRefresh = 0;
|
|
66
79
|
private readonly log: Logger = createLogger('epoch-cache');
|
|
67
80
|
|
|
81
|
+
protected enableProposerPipelining: boolean;
|
|
82
|
+
|
|
68
83
|
constructor(
|
|
69
84
|
private rollup: RollupContract,
|
|
70
85
|
private readonly l1constants: L1RollupConstants & {
|
|
@@ -72,10 +87,12 @@ export class EpochCache implements EpochCacheInterface {
|
|
|
72
87
|
lagInEpochsForRandao: number;
|
|
73
88
|
},
|
|
74
89
|
private readonly dateProvider: DateProvider = new DateProvider(),
|
|
75
|
-
protected readonly config = { cacheSize: 12, validatorRefreshIntervalSeconds: 60 },
|
|
90
|
+
protected readonly config = { cacheSize: 12, validatorRefreshIntervalSeconds: 60, enableProposerPipelining: false },
|
|
76
91
|
) {
|
|
92
|
+
this.enableProposerPipelining = this.config.enableProposerPipelining;
|
|
77
93
|
this.log.debug(`Initialized EpochCache`, {
|
|
78
94
|
l1constants,
|
|
95
|
+
enableProposerPipelining: this.enableProposerPipelining,
|
|
79
96
|
});
|
|
80
97
|
}
|
|
81
98
|
|
|
@@ -135,13 +152,39 @@ export class EpochCache implements EpochCacheInterface {
|
|
|
135
152
|
rollupManaLimit: Number(rollupManaLimit),
|
|
136
153
|
};
|
|
137
154
|
|
|
138
|
-
return new EpochCache(rollup, l1RollupConstants, deps.dateProvider
|
|
155
|
+
return new EpochCache(rollup, l1RollupConstants, deps.dateProvider, {
|
|
156
|
+
cacheSize: 12,
|
|
157
|
+
validatorRefreshIntervalSeconds: 60,
|
|
158
|
+
enableProposerPipelining: config.enableProposerPipelining,
|
|
159
|
+
});
|
|
139
160
|
}
|
|
140
161
|
|
|
141
162
|
public getL1Constants(): L1RollupConstants {
|
|
142
163
|
return this.l1constants;
|
|
143
164
|
}
|
|
144
165
|
|
|
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
|
+
|
|
145
188
|
public getEpochAndSlotNow(): EpochAndSlot & { nowMs: bigint } {
|
|
146
189
|
const nowMs = BigInt(this.dateProvider.now());
|
|
147
190
|
const nowSeconds = nowMs / 1000n;
|
|
@@ -153,23 +196,33 @@ export class EpochCache implements EpochCacheInterface {
|
|
|
153
196
|
}
|
|
154
197
|
|
|
155
198
|
private getEpochAndSlotAtSlot(slot: SlotNumber): EpochAndSlot {
|
|
156
|
-
|
|
157
|
-
const ts = getTimestampRangeForEpoch(epoch, this.l1constants)[0];
|
|
158
|
-
return { epoch, ts, slot };
|
|
199
|
+
return this.getEpochAndSlotAtTimestamp(getTimestampForSlot(slot, this.l1constants));
|
|
159
200
|
}
|
|
160
201
|
|
|
161
|
-
public getEpochAndSlotInNextL1Slot(): EpochAndSlot & {
|
|
162
|
-
const
|
|
163
|
-
const nextSlotTs =
|
|
164
|
-
return { ...this.getEpochAndSlotAtTimestamp(nextSlotTs),
|
|
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 };
|
|
206
|
+
}
|
|
207
|
+
|
|
208
|
+
public getTargetEpochAndSlotInNextL1Slot(): EpochAndSlot & { nowSeconds: bigint } {
|
|
209
|
+
if (!this.isProposerPipeliningEnabled()) {
|
|
210
|
+
return this.getEpochAndSlotInNextL1Slot();
|
|
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) };
|
|
165
217
|
}
|
|
166
218
|
|
|
167
219
|
private getEpochAndSlotAtTimestamp(ts: bigint): EpochAndSlot {
|
|
168
220
|
const slot = getSlotAtTimestamp(ts, this.l1constants);
|
|
221
|
+
const epoch = getEpochNumberAtTimestamp(ts, this.l1constants);
|
|
169
222
|
return {
|
|
170
|
-
epoch: getEpochNumberAtTimestamp(ts, this.l1constants),
|
|
171
|
-
ts: getTimestampForSlot(slot, this.l1constants),
|
|
172
223
|
slot,
|
|
224
|
+
epoch,
|
|
225
|
+
ts: getTimestampForSlot(slot, this.l1constants),
|
|
173
226
|
};
|
|
174
227
|
}
|
|
175
228
|
|
|
@@ -202,7 +255,7 @@ export class EpochCache implements EpochCacheInterface {
|
|
|
202
255
|
public async isEscapeHatchOpenAtSlot(slot: SlotTag = 'now'): Promise<boolean> {
|
|
203
256
|
const epoch =
|
|
204
257
|
slot === 'now'
|
|
205
|
-
? this.
|
|
258
|
+
? this.getEpochNow()
|
|
206
259
|
: slot === 'next'
|
|
207
260
|
? this.getEpochAndSlotInNextL1Slot().epoch
|
|
208
261
|
: getEpochAtSlot(slot, this.l1constants);
|
|
@@ -237,7 +290,7 @@ export class EpochCache implements EpochCacheInterface {
|
|
|
237
290
|
return epochData;
|
|
238
291
|
}
|
|
239
292
|
|
|
240
|
-
private getEpochAndTimestamp(slot: SlotTag = 'now') {
|
|
293
|
+
private getEpochAndTimestamp(slot: SlotTag = 'now'): { epoch: EpochNumber; ts: bigint } {
|
|
241
294
|
if (slot === 'now') {
|
|
242
295
|
return this.getEpochAndSlotNow();
|
|
243
296
|
} else if (slot === 'next') {
|
|
@@ -287,13 +340,24 @@ export class EpochCache implements EpochCacheInterface {
|
|
|
287
340
|
return BigInt(keccak256(this.getProposerIndexEncoding(epoch, slot, seed))) % size;
|
|
288
341
|
}
|
|
289
342
|
|
|
290
|
-
/** Returns the current and next L2 slot
|
|
343
|
+
/** Returns the current and next L2 slot in next eth L1 Slot. */
|
|
291
344
|
public getCurrentAndNextSlot(): { currentSlot: SlotNumber; nextSlot: SlotNumber } {
|
|
292
|
-
const
|
|
345
|
+
const currentSlot = this.getSlotNow();
|
|
293
346
|
const next = this.getEpochAndSlotInNextL1Slot();
|
|
294
347
|
|
|
295
348
|
return {
|
|
296
|
-
currentSlot
|
|
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,
|
|
297
361
|
nextSlot: next.slot,
|
|
298
362
|
};
|
|
299
363
|
}
|
|
@@ -3,7 +3,13 @@ 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
|
|
6
|
+
import {
|
|
7
|
+
type EpochAndSlot,
|
|
8
|
+
type EpochCacheInterface,
|
|
9
|
+
type EpochCommitteeInfo,
|
|
10
|
+
PROPOSER_PIPELINING_SLOT_OFFSET,
|
|
11
|
+
type SlotTag,
|
|
12
|
+
} from '../epoch_cache.js';
|
|
7
13
|
|
|
8
14
|
/** Default L1 constants for testing. */
|
|
9
15
|
const DEFAULT_L1_CONSTANTS: L1RollupConstants = {
|
|
@@ -32,6 +38,7 @@ export class TestEpochCache implements EpochCacheInterface {
|
|
|
32
38
|
private seed: bigint = 0n;
|
|
33
39
|
private registeredValidators: EthAddress[] = [];
|
|
34
40
|
private l1Constants: L1RollupConstants;
|
|
41
|
+
private proposerPipeliningEnabled = false;
|
|
35
42
|
|
|
36
43
|
constructor(l1Constants: Partial<L1RollupConstants> = {}) {
|
|
37
44
|
this.l1Constants = { ...DEFAULT_L1_CONSTANTS, ...l1Constants };
|
|
@@ -104,6 +111,10 @@ export class TestEpochCache implements EpochCacheInterface {
|
|
|
104
111
|
return this.l1Constants;
|
|
105
112
|
}
|
|
106
113
|
|
|
114
|
+
setProposerPipeliningEnabled(enabled: boolean): void {
|
|
115
|
+
this.proposerPipeliningEnabled = enabled;
|
|
116
|
+
}
|
|
117
|
+
|
|
107
118
|
getCommittee(_slot?: SlotTag): Promise<EpochCommitteeInfo> {
|
|
108
119
|
const epoch = getEpochAtSlot(this.currentSlot, this.l1Constants);
|
|
109
120
|
return Promise.resolve({
|
|
@@ -114,19 +125,58 @@ export class TestEpochCache implements EpochCacheInterface {
|
|
|
114
125
|
});
|
|
115
126
|
}
|
|
116
127
|
|
|
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
|
+
|
|
117
150
|
getEpochAndSlotNow(): EpochAndSlot & { nowMs: bigint } {
|
|
118
|
-
const
|
|
119
|
-
const ts = getTimestampRangeForEpoch(
|
|
120
|
-
return {
|
|
151
|
+
const epochNow = getEpochAtSlot(this.currentSlot, this.l1Constants);
|
|
152
|
+
const ts = getTimestampRangeForEpoch(epochNow, this.l1Constants)[0];
|
|
153
|
+
return {
|
|
154
|
+
epoch: epochNow,
|
|
155
|
+
slot: this.currentSlot,
|
|
156
|
+
ts,
|
|
157
|
+
nowMs: ts * 1000n,
|
|
158
|
+
};
|
|
121
159
|
}
|
|
122
160
|
|
|
123
|
-
getEpochAndSlotInNextL1Slot(): EpochAndSlot & {
|
|
124
|
-
const
|
|
125
|
-
const nextSlotTs =
|
|
161
|
+
getEpochAndSlotInNextL1Slot(): EpochAndSlot & { nowSeconds: bigint } {
|
|
162
|
+
const nowTs = getTimestampRangeForEpoch(getEpochAtSlot(this.currentSlot, this.l1Constants), this.l1Constants)[0];
|
|
163
|
+
const nextSlotTs = nowTs + BigInt(this.l1Constants.ethereumSlotDuration);
|
|
126
164
|
const nextSlot = getSlotAtTimestamp(nextSlotTs, this.l1Constants);
|
|
127
|
-
const
|
|
128
|
-
const ts = getTimestampRangeForEpoch(
|
|
129
|
-
return {
|
|
165
|
+
const epochNow = getEpochAtSlot(nextSlot, this.l1Constants);
|
|
166
|
+
const ts = getTimestampRangeForEpoch(epochNow, this.l1Constants)[0];
|
|
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) };
|
|
130
180
|
}
|
|
131
181
|
|
|
132
182
|
getProposerIndexEncoding(epoch: EpochNumber, slot: SlotNumber, seed: bigint): `0x${string}` {
|
|
@@ -142,9 +192,22 @@ export class TestEpochCache implements EpochCacheInterface {
|
|
|
142
192
|
}
|
|
143
193
|
|
|
144
194
|
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
|
+
|
|
145
208
|
return {
|
|
146
|
-
|
|
147
|
-
nextSlot:
|
|
209
|
+
targetSlot,
|
|
210
|
+
nextSlot: next.slot,
|
|
148
211
|
};
|
|
149
212
|
}
|
|
150
213
|
|
|
@@ -165,6 +228,10 @@ export class TestEpochCache implements EpochCacheInterface {
|
|
|
165
228
|
return Promise.resolve(validators.filter(v => committeeSet.has(v.toString())));
|
|
166
229
|
}
|
|
167
230
|
|
|
231
|
+
isEscapeHatchOpen(_epoch: EpochNumber): Promise<boolean> {
|
|
232
|
+
return Promise.resolve(this.escapeHatchOpen);
|
|
233
|
+
}
|
|
234
|
+
|
|
168
235
|
isEscapeHatchOpenAtSlot(_slot?: SlotTag): Promise<boolean> {
|
|
169
236
|
return Promise.resolve(this.escapeHatchOpen);
|
|
170
237
|
}
|