@aztec/epoch-cache 3.0.0-devnet.6 → 3.0.0-devnet.6-patch.1
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 +2 -1
- package/dest/epoch_cache.d.ts +24 -26
- package/dest/epoch_cache.d.ts.map +1 -1
- package/dest/epoch_cache.js +25 -11
- package/dest/index.d.ts +1 -1
- package/package.json +10 -9
- package/src/config.ts +2 -6
- package/src/epoch_cache.ts +57 -26
package/dest/config.d.ts
CHANGED
|
@@ -1,4 +1,5 @@
|
|
|
1
|
-
import { type L1ContractsConfig
|
|
1
|
+
import { type L1ContractsConfig } from '@aztec/ethereum/config';
|
|
2
|
+
import { type L1ReaderConfig } from '@aztec/ethereum/l1-reader';
|
|
2
3
|
export type EpochCacheConfig = Pick<L1ReaderConfig & L1ContractsConfig, 'l1RpcUrls' | 'l1ChainId' | 'viemPollingIntervalMS' | 'ethereumSlotDuration'>;
|
|
3
4
|
export declare function getEpochCacheConfigEnvVars(): EpochCacheConfig;
|
|
4
|
-
//# sourceMappingURL=
|
|
5
|
+
//# sourceMappingURL=data:application/json;base64,eyJ2ZXJzaW9uIjozLCJmaWxlIjoiY29uZmlnLmQudHMiLCJzb3VyY2VSb290IjoiIiwic291cmNlcyI6WyIuLi9zcmMvY29uZmlnLnRzIl0sIm5hbWVzIjpbXSwibWFwcGluZ3MiOiJBQUFBLE9BQU8sRUFBRSxLQUFLLGlCQUFpQixFQUErQixNQUFNLHdCQUF3QixDQUFDO0FBQzdGLE9BQU8sRUFBRSxLQUFLLGNBQWMsRUFBNEIsTUFBTSwyQkFBMkIsQ0FBQztBQUUxRixNQUFNLE1BQU0sZ0JBQWdCLEdBQUcsSUFBSSxDQUNqQyxjQUFjLEdBQUcsaUJBQWlCLEVBQ2xDLFdBQVcsR0FBRyxXQUFXLEdBQUcsdUJBQXVCLEdBQUcsc0JBQXNCLENBQzdFLENBQUM7QUFFRix3QkFBZ0IsMEJBQTBCLElBQUksZ0JBQWdCLENBRTdEIn0=
|
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,
|
|
1
|
+
{"version":3,"file":"config.d.ts","sourceRoot":"","sources":["../src/config.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,KAAK,iBAAiB,EAA+B,MAAM,wBAAwB,CAAC;AAC7F,OAAO,EAAE,KAAK,cAAc,EAA4B,MAAM,2BAA2B,CAAC;AAE1F,MAAM,MAAM,gBAAgB,GAAG,IAAI,CACjC,cAAc,GAAG,iBAAiB,EAClC,WAAW,GAAG,WAAW,GAAG,uBAAuB,GAAG,sBAAsB,CAC7E,CAAC;AAEF,wBAAgB,0BAA0B,IAAI,gBAAgB,CAE7D"}
|
package/dest/config.js
CHANGED
|
@@ -1,4 +1,5 @@
|
|
|
1
|
-
import { getL1ContractsConfigEnvVars
|
|
1
|
+
import { getL1ContractsConfigEnvVars } from '@aztec/ethereum/config';
|
|
2
|
+
import { getL1ReaderConfigFromEnv } from '@aztec/ethereum/l1-reader';
|
|
2
3
|
export function getEpochCacheConfigEnvVars() {
|
|
3
4
|
return {
|
|
4
5
|
...getL1ReaderConfigFromEnv(),
|
package/dest/epoch_cache.d.ts
CHANGED
|
@@ -1,32 +1,33 @@
|
|
|
1
|
-
import { RollupContract } from '@aztec/ethereum';
|
|
1
|
+
import { RollupContract } from '@aztec/ethereum/contracts';
|
|
2
|
+
import { EpochNumber, SlotNumber } from '@aztec/foundation/branded-types';
|
|
2
3
|
import { EthAddress } from '@aztec/foundation/eth-address';
|
|
3
4
|
import { DateProvider } from '@aztec/foundation/timer';
|
|
4
5
|
import { type L1RollupConstants } from '@aztec/stdlib/epoch-helpers';
|
|
5
6
|
import { type EpochCacheConfig } from './config.js';
|
|
6
7
|
export type EpochAndSlot = {
|
|
7
|
-
epoch:
|
|
8
|
-
slot:
|
|
8
|
+
epoch: EpochNumber;
|
|
9
|
+
slot: SlotNumber;
|
|
9
10
|
ts: bigint;
|
|
10
11
|
};
|
|
11
12
|
export type EpochCommitteeInfo = {
|
|
12
13
|
committee: EthAddress[] | undefined;
|
|
13
14
|
seed: bigint;
|
|
14
|
-
epoch:
|
|
15
|
+
epoch: EpochNumber;
|
|
15
16
|
};
|
|
16
|
-
export type SlotTag = 'now' | 'next' |
|
|
17
|
+
export type SlotTag = 'now' | 'next' | SlotNumber;
|
|
17
18
|
export interface EpochCacheInterface {
|
|
18
19
|
getCommittee(slot: SlotTag | undefined): Promise<EpochCommitteeInfo>;
|
|
19
20
|
getEpochAndSlotNow(): EpochAndSlot;
|
|
20
21
|
getEpochAndSlotInNextL1Slot(): EpochAndSlot & {
|
|
21
22
|
now: bigint;
|
|
22
23
|
};
|
|
23
|
-
getProposerIndexEncoding(epoch:
|
|
24
|
-
computeProposerIndex(slot:
|
|
24
|
+
getProposerIndexEncoding(epoch: EpochNumber, slot: SlotNumber, seed: bigint): `0x${string}`;
|
|
25
|
+
computeProposerIndex(slot: SlotNumber, epoch: EpochNumber, seed: bigint, size: bigint): bigint;
|
|
25
26
|
getProposerAttesterAddressInCurrentOrNextSlot(): Promise<{
|
|
26
27
|
currentProposer: EthAddress | undefined;
|
|
27
28
|
nextProposer: EthAddress | undefined;
|
|
28
|
-
currentSlot:
|
|
29
|
-
nextSlot:
|
|
29
|
+
currentSlot: SlotNumber;
|
|
30
|
+
nextSlot: SlotNumber;
|
|
30
31
|
}>;
|
|
31
32
|
getRegisteredValidators(): Promise<EthAddress[]>;
|
|
32
33
|
isInCommittee(slot: SlotTag, validator: EthAddress): Promise<boolean>;
|
|
@@ -49,11 +50,14 @@ export declare class EpochCache implements EpochCacheInterface {
|
|
|
49
50
|
cacheSize: number;
|
|
50
51
|
validatorRefreshIntervalSeconds: number;
|
|
51
52
|
};
|
|
52
|
-
protected cache: Map<
|
|
53
|
+
protected cache: Map<EpochNumber, EpochCommitteeInfo>;
|
|
53
54
|
private allValidators;
|
|
54
55
|
private lastValidatorRefresh;
|
|
55
56
|
private readonly log;
|
|
56
|
-
constructor(rollup: RollupContract, l1constants
|
|
57
|
+
constructor(rollup: RollupContract, l1constants: L1RollupConstants & {
|
|
58
|
+
lagInEpochsForValidatorSet: number;
|
|
59
|
+
lagInEpochsForRandao: number;
|
|
60
|
+
}, dateProvider?: DateProvider, config?: {
|
|
57
61
|
cacheSize: number;
|
|
58
62
|
validatorRefreshIntervalSeconds: number;
|
|
59
63
|
});
|
|
@@ -70,7 +74,7 @@ export declare class EpochCache implements EpochCacheInterface {
|
|
|
70
74
|
now: bigint;
|
|
71
75
|
};
|
|
72
76
|
private getEpochAndSlotAtTimestamp;
|
|
73
|
-
getCommitteeForEpoch(epoch:
|
|
77
|
+
getCommitteeForEpoch(epoch: EpochNumber): Promise<EpochCommitteeInfo>;
|
|
74
78
|
/**
|
|
75
79
|
* Get the current validator set
|
|
76
80
|
* @param nextSlot - If true, get the validator set for the next slot.
|
|
@@ -82,8 +86,8 @@ export declare class EpochCache implements EpochCacheInterface {
|
|
|
82
86
|
/**
|
|
83
87
|
* Get the ABI encoding of the proposer index - see ValidatorSelectionLib.sol computeProposerIndex
|
|
84
88
|
*/
|
|
85
|
-
getProposerIndexEncoding(epoch:
|
|
86
|
-
computeProposerIndex(slot:
|
|
89
|
+
getProposerIndexEncoding(epoch: EpochNumber, slot: SlotNumber, seed: bigint): `0x${string}`;
|
|
90
|
+
computeProposerIndex(slot: SlotNumber, epoch: EpochNumber, seed: bigint, size: bigint): bigint;
|
|
87
91
|
/**
|
|
88
92
|
* Returns the current and next proposer's attester address
|
|
89
93
|
*
|
|
@@ -91,35 +95,29 @@ export declare class EpochCache implements EpochCacheInterface {
|
|
|
91
95
|
* which can be the next slot. If this is the case, then it will send proposals early.
|
|
92
96
|
*/
|
|
93
97
|
getProposerAttesterAddressInCurrentOrNextSlot(): Promise<{
|
|
94
|
-
currentSlot:
|
|
95
|
-
nextSlot:
|
|
98
|
+
currentSlot: SlotNumber;
|
|
99
|
+
nextSlot: SlotNumber;
|
|
96
100
|
currentProposer: EthAddress | undefined;
|
|
97
101
|
nextProposer: EthAddress | undefined;
|
|
98
102
|
}>;
|
|
99
103
|
/**
|
|
100
|
-
* Get the proposer attester address in the
|
|
104
|
+
* Get the proposer attester address in the given L2 slot
|
|
101
105
|
* @returns The proposer attester address. If the committee does not exist, we throw a NoCommitteeError.
|
|
102
106
|
* If the committee is empty (i.e. target committee size is 0, and anyone can propose), we return undefined.
|
|
103
107
|
*/
|
|
104
|
-
getProposerAttesterAddressInSlot(slot:
|
|
108
|
+
getProposerAttesterAddressInSlot(slot: SlotNumber): Promise<EthAddress | undefined>;
|
|
105
109
|
/**
|
|
106
110
|
* Get the proposer attester address in the next slot
|
|
107
111
|
* @returns The proposer attester address. If the committee does not exist, we throw a NoCommitteeError.
|
|
108
112
|
* If the committee is empty (i.e. target committee size is 0, and anyone can propose), we return undefined.
|
|
109
113
|
*/
|
|
110
114
|
getProposerAttesterAddressInNextSlot(): Promise<EthAddress | undefined>;
|
|
111
|
-
/**
|
|
112
|
-
* Get the proposer attester address at a given epoch and slot
|
|
113
|
-
* @param when - The epoch and slot to get the proposer attester address at
|
|
114
|
-
* @returns The proposer attester address. If the committee does not exist, we throw a NoCommitteeError.
|
|
115
|
-
* If the committee is empty (i.e. target committee size is 0, and anyone can propose), we return undefined.
|
|
116
|
-
*/
|
|
117
115
|
private getProposerAttesterAddressAt;
|
|
118
|
-
getProposerFromEpochCommittee(epochCommitteeInfo: EpochCommitteeInfo, slot:
|
|
116
|
+
getProposerFromEpochCommittee(epochCommitteeInfo: EpochCommitteeInfo, slot: SlotNumber): EthAddress | undefined;
|
|
119
117
|
/** Check if a validator is in the given slot's committee */
|
|
120
118
|
isInCommittee(slot: SlotTag, validator: EthAddress): Promise<boolean>;
|
|
121
119
|
/** From the set of given addresses, return all that are on the committee for the given slot */
|
|
122
120
|
filterInCommittee(slot: SlotTag, validators: EthAddress[]): Promise<EthAddress[]>;
|
|
123
121
|
getRegisteredValidators(): Promise<EthAddress[]>;
|
|
124
122
|
}
|
|
125
|
-
//# sourceMappingURL=
|
|
123
|
+
//# sourceMappingURL=data:application/json;base64,eyJ2ZXJzaW9uIjozLCJmaWxlIjoiZXBvY2hfY2FjaGUuZC50cyIsInNvdXJjZVJvb3QiOiIiLCJzb3VyY2VzIjpbIi4uL3NyYy9lcG9jaF9jYWNoZS50cyJdLCJuYW1lcyI6W10sIm1hcHBpbmdzIjoiQUFDQSxPQUFPLEVBQW9CLGNBQWMsRUFBRSxNQUFNLDJCQUEyQixDQUFDO0FBQzdFLE9BQU8sRUFBRSxXQUFXLEVBQUUsVUFBVSxFQUFFLE1BQU0saUNBQWlDLENBQUM7QUFDMUUsT0FBTyxFQUFFLFVBQVUsRUFBRSxNQUFNLCtCQUErQixDQUFDO0FBRTNELE9BQU8sRUFBRSxZQUFZLEVBQUUsTUFBTSx5QkFBeUIsQ0FBQztBQUN2RCxPQUFPLEVBQ0wsS0FBSyxpQkFBaUIsRUFPdkIsTUFBTSw2QkFBNkIsQ0FBQztBQUlyQyxPQUFPLEVBQUUsS0FBSyxnQkFBZ0IsRUFBOEIsTUFBTSxhQUFhLENBQUM7QUFFaEYsTUFBTSxNQUFNLFlBQVksR0FBRztJQUN6QixLQUFLLEVBQUUsV0FBVyxDQUFDO0lBQ25CLElBQUksRUFBRSxVQUFVLENBQUM7SUFDakIsRUFBRSxFQUFFLE1BQU0sQ0FBQztDQUNaLENBQUM7QUFFRixNQUFNLE1BQU0sa0JBQWtCLEdBQUc7SUFDL0IsU0FBUyxFQUFFLFVBQVUsRUFBRSxHQUFHLFNBQVMsQ0FBQztJQUNwQyxJQUFJLEVBQUUsTUFBTSxDQUFDO0lBQ2IsS0FBSyxFQUFFLFdBQVcsQ0FBQztDQUNwQixDQUFDO0FBRUYsTUFBTSxNQUFNLE9BQU8sR0FBRyxLQUFLLEdBQUcsTUFBTSxHQUFHLFVBQVUsQ0FBQztBQUVsRCxNQUFNLFdBQVcsbUJBQW1CO0lBQ2xDLFlBQVksQ0FBQyxJQUFJLEVBQUUsT0FBTyxHQUFHLFNBQVMsR0FBRyxPQUFPLENBQUMsa0JBQWtCLENBQUMsQ0FBQztJQUNyRSxrQkFBa0IsSUFBSSxZQUFZLENBQUM7SUFDbkMsMkJBQTJCLElBQUksWUFBWSxHQUFHO1FBQUUsR0FBRyxFQUFFLE1BQU0sQ0FBQTtLQUFFLENBQUM7SUFDOUQsd0JBQXdCLENBQUMs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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":"AACA,OAAO,EAAoB,cAAc,EAAE,MAAM,2BAA2B,CAAC;AAC7E,OAAO,EAAE,WAAW,EAAE,UAAU,EAAE,MAAM,iCAAiC,CAAC;AAC1E,OAAO,EAAE,UAAU,EAAE,MAAM,+BAA+B,CAAC;AAE3D,OAAO,EAAE,YAAY,EAAE,MAAM,yBAAyB,CAAC;AACvD,OAAO,EACL,KAAK,iBAAiB,EAOvB,MAAM,6BAA6B,CAAC;AAIrC,OAAO,EAAE,KAAK,gBAAgB,EAA8B,MAAM,aAAa,CAAC;AAEhF,MAAM,MAAM,YAAY,GAAG;IACzB,KAAK,EAAE,WAAW,CAAC;IACnB,IAAI,EAAE,UAAU,CAAC;IACjB,EAAE,EAAE,MAAM,CAAC;CACZ,CAAC;AAEF,MAAM,MAAM,kBAAkB,GAAG;IAC/B,SAAS,EAAE,UAAU,EAAE,GAAG,SAAS,CAAC;IACpC,IAAI,EAAE,MAAM,CAAC;IACb,KAAK,EAAE,WAAW,CAAC;CACpB,CAAC;AAEF,MAAM,MAAM,OAAO,GAAG,KAAK,GAAG,MAAM,GAAG,UAAU,CAAC;AAElD,MAAM,WAAW,mBAAmB;IAClC,YAAY,CAAC,IAAI,EAAE,OAAO,GAAG,SAAS,GAAG,OAAO,CAAC,kBAAkB,CAAC,CAAC;IACrE,kBAAkB,IAAI,YAAY,CAAC;IACnC,2BAA2B,IAAI,YAAY,GAAG;QAAE,GAAG,EAAE,MAAM,CAAA;KAAE,CAAC;IAC9D,wBAAwB,CAAC,KAAK,EAAE,WAAW,EAAE,IAAI,EAAE,UAAU,EAAE,IAAI,EAAE,MAAM,GAAG,KAAK,MAAM,EAAE,CAAC;IAC5F,oBAAoB,CAAC,IAAI,EAAE,UAAU,EAAE,KAAK,EAAE,WAAW,EAAE,IAAI,EAAE,MAAM,EAAE,IAAI,EAAE,MAAM,GAAG,MAAM,CAAC;IAC/F,6CAA6C,IAAI,OAAO,CAAC;QACvD,eAAe,EAAE,UAAU,GAAG,SAAS,CAAC;QACxC,YAAY,EAAE,UAAU,GAAG,SAAS,CAAC;QACrC,WAAW,EAAE,UAAU,CAAC;QACxB,QAAQ,EAAE,UAAU,CAAC;KACtB,CAAC,CAAC;IACH,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;CACnF;AAED;;;;;;;;GAQG;AACH,qBAAa,UAAW,YAAW,mBAAmB;IAQlD,OAAO,CAAC,MAAM;IACd,OAAO,CAAC,QAAQ,CAAC,WAAW;IAI5B,OAAO,CAAC,QAAQ,CAAC,YAAY;IAC7B,SAAS,CAAC,QAAQ,CAAC,MAAM;;;;IAZ3B,SAAS,CAAC,KAAK,EAAE,GAAG,CAAC,WAAW,EAAE,kBAAkB,CAAC,CAAa;IAClE,OAAO,CAAC,aAAa,CAA0B;IAC/C,OAAO,CAAC,oBAAoB,CAAK;IACjC,OAAO,CAAC,QAAQ,CAAC,GAAG,CAAuC;IAE3D,YACU,MAAM,EAAE,cAAc,EACb,WAAW,EAAE,iBAAiB,GAAG;QAChD,0BAA0B,EAAE,MAAM,CAAC;QACnC,oBAAoB,EAAE,MAAM,CAAC;KAC9B,EACgB,YAAY,GAAE,YAAiC,EAC7C,MAAM;;;KAAyD,EAKnF;IAED,OAAa,MAAM,CACjB,eAAe,EAAE,UAAU,GAAG,cAAc,EAC5C,MAAM,CAAC,EAAE,gBAAgB,EACzB,IAAI,GAAE;QAAE,YAAY,CAAC,EAAE,YAAY,CAAA;KAAO,uBAgD3C;IAEM,cAAc,IAAI,iBAAiB,CAEzC;IAEM,kBAAkB,IAAI,YAAY,GAAG;QAAE,GAAG,EAAE,MAAM,CAAA;KAAE,CAG1D;IAEM,YAAY,IAAI,MAAM,CAE5B;IAED,OAAO,CAAC,qBAAqB;IAMtB,2BAA2B,IAAI,YAAY,GAAG;QAAE,GAAG,EAAE,MAAM,CAAA;KAAE,CAInE;IAED,OAAO,CAAC,0BAA0B;IAS3B,oBAAoB,CAAC,KAAK,EAAE,WAAW,GAAG,OAAO,CAAC,kBAAkB,CAAC,CAG3E;IAED;;;;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;;;;;OAKG;IACU,6CAA6C,IAAI,OAAO,CAAC;QACpE,WAAW,EAAE,UAAU,CAAC;QACxB,QAAQ,EAAE,UAAU,CAAC;QACrB,eAAe,EAAE,UAAU,GAAG,SAAS,CAAC;QACxC,YAAY,EAAE,UAAU,GAAG,SAAS,CAAC;KACtC,CAAC,CAUD;IAED;;;;OAIG;IACI,gCAAgC,CAAC,IAAI,EAAE,UAAU,GAAG,OAAO,CAAC,UAAU,GAAG,SAAS,CAAC,CAGzF;IAED;;;;OAIG;IACI,oCAAoC,IAAI,OAAO,CAAC,UAAU,GAAG,SAAS,CAAC,CAG7E;YAQa,4BAA4B;IAanC,6BAA6B,CAClC,kBAAkB,EAAE,kBAAkB,EACtC,IAAI,EAAE,UAAU,GACf,UAAU,GAAG,SAAS,CAYxB;IAED,4DAA4D;IACtD,aAAa,CAAC,IAAI,EAAE,OAAO,EAAE,SAAS,EAAE,UAAU,GAAG,OAAO,CAAC,OAAO,CAAC,CAM1E;IAED,+FAA+F;IACzF,iBAAiB,CAAC,IAAI,EAAE,OAAO,EAAE,UAAU,EAAE,UAAU,EAAE,GAAG,OAAO,CAAC,UAAU,EAAE,CAAC,CAOtF;IAEK,uBAAuB,IAAI,OAAO,CAAC,UAAU,EAAE,CAAC,CASrD;CACF"}
|
package/dest/epoch_cache.js
CHANGED
|
@@ -1,8 +1,9 @@
|
|
|
1
|
-
import {
|
|
1
|
+
import { createEthereumChain } from '@aztec/ethereum/chain';
|
|
2
|
+
import { NoCommitteeError, RollupContract } from '@aztec/ethereum/contracts';
|
|
2
3
|
import { EthAddress } from '@aztec/foundation/eth-address';
|
|
3
4
|
import { createLogger } from '@aztec/foundation/log';
|
|
4
5
|
import { DateProvider } from '@aztec/foundation/timer';
|
|
5
|
-
import {
|
|
6
|
+
import { getEpochAtSlot, getEpochNumberAtTimestamp, getSlotAtTimestamp, getSlotRangeForEpoch, getTimestampForSlot, getTimestampRangeForEpoch } from '@aztec/stdlib/epoch-helpers';
|
|
6
7
|
import { createPublicClient, encodeAbiParameters, fallback, http, keccak256 } from 'viem';
|
|
7
8
|
import { getEpochCacheConfigEnvVars } from './config.js';
|
|
8
9
|
/**
|
|
@@ -18,11 +19,12 @@ import { getEpochCacheConfigEnvVars } from './config.js';
|
|
|
18
19
|
l1constants;
|
|
19
20
|
dateProvider;
|
|
20
21
|
config;
|
|
22
|
+
// eslint-disable-next-line aztec-custom/no-non-primitive-in-collections
|
|
21
23
|
cache;
|
|
22
24
|
allValidators;
|
|
23
25
|
lastValidatorRefresh;
|
|
24
26
|
log;
|
|
25
|
-
constructor(rollup, l1constants
|
|
27
|
+
constructor(rollup, l1constants, dateProvider = new DateProvider(), config = {
|
|
26
28
|
cacheSize: 12,
|
|
27
29
|
validatorRefreshIntervalSeconds: 60
|
|
28
30
|
}){
|
|
@@ -53,12 +55,14 @@ import { getEpochCacheConfigEnvVars } from './config.js';
|
|
|
53
55
|
});
|
|
54
56
|
rollup = new RollupContract(publicClient, rollupOrAddress.toString());
|
|
55
57
|
}
|
|
56
|
-
const [l1StartBlock, l1GenesisTime, proofSubmissionEpochs, slotDuration, epochDuration] = await Promise.all([
|
|
58
|
+
const [l1StartBlock, l1GenesisTime, proofSubmissionEpochs, slotDuration, epochDuration, lagInEpochsForValidatorSet, lagInEpochsForRandao] = await Promise.all([
|
|
57
59
|
rollup.getL1StartBlock(),
|
|
58
60
|
rollup.getL1GenesisTime(),
|
|
59
61
|
rollup.getProofSubmissionEpochs(),
|
|
60
62
|
rollup.getSlotDuration(),
|
|
61
|
-
rollup.getEpochDuration()
|
|
63
|
+
rollup.getEpochDuration(),
|
|
64
|
+
rollup.getLagInEpochsForValidatorSet(),
|
|
65
|
+
rollup.getLagInEpochsForRandao()
|
|
62
66
|
]);
|
|
63
67
|
const l1RollupConstants = {
|
|
64
68
|
l1StartBlock,
|
|
@@ -66,7 +70,9 @@ import { getEpochCacheConfigEnvVars } from './config.js';
|
|
|
66
70
|
proofSubmissionEpochs: Number(proofSubmissionEpochs),
|
|
67
71
|
slotDuration: Number(slotDuration),
|
|
68
72
|
epochDuration: Number(epochDuration),
|
|
69
|
-
ethereumSlotDuration: config.ethereumSlotDuration
|
|
73
|
+
ethereumSlotDuration: config.ethereumSlotDuration,
|
|
74
|
+
lagInEpochsForValidatorSet: Number(lagInEpochsForValidatorSet),
|
|
75
|
+
lagInEpochsForRandao: Number(lagInEpochsForRandao)
|
|
70
76
|
};
|
|
71
77
|
return new EpochCache(rollup, l1RollupConstants, deps.dateProvider);
|
|
72
78
|
}
|
|
@@ -145,10 +151,18 @@ import { getEpochCacheConfigEnvVars } from './config.js';
|
|
|
145
151
|
}
|
|
146
152
|
async computeCommittee(when) {
|
|
147
153
|
const { ts, epoch } = when;
|
|
148
|
-
const [committeeHex, seed] = await Promise.all([
|
|
154
|
+
const [committeeHex, seed, l1Timestamp] = await Promise.all([
|
|
149
155
|
this.rollup.getCommitteeAt(ts),
|
|
150
|
-
this.rollup.getSampleSeedAt(ts)
|
|
156
|
+
this.rollup.getSampleSeedAt(ts),
|
|
157
|
+
this.rollup.client.getBlock({
|
|
158
|
+
includeTransactions: false
|
|
159
|
+
}).then((b)=>b.timestamp)
|
|
151
160
|
]);
|
|
161
|
+
const { lagInEpochsForValidatorSet, epochDuration, slotDuration } = this.l1constants;
|
|
162
|
+
const sub = BigInt(lagInEpochsForValidatorSet) * BigInt(epochDuration) * BigInt(slotDuration);
|
|
163
|
+
if (ts - sub > l1Timestamp) {
|
|
164
|
+
throw new Error(`Cannot query committee for future epoch ${epoch} with timestamp ${ts} (current L1 time is ${l1Timestamp}). Check your Ethereum node is synced.`);
|
|
165
|
+
}
|
|
152
166
|
const committee = committeeHex?.map((v)=>EthAddress.fromString(v));
|
|
153
167
|
return {
|
|
154
168
|
committee,
|
|
@@ -173,8 +187,8 @@ import { getEpochCacheConfigEnvVars } from './config.js';
|
|
|
173
187
|
name: 'seed'
|
|
174
188
|
}
|
|
175
189
|
], [
|
|
176
|
-
epoch,
|
|
177
|
-
slot,
|
|
190
|
+
BigInt(epoch),
|
|
191
|
+
BigInt(slot),
|
|
178
192
|
seed
|
|
179
193
|
]);
|
|
180
194
|
}
|
|
@@ -201,7 +215,7 @@ import { getEpochCacheConfigEnvVars } from './config.js';
|
|
|
201
215
|
};
|
|
202
216
|
}
|
|
203
217
|
/**
|
|
204
|
-
* Get the proposer attester address in the
|
|
218
|
+
* Get the proposer attester address in the given L2 slot
|
|
205
219
|
* @returns The proposer attester address. If the committee does not exist, we throw a NoCommitteeError.
|
|
206
220
|
* If the committee is empty (i.e. target committee size is 0, and anyone can propose), we return undefined.
|
|
207
221
|
*/ getProposerAttesterAddressInSlot(slot) {
|
package/dest/index.d.ts
CHANGED
|
@@ -1,3 +1,3 @@
|
|
|
1
1
|
export * from './epoch_cache.js';
|
|
2
2
|
export * from './config.js';
|
|
3
|
-
//# sourceMappingURL=
|
|
3
|
+
//# sourceMappingURL=data:application/json;base64,eyJ2ZXJzaW9uIjozLCJmaWxlIjoiaW5kZXguZC50cyIsInNvdXJjZVJvb3QiOiIiLCJzb3VyY2VzIjpbIi4uL3NyYy9pbmRleC50cyJdLCJuYW1lcyI6W10sIm1hcHBpbmdzIjoiQUFBQSxjQUFjLGtCQUFrQixDQUFDO0FBQ2pDLGNBQWMsYUFBYSxDQUFDIn0=
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@aztec/epoch-cache",
|
|
3
|
-
"version": "3.0.0-devnet.6",
|
|
3
|
+
"version": "3.0.0-devnet.6-patch.1",
|
|
4
4
|
"type": "module",
|
|
5
5
|
"exports": {
|
|
6
6
|
".": "./dest/index.js",
|
|
@@ -15,10 +15,10 @@
|
|
|
15
15
|
"tsconfig": "./tsconfig.json"
|
|
16
16
|
},
|
|
17
17
|
"scripts": {
|
|
18
|
-
"build": "yarn clean && tsc
|
|
19
|
-
"build:dev": "tsc
|
|
18
|
+
"build": "yarn clean && ../scripts/tsc.sh",
|
|
19
|
+
"build:dev": "../scripts/tsc.sh --watch",
|
|
20
20
|
"clean": "rm -rf ./dest .tsbuildinfo",
|
|
21
|
-
"start:dev": "
|
|
21
|
+
"start:dev": "concurrently -k \"tsgo -b -w\" \"nodemon --watch dest --exec yarn start\"",
|
|
22
22
|
"start": "node ./dest/index.js",
|
|
23
23
|
"test": "NODE_NO_WARNINGS=1 node --experimental-vm-modules ../node_modules/.bin/jest --passWithNoTests --maxWorkers=${JEST_MAX_WORKERS:-8}"
|
|
24
24
|
},
|
|
@@ -26,22 +26,23 @@
|
|
|
26
26
|
"../package.common.json"
|
|
27
27
|
],
|
|
28
28
|
"dependencies": {
|
|
29
|
-
"@aztec/ethereum": "3.0.0-devnet.6",
|
|
30
|
-
"@aztec/foundation": "3.0.0-devnet.6",
|
|
31
|
-
"@aztec/l1-artifacts": "3.0.0-devnet.6",
|
|
32
|
-
"@aztec/stdlib": "3.0.0-devnet.6",
|
|
29
|
+
"@aztec/ethereum": "3.0.0-devnet.6-patch.1",
|
|
30
|
+
"@aztec/foundation": "3.0.0-devnet.6-patch.1",
|
|
31
|
+
"@aztec/l1-artifacts": "3.0.0-devnet.6-patch.1",
|
|
32
|
+
"@aztec/stdlib": "3.0.0-devnet.6-patch.1",
|
|
33
33
|
"@viem/anvil": "^0.0.10",
|
|
34
34
|
"dotenv": "^16.0.3",
|
|
35
35
|
"get-port": "^7.1.0",
|
|
36
36
|
"jest-mock-extended": "^4.0.0",
|
|
37
37
|
"tslib": "^2.4.0",
|
|
38
|
-
"viem": "npm:@
|
|
38
|
+
"viem": "npm:@aztec/viem@2.38.2",
|
|
39
39
|
"zod": "^3.23.8"
|
|
40
40
|
},
|
|
41
41
|
"devDependencies": {
|
|
42
42
|
"@jest/globals": "^30.0.0",
|
|
43
43
|
"@types/jest": "^30.0.0",
|
|
44
44
|
"@types/node": "^22.15.17",
|
|
45
|
+
"@typescript/native-preview": "7.0.0-dev.20251126.1",
|
|
45
46
|
"jest": "^30.0.0",
|
|
46
47
|
"ts-node": "^10.9.1",
|
|
47
48
|
"typescript": "^5.3.3"
|
package/src/config.ts
CHANGED
|
@@ -1,9 +1,5 @@
|
|
|
1
|
-
import {
|
|
2
|
-
|
|
3
|
-
type L1ReaderConfig,
|
|
4
|
-
getL1ContractsConfigEnvVars,
|
|
5
|
-
getL1ReaderConfigFromEnv,
|
|
6
|
-
} from '@aztec/ethereum';
|
|
1
|
+
import { type L1ContractsConfig, getL1ContractsConfigEnvVars } from '@aztec/ethereum/config';
|
|
2
|
+
import { type L1ReaderConfig, getL1ReaderConfigFromEnv } from '@aztec/ethereum/l1-reader';
|
|
7
3
|
|
|
8
4
|
export type EpochCacheConfig = Pick<
|
|
9
5
|
L1ReaderConfig & L1ContractsConfig,
|
package/src/epoch_cache.ts
CHANGED
|
@@ -1,9 +1,10 @@
|
|
|
1
|
-
import {
|
|
1
|
+
import { createEthereumChain } from '@aztec/ethereum/chain';
|
|
2
|
+
import { NoCommitteeError, RollupContract } from '@aztec/ethereum/contracts';
|
|
3
|
+
import { EpochNumber, SlotNumber } from '@aztec/foundation/branded-types';
|
|
2
4
|
import { EthAddress } from '@aztec/foundation/eth-address';
|
|
3
5
|
import { type Logger, createLogger } from '@aztec/foundation/log';
|
|
4
6
|
import { DateProvider } from '@aztec/foundation/timer';
|
|
5
7
|
import {
|
|
6
|
-
EmptyL1RollupConstants,
|
|
7
8
|
type L1RollupConstants,
|
|
8
9
|
getEpochAtSlot,
|
|
9
10
|
getEpochNumberAtTimestamp,
|
|
@@ -18,30 +19,30 @@ import { createPublicClient, encodeAbiParameters, fallback, http, keccak256 } fr
|
|
|
18
19
|
import { type EpochCacheConfig, getEpochCacheConfigEnvVars } from './config.js';
|
|
19
20
|
|
|
20
21
|
export type EpochAndSlot = {
|
|
21
|
-
epoch:
|
|
22
|
-
slot:
|
|
22
|
+
epoch: EpochNumber;
|
|
23
|
+
slot: SlotNumber;
|
|
23
24
|
ts: bigint;
|
|
24
25
|
};
|
|
25
26
|
|
|
26
27
|
export type EpochCommitteeInfo = {
|
|
27
28
|
committee: EthAddress[] | undefined;
|
|
28
29
|
seed: bigint;
|
|
29
|
-
epoch:
|
|
30
|
+
epoch: EpochNumber;
|
|
30
31
|
};
|
|
31
32
|
|
|
32
|
-
export type SlotTag = 'now' | 'next' |
|
|
33
|
+
export type SlotTag = 'now' | 'next' | SlotNumber;
|
|
33
34
|
|
|
34
35
|
export interface EpochCacheInterface {
|
|
35
36
|
getCommittee(slot: SlotTag | undefined): Promise<EpochCommitteeInfo>;
|
|
36
37
|
getEpochAndSlotNow(): EpochAndSlot;
|
|
37
38
|
getEpochAndSlotInNextL1Slot(): EpochAndSlot & { now: bigint };
|
|
38
|
-
getProposerIndexEncoding(epoch:
|
|
39
|
-
computeProposerIndex(slot:
|
|
39
|
+
getProposerIndexEncoding(epoch: EpochNumber, slot: SlotNumber, seed: bigint): `0x${string}`;
|
|
40
|
+
computeProposerIndex(slot: SlotNumber, epoch: EpochNumber, seed: bigint, size: bigint): bigint;
|
|
40
41
|
getProposerAttesterAddressInCurrentOrNextSlot(): Promise<{
|
|
41
42
|
currentProposer: EthAddress | undefined;
|
|
42
43
|
nextProposer: EthAddress | undefined;
|
|
43
|
-
currentSlot:
|
|
44
|
-
nextSlot:
|
|
44
|
+
currentSlot: SlotNumber;
|
|
45
|
+
nextSlot: SlotNumber;
|
|
45
46
|
}>;
|
|
46
47
|
getRegisteredValidators(): Promise<EthAddress[]>;
|
|
47
48
|
isInCommittee(slot: SlotTag, validator: EthAddress): Promise<boolean>;
|
|
@@ -58,14 +59,18 @@ export interface EpochCacheInterface {
|
|
|
58
59
|
* Note: This class is very dependent on the system clock being in sync.
|
|
59
60
|
*/
|
|
60
61
|
export class EpochCache implements EpochCacheInterface {
|
|
61
|
-
|
|
62
|
+
// eslint-disable-next-line aztec-custom/no-non-primitive-in-collections
|
|
63
|
+
protected cache: Map<EpochNumber, EpochCommitteeInfo> = new Map();
|
|
62
64
|
private allValidators: Set<string> = new Set();
|
|
63
65
|
private lastValidatorRefresh = 0;
|
|
64
66
|
private readonly log: Logger = createLogger('epoch-cache');
|
|
65
67
|
|
|
66
68
|
constructor(
|
|
67
69
|
private rollup: RollupContract,
|
|
68
|
-
private readonly l1constants: L1RollupConstants
|
|
70
|
+
private readonly l1constants: L1RollupConstants & {
|
|
71
|
+
lagInEpochsForValidatorSet: number;
|
|
72
|
+
lagInEpochsForRandao: number;
|
|
73
|
+
},
|
|
69
74
|
private readonly dateProvider: DateProvider = new DateProvider(),
|
|
70
75
|
protected readonly config = { cacheSize: 12, validatorRefreshIntervalSeconds: 60 },
|
|
71
76
|
) {
|
|
@@ -95,21 +100,33 @@ export class EpochCache implements EpochCacheInterface {
|
|
|
95
100
|
rollup = new RollupContract(publicClient, rollupOrAddress.toString());
|
|
96
101
|
}
|
|
97
102
|
|
|
98
|
-
const [
|
|
103
|
+
const [
|
|
104
|
+
l1StartBlock,
|
|
105
|
+
l1GenesisTime,
|
|
106
|
+
proofSubmissionEpochs,
|
|
107
|
+
slotDuration,
|
|
108
|
+
epochDuration,
|
|
109
|
+
lagInEpochsForValidatorSet,
|
|
110
|
+
lagInEpochsForRandao,
|
|
111
|
+
] = await Promise.all([
|
|
99
112
|
rollup.getL1StartBlock(),
|
|
100
113
|
rollup.getL1GenesisTime(),
|
|
101
114
|
rollup.getProofSubmissionEpochs(),
|
|
102
115
|
rollup.getSlotDuration(),
|
|
103
116
|
rollup.getEpochDuration(),
|
|
117
|
+
rollup.getLagInEpochsForValidatorSet(),
|
|
118
|
+
rollup.getLagInEpochsForRandao(),
|
|
104
119
|
] as const);
|
|
105
120
|
|
|
106
|
-
const l1RollupConstants
|
|
121
|
+
const l1RollupConstants = {
|
|
107
122
|
l1StartBlock,
|
|
108
123
|
l1GenesisTime,
|
|
109
124
|
proofSubmissionEpochs: Number(proofSubmissionEpochs),
|
|
110
125
|
slotDuration: Number(slotDuration),
|
|
111
126
|
epochDuration: Number(epochDuration),
|
|
112
127
|
ethereumSlotDuration: config.ethereumSlotDuration,
|
|
128
|
+
lagInEpochsForValidatorSet: Number(lagInEpochsForValidatorSet),
|
|
129
|
+
lagInEpochsForRandao: Number(lagInEpochsForRandao),
|
|
113
130
|
};
|
|
114
131
|
|
|
115
132
|
return new EpochCache(rollup, l1RollupConstants, deps.dateProvider);
|
|
@@ -128,7 +145,7 @@ export class EpochCache implements EpochCacheInterface {
|
|
|
128
145
|
return BigInt(Math.floor(this.dateProvider.now() / 1000));
|
|
129
146
|
}
|
|
130
147
|
|
|
131
|
-
private getEpochAndSlotAtSlot(slot:
|
|
148
|
+
private getEpochAndSlotAtSlot(slot: SlotNumber): EpochAndSlot {
|
|
132
149
|
const epoch = getEpochAtSlot(slot, this.l1constants);
|
|
133
150
|
const ts = getTimestampRangeForEpoch(epoch, this.l1constants)[0];
|
|
134
151
|
return { epoch, ts, slot };
|
|
@@ -149,7 +166,7 @@ export class EpochCache implements EpochCacheInterface {
|
|
|
149
166
|
};
|
|
150
167
|
}
|
|
151
168
|
|
|
152
|
-
public getCommitteeForEpoch(epoch:
|
|
169
|
+
public getCommitteeForEpoch(epoch: EpochNumber): Promise<EpochCommitteeInfo> {
|
|
153
170
|
const [startSlot] = getSlotRangeForEpoch(epoch, this.l1constants);
|
|
154
171
|
return this.getCommittee(startSlot);
|
|
155
172
|
}
|
|
@@ -191,9 +208,20 @@ export class EpochCache implements EpochCacheInterface {
|
|
|
191
208
|
}
|
|
192
209
|
}
|
|
193
210
|
|
|
194
|
-
private async computeCommittee(when: { epoch:
|
|
211
|
+
private async computeCommittee(when: { epoch: EpochNumber; ts: bigint }): Promise<EpochCommitteeInfo> {
|
|
195
212
|
const { ts, epoch } = when;
|
|
196
|
-
const [committeeHex, seed] = await Promise.all([
|
|
213
|
+
const [committeeHex, seed, l1Timestamp] = await Promise.all([
|
|
214
|
+
this.rollup.getCommitteeAt(ts),
|
|
215
|
+
this.rollup.getSampleSeedAt(ts),
|
|
216
|
+
this.rollup.client.getBlock({ includeTransactions: false }).then(b => b.timestamp),
|
|
217
|
+
]);
|
|
218
|
+
const { lagInEpochsForValidatorSet, epochDuration, slotDuration } = this.l1constants;
|
|
219
|
+
const sub = BigInt(lagInEpochsForValidatorSet) * BigInt(epochDuration) * BigInt(slotDuration);
|
|
220
|
+
if (ts - sub > l1Timestamp) {
|
|
221
|
+
throw new Error(
|
|
222
|
+
`Cannot query committee for future epoch ${epoch} with timestamp ${ts} (current L1 time is ${l1Timestamp}). Check your Ethereum node is synced.`,
|
|
223
|
+
);
|
|
224
|
+
}
|
|
197
225
|
const committee = committeeHex?.map((v: `0x${string}`) => EthAddress.fromString(v));
|
|
198
226
|
return { committee, seed, epoch };
|
|
199
227
|
}
|
|
@@ -201,18 +229,18 @@ export class EpochCache implements EpochCacheInterface {
|
|
|
201
229
|
/**
|
|
202
230
|
* Get the ABI encoding of the proposer index - see ValidatorSelectionLib.sol computeProposerIndex
|
|
203
231
|
*/
|
|
204
|
-
getProposerIndexEncoding(epoch:
|
|
232
|
+
getProposerIndexEncoding(epoch: EpochNumber, slot: SlotNumber, seed: bigint): `0x${string}` {
|
|
205
233
|
return encodeAbiParameters(
|
|
206
234
|
[
|
|
207
235
|
{ type: 'uint256', name: 'epoch' },
|
|
208
236
|
{ type: 'uint256', name: 'slot' },
|
|
209
237
|
{ type: 'uint256', name: 'seed' },
|
|
210
238
|
],
|
|
211
|
-
[epoch, slot, seed],
|
|
239
|
+
[BigInt(epoch), BigInt(slot), seed],
|
|
212
240
|
);
|
|
213
241
|
}
|
|
214
242
|
|
|
215
|
-
public computeProposerIndex(slot:
|
|
243
|
+
public computeProposerIndex(slot: SlotNumber, epoch: EpochNumber, seed: bigint, size: bigint): bigint {
|
|
216
244
|
// if committe size is 0, then mod 1 is 0
|
|
217
245
|
if (size === 0n) {
|
|
218
246
|
return 0n;
|
|
@@ -227,8 +255,8 @@ export class EpochCache implements EpochCacheInterface {
|
|
|
227
255
|
* which can be the next slot. If this is the case, then it will send proposals early.
|
|
228
256
|
*/
|
|
229
257
|
public async getProposerAttesterAddressInCurrentOrNextSlot(): Promise<{
|
|
230
|
-
currentSlot:
|
|
231
|
-
nextSlot:
|
|
258
|
+
currentSlot: SlotNumber;
|
|
259
|
+
nextSlot: SlotNumber;
|
|
232
260
|
currentProposer: EthAddress | undefined;
|
|
233
261
|
nextProposer: EthAddress | undefined;
|
|
234
262
|
}> {
|
|
@@ -244,11 +272,11 @@ export class EpochCache implements EpochCacheInterface {
|
|
|
244
272
|
}
|
|
245
273
|
|
|
246
274
|
/**
|
|
247
|
-
* Get the proposer attester address in the
|
|
275
|
+
* Get the proposer attester address in the given L2 slot
|
|
248
276
|
* @returns The proposer attester address. If the committee does not exist, we throw a NoCommitteeError.
|
|
249
277
|
* If the committee is empty (i.e. target committee size is 0, and anyone can propose), we return undefined.
|
|
250
278
|
*/
|
|
251
|
-
public getProposerAttesterAddressInSlot(slot:
|
|
279
|
+
public getProposerAttesterAddressInSlot(slot: SlotNumber): Promise<EthAddress | undefined> {
|
|
252
280
|
const epochAndSlot = this.getEpochAndSlotAtSlot(slot);
|
|
253
281
|
return this.getProposerAttesterAddressAt(epochAndSlot);
|
|
254
282
|
}
|
|
@@ -282,7 +310,10 @@ export class EpochCache implements EpochCacheInterface {
|
|
|
282
310
|
return committee[Number(proposerIndex)];
|
|
283
311
|
}
|
|
284
312
|
|
|
285
|
-
public getProposerFromEpochCommittee(
|
|
313
|
+
public getProposerFromEpochCommittee(
|
|
314
|
+
epochCommitteeInfo: EpochCommitteeInfo,
|
|
315
|
+
slot: SlotNumber,
|
|
316
|
+
): EthAddress | undefined {
|
|
286
317
|
if (!epochCommitteeInfo.committee || epochCommitteeInfo.committee.length === 0) {
|
|
287
318
|
return undefined;
|
|
288
319
|
}
|