@aztec/epoch-cache 0.0.1-commit.f2ce05ee → 0.0.1-commit.f5d02921e
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 -6
- package/dest/epoch_cache.d.ts.map +1 -1
- package/dest/epoch_cache.js +82 -34
- 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 +56 -12
- package/package.json +5 -6
- package/src/config.ts +9 -3
- package/src/epoch_cache.ts +97 -27
- package/src/test/test_epoch_cache.ts +80 -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,39 @@ 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
|
-
nowInSeconds(): bigint;
|
|
76
101
|
private getEpochAndSlotAtSlot;
|
|
77
102
|
getEpochAndSlotInNextL1Slot(): EpochAndSlot & {
|
|
78
|
-
|
|
103
|
+
nowSeconds: bigint;
|
|
104
|
+
};
|
|
105
|
+
getTargetEpochAndSlotInNextL1Slot(): EpochAndSlot & {
|
|
106
|
+
nowSeconds: bigint;
|
|
79
107
|
};
|
|
80
108
|
private getEpochAndSlotAtTimestamp;
|
|
81
109
|
getCommitteeForEpoch(epoch: EpochNumber): Promise<EpochCommitteeInfo>;
|
|
@@ -106,11 +134,16 @@ export declare class EpochCache implements EpochCacheInterface {
|
|
|
106
134
|
*/
|
|
107
135
|
getProposerIndexEncoding(epoch: EpochNumber, slot: SlotNumber, seed: bigint): `0x${string}`;
|
|
108
136
|
computeProposerIndex(slot: SlotNumber, epoch: EpochNumber, seed: bigint, size: bigint): bigint;
|
|
109
|
-
/** Returns the current and next L2 slot
|
|
137
|
+
/** Returns the current and next L2 slot in next eth L1 Slot. */
|
|
110
138
|
getCurrentAndNextSlot(): {
|
|
111
139
|
currentSlot: SlotNumber;
|
|
112
140
|
nextSlot: SlotNumber;
|
|
113
141
|
};
|
|
142
|
+
/** Returns the target and next L2 slot in the next L1 slot. */
|
|
143
|
+
getTargetAndNextSlot(): {
|
|
144
|
+
targetSlot: SlotNumber;
|
|
145
|
+
nextSlot: SlotNumber;
|
|
146
|
+
};
|
|
114
147
|
/**
|
|
115
148
|
* Get the proposer attester address in the given L2 slot
|
|
116
149
|
* @returns The proposer attester address. If the committee does not exist, we throw a NoCommitteeError.
|
|
@@ -131,4 +164,4 @@ export declare class EpochCache implements EpochCacheInterface {
|
|
|
131
164
|
filterInCommittee(slot: SlotTag, validators: EthAddress[]): Promise<EthAddress[]>;
|
|
132
165
|
getRegisteredValidators(): Promise<EthAddress[]>;
|
|
133
166
|
}
|
|
134
|
-
//# sourceMappingURL=data:application/json;base64,
|
|
167
|
+
//# sourceMappingURL=data:application/json;base64,eyJ2ZXJzaW9uIjozLCJmaWxlIjoiZXBvY2hfY2FjaGUuZC50cyIsInNvdXJjZVJvb3QiOiIiLCJzb3VyY2VzIjpbIi4uL3NyYy9lcG9jaF9jYWNoZS50cyJdLCJuYW1lcyI6W10sIm1hcHBpbmdzIjoiQUFFQSxPQUFPLEVBQW9CLGNBQWMsRUFBRSxNQUFNLDJCQUEyQixDQUFDO0FBQzdFLE9BQU8sRUFBRSxXQUFXLEVBQUUsVUFBVSxFQUFFLE1BQU0saUNBQWlDLENBQUM7QUFDMUUsT0FBTyxFQUFFLFVBQVUsRUFBRSxNQUFNLCtCQUErQixDQUFDO0FBRTNELE9BQU8sRUFBRSxZQUFZLEVBQUUsTUFBTSx5QkFBeUIsQ0FBQztBQUN2RCxPQUFPLEVBQ0wsS0FBSyxpQkFBaUIsRUFRdkIsTUFBTSw2QkFBNkIsQ0FBQztBQUlyQyxPQUFPLEVBQUUsS0FBSyxnQkFBZ0IsRUFBOEIsTUFBTSxhQUFhLENBQUM7QUFFaEYsK0VBQStFO0FBQy9FLGVBQU8sTUFBTSwrQkFBK0IsSUFBSSxDQUFDO0FBRWpELHdEQUF3RDtBQUN4RCxNQUFNLE1BQU0sWUFBWSxHQUFHO0lBQ3pCLElBQUksRUFBRSxVQUFVLENBQUM7SUFDakIsS0FBSyxFQUFFLFdBQVcsQ0FBQztJQUNuQixFQUFFLEVBQUUsTUFBTSxDQUFDO0NBQ1osQ0FBQztBQUVGLE1BQU0sTUFBTSxrQkFBa0IsR0FBRztJQUMvQixTQUFTLEVBQUUsVUFBVSxFQUFFLEdBQUcsU0FBUyxDQUFDO0lBQ3BDLElBQUksRUFBRSxNQUFNLENBQUM7SUFDYixLQUFLLEVBQUUsV0FBVyxDQUFDO0lBQ25CLCtEQUErRDtJQUMvRCxpQkFBaUIsRUFBRSxPQUFPLENBQUM7Q0FDNUIsQ0FBQztBQUVGLE1BQU0sTUFBTSxPQUFPLEdBQUcsS0FBSyxHQUFHLE1BQU0sR0FBRyxVQUFVLENBQUM7QUFFbEQsTUFBTSxXQUFXLG1CQUFtQjtJQUNsQyxZQUFZLENBQUMsSUFBSSxFQUFFLE9BQU8sR0FBRyxTQUFTLEdBQUcsT0FBTyxDQUFDLGtCQUFrQixDQUFDLENBQUM7SUFDckUsVUFB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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":"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,EAQvB,MAAM,6BAA6B,CAAC;AAIrC,OAAO,EAAE,KAAK,gBAAgB,EAA8B,MAAM,aAAa,CAAC;AAEhF,+EAA+E;AAC/E,eAAO,MAAM,+BAA+B,IAAI,CAAC;AAEjD,wDAAwD;AACxD,MAAM,MAAM,YAAY,GAAG;IACzB,IAAI,EAAE,UAAU,CAAC;IACjB,KAAK,EAAE,WAAW,CAAC;IACnB,EAAE,EAAE,MAAM,CAAC;CACZ,CAAC;AAEF,MAAM,MAAM,kBAAkB,GAAG;IAC/B,SAAS,EAAE,UAAU,EAAE,GAAG,SAAS,CAAC;IACpC,IAAI,EAAE,MAAM,CAAC;IACb,KAAK,EAAE,WAAW,CAAC;IACnB,+DAA+D;IAC/D,iBAAiB,EAAE,OAAO,CAAC;CAC5B,CAAC;AAEF,MAAM,MAAM,OAAO,GAAG,KAAK,GAAG,MAAM,GAAG,UAAU,CAAC;AAElD,MAAM,WAAW,mBAAmB;IAClC,YAAY,CAAC,IAAI,EAAE,OAAO,GAAG,SAAS,GAAG,OAAO,CAAC,kBAAkB,CAAC,CAAC;IACrE,UAAU,IAAI,UAAU,CAAC;IACzB,aAAa,IAAI,UAAU,CAAC;IAC5B,WAAW,IAAI,WAAW,CAAC;IAC3B,cAAc,IAAI,WAAW,CAAC;IAC9B,kBAAkB,IAAI,YAAY,GAAG;QAAE,KAAK,EAAE,MAAM,CAAA;KAAE,CAAC;IACvD,2BAA2B,IAAI,YAAY,GAAG;QAAE,UAAU,EAAE,MAAM,CAAA;KAAE,CAAC;IACrE,iFAAiF;IACjF,iCAAiC,IAAI,YAAY,GAAG;QAAE,UAAU,EAAE,MAAM,CAAA;KAAE,CAAC;IAC3E,2BAA2B,IAAI,OAAO,CAAC;IACvC,iBAAiB,CAAC,KAAK,EAAE,WAAW,GAAG,OAAO,CAAC,OAAO,CAAC,CAAC;IACxD,uBAAuB,CAAC,IAAI,EAAE,OAAO,GAAG,OAAO,CAAC,OAAO,CAAC,CAAC;IACzD,wBAAwB,CAAC,KAAK,EAAE,WAAW,EAAE,IAAI,EAAE,UAAU,EAAE,IAAI,EAAE,MAAM,GAAG,KAAK,MAAM,EAAE,CAAC;IAC5F,oBAAoB,CAAC,IAAI,EAAE,UAAU,EAAE,KAAK,EAAE,WAAW,EAAE,IAAI,EAAE,MAAM,EAAE,IAAI,EAAE,MAAM,GAAG,MAAM,CAAC;IAC/F,qBAAqB,IAAI;QAAE,WAAW,EAAE,UAAU,CAAC;QAAC,QAAQ,EAAE,UAAU,CAAA;KAAE,CAAC;IAC3E,oBAAoB,IAAI;QAAE,UAAU,EAAE,UAAU,CAAC;QAAC,QAAQ,EAAE,UAAU,CAAA;KAAE,CAAC;IACzE,gCAAgC,CAAC,IAAI,EAAE,UAAU,GAAG,OAAO,CAAC,UAAU,GAAG,SAAS,CAAC,CAAC;IACpF,uBAAuB,IAAI,OAAO,CAAC,UAAU,EAAE,CAAC,CAAC;IACjD,aAAa,CAAC,IAAI,EAAE,OAAO,EAAE,SAAS,EAAE,UAAU,GAAG,OAAO,CAAC,OAAO,CAAC,CAAC;IACtE,iBAAiB,CAAC,IAAI,EAAE,OAAO,EAAE,UAAU,EAAE,UAAU,EAAE,GAAG,OAAO,CAAC,UAAU,EAAE,CAAC,CAAC;IAClF,cAAc,IAAI,iBAAiB,CAAC;CACrC;AAED;;;;;;;;GAQG;AACH,qBAAa,UAAW,YAAW,mBAAmB;IAUlD,OAAO,CAAC,MAAM;IACd,OAAO,CAAC,QAAQ,CAAC,WAAW;IAI5B,OAAO,CAAC,QAAQ,CAAC,YAAY;IAC7B,SAAS,CAAC,QAAQ,CAAC,MAAM;;;;;IAd3B,SAAS,CAAC,KAAK,EAAE,GAAG,CAAC,WAAW,EAAE,kBAAkB,CAAC,CAAa;IAClE,OAAO,CAAC,aAAa,CAA0B;IAC/C,OAAO,CAAC,oBAAoB,CAAK;IACjC,OAAO,CAAC,QAAQ,CAAC,GAAG,CAAuC;IAE3D,SAAS,CAAC,wBAAwB,EAAE,OAAO,CAAC;IAE5C,YACU,MAAM,EAAE,cAAc,EACb,WAAW,EAAE,iBAAiB,GAAG;QAChD,0BAA0B,EAAE,MAAM,CAAC;QACnC,oBAAoB,EAAE,MAAM,CAAC;KAC9B,EACgB,YAAY,GAAE,YAAiC,EAC7C,MAAM;;;;KAA0F,EAOpH;IAED,OAAa,MAAM,CACjB,eAAe,EAAE,UAAU,GAAG,cAAc,EAC5C,MAAM,CAAC,EAAE,gBAAgB,EACzB,IAAI,GAAE;QAAE,YAAY,CAAC,EAAE,YAAY,CAAA;KAAO,uBA0D3C;IAEM,cAAc,IAAI,iBAAiB,CAEzC;IAEM,2BAA2B,IAAI,OAAO,CAE5C;IAEM,UAAU,IAAI,UAAU,CAE9B;IAEM,aAAa,IAAI,UAAU,CAIjC;IAEM,WAAW,IAAI,WAAW,CAEhC;IAEM,cAAc,IAAI,WAAW,CAEnC;IAEM,kBAAkB,IAAI,YAAY,GAAG;QAAE,KAAK,EAAE,MAAM,CAAA;KAAE,CAI5D;IAED,OAAO,CAAC,qBAAqB;IAItB,2BAA2B,IAAI,YAAY,GAAG;QAAE,UAAU,EAAE,MAAM,CAAA;KAAE,CAI1E;IAEM,iCAAiC,IAAI,YAAY,GAAG;QAAE,UAAU,EAAE,MAAM,CAAA;KAAE,CAShF;IAED,OAAO,CAAC,0BAA0B;IAU3B,oBAAoB,CAAC,KAAK,EAAE,WAAW,GAAG,OAAO,CAAC,kBAAkB,CAAC,CAG3E;IAED;;;;;OAKG;IACU,iBAAiB,CAAC,KAAK,EAAE,WAAW,GAAG,OAAO,CAAC,OAAO,CAAC,CAOnE;IAED;;;;;OAKG;IACU,uBAAuB,CAAC,IAAI,GAAE,OAAe,GAAG,OAAO,CAAC,OAAO,CAAC,CAS5E;IAED;;;;OAIG;IACU,YAAY,CAAC,IAAI,GAAE,OAAe,GAAG,OAAO,CAAC,kBAAkB,CAAC,CAoB5E;IAED,OAAO,CAAC,oBAAoB;YAUd,gBAAgB;IAkB9B;;OAEG;IACH,wBAAwB,CAAC,KAAK,EAAE,WAAW,EAAE,IAAI,EAAE,UAAU,EAAE,IAAI,EAAE,MAAM,GAAG,KAAK,MAAM,EAAE,CAS1F;IAEM,oBAAoB,CAAC,IAAI,EAAE,UAAU,EAAE,KAAK,EAAE,WAAW,EAAE,IAAI,EAAE,MAAM,EAAE,IAAI,EAAE,MAAM,GAAG,MAAM,CAMpG;IAED,gEAAgE;IACzD,qBAAqB,IAAI;QAAE,WAAW,EAAE,UAAU,CAAC;QAAC,QAAQ,EAAE,UAAU,CAAA;KAAE,CAQhF;IAED,+DAA+D;IACxD,oBAAoB,IAAI;QAAE,UAAU,EAAE,UAAU,CAAC;QAAC,QAAQ,EAAE,UAAU,CAAA;KAAE,CAW9E;IAED;;;;OAIG;IACI,gCAAgC,CAAC,IAAI,EAAE,UAAU,GAAG,OAAO,CAAC,UAAU,GAAG,SAAS,CAAC,CAGzF;IAED;;;;OAIG;IACI,oCAAoC,IAAI,OAAO,CAAC,UAAU,GAAG,SAAS,CAAC,CAG7E;YAQa,4BAA4B;IAanC,6BAA6B,CAClC,kBAAkB,EAAE,kBAAkB,EACtC,IAAI,EAAE,UAAU,GACf,UAAU,GAAG,SAAS,CAYxB;IAED,4DAA4D;IACtD,aAAa,CAAC,IAAI,EAAE,OAAO,EAAE,SAAS,EAAE,UAAU,GAAG,OAAO,CAAC,OAAO,CAAC,CAM1E;IAED,+FAA+F;IACzF,iBAAiB,CAAC,IAAI,EAAE,OAAO,EAAE,UAAU,EAAE,UAAU,EAAE,GAAG,OAAO,CAAC,UAAU,EAAE,CAAC,CAOtF;IAEK,uBAAuB,IAAI,OAAO,CAAC,UAAU,EAAE,CAAC,CAUrD;CACF"}
|
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, getNextL1SlotTimestamp, getSlotAtNextL1Block, 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,14 +57,14 @@ 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, targetCommitteeSize] = 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(),
|
|
@@ -65,7 +72,8 @@ import { getEpochCacheConfigEnvVars } from './config.js';
|
|
|
65
72
|
rollup.getEpochDuration(),
|
|
66
73
|
rollup.getLagInEpochsForValidatorSet(),
|
|
67
74
|
rollup.getLagInEpochsForRandao(),
|
|
68
|
-
rollup.getTargetCommitteeSize()
|
|
75
|
+
rollup.getTargetCommitteeSize(),
|
|
76
|
+
rollup.getManaLimit()
|
|
69
77
|
]);
|
|
70
78
|
const l1RollupConstants = {
|
|
71
79
|
l1StartBlock,
|
|
@@ -76,13 +84,35 @@ import { getEpochCacheConfigEnvVars } from './config.js';
|
|
|
76
84
|
ethereumSlotDuration: config.ethereumSlotDuration,
|
|
77
85
|
lagInEpochsForValidatorSet: Number(lagInEpochsForValidatorSet),
|
|
78
86
|
lagInEpochsForRandao: Number(lagInEpochsForRandao),
|
|
79
|
-
targetCommitteeSize: Number(targetCommitteeSize)
|
|
87
|
+
targetCommitteeSize: Number(targetCommitteeSize),
|
|
88
|
+
rollupManaLimit: Number(rollupManaLimit)
|
|
80
89
|
};
|
|
81
|
-
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
|
+
});
|
|
82
95
|
}
|
|
83
96
|
getL1Constants() {
|
|
84
97
|
return this.l1constants;
|
|
85
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
|
+
}
|
|
86
116
|
getEpochAndSlotNow() {
|
|
87
117
|
const nowMs = BigInt(this.dateProvider.now());
|
|
88
118
|
const nowSeconds = nowMs / 1000n;
|
|
@@ -91,32 +121,37 @@ import { getEpochCacheConfigEnvVars } from './config.js';
|
|
|
91
121
|
nowMs
|
|
92
122
|
};
|
|
93
123
|
}
|
|
94
|
-
nowInSeconds() {
|
|
95
|
-
return BigInt(Math.floor(this.dateProvider.now() / 1000));
|
|
96
|
-
}
|
|
97
124
|
getEpochAndSlotAtSlot(slot) {
|
|
98
|
-
|
|
99
|
-
const ts = getTimestampRangeForEpoch(epoch, this.l1constants)[0];
|
|
100
|
-
return {
|
|
101
|
-
epoch,
|
|
102
|
-
ts,
|
|
103
|
-
slot
|
|
104
|
-
};
|
|
125
|
+
return this.getEpochAndSlotAtTimestamp(getTimestampForSlot(slot, this.l1constants));
|
|
105
126
|
}
|
|
106
127
|
getEpochAndSlotInNextL1Slot() {
|
|
107
|
-
const
|
|
108
|
-
const nextSlotTs =
|
|
128
|
+
const nowSeconds = this.dateProvider.nowInSeconds();
|
|
129
|
+
const nextSlotTs = getNextL1SlotTimestamp(nowSeconds, this.l1constants);
|
|
109
130
|
return {
|
|
110
131
|
...this.getEpochAndSlotAtTimestamp(nextSlotTs),
|
|
111
|
-
|
|
132
|
+
nowSeconds: BigInt(nowSeconds)
|
|
133
|
+
};
|
|
134
|
+
}
|
|
135
|
+
getTargetEpochAndSlotInNextL1Slot() {
|
|
136
|
+
if (!this.isProposerPipeliningEnabled()) {
|
|
137
|
+
return this.getEpochAndSlotInNextL1Slot();
|
|
138
|
+
}
|
|
139
|
+
const result = this.getEpochAndSlotInNextL1Slot();
|
|
140
|
+
const offset = PROPOSER_PIPELINING_SLOT_OFFSET;
|
|
141
|
+
const targetSlot = SlotNumber(result.slot + offset);
|
|
142
|
+
return {
|
|
143
|
+
...result,
|
|
144
|
+
slot: targetSlot,
|
|
145
|
+
epoch: getEpochAtSlot(targetSlot, this.l1constants)
|
|
112
146
|
};
|
|
113
147
|
}
|
|
114
148
|
getEpochAndSlotAtTimestamp(ts) {
|
|
115
149
|
const slot = getSlotAtTimestamp(ts, this.l1constants);
|
|
150
|
+
const epoch = getEpochNumberAtTimestamp(ts, this.l1constants);
|
|
116
151
|
return {
|
|
117
|
-
|
|
118
|
-
|
|
119
|
-
slot
|
|
152
|
+
slot,
|
|
153
|
+
epoch,
|
|
154
|
+
ts: getTimestampForSlot(slot, this.l1constants)
|
|
120
155
|
};
|
|
121
156
|
}
|
|
122
157
|
getCommitteeForEpoch(epoch) {
|
|
@@ -142,7 +177,7 @@ import { getEpochCacheConfigEnvVars } from './config.js';
|
|
|
142
177
|
* This is a lightweight helper intended for callers that already have a slot number and only
|
|
143
178
|
* need the escape hatch flag (without pulling full committee info).
|
|
144
179
|
*/ async isEscapeHatchOpenAtSlot(slot = 'now') {
|
|
145
|
-
const epoch = slot === 'now' ? this.
|
|
180
|
+
const epoch = slot === 'now' ? this.getEpochNow() : slot === 'next' ? this.getEpochAndSlotInNextL1Slot().epoch : getEpochAtSlot(slot, this.l1constants);
|
|
146
181
|
return await this.isEscapeHatchOpen(epoch);
|
|
147
182
|
}
|
|
148
183
|
/**
|
|
@@ -227,14 +262,26 @@ import { getEpochCacheConfigEnvVars } from './config.js';
|
|
|
227
262
|
}
|
|
228
263
|
return BigInt(keccak256(this.getProposerIndexEncoding(epoch, slot, seed))) % size;
|
|
229
264
|
}
|
|
230
|
-
/** Returns the current and next L2 slot
|
|
231
|
-
const
|
|
265
|
+
/** Returns the current and next L2 slot in next eth L1 Slot. */ getCurrentAndNextSlot() {
|
|
266
|
+
const currentSlot = this.getSlotNow();
|
|
232
267
|
const next = this.getEpochAndSlotInNextL1Slot();
|
|
233
268
|
return {
|
|
234
|
-
currentSlot
|
|
269
|
+
currentSlot,
|
|
235
270
|
nextSlot: next.slot
|
|
236
271
|
};
|
|
237
272
|
}
|
|
273
|
+
/** Returns the target and next L2 slot in the next L1 slot. */ getTargetAndNextSlot() {
|
|
274
|
+
const nowSeconds = BigInt(this.dateProvider.nowInSeconds());
|
|
275
|
+
const offset = this.isProposerPipeliningEnabled() ? PROPOSER_PIPELINING_SLOT_OFFSET : 0;
|
|
276
|
+
const currentSlot = getSlotAtTimestamp(nowSeconds, this.l1constants);
|
|
277
|
+
const targetSlot = SlotNumber(currentSlot + offset);
|
|
278
|
+
const nextL2SlotOnL1 = getSlotAtNextL1Block(nowSeconds, this.l1constants);
|
|
279
|
+
const nextSlot = SlotNumber(nextL2SlotOnL1 + offset);
|
|
280
|
+
return {
|
|
281
|
+
targetSlot,
|
|
282
|
+
nextSlot
|
|
283
|
+
};
|
|
284
|
+
}
|
|
238
285
|
/**
|
|
239
286
|
* Get the proposer attester address in the given L2 slot
|
|
240
287
|
* @returns The proposer attester address. If the committee does not exist, we throw a NoCommitteeError.
|
|
@@ -292,10 +339,11 @@ import { getEpochCacheConfigEnvVars } from './config.js';
|
|
|
292
339
|
async getRegisteredValidators() {
|
|
293
340
|
const validatorRefreshIntervalMs = this.config.validatorRefreshIntervalSeconds * 1000;
|
|
294
341
|
const validatorRefreshTime = this.lastValidatorRefresh + validatorRefreshIntervalMs;
|
|
295
|
-
|
|
296
|
-
|
|
342
|
+
const now = this.dateProvider.now();
|
|
343
|
+
if (validatorRefreshTime < now) {
|
|
344
|
+
const currentSet = await this.rollup.getAttesters(BigInt(Math.floor(now / 1000)));
|
|
297
345
|
this.allValidators = new Set(currentSet.map((v)=>v.toString()));
|
|
298
|
-
this.lastValidatorRefresh =
|
|
346
|
+
this.lastValidatorRefresh = now;
|
|
299
347
|
}
|
|
300
348
|
return Array.from(this.allValidators.keys()).map((v)=>EthAddress.fromString(v));
|
|
301
349
|
}
|
|
@@ -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,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,
|
|
@@ -7,7 +8,8 @@ import { getEpochAtSlot, getSlotAtTimestamp, getTimestampRangeForEpoch } from '@
|
|
|
7
8
|
epochDuration: 16,
|
|
8
9
|
ethereumSlotDuration: 12,
|
|
9
10
|
proofSubmissionEpochs: 2,
|
|
10
|
-
targetCommitteeSize: 48
|
|
11
|
+
targetCommitteeSize: 48,
|
|
12
|
+
rollupManaLimit: Number.MAX_SAFE_INTEGER
|
|
11
13
|
};
|
|
12
14
|
/**
|
|
13
15
|
* A test implementation of EpochCacheInterface that allows manual configuration
|
|
@@ -23,6 +25,7 @@ import { getEpochAtSlot, getSlotAtTimestamp, getTimestampRangeForEpoch } from '@
|
|
|
23
25
|
seed = 0n;
|
|
24
26
|
registeredValidators = [];
|
|
25
27
|
l1Constants;
|
|
28
|
+
proposerPipeliningEnabled = false;
|
|
26
29
|
constructor(l1Constants = {}){
|
|
27
30
|
this.l1Constants = {
|
|
28
31
|
...DEFAULT_L1_CONSTANTS,
|
|
@@ -84,6 +87,9 @@ import { getEpochAtSlot, getSlotAtTimestamp, getTimestampRangeForEpoch } from '@
|
|
|
84
87
|
getL1Constants() {
|
|
85
88
|
return this.l1Constants;
|
|
86
89
|
}
|
|
90
|
+
setProposerPipeliningEnabled(enabled) {
|
|
91
|
+
this.proposerPipeliningEnabled = enabled;
|
|
92
|
+
}
|
|
87
93
|
getCommittee(_slot) {
|
|
88
94
|
const epoch = getEpochAtSlot(this.currentSlot, this.l1Constants);
|
|
89
95
|
return Promise.resolve({
|
|
@@ -93,27 +99,52 @@ import { getEpochAtSlot, getSlotAtTimestamp, getTimestampRangeForEpoch } from '@
|
|
|
93
99
|
isEscapeHatchOpen: this.escapeHatchOpen
|
|
94
100
|
});
|
|
95
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
|
+
}
|
|
96
117
|
getEpochAndSlotNow() {
|
|
97
|
-
const
|
|
98
|
-
const ts = getTimestampRangeForEpoch(
|
|
118
|
+
const epochNow = getEpochAtSlot(this.currentSlot, this.l1Constants);
|
|
119
|
+
const ts = getTimestampRangeForEpoch(epochNow, this.l1Constants)[0];
|
|
99
120
|
return {
|
|
100
|
-
epoch,
|
|
121
|
+
epoch: epochNow,
|
|
101
122
|
slot: this.currentSlot,
|
|
102
123
|
ts,
|
|
103
124
|
nowMs: ts * 1000n
|
|
104
125
|
};
|
|
105
126
|
}
|
|
106
127
|
getEpochAndSlotInNextL1Slot() {
|
|
107
|
-
const
|
|
108
|
-
const nextSlotTs =
|
|
128
|
+
const nowTs = getTimestampRangeForEpoch(getEpochAtSlot(this.currentSlot, this.l1Constants), this.l1Constants)[0];
|
|
129
|
+
const nextSlotTs = nowTs + BigInt(this.l1Constants.ethereumSlotDuration);
|
|
109
130
|
const nextSlot = getSlotAtTimestamp(nextSlotTs, this.l1Constants);
|
|
110
|
-
const
|
|
111
|
-
const ts = getTimestampRangeForEpoch(
|
|
131
|
+
const epochNow = getEpochAtSlot(nextSlot, this.l1Constants);
|
|
132
|
+
const ts = getTimestampRangeForEpoch(epochNow, this.l1Constants)[0];
|
|
112
133
|
return {
|
|
113
|
-
epoch,
|
|
134
|
+
epoch: epochNow,
|
|
114
135
|
slot: nextSlot,
|
|
115
136
|
ts,
|
|
116
|
-
|
|
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)
|
|
117
148
|
};
|
|
118
149
|
}
|
|
119
150
|
getProposerIndexEncoding(epoch, slot, seed) {
|
|
@@ -127,9 +158,19 @@ import { getEpochAtSlot, getSlotAtTimestamp, getTimestampRangeForEpoch } from '@
|
|
|
127
158
|
return BigInt(slot) % size;
|
|
128
159
|
}
|
|
129
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();
|
|
130
171
|
return {
|
|
131
|
-
|
|
132
|
-
nextSlot:
|
|
172
|
+
targetSlot,
|
|
173
|
+
nextSlot: next.slot
|
|
133
174
|
};
|
|
134
175
|
}
|
|
135
176
|
getProposerAttesterAddressInSlot(_slot) {
|
|
@@ -145,6 +186,9 @@ import { getEpochAtSlot, getSlotAtTimestamp, getTimestampRangeForEpoch } from '@
|
|
|
145
186
|
const committeeSet = new Set(this.committee.map((v)=>v.toString()));
|
|
146
187
|
return Promise.resolve(validators.filter((v)=>committeeSet.has(v.toString())));
|
|
147
188
|
}
|
|
189
|
+
isEscapeHatchOpen(_epoch) {
|
|
190
|
+
return Promise.resolve(this.escapeHatchOpen);
|
|
191
|
+
}
|
|
148
192
|
isEscapeHatchOpenAtSlot(_slot) {
|
|
149
193
|
return Promise.resolve(this.escapeHatchOpen);
|
|
150
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.f5d02921e",
|
|
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.f5d02921e",
|
|
30
|
+
"@aztec/foundation": "0.0.1-commit.f5d02921e",
|
|
31
|
+
"@aztec/l1-artifacts": "0.0.1-commit.f5d02921e",
|
|
32
|
+
"@aztec/stdlib": "0.0.1-commit.f5d02921e",
|
|
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';
|
|
@@ -8,19 +9,24 @@ import {
|
|
|
8
9
|
type L1RollupConstants,
|
|
9
10
|
getEpochAtSlot,
|
|
10
11
|
getEpochNumberAtTimestamp,
|
|
12
|
+
getNextL1SlotTimestamp,
|
|
13
|
+
getSlotAtNextL1Block,
|
|
11
14
|
getSlotAtTimestamp,
|
|
12
15
|
getSlotRangeForEpoch,
|
|
13
16
|
getTimestampForSlot,
|
|
14
|
-
getTimestampRangeForEpoch,
|
|
15
17
|
} from '@aztec/stdlib/epoch-helpers';
|
|
16
18
|
|
|
17
|
-
import { createPublicClient, encodeAbiParameters,
|
|
19
|
+
import { createPublicClient, encodeAbiParameters, keccak256 } from 'viem';
|
|
18
20
|
|
|
19
21
|
import { type EpochCacheConfig, getEpochCacheConfigEnvVars } from './config.js';
|
|
20
22
|
|
|
23
|
+
/** When proposer pipelining is enabled, the proposer builds one slot ahead. */
|
|
24
|
+
export const PROPOSER_PIPELINING_SLOT_OFFSET = 1;
|
|
25
|
+
|
|
26
|
+
/** Flat return type for compound epoch/slot getters. */
|
|
21
27
|
export type EpochAndSlot = {
|
|
22
|
-
epoch: EpochNumber;
|
|
23
28
|
slot: SlotNumber;
|
|
29
|
+
epoch: EpochNumber;
|
|
24
30
|
ts: bigint;
|
|
25
31
|
};
|
|
26
32
|
|
|
@@ -36,11 +42,21 @@ export type SlotTag = 'now' | 'next' | SlotNumber;
|
|
|
36
42
|
|
|
37
43
|
export interface EpochCacheInterface {
|
|
38
44
|
getCommittee(slot: SlotTag | undefined): Promise<EpochCommitteeInfo>;
|
|
45
|
+
getSlotNow(): SlotNumber;
|
|
46
|
+
getTargetSlot(): SlotNumber;
|
|
47
|
+
getEpochNow(): EpochNumber;
|
|
48
|
+
getTargetEpoch(): EpochNumber;
|
|
39
49
|
getEpochAndSlotNow(): EpochAndSlot & { nowMs: bigint };
|
|
40
|
-
getEpochAndSlotInNextL1Slot(): EpochAndSlot & {
|
|
50
|
+
getEpochAndSlotInNextL1Slot(): EpochAndSlot & { nowSeconds: bigint };
|
|
51
|
+
/** Returns epoch/slot info for the next L1 slot with pipeline offset applied. */
|
|
52
|
+
getTargetEpochAndSlotInNextL1Slot(): EpochAndSlot & { nowSeconds: bigint };
|
|
53
|
+
isProposerPipeliningEnabled(): boolean;
|
|
54
|
+
isEscapeHatchOpen(epoch: EpochNumber): Promise<boolean>;
|
|
55
|
+
isEscapeHatchOpenAtSlot(slot: SlotTag): Promise<boolean>;
|
|
41
56
|
getProposerIndexEncoding(epoch: EpochNumber, slot: SlotNumber, seed: bigint): `0x${string}`;
|
|
42
57
|
computeProposerIndex(slot: SlotNumber, epoch: EpochNumber, seed: bigint, size: bigint): bigint;
|
|
43
58
|
getCurrentAndNextSlot(): { currentSlot: SlotNumber; nextSlot: SlotNumber };
|
|
59
|
+
getTargetAndNextSlot(): { targetSlot: SlotNumber; nextSlot: SlotNumber };
|
|
44
60
|
getProposerAttesterAddressInSlot(slot: SlotNumber): Promise<EthAddress | undefined>;
|
|
45
61
|
getRegisteredValidators(): Promise<EthAddress[]>;
|
|
46
62
|
isInCommittee(slot: SlotTag, validator: EthAddress): Promise<boolean>;
|
|
@@ -64,6 +80,8 @@ export class EpochCache implements EpochCacheInterface {
|
|
|
64
80
|
private lastValidatorRefresh = 0;
|
|
65
81
|
private readonly log: Logger = createLogger('epoch-cache');
|
|
66
82
|
|
|
83
|
+
protected enableProposerPipelining: boolean;
|
|
84
|
+
|
|
67
85
|
constructor(
|
|
68
86
|
private rollup: RollupContract,
|
|
69
87
|
private readonly l1constants: L1RollupConstants & {
|
|
@@ -71,10 +89,12 @@ export class EpochCache implements EpochCacheInterface {
|
|
|
71
89
|
lagInEpochsForRandao: number;
|
|
72
90
|
},
|
|
73
91
|
private readonly dateProvider: DateProvider = new DateProvider(),
|
|
74
|
-
protected readonly config = { cacheSize: 12, validatorRefreshIntervalSeconds: 60 },
|
|
92
|
+
protected readonly config = { cacheSize: 12, validatorRefreshIntervalSeconds: 60, enableProposerPipelining: false },
|
|
75
93
|
) {
|
|
94
|
+
this.enableProposerPipelining = this.config.enableProposerPipelining;
|
|
76
95
|
this.log.debug(`Initialized EpochCache`, {
|
|
77
96
|
l1constants,
|
|
97
|
+
enableProposerPipelining: this.enableProposerPipelining,
|
|
78
98
|
});
|
|
79
99
|
}
|
|
80
100
|
|
|
@@ -93,7 +113,7 @@ export class EpochCache implements EpochCacheInterface {
|
|
|
93
113
|
const chain = createEthereumChain(config.l1RpcUrls, config.l1ChainId);
|
|
94
114
|
const publicClient = createPublicClient({
|
|
95
115
|
chain: chain.chainInfo,
|
|
96
|
-
transport:
|
|
116
|
+
transport: makeL1HttpTransport(config.l1RpcUrls, { timeout: config.l1HttpTimeoutMS }),
|
|
97
117
|
pollingInterval: config.viemPollingIntervalMS,
|
|
98
118
|
});
|
|
99
119
|
rollup = new RollupContract(publicClient, rollupOrAddress.toString());
|
|
@@ -108,6 +128,7 @@ export class EpochCache implements EpochCacheInterface {
|
|
|
108
128
|
lagInEpochsForValidatorSet,
|
|
109
129
|
lagInEpochsForRandao,
|
|
110
130
|
targetCommitteeSize,
|
|
131
|
+
rollupManaLimit,
|
|
111
132
|
] = await Promise.all([
|
|
112
133
|
rollup.getL1StartBlock(),
|
|
113
134
|
rollup.getL1GenesisTime(),
|
|
@@ -117,6 +138,7 @@ export class EpochCache implements EpochCacheInterface {
|
|
|
117
138
|
rollup.getLagInEpochsForValidatorSet(),
|
|
118
139
|
rollup.getLagInEpochsForRandao(),
|
|
119
140
|
rollup.getTargetCommitteeSize(),
|
|
141
|
+
rollup.getManaLimit(),
|
|
120
142
|
] as const);
|
|
121
143
|
|
|
122
144
|
const l1RollupConstants = {
|
|
@@ -129,43 +151,76 @@ export class EpochCache implements EpochCacheInterface {
|
|
|
129
151
|
lagInEpochsForValidatorSet: Number(lagInEpochsForValidatorSet),
|
|
130
152
|
lagInEpochsForRandao: Number(lagInEpochsForRandao),
|
|
131
153
|
targetCommitteeSize: Number(targetCommitteeSize),
|
|
154
|
+
rollupManaLimit: Number(rollupManaLimit),
|
|
132
155
|
};
|
|
133
156
|
|
|
134
|
-
return new EpochCache(rollup, l1RollupConstants, deps.dateProvider
|
|
157
|
+
return new EpochCache(rollup, l1RollupConstants, deps.dateProvider, {
|
|
158
|
+
cacheSize: 12,
|
|
159
|
+
validatorRefreshIntervalSeconds: 60,
|
|
160
|
+
enableProposerPipelining: config.enableProposerPipelining,
|
|
161
|
+
});
|
|
135
162
|
}
|
|
136
163
|
|
|
137
164
|
public getL1Constants(): L1RollupConstants {
|
|
138
165
|
return this.l1constants;
|
|
139
166
|
}
|
|
140
167
|
|
|
168
|
+
public isProposerPipeliningEnabled(): boolean {
|
|
169
|
+
return this.enableProposerPipelining;
|
|
170
|
+
}
|
|
171
|
+
|
|
172
|
+
public getSlotNow(): SlotNumber {
|
|
173
|
+
return this.getEpochAndSlotNow().slot;
|
|
174
|
+
}
|
|
175
|
+
|
|
176
|
+
public getTargetSlot(): SlotNumber {
|
|
177
|
+
const slotNow = this.getSlotNow();
|
|
178
|
+
const offset = this.isProposerPipeliningEnabled() ? PROPOSER_PIPELINING_SLOT_OFFSET : 0;
|
|
179
|
+
return SlotNumber(slotNow + offset);
|
|
180
|
+
}
|
|
181
|
+
|
|
182
|
+
public getEpochNow(): EpochNumber {
|
|
183
|
+
return this.getEpochAndSlotNow().epoch;
|
|
184
|
+
}
|
|
185
|
+
|
|
186
|
+
public getTargetEpoch(): EpochNumber {
|
|
187
|
+
return getEpochAtSlot(this.getTargetSlot(), this.l1constants);
|
|
188
|
+
}
|
|
189
|
+
|
|
141
190
|
public getEpochAndSlotNow(): EpochAndSlot & { nowMs: bigint } {
|
|
142
191
|
const nowMs = BigInt(this.dateProvider.now());
|
|
143
192
|
const nowSeconds = nowMs / 1000n;
|
|
144
193
|
return { ...this.getEpochAndSlotAtTimestamp(nowSeconds), nowMs };
|
|
145
194
|
}
|
|
146
195
|
|
|
147
|
-
|
|
148
|
-
return
|
|
196
|
+
private getEpochAndSlotAtSlot(slot: SlotNumber): EpochAndSlot {
|
|
197
|
+
return this.getEpochAndSlotAtTimestamp(getTimestampForSlot(slot, this.l1constants));
|
|
149
198
|
}
|
|
150
199
|
|
|
151
|
-
|
|
152
|
-
const
|
|
153
|
-
const
|
|
154
|
-
return {
|
|
200
|
+
public getEpochAndSlotInNextL1Slot(): EpochAndSlot & { nowSeconds: bigint } {
|
|
201
|
+
const nowSeconds = this.dateProvider.nowInSeconds();
|
|
202
|
+
const nextSlotTs = getNextL1SlotTimestamp(nowSeconds, this.l1constants);
|
|
203
|
+
return { ...this.getEpochAndSlotAtTimestamp(nextSlotTs), nowSeconds: BigInt(nowSeconds) };
|
|
155
204
|
}
|
|
156
205
|
|
|
157
|
-
public
|
|
158
|
-
|
|
159
|
-
|
|
160
|
-
|
|
206
|
+
public getTargetEpochAndSlotInNextL1Slot(): EpochAndSlot & { nowSeconds: bigint } {
|
|
207
|
+
if (!this.isProposerPipeliningEnabled()) {
|
|
208
|
+
return this.getEpochAndSlotInNextL1Slot();
|
|
209
|
+
}
|
|
210
|
+
|
|
211
|
+
const result = this.getEpochAndSlotInNextL1Slot();
|
|
212
|
+
const offset = PROPOSER_PIPELINING_SLOT_OFFSET;
|
|
213
|
+
const targetSlot = SlotNumber(result.slot + offset);
|
|
214
|
+
return { ...result, slot: targetSlot, epoch: getEpochAtSlot(targetSlot, this.l1constants) };
|
|
161
215
|
}
|
|
162
216
|
|
|
163
217
|
private getEpochAndSlotAtTimestamp(ts: bigint): EpochAndSlot {
|
|
164
218
|
const slot = getSlotAtTimestamp(ts, this.l1constants);
|
|
219
|
+
const epoch = getEpochNumberAtTimestamp(ts, this.l1constants);
|
|
165
220
|
return {
|
|
166
|
-
epoch: getEpochNumberAtTimestamp(ts, this.l1constants),
|
|
167
|
-
ts: getTimestampForSlot(slot, this.l1constants),
|
|
168
221
|
slot,
|
|
222
|
+
epoch,
|
|
223
|
+
ts: getTimestampForSlot(slot, this.l1constants),
|
|
169
224
|
};
|
|
170
225
|
}
|
|
171
226
|
|
|
@@ -198,7 +253,7 @@ export class EpochCache implements EpochCacheInterface {
|
|
|
198
253
|
public async isEscapeHatchOpenAtSlot(slot: SlotTag = 'now'): Promise<boolean> {
|
|
199
254
|
const epoch =
|
|
200
255
|
slot === 'now'
|
|
201
|
-
? this.
|
|
256
|
+
? this.getEpochNow()
|
|
202
257
|
: slot === 'next'
|
|
203
258
|
? this.getEpochAndSlotInNextL1Slot().epoch
|
|
204
259
|
: getEpochAtSlot(slot, this.l1constants);
|
|
@@ -233,7 +288,7 @@ export class EpochCache implements EpochCacheInterface {
|
|
|
233
288
|
return epochData;
|
|
234
289
|
}
|
|
235
290
|
|
|
236
|
-
private getEpochAndTimestamp(slot: SlotTag = 'now') {
|
|
291
|
+
private getEpochAndTimestamp(slot: SlotTag = 'now'): { epoch: EpochNumber; ts: bigint } {
|
|
237
292
|
if (slot === 'now') {
|
|
238
293
|
return this.getEpochAndSlotNow();
|
|
239
294
|
} else if (slot === 'next') {
|
|
@@ -283,17 +338,31 @@ export class EpochCache implements EpochCacheInterface {
|
|
|
283
338
|
return BigInt(keccak256(this.getProposerIndexEncoding(epoch, slot, seed))) % size;
|
|
284
339
|
}
|
|
285
340
|
|
|
286
|
-
/** Returns the current and next L2 slot
|
|
341
|
+
/** Returns the current and next L2 slot in next eth L1 Slot. */
|
|
287
342
|
public getCurrentAndNextSlot(): { currentSlot: SlotNumber; nextSlot: SlotNumber } {
|
|
288
|
-
const
|
|
343
|
+
const currentSlot = this.getSlotNow();
|
|
289
344
|
const next = this.getEpochAndSlotInNextL1Slot();
|
|
290
345
|
|
|
291
346
|
return {
|
|
292
|
-
currentSlot
|
|
347
|
+
currentSlot,
|
|
293
348
|
nextSlot: next.slot,
|
|
294
349
|
};
|
|
295
350
|
}
|
|
296
351
|
|
|
352
|
+
/** Returns the target and next L2 slot in the next L1 slot. */
|
|
353
|
+
public getTargetAndNextSlot(): { targetSlot: SlotNumber; nextSlot: SlotNumber } {
|
|
354
|
+
const nowSeconds = BigInt(this.dateProvider.nowInSeconds());
|
|
355
|
+
const offset = this.isProposerPipeliningEnabled() ? PROPOSER_PIPELINING_SLOT_OFFSET : 0;
|
|
356
|
+
|
|
357
|
+
const currentSlot = getSlotAtTimestamp(nowSeconds, this.l1constants);
|
|
358
|
+
const targetSlot = SlotNumber(currentSlot + offset);
|
|
359
|
+
|
|
360
|
+
const nextL2SlotOnL1 = getSlotAtNextL1Block(nowSeconds, this.l1constants);
|
|
361
|
+
const nextSlot = SlotNumber(nextL2SlotOnL1 + offset);
|
|
362
|
+
|
|
363
|
+
return { targetSlot, nextSlot };
|
|
364
|
+
}
|
|
365
|
+
|
|
297
366
|
/**
|
|
298
367
|
* Get the proposer attester address in the given L2 slot
|
|
299
368
|
* @returns The proposer attester address. If the committee does not exist, we throw a NoCommitteeError.
|
|
@@ -372,10 +441,11 @@ export class EpochCache implements EpochCacheInterface {
|
|
|
372
441
|
async getRegisteredValidators(): Promise<EthAddress[]> {
|
|
373
442
|
const validatorRefreshIntervalMs = this.config.validatorRefreshIntervalSeconds * 1000;
|
|
374
443
|
const validatorRefreshTime = this.lastValidatorRefresh + validatorRefreshIntervalMs;
|
|
375
|
-
|
|
376
|
-
|
|
444
|
+
const now = this.dateProvider.now();
|
|
445
|
+
if (validatorRefreshTime < now) {
|
|
446
|
+
const currentSet = await this.rollup.getAttesters(BigInt(Math.floor(now / 1000)));
|
|
377
447
|
this.allValidators = new Set(currentSet.map(v => v.toString()));
|
|
378
|
-
this.lastValidatorRefresh =
|
|
448
|
+
this.lastValidatorRefresh = now;
|
|
379
449
|
}
|
|
380
450
|
return Array.from(this.allValidators.keys()).map(v => EthAddress.fromString(v));
|
|
381
451
|
}
|
|
@@ -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 = {
|
|
@@ -14,6 +20,7 @@ const DEFAULT_L1_CONSTANTS: L1RollupConstants = {
|
|
|
14
20
|
ethereumSlotDuration: 12,
|
|
15
21
|
proofSubmissionEpochs: 2,
|
|
16
22
|
targetCommitteeSize: 48,
|
|
23
|
+
rollupManaLimit: Number.MAX_SAFE_INTEGER,
|
|
17
24
|
};
|
|
18
25
|
|
|
19
26
|
/**
|
|
@@ -31,6 +38,7 @@ export class TestEpochCache implements EpochCacheInterface {
|
|
|
31
38
|
private seed: bigint = 0n;
|
|
32
39
|
private registeredValidators: EthAddress[] = [];
|
|
33
40
|
private l1Constants: L1RollupConstants;
|
|
41
|
+
private proposerPipeliningEnabled = false;
|
|
34
42
|
|
|
35
43
|
constructor(l1Constants: Partial<L1RollupConstants> = {}) {
|
|
36
44
|
this.l1Constants = { ...DEFAULT_L1_CONSTANTS, ...l1Constants };
|
|
@@ -103,6 +111,10 @@ export class TestEpochCache implements EpochCacheInterface {
|
|
|
103
111
|
return this.l1Constants;
|
|
104
112
|
}
|
|
105
113
|
|
|
114
|
+
setProposerPipeliningEnabled(enabled: boolean): void {
|
|
115
|
+
this.proposerPipeliningEnabled = enabled;
|
|
116
|
+
}
|
|
117
|
+
|
|
106
118
|
getCommittee(_slot?: SlotTag): Promise<EpochCommitteeInfo> {
|
|
107
119
|
const epoch = getEpochAtSlot(this.currentSlot, this.l1Constants);
|
|
108
120
|
return Promise.resolve({
|
|
@@ -113,19 +125,58 @@ export class TestEpochCache implements EpochCacheInterface {
|
|
|
113
125
|
});
|
|
114
126
|
}
|
|
115
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
|
+
|
|
116
150
|
getEpochAndSlotNow(): EpochAndSlot & { nowMs: bigint } {
|
|
117
|
-
const
|
|
118
|
-
const ts = getTimestampRangeForEpoch(
|
|
119
|
-
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
|
+
};
|
|
120
159
|
}
|
|
121
160
|
|
|
122
|
-
getEpochAndSlotInNextL1Slot(): EpochAndSlot & {
|
|
123
|
-
const
|
|
124
|
-
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);
|
|
125
164
|
const nextSlot = getSlotAtTimestamp(nextSlotTs, this.l1Constants);
|
|
126
|
-
const
|
|
127
|
-
const ts = getTimestampRangeForEpoch(
|
|
128
|
-
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) };
|
|
129
180
|
}
|
|
130
181
|
|
|
131
182
|
getProposerIndexEncoding(epoch: EpochNumber, slot: SlotNumber, seed: bigint): `0x${string}` {
|
|
@@ -141,9 +192,22 @@ export class TestEpochCache implements EpochCacheInterface {
|
|
|
141
192
|
}
|
|
142
193
|
|
|
143
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
|
+
|
|
144
208
|
return {
|
|
145
|
-
|
|
146
|
-
nextSlot:
|
|
209
|
+
targetSlot,
|
|
210
|
+
nextSlot: next.slot,
|
|
147
211
|
};
|
|
148
212
|
}
|
|
149
213
|
|
|
@@ -164,6 +228,10 @@ export class TestEpochCache implements EpochCacheInterface {
|
|
|
164
228
|
return Promise.resolve(validators.filter(v => committeeSet.has(v.toString())));
|
|
165
229
|
}
|
|
166
230
|
|
|
231
|
+
isEscapeHatchOpen(_epoch: EpochNumber): Promise<boolean> {
|
|
232
|
+
return Promise.resolve(this.escapeHatchOpen);
|
|
233
|
+
}
|
|
234
|
+
|
|
167
235
|
isEscapeHatchOpenAtSlot(_slot?: SlotTag): Promise<boolean> {
|
|
168
236
|
return Promise.resolve(this.escapeHatchOpen);
|
|
169
237
|
}
|