@aztec/epoch-cache 0.0.1-commit.87a0206 → 0.0.1-commit.88e6f9396
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 +40 -5
- package/dest/epoch_cache.d.ts.map +1 -1
- package/dest/epoch_cache.js +76 -28
- 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 +57 -12
- package/package.json +5 -6
- package/src/config.ts +9 -3
- package/src/epoch_cache.ts +93 -21
- package/src/test/test_epoch_cache.ts +81 -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,22 +22,38 @@ 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>;
|
|
37
55
|
filterInCommittee(slot: SlotTag, validators: EthAddress[]): Promise<EthAddress[]>;
|
|
56
|
+
getL1Constants(): L1RollupConstants;
|
|
38
57
|
}
|
|
39
58
|
/**
|
|
40
59
|
* Epoch cache
|
|
@@ -52,29 +71,40 @@ export declare class EpochCache implements EpochCacheInterface {
|
|
|
52
71
|
protected readonly config: {
|
|
53
72
|
cacheSize: number;
|
|
54
73
|
validatorRefreshIntervalSeconds: number;
|
|
74
|
+
enableProposerPipelining: boolean;
|
|
55
75
|
};
|
|
56
76
|
protected cache: Map<EpochNumber, EpochCommitteeInfo>;
|
|
57
77
|
private allValidators;
|
|
58
78
|
private lastValidatorRefresh;
|
|
59
79
|
private readonly log;
|
|
80
|
+
protected enableProposerPipelining: boolean;
|
|
60
81
|
constructor(rollup: RollupContract, l1constants: L1RollupConstants & {
|
|
61
82
|
lagInEpochsForValidatorSet: number;
|
|
62
83
|
lagInEpochsForRandao: number;
|
|
63
84
|
}, dateProvider?: DateProvider, config?: {
|
|
64
85
|
cacheSize: number;
|
|
65
86
|
validatorRefreshIntervalSeconds: number;
|
|
87
|
+
enableProposerPipelining: boolean;
|
|
66
88
|
});
|
|
67
89
|
static create(rollupOrAddress: EthAddress | RollupContract, config?: EpochCacheConfig, deps?: {
|
|
68
90
|
dateProvider?: DateProvider;
|
|
69
91
|
}): Promise<EpochCache>;
|
|
70
92
|
getL1Constants(): L1RollupConstants;
|
|
93
|
+
isProposerPipeliningEnabled(): boolean;
|
|
94
|
+
getSlotNow(): SlotNumber;
|
|
95
|
+
getTargetSlot(): SlotNumber;
|
|
96
|
+
getEpochNow(): EpochNumber;
|
|
97
|
+
getTargetEpoch(): EpochNumber;
|
|
71
98
|
getEpochAndSlotNow(): EpochAndSlot & {
|
|
72
99
|
nowMs: bigint;
|
|
73
100
|
};
|
|
74
101
|
nowInSeconds(): bigint;
|
|
75
102
|
private getEpochAndSlotAtSlot;
|
|
76
103
|
getEpochAndSlotInNextL1Slot(): EpochAndSlot & {
|
|
77
|
-
|
|
104
|
+
nowSeconds: bigint;
|
|
105
|
+
};
|
|
106
|
+
getTargetEpochAndSlotInNextL1Slot(): EpochAndSlot & {
|
|
107
|
+
nowSeconds: bigint;
|
|
78
108
|
};
|
|
79
109
|
private getEpochAndSlotAtTimestamp;
|
|
80
110
|
getCommitteeForEpoch(epoch: EpochNumber): Promise<EpochCommitteeInfo>;
|
|
@@ -105,11 +135,16 @@ export declare class EpochCache implements EpochCacheInterface {
|
|
|
105
135
|
*/
|
|
106
136
|
getProposerIndexEncoding(epoch: EpochNumber, slot: SlotNumber, seed: bigint): `0x${string}`;
|
|
107
137
|
computeProposerIndex(slot: SlotNumber, epoch: EpochNumber, seed: bigint, size: bigint): bigint;
|
|
108
|
-
/** Returns the current and next L2 slot
|
|
138
|
+
/** Returns the current and next L2 slot in next eth L1 Slot. */
|
|
109
139
|
getCurrentAndNextSlot(): {
|
|
110
140
|
currentSlot: SlotNumber;
|
|
111
141
|
nextSlot: SlotNumber;
|
|
112
142
|
};
|
|
143
|
+
/** Returns the taget and next L2 slot in the next L1 slot */
|
|
144
|
+
getTargetAndNextSlot(): {
|
|
145
|
+
targetSlot: SlotNumber;
|
|
146
|
+
nextSlot: SlotNumber;
|
|
147
|
+
};
|
|
113
148
|
/**
|
|
114
149
|
* Get the proposer attester address in the given L2 slot
|
|
115
150
|
* @returns The proposer attester address. If the committee does not exist, we throw a NoCommitteeError.
|
|
@@ -130,4 +165,4 @@ export declare class EpochCache implements EpochCacheInterface {
|
|
|
130
165
|
filterInCommittee(slot: SlotTag, validators: EthAddress[]): Promise<EthAddress[]>;
|
|
131
166
|
getRegisteredValidators(): Promise<EthAddress[]>;
|
|
132
167
|
}
|
|
133
|
-
//# 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":"
|
|
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,11 +1,14 @@
|
|
|
1
1
|
import { createEthereumChain } from '@aztec/ethereum/chain';
|
|
2
|
+
import { makeL1HttpTransport } from '@aztec/ethereum/client';
|
|
2
3
|
import { NoCommitteeError, RollupContract } from '@aztec/ethereum/contracts';
|
|
4
|
+
import { SlotNumber } from '@aztec/foundation/branded-types';
|
|
3
5
|
import { EthAddress } from '@aztec/foundation/eth-address';
|
|
4
6
|
import { createLogger } from '@aztec/foundation/log';
|
|
5
7
|
import { DateProvider } from '@aztec/foundation/timer';
|
|
6
|
-
import { getEpochAtSlot, getEpochNumberAtTimestamp, getSlotAtTimestamp, getSlotRangeForEpoch, getTimestampForSlot
|
|
7
|
-
import { createPublicClient, encodeAbiParameters,
|
|
8
|
+
import { getEpochAtSlot, getEpochNumberAtTimestamp, getSlotAtTimestamp, getSlotRangeForEpoch, getTimestampForSlot } from '@aztec/stdlib/epoch-helpers';
|
|
9
|
+
import { createPublicClient, encodeAbiParameters, keccak256 } from 'viem';
|
|
8
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;
|
|
9
12
|
/**
|
|
10
13
|
* Epoch cache
|
|
11
14
|
*
|
|
@@ -24,9 +27,11 @@ import { getEpochCacheConfigEnvVars } from './config.js';
|
|
|
24
27
|
allValidators;
|
|
25
28
|
lastValidatorRefresh;
|
|
26
29
|
log;
|
|
30
|
+
enableProposerPipelining;
|
|
27
31
|
constructor(rollup, l1constants, dateProvider = new DateProvider(), config = {
|
|
28
32
|
cacheSize: 12,
|
|
29
|
-
validatorRefreshIntervalSeconds: 60
|
|
33
|
+
validatorRefreshIntervalSeconds: 60,
|
|
34
|
+
enableProposerPipelining: false
|
|
30
35
|
}){
|
|
31
36
|
this.rollup = rollup;
|
|
32
37
|
this.l1constants = l1constants;
|
|
@@ -36,8 +41,10 @@ import { getEpochCacheConfigEnvVars } from './config.js';
|
|
|
36
41
|
this.allValidators = new Set();
|
|
37
42
|
this.lastValidatorRefresh = 0;
|
|
38
43
|
this.log = createLogger('epoch-cache');
|
|
44
|
+
this.enableProposerPipelining = this.config.enableProposerPipelining;
|
|
39
45
|
this.log.debug(`Initialized EpochCache`, {
|
|
40
|
-
l1constants
|
|
46
|
+
l1constants,
|
|
47
|
+
enableProposerPipelining: this.enableProposerPipelining
|
|
41
48
|
});
|
|
42
49
|
}
|
|
43
50
|
static async create(rollupOrAddress, config, deps = {}) {
|
|
@@ -50,21 +57,23 @@ import { getEpochCacheConfigEnvVars } from './config.js';
|
|
|
50
57
|
const chain = createEthereumChain(config.l1RpcUrls, config.l1ChainId);
|
|
51
58
|
const publicClient = createPublicClient({
|
|
52
59
|
chain: chain.chainInfo,
|
|
53
|
-
transport:
|
|
54
|
-
|
|
55
|
-
|
|
60
|
+
transport: makeL1HttpTransport(config.l1RpcUrls, {
|
|
61
|
+
timeout: config.l1HttpTimeoutMS
|
|
62
|
+
}),
|
|
56
63
|
pollingInterval: config.viemPollingIntervalMS
|
|
57
64
|
});
|
|
58
65
|
rollup = new RollupContract(publicClient, rollupOrAddress.toString());
|
|
59
66
|
}
|
|
60
|
-
const [l1StartBlock, l1GenesisTime, proofSubmissionEpochs, slotDuration, epochDuration, lagInEpochsForValidatorSet, lagInEpochsForRandao] = await Promise.all([
|
|
67
|
+
const [l1StartBlock, l1GenesisTime, proofSubmissionEpochs, slotDuration, epochDuration, lagInEpochsForValidatorSet, lagInEpochsForRandao, targetCommitteeSize, rollupManaLimit] = await Promise.all([
|
|
61
68
|
rollup.getL1StartBlock(),
|
|
62
69
|
rollup.getL1GenesisTime(),
|
|
63
70
|
rollup.getProofSubmissionEpochs(),
|
|
64
71
|
rollup.getSlotDuration(),
|
|
65
72
|
rollup.getEpochDuration(),
|
|
66
73
|
rollup.getLagInEpochsForValidatorSet(),
|
|
67
|
-
rollup.getLagInEpochsForRandao()
|
|
74
|
+
rollup.getLagInEpochsForRandao(),
|
|
75
|
+
rollup.getTargetCommitteeSize(),
|
|
76
|
+
rollup.getManaLimit()
|
|
68
77
|
]);
|
|
69
78
|
const l1RollupConstants = {
|
|
70
79
|
l1StartBlock,
|
|
@@ -74,13 +83,36 @@ import { getEpochCacheConfigEnvVars } from './config.js';
|
|
|
74
83
|
epochDuration: Number(epochDuration),
|
|
75
84
|
ethereumSlotDuration: config.ethereumSlotDuration,
|
|
76
85
|
lagInEpochsForValidatorSet: Number(lagInEpochsForValidatorSet),
|
|
77
|
-
lagInEpochsForRandao: Number(lagInEpochsForRandao)
|
|
86
|
+
lagInEpochsForRandao: Number(lagInEpochsForRandao),
|
|
87
|
+
targetCommitteeSize: Number(targetCommitteeSize),
|
|
88
|
+
rollupManaLimit: Number(rollupManaLimit)
|
|
78
89
|
};
|
|
79
|
-
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
|
+
});
|
|
80
95
|
}
|
|
81
96
|
getL1Constants() {
|
|
82
97
|
return this.l1constants;
|
|
83
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
|
+
}
|
|
84
116
|
getEpochAndSlotNow() {
|
|
85
117
|
const nowMs = BigInt(this.dateProvider.now());
|
|
86
118
|
const nowSeconds = nowMs / 1000n;
|
|
@@ -93,28 +125,36 @@ import { getEpochCacheConfigEnvVars } from './config.js';
|
|
|
93
125
|
return BigInt(Math.floor(this.dateProvider.now() / 1000));
|
|
94
126
|
}
|
|
95
127
|
getEpochAndSlotAtSlot(slot) {
|
|
96
|
-
|
|
97
|
-
const ts = getTimestampRangeForEpoch(epoch, this.l1constants)[0];
|
|
98
|
-
return {
|
|
99
|
-
epoch,
|
|
100
|
-
ts,
|
|
101
|
-
slot
|
|
102
|
-
};
|
|
128
|
+
return this.getEpochAndSlotAtTimestamp(getTimestampForSlot(slot, this.l1constants));
|
|
103
129
|
}
|
|
104
130
|
getEpochAndSlotInNextL1Slot() {
|
|
105
|
-
const
|
|
106
|
-
const nextSlotTs =
|
|
131
|
+
const nowSeconds = this.nowInSeconds();
|
|
132
|
+
const nextSlotTs = nowSeconds + BigInt(this.l1constants.ethereumSlotDuration);
|
|
107
133
|
return {
|
|
108
134
|
...this.getEpochAndSlotAtTimestamp(nextSlotTs),
|
|
109
|
-
|
|
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)
|
|
110
149
|
};
|
|
111
150
|
}
|
|
112
151
|
getEpochAndSlotAtTimestamp(ts) {
|
|
113
152
|
const slot = getSlotAtTimestamp(ts, this.l1constants);
|
|
153
|
+
const epoch = getEpochNumberAtTimestamp(ts, this.l1constants);
|
|
114
154
|
return {
|
|
115
|
-
|
|
116
|
-
|
|
117
|
-
slot
|
|
155
|
+
slot,
|
|
156
|
+
epoch,
|
|
157
|
+
ts: getTimestampForSlot(slot, this.l1constants)
|
|
118
158
|
};
|
|
119
159
|
}
|
|
120
160
|
getCommitteeForEpoch(epoch) {
|
|
@@ -140,7 +180,7 @@ import { getEpochCacheConfigEnvVars } from './config.js';
|
|
|
140
180
|
* This is a lightweight helper intended for callers that already have a slot number and only
|
|
141
181
|
* need the escape hatch flag (without pulling full committee info).
|
|
142
182
|
*/ async isEscapeHatchOpenAtSlot(slot = 'now') {
|
|
143
|
-
const epoch = slot === 'now' ? this.
|
|
183
|
+
const epoch = slot === 'now' ? this.getEpochNow() : slot === 'next' ? this.getEpochAndSlotInNextL1Slot().epoch : getEpochAtSlot(slot, this.l1constants);
|
|
144
184
|
return await this.isEscapeHatchOpen(epoch);
|
|
145
185
|
}
|
|
146
186
|
/**
|
|
@@ -225,11 +265,19 @@ import { getEpochCacheConfigEnvVars } from './config.js';
|
|
|
225
265
|
}
|
|
226
266
|
return BigInt(keccak256(this.getProposerIndexEncoding(epoch, slot, seed))) % size;
|
|
227
267
|
}
|
|
228
|
-
/** Returns the current and next L2 slot
|
|
229
|
-
const
|
|
268
|
+
/** Returns the current and next L2 slot in next eth L1 Slot. */ getCurrentAndNextSlot() {
|
|
269
|
+
const currentSlot = this.getSlotNow();
|
|
230
270
|
const next = this.getEpochAndSlotInNextL1Slot();
|
|
231
271
|
return {
|
|
232
|
-
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,
|
|
233
281
|
nextSlot: next.slot
|
|
234
282
|
};
|
|
235
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":"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"}
|
|
@@ -1,12 +1,15 @@
|
|
|
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,
|
|
6
7
|
slotDuration: 24,
|
|
7
8
|
epochDuration: 16,
|
|
8
9
|
ethereumSlotDuration: 12,
|
|
9
|
-
proofSubmissionEpochs: 2
|
|
10
|
+
proofSubmissionEpochs: 2,
|
|
11
|
+
targetCommitteeSize: 48,
|
|
12
|
+
rollupManaLimit: Number.MAX_SAFE_INTEGER
|
|
10
13
|
};
|
|
11
14
|
/**
|
|
12
15
|
* A test implementation of EpochCacheInterface that allows manual configuration
|
|
@@ -22,6 +25,7 @@ import { getEpochAtSlot, getSlotAtTimestamp, getTimestampRangeForEpoch } from '@
|
|
|
22
25
|
seed = 0n;
|
|
23
26
|
registeredValidators = [];
|
|
24
27
|
l1Constants;
|
|
28
|
+
proposerPipeliningEnabled = false;
|
|
25
29
|
constructor(l1Constants = {}){
|
|
26
30
|
this.l1Constants = {
|
|
27
31
|
...DEFAULT_L1_CONSTANTS,
|
|
@@ -83,6 +87,9 @@ import { getEpochAtSlot, getSlotAtTimestamp, getTimestampRangeForEpoch } from '@
|
|
|
83
87
|
getL1Constants() {
|
|
84
88
|
return this.l1Constants;
|
|
85
89
|
}
|
|
90
|
+
setProposerPipeliningEnabled(enabled) {
|
|
91
|
+
this.proposerPipeliningEnabled = enabled;
|
|
92
|
+
}
|
|
86
93
|
getCommittee(_slot) {
|
|
87
94
|
const epoch = getEpochAtSlot(this.currentSlot, this.l1Constants);
|
|
88
95
|
return Promise.resolve({
|
|
@@ -92,27 +99,52 @@ import { getEpochAtSlot, getSlotAtTimestamp, getTimestampRangeForEpoch } from '@
|
|
|
92
99
|
isEscapeHatchOpen: this.escapeHatchOpen
|
|
93
100
|
});
|
|
94
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
|
+
}
|
|
95
117
|
getEpochAndSlotNow() {
|
|
96
|
-
const
|
|
97
|
-
const ts = getTimestampRangeForEpoch(
|
|
118
|
+
const epochNow = getEpochAtSlot(this.currentSlot, this.l1Constants);
|
|
119
|
+
const ts = getTimestampRangeForEpoch(epochNow, this.l1Constants)[0];
|
|
98
120
|
return {
|
|
99
|
-
epoch,
|
|
121
|
+
epoch: epochNow,
|
|
100
122
|
slot: this.currentSlot,
|
|
101
123
|
ts,
|
|
102
124
|
nowMs: ts * 1000n
|
|
103
125
|
};
|
|
104
126
|
}
|
|
105
127
|
getEpochAndSlotInNextL1Slot() {
|
|
106
|
-
const
|
|
107
|
-
const nextSlotTs =
|
|
128
|
+
const nowTs = getTimestampRangeForEpoch(getEpochAtSlot(this.currentSlot, this.l1Constants), this.l1Constants)[0];
|
|
129
|
+
const nextSlotTs = nowTs + BigInt(this.l1Constants.ethereumSlotDuration);
|
|
108
130
|
const nextSlot = getSlotAtTimestamp(nextSlotTs, this.l1Constants);
|
|
109
|
-
const
|
|
110
|
-
const ts = getTimestampRangeForEpoch(
|
|
131
|
+
const epochNow = getEpochAtSlot(nextSlot, this.l1Constants);
|
|
132
|
+
const ts = getTimestampRangeForEpoch(epochNow, this.l1Constants)[0];
|
|
111
133
|
return {
|
|
112
|
-
epoch,
|
|
134
|
+
epoch: epochNow,
|
|
113
135
|
slot: nextSlot,
|
|
114
136
|
ts,
|
|
115
|
-
|
|
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)
|
|
116
148
|
};
|
|
117
149
|
}
|
|
118
150
|
getProposerIndexEncoding(epoch, slot, seed) {
|
|
@@ -126,9 +158,19 @@ import { getEpochAtSlot, getSlotAtTimestamp, getTimestampRangeForEpoch } from '@
|
|
|
126
158
|
return BigInt(slot) % size;
|
|
127
159
|
}
|
|
128
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();
|
|
129
171
|
return {
|
|
130
|
-
|
|
131
|
-
nextSlot:
|
|
172
|
+
targetSlot,
|
|
173
|
+
nextSlot: next.slot
|
|
132
174
|
};
|
|
133
175
|
}
|
|
134
176
|
getProposerAttesterAddressInSlot(_slot) {
|
|
@@ -144,6 +186,9 @@ import { getEpochAtSlot, getSlotAtTimestamp, getTimestampRangeForEpoch } from '@
|
|
|
144
186
|
const committeeSet = new Set(this.committee.map((v)=>v.toString()));
|
|
145
187
|
return Promise.resolve(validators.filter((v)=>committeeSet.has(v.toString())));
|
|
146
188
|
}
|
|
189
|
+
isEscapeHatchOpen(_epoch) {
|
|
190
|
+
return Promise.resolve(this.escapeHatchOpen);
|
|
191
|
+
}
|
|
147
192
|
isEscapeHatchOpenAtSlot(_slot) {
|
|
148
193
|
return Promise.resolve(this.escapeHatchOpen);
|
|
149
194
|
}
|
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.88e6f9396",
|
|
4
4
|
"type": "module",
|
|
5
5
|
"exports": {
|
|
6
6
|
".": "./dest/index.js",
|
|
@@ -26,11 +26,10 @@
|
|
|
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.
|
|
33
|
-
"@viem/anvil": "^0.0.10",
|
|
29
|
+
"@aztec/ethereum": "0.0.1-commit.88e6f9396",
|
|
30
|
+
"@aztec/foundation": "0.0.1-commit.88e6f9396",
|
|
31
|
+
"@aztec/l1-artifacts": "0.0.1-commit.88e6f9396",
|
|
32
|
+
"@aztec/stdlib": "0.0.1-commit.88e6f9396",
|
|
34
33
|
"dotenv": "^16.0.3",
|
|
35
34
|
"get-port": "^7.1.0",
|
|
36
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
|
@@ -1,4 +1,5 @@
|
|
|
1
1
|
import { createEthereumChain } from '@aztec/ethereum/chain';
|
|
2
|
+
import { makeL1HttpTransport } from '@aztec/ethereum/client';
|
|
2
3
|
import { NoCommitteeError, RollupContract } from '@aztec/ethereum/contracts';
|
|
3
4
|
import { EpochNumber, SlotNumber } from '@aztec/foundation/branded-types';
|
|
4
5
|
import { EthAddress } from '@aztec/foundation/eth-address';
|
|
@@ -11,16 +12,19 @@ import {
|
|
|
11
12
|
getSlotAtTimestamp,
|
|
12
13
|
getSlotRangeForEpoch,
|
|
13
14
|
getTimestampForSlot,
|
|
14
|
-
getTimestampRangeForEpoch,
|
|
15
15
|
} from '@aztec/stdlib/epoch-helpers';
|
|
16
16
|
|
|
17
|
-
import { createPublicClient, encodeAbiParameters,
|
|
17
|
+
import { createPublicClient, encodeAbiParameters, keccak256 } from 'viem';
|
|
18
18
|
|
|
19
19
|
import { type EpochCacheConfig, getEpochCacheConfigEnvVars } from './config.js';
|
|
20
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. */
|
|
21
25
|
export type EpochAndSlot = {
|
|
22
|
-
epoch: EpochNumber;
|
|
23
26
|
slot: SlotNumber;
|
|
27
|
+
epoch: EpochNumber;
|
|
24
28
|
ts: bigint;
|
|
25
29
|
};
|
|
26
30
|
|
|
@@ -36,15 +40,26 @@ export type SlotTag = 'now' | 'next' | SlotNumber;
|
|
|
36
40
|
|
|
37
41
|
export interface EpochCacheInterface {
|
|
38
42
|
getCommittee(slot: SlotTag | undefined): Promise<EpochCommitteeInfo>;
|
|
43
|
+
getSlotNow(): SlotNumber;
|
|
44
|
+
getTargetSlot(): SlotNumber;
|
|
45
|
+
getEpochNow(): EpochNumber;
|
|
46
|
+
getTargetEpoch(): EpochNumber;
|
|
39
47
|
getEpochAndSlotNow(): EpochAndSlot & { nowMs: bigint };
|
|
40
|
-
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>;
|
|
41
54
|
getProposerIndexEncoding(epoch: EpochNumber, slot: SlotNumber, seed: bigint): `0x${string}`;
|
|
42
55
|
computeProposerIndex(slot: SlotNumber, epoch: EpochNumber, seed: bigint, size: bigint): bigint;
|
|
43
56
|
getCurrentAndNextSlot(): { currentSlot: SlotNumber; nextSlot: SlotNumber };
|
|
57
|
+
getTargetAndNextSlot(): { targetSlot: SlotNumber; nextSlot: SlotNumber };
|
|
44
58
|
getProposerAttesterAddressInSlot(slot: SlotNumber): Promise<EthAddress | undefined>;
|
|
45
59
|
getRegisteredValidators(): Promise<EthAddress[]>;
|
|
46
60
|
isInCommittee(slot: SlotTag, validator: EthAddress): Promise<boolean>;
|
|
47
61
|
filterInCommittee(slot: SlotTag, validators: EthAddress[]): Promise<EthAddress[]>;
|
|
62
|
+
getL1Constants(): L1RollupConstants;
|
|
48
63
|
}
|
|
49
64
|
|
|
50
65
|
/**
|
|
@@ -63,6 +78,8 @@ export class EpochCache implements EpochCacheInterface {
|
|
|
63
78
|
private lastValidatorRefresh = 0;
|
|
64
79
|
private readonly log: Logger = createLogger('epoch-cache');
|
|
65
80
|
|
|
81
|
+
protected enableProposerPipelining: boolean;
|
|
82
|
+
|
|
66
83
|
constructor(
|
|
67
84
|
private rollup: RollupContract,
|
|
68
85
|
private readonly l1constants: L1RollupConstants & {
|
|
@@ -70,10 +87,12 @@ export class EpochCache implements EpochCacheInterface {
|
|
|
70
87
|
lagInEpochsForRandao: number;
|
|
71
88
|
},
|
|
72
89
|
private readonly dateProvider: DateProvider = new DateProvider(),
|
|
73
|
-
protected readonly config = { cacheSize: 12, validatorRefreshIntervalSeconds: 60 },
|
|
90
|
+
protected readonly config = { cacheSize: 12, validatorRefreshIntervalSeconds: 60, enableProposerPipelining: false },
|
|
74
91
|
) {
|
|
92
|
+
this.enableProposerPipelining = this.config.enableProposerPipelining;
|
|
75
93
|
this.log.debug(`Initialized EpochCache`, {
|
|
76
94
|
l1constants,
|
|
95
|
+
enableProposerPipelining: this.enableProposerPipelining,
|
|
77
96
|
});
|
|
78
97
|
}
|
|
79
98
|
|
|
@@ -92,7 +111,7 @@ export class EpochCache implements EpochCacheInterface {
|
|
|
92
111
|
const chain = createEthereumChain(config.l1RpcUrls, config.l1ChainId);
|
|
93
112
|
const publicClient = createPublicClient({
|
|
94
113
|
chain: chain.chainInfo,
|
|
95
|
-
transport:
|
|
114
|
+
transport: makeL1HttpTransport(config.l1RpcUrls, { timeout: config.l1HttpTimeoutMS }),
|
|
96
115
|
pollingInterval: config.viemPollingIntervalMS,
|
|
97
116
|
});
|
|
98
117
|
rollup = new RollupContract(publicClient, rollupOrAddress.toString());
|
|
@@ -106,6 +125,8 @@ export class EpochCache implements EpochCacheInterface {
|
|
|
106
125
|
epochDuration,
|
|
107
126
|
lagInEpochsForValidatorSet,
|
|
108
127
|
lagInEpochsForRandao,
|
|
128
|
+
targetCommitteeSize,
|
|
129
|
+
rollupManaLimit,
|
|
109
130
|
] = await Promise.all([
|
|
110
131
|
rollup.getL1StartBlock(),
|
|
111
132
|
rollup.getL1GenesisTime(),
|
|
@@ -114,6 +135,8 @@ export class EpochCache implements EpochCacheInterface {
|
|
|
114
135
|
rollup.getEpochDuration(),
|
|
115
136
|
rollup.getLagInEpochsForValidatorSet(),
|
|
116
137
|
rollup.getLagInEpochsForRandao(),
|
|
138
|
+
rollup.getTargetCommitteeSize(),
|
|
139
|
+
rollup.getManaLimit(),
|
|
117
140
|
] as const);
|
|
118
141
|
|
|
119
142
|
const l1RollupConstants = {
|
|
@@ -125,15 +148,43 @@ export class EpochCache implements EpochCacheInterface {
|
|
|
125
148
|
ethereumSlotDuration: config.ethereumSlotDuration,
|
|
126
149
|
lagInEpochsForValidatorSet: Number(lagInEpochsForValidatorSet),
|
|
127
150
|
lagInEpochsForRandao: Number(lagInEpochsForRandao),
|
|
151
|
+
targetCommitteeSize: Number(targetCommitteeSize),
|
|
152
|
+
rollupManaLimit: Number(rollupManaLimit),
|
|
128
153
|
};
|
|
129
154
|
|
|
130
|
-
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
|
+
});
|
|
131
160
|
}
|
|
132
161
|
|
|
133
162
|
public getL1Constants(): L1RollupConstants {
|
|
134
163
|
return this.l1constants;
|
|
135
164
|
}
|
|
136
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
|
+
|
|
137
188
|
public getEpochAndSlotNow(): EpochAndSlot & { nowMs: bigint } {
|
|
138
189
|
const nowMs = BigInt(this.dateProvider.now());
|
|
139
190
|
const nowSeconds = nowMs / 1000n;
|
|
@@ -145,23 +196,33 @@ export class EpochCache implements EpochCacheInterface {
|
|
|
145
196
|
}
|
|
146
197
|
|
|
147
198
|
private getEpochAndSlotAtSlot(slot: SlotNumber): EpochAndSlot {
|
|
148
|
-
|
|
149
|
-
const ts = getTimestampRangeForEpoch(epoch, this.l1constants)[0];
|
|
150
|
-
return { epoch, ts, slot };
|
|
199
|
+
return this.getEpochAndSlotAtTimestamp(getTimestampForSlot(slot, this.l1constants));
|
|
151
200
|
}
|
|
152
201
|
|
|
153
|
-
public getEpochAndSlotInNextL1Slot(): EpochAndSlot & {
|
|
154
|
-
const
|
|
155
|
-
const nextSlotTs =
|
|
156
|
-
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) };
|
|
157
217
|
}
|
|
158
218
|
|
|
159
219
|
private getEpochAndSlotAtTimestamp(ts: bigint): EpochAndSlot {
|
|
160
220
|
const slot = getSlotAtTimestamp(ts, this.l1constants);
|
|
221
|
+
const epoch = getEpochNumberAtTimestamp(ts, this.l1constants);
|
|
161
222
|
return {
|
|
162
|
-
epoch: getEpochNumberAtTimestamp(ts, this.l1constants),
|
|
163
|
-
ts: getTimestampForSlot(slot, this.l1constants),
|
|
164
223
|
slot,
|
|
224
|
+
epoch,
|
|
225
|
+
ts: getTimestampForSlot(slot, this.l1constants),
|
|
165
226
|
};
|
|
166
227
|
}
|
|
167
228
|
|
|
@@ -194,7 +255,7 @@ export class EpochCache implements EpochCacheInterface {
|
|
|
194
255
|
public async isEscapeHatchOpenAtSlot(slot: SlotTag = 'now'): Promise<boolean> {
|
|
195
256
|
const epoch =
|
|
196
257
|
slot === 'now'
|
|
197
|
-
? this.
|
|
258
|
+
? this.getEpochNow()
|
|
198
259
|
: slot === 'next'
|
|
199
260
|
? this.getEpochAndSlotInNextL1Slot().epoch
|
|
200
261
|
: getEpochAtSlot(slot, this.l1constants);
|
|
@@ -229,7 +290,7 @@ export class EpochCache implements EpochCacheInterface {
|
|
|
229
290
|
return epochData;
|
|
230
291
|
}
|
|
231
292
|
|
|
232
|
-
private getEpochAndTimestamp(slot: SlotTag = 'now') {
|
|
293
|
+
private getEpochAndTimestamp(slot: SlotTag = 'now'): { epoch: EpochNumber; ts: bigint } {
|
|
233
294
|
if (slot === 'now') {
|
|
234
295
|
return this.getEpochAndSlotNow();
|
|
235
296
|
} else if (slot === 'next') {
|
|
@@ -279,13 +340,24 @@ export class EpochCache implements EpochCacheInterface {
|
|
|
279
340
|
return BigInt(keccak256(this.getProposerIndexEncoding(epoch, slot, seed))) % size;
|
|
280
341
|
}
|
|
281
342
|
|
|
282
|
-
/** Returns the current and next L2 slot
|
|
343
|
+
/** Returns the current and next L2 slot in next eth L1 Slot. */
|
|
283
344
|
public getCurrentAndNextSlot(): { currentSlot: SlotNumber; nextSlot: SlotNumber } {
|
|
284
|
-
const
|
|
345
|
+
const currentSlot = this.getSlotNow();
|
|
285
346
|
const next = this.getEpochAndSlotInNextL1Slot();
|
|
286
347
|
|
|
287
348
|
return {
|
|
288
|
-
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,
|
|
289
361
|
nextSlot: next.slot,
|
|
290
362
|
};
|
|
291
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 = {
|
|
@@ -13,6 +19,8 @@ const DEFAULT_L1_CONSTANTS: L1RollupConstants = {
|
|
|
13
19
|
epochDuration: 16,
|
|
14
20
|
ethereumSlotDuration: 12,
|
|
15
21
|
proofSubmissionEpochs: 2,
|
|
22
|
+
targetCommitteeSize: 48,
|
|
23
|
+
rollupManaLimit: Number.MAX_SAFE_INTEGER,
|
|
16
24
|
};
|
|
17
25
|
|
|
18
26
|
/**
|
|
@@ -30,6 +38,7 @@ export class TestEpochCache implements EpochCacheInterface {
|
|
|
30
38
|
private seed: bigint = 0n;
|
|
31
39
|
private registeredValidators: EthAddress[] = [];
|
|
32
40
|
private l1Constants: L1RollupConstants;
|
|
41
|
+
private proposerPipeliningEnabled = false;
|
|
33
42
|
|
|
34
43
|
constructor(l1Constants: Partial<L1RollupConstants> = {}) {
|
|
35
44
|
this.l1Constants = { ...DEFAULT_L1_CONSTANTS, ...l1Constants };
|
|
@@ -102,6 +111,10 @@ export class TestEpochCache implements EpochCacheInterface {
|
|
|
102
111
|
return this.l1Constants;
|
|
103
112
|
}
|
|
104
113
|
|
|
114
|
+
setProposerPipeliningEnabled(enabled: boolean): void {
|
|
115
|
+
this.proposerPipeliningEnabled = enabled;
|
|
116
|
+
}
|
|
117
|
+
|
|
105
118
|
getCommittee(_slot?: SlotTag): Promise<EpochCommitteeInfo> {
|
|
106
119
|
const epoch = getEpochAtSlot(this.currentSlot, this.l1Constants);
|
|
107
120
|
return Promise.resolve({
|
|
@@ -112,19 +125,58 @@ export class TestEpochCache implements EpochCacheInterface {
|
|
|
112
125
|
});
|
|
113
126
|
}
|
|
114
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
|
+
|
|
115
150
|
getEpochAndSlotNow(): EpochAndSlot & { nowMs: bigint } {
|
|
116
|
-
const
|
|
117
|
-
const ts = getTimestampRangeForEpoch(
|
|
118
|
-
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
|
+
};
|
|
119
159
|
}
|
|
120
160
|
|
|
121
|
-
getEpochAndSlotInNextL1Slot(): EpochAndSlot & {
|
|
122
|
-
const
|
|
123
|
-
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);
|
|
124
164
|
const nextSlot = getSlotAtTimestamp(nextSlotTs, this.l1Constants);
|
|
125
|
-
const
|
|
126
|
-
const ts = getTimestampRangeForEpoch(
|
|
127
|
-
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) };
|
|
128
180
|
}
|
|
129
181
|
|
|
130
182
|
getProposerIndexEncoding(epoch: EpochNumber, slot: SlotNumber, seed: bigint): `0x${string}` {
|
|
@@ -140,9 +192,22 @@ export class TestEpochCache implements EpochCacheInterface {
|
|
|
140
192
|
}
|
|
141
193
|
|
|
142
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
|
+
|
|
143
208
|
return {
|
|
144
|
-
|
|
145
|
-
nextSlot:
|
|
209
|
+
targetSlot,
|
|
210
|
+
nextSlot: next.slot,
|
|
146
211
|
};
|
|
147
212
|
}
|
|
148
213
|
|
|
@@ -163,6 +228,10 @@ export class TestEpochCache implements EpochCacheInterface {
|
|
|
163
228
|
return Promise.resolve(validators.filter(v => committeeSet.has(v.toString())));
|
|
164
229
|
}
|
|
165
230
|
|
|
231
|
+
isEscapeHatchOpen(_epoch: EpochNumber): Promise<boolean> {
|
|
232
|
+
return Promise.resolve(this.escapeHatchOpen);
|
|
233
|
+
}
|
|
234
|
+
|
|
166
235
|
isEscapeHatchOpenAtSlot(_slot?: SlotTag): Promise<boolean> {
|
|
167
236
|
return Promise.resolve(this.escapeHatchOpen);
|
|
168
237
|
}
|