@aztec/epoch-cache 0.87.7 → 1.0.0-nightly.20250604
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/epoch_cache.d.ts +12 -9
- package/dest/epoch_cache.d.ts.map +1 -1
- package/dest/epoch_cache.js +30 -9
- package/package.json +5 -5
- package/src/epoch_cache.ts +39 -12
package/dest/epoch_cache.d.ts
CHANGED
|
@@ -18,7 +18,7 @@ export interface EpochCacheInterface {
|
|
|
18
18
|
getEpochAndSlotNow(): EpochAndSlot;
|
|
19
19
|
getProposerIndexEncoding(epoch: bigint, slot: bigint, seed: bigint): `0x${string}`;
|
|
20
20
|
computeProposerIndex(slot: bigint, epoch: bigint, seed: bigint, size: bigint): bigint;
|
|
21
|
-
|
|
21
|
+
getProposerAttesterAddressInCurrentOrNextSlot(): Promise<{
|
|
22
22
|
currentProposer: EthAddress;
|
|
23
23
|
nextProposer: EthAddress;
|
|
24
24
|
currentSlot: bigint;
|
|
@@ -52,8 +52,9 @@ export declare class EpochCache implements EpochCacheInterface {
|
|
|
52
52
|
getEpochAndSlotNow(): EpochAndSlot;
|
|
53
53
|
private nowInSeconds;
|
|
54
54
|
private getEpochAndSlotAtSlot;
|
|
55
|
-
|
|
55
|
+
getEpochAndSlotInNextSlot(): EpochAndSlot;
|
|
56
56
|
private getEpochAndSlotAtTimestamp;
|
|
57
|
+
getCommitteeForEpoch(epoch: bigint): Promise<EpochCommitteeInfo>;
|
|
57
58
|
/**
|
|
58
59
|
* Get the current validator set
|
|
59
60
|
* @param nextSlot - If true, get the validator set for the next slot.
|
|
@@ -68,22 +69,24 @@ export declare class EpochCache implements EpochCacheInterface {
|
|
|
68
69
|
getProposerIndexEncoding(epoch: bigint, slot: bigint, seed: bigint): `0x${string}`;
|
|
69
70
|
computeProposerIndex(slot: bigint, epoch: bigint, seed: bigint, size: bigint): bigint;
|
|
70
71
|
/**
|
|
71
|
-
* Returns the current and next proposer
|
|
72
|
+
* Returns the current and next proposer's attester address
|
|
72
73
|
*
|
|
73
|
-
* We return the next proposer as the node will check if it is the proposer at the next ethereum block,
|
|
74
|
-
* can be the next slot. If this is the case, then it will send proposals early.
|
|
74
|
+
* We return the next proposer's attester address as the node will check if it is the proposer at the next ethereum block,
|
|
75
|
+
* which can be the next slot. If this is the case, then it will send proposals early.
|
|
75
76
|
*/
|
|
76
|
-
|
|
77
|
-
currentProposer: EthAddress;
|
|
78
|
-
nextProposer: EthAddress;
|
|
77
|
+
getProposerAttesterAddressInCurrentOrNextSlot(): Promise<{
|
|
79
78
|
currentSlot: bigint;
|
|
80
79
|
nextSlot: bigint;
|
|
80
|
+
currentProposer: EthAddress;
|
|
81
|
+
nextProposer: EthAddress;
|
|
81
82
|
}>;
|
|
82
|
-
|
|
83
|
+
getProposerAttesterAddressInNextSlot(): Promise<EthAddress>;
|
|
84
|
+
private getProposerAttesterAddressAt;
|
|
83
85
|
/**
|
|
84
86
|
* Check if a validator is in the current epoch's committee
|
|
85
87
|
*/
|
|
86
88
|
isInCommittee(validator: EthAddress): Promise<boolean>;
|
|
89
|
+
filterInCommittee(validators: EthAddress[]): Promise<EthAddress[]>;
|
|
87
90
|
}
|
|
88
91
|
export {};
|
|
89
92
|
//# sourceMappingURL=epoch_cache.d.ts.map
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"epoch_cache.d.ts","sourceRoot":"","sources":["../src/epoch_cache.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,cAAc,EAAuB,MAAM,iBAAiB,CAAC;AACtE,OAAO,EAAE,UAAU,EAAE,MAAM,+BAA+B,CAAC;AAE3D,OAAO,EAAE,YAAY,EAAE,MAAM,yBAAyB,CAAC;AACvD,OAAO,EAEL,KAAK,iBAAiB,
|
|
1
|
+
{"version":3,"file":"epoch_cache.d.ts","sourceRoot":"","sources":["../src/epoch_cache.ts"],"names":[],"mappings":"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"}
|
package/dest/epoch_cache.js
CHANGED
|
@@ -2,7 +2,7 @@ import { RollupContract, createEthereumChain } from '@aztec/ethereum';
|
|
|
2
2
|
import { EthAddress } from '@aztec/foundation/eth-address';
|
|
3
3
|
import { createLogger } from '@aztec/foundation/log';
|
|
4
4
|
import { DateProvider } from '@aztec/foundation/timer';
|
|
5
|
-
import { EmptyL1RollupConstants, getEpochAtSlot, getEpochNumberAtTimestamp, getSlotAtTimestamp, getTimestampRangeForEpoch } from '@aztec/stdlib/epoch-helpers';
|
|
5
|
+
import { EmptyL1RollupConstants, getEpochAtSlot, getEpochNumberAtTimestamp, getSlotAtTimestamp, getSlotRangeForEpoch, getTimestampRangeForEpoch } from '@aztec/stdlib/epoch-helpers';
|
|
6
6
|
import { createPublicClient, encodeAbiParameters, fallback, http, keccak256 } from 'viem';
|
|
7
7
|
import { getEpochCacheConfigEnvVars } from './config.js';
|
|
8
8
|
/**
|
|
@@ -86,7 +86,7 @@ import { getEpochCacheConfigEnvVars } from './config.js';
|
|
|
86
86
|
};
|
|
87
87
|
}
|
|
88
88
|
getEpochAndSlotInNextSlot() {
|
|
89
|
-
const nextSlotTs = this.nowInSeconds() + BigInt(this.l1constants.
|
|
89
|
+
const nextSlotTs = this.nowInSeconds() + BigInt(this.l1constants.ethereumSlotDuration);
|
|
90
90
|
return this.getEpochAndSlotAtTimestamp(nextSlotTs);
|
|
91
91
|
}
|
|
92
92
|
getEpochAndSlotAtTimestamp(ts) {
|
|
@@ -96,6 +96,10 @@ import { getEpochCacheConfigEnvVars } from './config.js';
|
|
|
96
96
|
ts
|
|
97
97
|
};
|
|
98
98
|
}
|
|
99
|
+
getCommitteeForEpoch(epoch) {
|
|
100
|
+
const [startSlot] = getSlotRangeForEpoch(epoch, this.l1constants);
|
|
101
|
+
return this.getCommittee(startSlot);
|
|
102
|
+
}
|
|
99
103
|
/**
|
|
100
104
|
* Get the current validator set
|
|
101
105
|
* @param nextSlot - If true, get the validator set for the next slot.
|
|
@@ -109,6 +113,10 @@ import { getEpochCacheConfigEnvVars } from './config.js';
|
|
|
109
113
|
epoch,
|
|
110
114
|
ts
|
|
111
115
|
});
|
|
116
|
+
// If the committee size is 0, then do not cache
|
|
117
|
+
if (epochData.committee.length == 0) {
|
|
118
|
+
return epochData;
|
|
119
|
+
}
|
|
112
120
|
this.cache.set(epoch, epochData);
|
|
113
121
|
const toPurge = Array.from(this.cache.keys()).sort((a, b)=>Number(b - a)).slice(this.config.cacheSize);
|
|
114
122
|
toPurge.forEach((key)=>this.cache.delete(key));
|
|
@@ -159,24 +167,32 @@ import { getEpochCacheConfigEnvVars } from './config.js';
|
|
|
159
167
|
]);
|
|
160
168
|
}
|
|
161
169
|
computeProposerIndex(slot, epoch, seed, size) {
|
|
170
|
+
// if committe size is 0, then mod 1 is 0
|
|
171
|
+
if (size === 0n) {
|
|
172
|
+
return 0n;
|
|
173
|
+
}
|
|
162
174
|
return BigInt(keccak256(this.getProposerIndexEncoding(epoch, slot, seed))) % size;
|
|
163
175
|
}
|
|
164
176
|
/**
|
|
165
|
-
* Returns the current and next proposer
|
|
177
|
+
* Returns the current and next proposer's attester address
|
|
166
178
|
*
|
|
167
|
-
* We return the next proposer as the node will check if it is the proposer at the next ethereum block,
|
|
168
|
-
* can be the next slot. If this is the case, then it will send proposals early.
|
|
169
|
-
*/ async
|
|
179
|
+
* We return the next proposer's attester address as the node will check if it is the proposer at the next ethereum block,
|
|
180
|
+
* which can be the next slot. If this is the case, then it will send proposals early.
|
|
181
|
+
*/ async getProposerAttesterAddressInCurrentOrNextSlot() {
|
|
170
182
|
const current = this.getEpochAndSlotNow();
|
|
171
183
|
const next = this.getEpochAndSlotInNextSlot();
|
|
172
184
|
return {
|
|
173
|
-
currentProposer: await this.
|
|
174
|
-
nextProposer: await this.
|
|
185
|
+
currentProposer: await this.getProposerAttesterAddressAt(current),
|
|
186
|
+
nextProposer: await this.getProposerAttesterAddressAt(next),
|
|
175
187
|
currentSlot: current.slot,
|
|
176
188
|
nextSlot: next.slot
|
|
177
189
|
};
|
|
178
190
|
}
|
|
179
|
-
|
|
191
|
+
getProposerAttesterAddressInNextSlot() {
|
|
192
|
+
const epochAndSlot = this.getEpochAndSlotInNextSlot();
|
|
193
|
+
return this.getProposerAttesterAddressAt(epochAndSlot);
|
|
194
|
+
}
|
|
195
|
+
async getProposerAttesterAddressAt(when) {
|
|
180
196
|
const { epoch, slot } = when;
|
|
181
197
|
const { seed, committee } = await this.getCommittee(slot);
|
|
182
198
|
const proposerIndex = this.computeProposerIndex(slot, epoch, seed, BigInt(committee.length));
|
|
@@ -188,4 +204,9 @@ import { getEpochCacheConfigEnvVars } from './config.js';
|
|
|
188
204
|
const { committee } = await this.getCommittee();
|
|
189
205
|
return committee.some((v)=>v.equals(validator));
|
|
190
206
|
}
|
|
207
|
+
async filterInCommittee(validators) {
|
|
208
|
+
const { committee } = await this.getCommittee();
|
|
209
|
+
const committeeSet = new Set(committee.map((v)=>v.toString()));
|
|
210
|
+
return validators.filter((v)=>committeeSet.has(v.toString()));
|
|
211
|
+
}
|
|
191
212
|
}
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@aztec/epoch-cache",
|
|
3
|
-
"version": "0.
|
|
3
|
+
"version": "1.0.0-nightly.20250604",
|
|
4
4
|
"type": "module",
|
|
5
5
|
"exports": {
|
|
6
6
|
".": "./dest/index.js",
|
|
@@ -26,10 +26,10 @@
|
|
|
26
26
|
"../package.common.json"
|
|
27
27
|
],
|
|
28
28
|
"dependencies": {
|
|
29
|
-
"@aztec/ethereum": "0.
|
|
30
|
-
"@aztec/foundation": "0.
|
|
31
|
-
"@aztec/l1-artifacts": "0.
|
|
32
|
-
"@aztec/stdlib": "0.
|
|
29
|
+
"@aztec/ethereum": "1.0.0-nightly.20250604",
|
|
30
|
+
"@aztec/foundation": "1.0.0-nightly.20250604",
|
|
31
|
+
"@aztec/l1-artifacts": "1.0.0-nightly.20250604",
|
|
32
|
+
"@aztec/stdlib": "1.0.0-nightly.20250604",
|
|
33
33
|
"@viem/anvil": "^0.0.10",
|
|
34
34
|
"dotenv": "^16.0.3",
|
|
35
35
|
"get-port": "^7.1.0",
|
package/src/epoch_cache.ts
CHANGED
|
@@ -8,6 +8,7 @@ import {
|
|
|
8
8
|
getEpochAtSlot,
|
|
9
9
|
getEpochNumberAtTimestamp,
|
|
10
10
|
getSlotAtTimestamp,
|
|
11
|
+
getSlotRangeForEpoch,
|
|
11
12
|
getTimestampRangeForEpoch,
|
|
12
13
|
} from '@aztec/stdlib/epoch-helpers';
|
|
13
14
|
|
|
@@ -32,7 +33,7 @@ export interface EpochCacheInterface {
|
|
|
32
33
|
getEpochAndSlotNow(): EpochAndSlot;
|
|
33
34
|
getProposerIndexEncoding(epoch: bigint, slot: bigint, seed: bigint): `0x${string}`;
|
|
34
35
|
computeProposerIndex(slot: bigint, epoch: bigint, seed: bigint, size: bigint): bigint;
|
|
35
|
-
|
|
36
|
+
getProposerAttesterAddressInCurrentOrNextSlot(): Promise<{
|
|
36
37
|
currentProposer: EthAddress;
|
|
37
38
|
nextProposer: EthAddress;
|
|
38
39
|
currentSlot: bigint;
|
|
@@ -132,8 +133,8 @@ export class EpochCache implements EpochCacheInterface {
|
|
|
132
133
|
return { epoch, ts, slot };
|
|
133
134
|
}
|
|
134
135
|
|
|
135
|
-
|
|
136
|
-
const nextSlotTs = this.nowInSeconds() + BigInt(this.l1constants.
|
|
136
|
+
public getEpochAndSlotInNextSlot(): EpochAndSlot {
|
|
137
|
+
const nextSlotTs = this.nowInSeconds() + BigInt(this.l1constants.ethereumSlotDuration);
|
|
137
138
|
return this.getEpochAndSlotAtTimestamp(nextSlotTs);
|
|
138
139
|
}
|
|
139
140
|
|
|
@@ -145,6 +146,11 @@ export class EpochCache implements EpochCacheInterface {
|
|
|
145
146
|
};
|
|
146
147
|
}
|
|
147
148
|
|
|
149
|
+
public getCommitteeForEpoch(epoch: bigint): Promise<EpochCommitteeInfo> {
|
|
150
|
+
const [startSlot] = getSlotRangeForEpoch(epoch, this.l1constants);
|
|
151
|
+
return this.getCommittee(startSlot);
|
|
152
|
+
}
|
|
153
|
+
|
|
148
154
|
/**
|
|
149
155
|
* Get the current validator set
|
|
150
156
|
* @param nextSlot - If true, get the validator set for the next slot.
|
|
@@ -158,6 +164,10 @@ export class EpochCache implements EpochCacheInterface {
|
|
|
158
164
|
}
|
|
159
165
|
|
|
160
166
|
const epochData = await this.computeCommittee({ epoch, ts });
|
|
167
|
+
// If the committee size is 0, then do not cache
|
|
168
|
+
if (epochData.committee.length == 0) {
|
|
169
|
+
return epochData;
|
|
170
|
+
}
|
|
161
171
|
this.cache.set(epoch, epochData);
|
|
162
172
|
|
|
163
173
|
const toPurge = Array.from(this.cache.keys())
|
|
@@ -200,35 +210,46 @@ export class EpochCache implements EpochCacheInterface {
|
|
|
200
210
|
}
|
|
201
211
|
|
|
202
212
|
computeProposerIndex(slot: bigint, epoch: bigint, seed: bigint, size: bigint): bigint {
|
|
213
|
+
// if committe size is 0, then mod 1 is 0
|
|
214
|
+
if (size === 0n) {
|
|
215
|
+
return 0n;
|
|
216
|
+
}
|
|
203
217
|
return BigInt(keccak256(this.getProposerIndexEncoding(epoch, slot, seed))) % size;
|
|
204
218
|
}
|
|
205
219
|
|
|
206
220
|
/**
|
|
207
|
-
* Returns the current and next proposer
|
|
221
|
+
* Returns the current and next proposer's attester address
|
|
208
222
|
*
|
|
209
|
-
* We return the next proposer as the node will check if it is the proposer at the next ethereum block,
|
|
210
|
-
* can be the next slot. If this is the case, then it will send proposals early.
|
|
223
|
+
* We return the next proposer's attester address as the node will check if it is the proposer at the next ethereum block,
|
|
224
|
+
* which can be the next slot. If this is the case, then it will send proposals early.
|
|
211
225
|
*/
|
|
212
|
-
async
|
|
213
|
-
currentProposer: EthAddress;
|
|
214
|
-
nextProposer: EthAddress;
|
|
226
|
+
async getProposerAttesterAddressInCurrentOrNextSlot(): Promise<{
|
|
215
227
|
currentSlot: bigint;
|
|
216
228
|
nextSlot: bigint;
|
|
229
|
+
currentProposer: EthAddress;
|
|
230
|
+
nextProposer: EthAddress;
|
|
217
231
|
}> {
|
|
218
232
|
const current = this.getEpochAndSlotNow();
|
|
219
233
|
const next = this.getEpochAndSlotInNextSlot();
|
|
220
234
|
|
|
221
235
|
return {
|
|
222
|
-
currentProposer: await this.
|
|
223
|
-
nextProposer: await this.
|
|
236
|
+
currentProposer: await this.getProposerAttesterAddressAt(current),
|
|
237
|
+
nextProposer: await this.getProposerAttesterAddressAt(next),
|
|
224
238
|
currentSlot: current.slot,
|
|
225
239
|
nextSlot: next.slot,
|
|
226
240
|
};
|
|
227
241
|
}
|
|
228
242
|
|
|
229
|
-
|
|
243
|
+
getProposerAttesterAddressInNextSlot(): Promise<EthAddress> {
|
|
244
|
+
const epochAndSlot = this.getEpochAndSlotInNextSlot();
|
|
245
|
+
|
|
246
|
+
return this.getProposerAttesterAddressAt(epochAndSlot);
|
|
247
|
+
}
|
|
248
|
+
|
|
249
|
+
private async getProposerAttesterAddressAt(when: EpochAndSlot) {
|
|
230
250
|
const { epoch, slot } = when;
|
|
231
251
|
const { seed, committee } = await this.getCommittee(slot);
|
|
252
|
+
|
|
232
253
|
const proposerIndex = this.computeProposerIndex(slot, epoch, seed, BigInt(committee.length));
|
|
233
254
|
return committee[Number(proposerIndex)];
|
|
234
255
|
}
|
|
@@ -240,4 +261,10 @@ export class EpochCache implements EpochCacheInterface {
|
|
|
240
261
|
const { committee } = await this.getCommittee();
|
|
241
262
|
return committee.some(v => v.equals(validator));
|
|
242
263
|
}
|
|
264
|
+
|
|
265
|
+
async filterInCommittee(validators: EthAddress[]): Promise<EthAddress[]> {
|
|
266
|
+
const { committee } = await this.getCommittee();
|
|
267
|
+
const committeeSet = new Set(committee.map(v => v.toString()));
|
|
268
|
+
return validators.filter(v => committeeSet.has(v.toString()));
|
|
269
|
+
}
|
|
243
270
|
}
|