@aztec/epoch-cache 1.0.0-nightly.20250616 → 1.0.0-nightly.20250618
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 +13 -2
- package/dest/epoch_cache.d.ts.map +1 -1
- package/dest/epoch_cache.js +30 -10
- package/package.json +11 -8
- package/src/epoch_cache.ts +31 -9
package/dest/epoch_cache.d.ts
CHANGED
|
@@ -9,7 +9,7 @@ type EpochAndSlot = {
|
|
|
9
9
|
ts: bigint;
|
|
10
10
|
};
|
|
11
11
|
export type EpochCommitteeInfo = {
|
|
12
|
-
committee: EthAddress[];
|
|
12
|
+
committee: EthAddress[] | undefined;
|
|
13
13
|
seed: bigint;
|
|
14
14
|
epoch: bigint;
|
|
15
15
|
};
|
|
@@ -42,7 +42,7 @@ export declare class EpochCache implements EpochCacheInterface {
|
|
|
42
42
|
private readonly config;
|
|
43
43
|
private cache;
|
|
44
44
|
private readonly log;
|
|
45
|
-
constructor(rollup: RollupContract, initialEpoch?: bigint, initialValidators?: EthAddress[], initialSampleSeed?: bigint, l1constants?: L1RollupConstants, dateProvider?: DateProvider, config?: {
|
|
45
|
+
constructor(rollup: RollupContract, initialEpoch?: bigint, initialValidators?: EthAddress[] | undefined, initialSampleSeed?: bigint, l1constants?: L1RollupConstants, dateProvider?: DateProvider, config?: {
|
|
46
46
|
cacheSize: number;
|
|
47
47
|
});
|
|
48
48
|
static create(rollupAddress: EthAddress, config?: EpochCacheConfig, deps?: {
|
|
@@ -84,7 +84,18 @@ export declare class EpochCache implements EpochCacheInterface {
|
|
|
84
84
|
currentProposer: EthAddress | undefined;
|
|
85
85
|
nextProposer: EthAddress | undefined;
|
|
86
86
|
}>;
|
|
87
|
+
/**
|
|
88
|
+
* Get the proposer attester address in the next slot
|
|
89
|
+
* @returns The proposer attester address. If the committee does not exist, we throw a NoCommitteeError.
|
|
90
|
+
* If the committee is empty (i.e. target committee size is 0, and anyone can propose), we return undefined.
|
|
91
|
+
*/
|
|
87
92
|
getProposerAttesterAddressInNextSlot(): Promise<EthAddress | undefined>;
|
|
93
|
+
/**
|
|
94
|
+
* Get the proposer attester address at a given epoch and slot
|
|
95
|
+
* @param when - The epoch and slot to get the proposer attester address at
|
|
96
|
+
* @returns The proposer attester address. If the committee does not exist, we throw a NoCommitteeError.
|
|
97
|
+
* If the committee is empty (i.e. target committee size is 0, and anyone can propose), we return undefined.
|
|
98
|
+
*/
|
|
88
99
|
private getProposerAttesterAddressAt;
|
|
89
100
|
/**
|
|
90
101
|
* Check if a validator is in the current epoch's committee
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"epoch_cache.d.ts","sourceRoot":"","sources":["../src/epoch_cache.ts"],"names":[],"mappings":"AAAA,OAAO,
|
|
1
|
+
{"version":3,"file":"epoch_cache.d.ts","sourceRoot":"","sources":["../src/epoch_cache.ts"],"names":[],"mappings":"AAAA,OAAO,EAAoB,cAAc,EAAuB,MAAM,iBAAiB,CAAC;AACxF,OAAO,EAAE,UAAU,EAAE,MAAM,+BAA+B,CAAC;AAE3D,OAAO,EAAE,YAAY,EAAE,MAAM,yBAAyB,CAAC;AACvD,OAAO,EAEL,KAAK,iBAAiB,EAOvB,MAAM,6BAA6B,CAAC;AAIrC,OAAO,EAAE,KAAK,gBAAgB,EAA8B,MAAM,aAAa,CAAC;AAEhF,KAAK,YAAY,GAAG;IAClB,KAAK,EAAE,MAAM,CAAC;IACd,IAAI,EAAE,MAAM,CAAC;IACb,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,MAAM,CAAC;CACf,CAAC;AAEF,MAAM,WAAW,mBAAmB;IAClC,YAAY,CAAC,IAAI,EAAE,KAAK,GAAG,MAAM,GAAG,MAAM,GAAG,SAAS,GAAG,OAAO,CAAC,kBAAkB,CAAC,CAAC;IACrF,kBAAkB,IAAI,YAAY,CAAC;IACnC,wBAAwB,CAAC,KAAK,EAAE,MAAM,EAAE,IAAI,EAAE,MAAM,EAAE,IAAI,EAAE,MAAM,GAAG,KAAK,MAAM,EAAE,CAAC;IACnF,oBAAoB,CAAC,IAAI,EAAE,MAAM,EAAE,KAAK,EAAE,MAAM,EAAE,IAAI,EAAE,MAAM,EAAE,IAAI,EAAE,MAAM,GAAG,MAAM,CAAC;IACtF,6CAA6C,IAAI,OAAO,CAAC;QACvD,eAAe,EAAE,UAAU,GAAG,SAAS,CAAC;QACxC,YAAY,EAAE,UAAU,GAAG,SAAS,CAAC;QACrC,WAAW,EAAE,MAAM,CAAC;QACpB,QAAQ,EAAE,MAAM,CAAC;KAClB,CAAC,CAAC;IACH,aAAa,CAAC,SAAS,EAAE,UAAU,GAAG,OAAO,CAAC,OAAO,CAAC,CAAC;CACxD;AAED;;;;;;;;GAQG;AACH,qBAAa,UAAW,YAAW,mBAAmB;IAKlD,OAAO,CAAC,MAAM;IAId,OAAO,CAAC,QAAQ,CAAC,WAAW;IAC5B,OAAO,CAAC,QAAQ,CAAC,YAAY;IAC7B,OAAO,CAAC,QAAQ,CAAC,MAAM;IAVzB,OAAO,CAAC,KAAK,CAA8C;IAC3D,OAAO,CAAC,QAAQ,CAAC,GAAG,CAAuC;gBAGjD,MAAM,EAAE,cAAc,EAC9B,YAAY,GAAE,MAAW,EACzB,iBAAiB,GAAE,UAAU,EAAE,GAAG,SAAqB,EACvD,iBAAiB,GAAE,MAAW,EACb,WAAW,GAAE,iBAA0C,EACvD,YAAY,GAAE,YAAiC,EAC/C,MAAM;;KAAoB;WAWhC,MAAM,CACjB,aAAa,EAAE,UAAU,EACzB,MAAM,CAAC,EAAE,gBAAgB,EACzB,IAAI,GAAE;QAAE,YAAY,CAAC,EAAE,YAAY,CAAA;KAAO;IAuCrC,cAAc,IAAI,iBAAiB;IAInC,kBAAkB,IAAI,YAAY,GAAG;QAAE,GAAG,EAAE,MAAM,CAAA;KAAE;IAKpD,YAAY,IAAI,MAAM;IAI7B,OAAO,CAAC,qBAAqB;IAMtB,2BAA2B,IAAI,YAAY,GAAG;QAAE,GAAG,EAAE,MAAM,CAAA;KAAE;IAMpE,OAAO,CAAC,0BAA0B;IAS3B,oBAAoB,CAAC,KAAK,EAAE,MAAM,GAAG,OAAO,CAAC,kBAAkB,CAAC;IAKvE;;;;OAIG;IACU,YAAY,CAAC,IAAI,GAAE,KAAK,GAAG,MAAM,GAAG,MAAc,GAAG,OAAO,CAAC,kBAAkB,CAAC;IAsB7F,OAAO,CAAC,oBAAoB;YAUd,gBAAgB;IAO9B;;OAEG;IACH,wBAAwB,CAAC,KAAK,EAAE,MAAM,EAAE,IAAI,EAAE,MAAM,EAAE,IAAI,EAAE,MAAM,GAAG,KAAK,MAAM,EAAE;IAWlF,oBAAoB,CAAC,IAAI,EAAE,MAAM,EAAE,KAAK,EAAE,MAAM,EAAE,IAAI,EAAE,MAAM,EAAE,IAAI,EAAE,MAAM,GAAG,MAAM;IAQrF;;;;;OAKG;IACG,6CAA6C,IAAI,OAAO,CAAC;QAC7D,WAAW,EAAE,MAAM,CAAC;QACpB,QAAQ,EAAE,MAAM,CAAC;QACjB,eAAe,EAAE,UAAU,GAAG,SAAS,CAAC;QACxC,YAAY,EAAE,UAAU,GAAG,SAAS,CAAC;KACtC,CAAC;IAYF;;;;OAIG;IACH,oCAAoC,IAAI,OAAO,CAAC,UAAU,GAAG,SAAS,CAAC;IAMvE;;;;;OAKG;YACW,4BAA4B;IAa1C;;OAEG;IACG,aAAa,CAAC,SAAS,EAAE,UAAU,GAAG,OAAO,CAAC,OAAO,CAAC;IAQtD,iBAAiB,CAAC,UAAU,EAAE,UAAU,EAAE,GAAG,OAAO,CAAC,UAAU,EAAE,CAAC;CAQzE"}
|
package/dest/epoch_cache.js
CHANGED
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
import { RollupContract, createEthereumChain } from '@aztec/ethereum';
|
|
1
|
+
import { NoCommitteeError, 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';
|
|
@@ -20,7 +20,7 @@ import { getEpochCacheConfigEnvVars } from './config.js';
|
|
|
20
20
|
config;
|
|
21
21
|
cache;
|
|
22
22
|
log;
|
|
23
|
-
constructor(rollup, initialEpoch = 0n, initialValidators =
|
|
23
|
+
constructor(rollup, initialEpoch = 0n, initialValidators = undefined, initialSampleSeed = 0n, l1constants = EmptyL1RollupConstants, dateProvider = new DateProvider(), config = {
|
|
24
24
|
cacheSize: 12
|
|
25
25
|
}){
|
|
26
26
|
this.rollup = rollup;
|
|
@@ -34,7 +34,7 @@ import { getEpochCacheConfigEnvVars } from './config.js';
|
|
|
34
34
|
committee: initialValidators,
|
|
35
35
|
seed: initialSampleSeed
|
|
36
36
|
});
|
|
37
|
-
this.log.debug(`Initialized EpochCache with ${initialValidators
|
|
37
|
+
this.log.debug(`Initialized EpochCache with ${initialValidators?.length ?? 'no'} validators`, {
|
|
38
38
|
l1constants,
|
|
39
39
|
initialValidators,
|
|
40
40
|
initialSampleSeed,
|
|
@@ -65,7 +65,7 @@ import { getEpochCacheConfigEnvVars } from './config.js';
|
|
|
65
65
|
epochDuration: config.aztecEpochDuration,
|
|
66
66
|
ethereumSlotDuration: config.ethereumSlotDuration
|
|
67
67
|
};
|
|
68
|
-
return new EpochCache(rollup, epochNumber, initialValidators
|
|
68
|
+
return new EpochCache(rollup, epochNumber, initialValidators?.map((v)=>EthAddress.fromString(v)), sampleSeed, l1RollupConstants, deps.dateProvider);
|
|
69
69
|
}
|
|
70
70
|
getL1Constants() {
|
|
71
71
|
return this.l1constants;
|
|
@@ -122,8 +122,8 @@ import { getEpochCacheConfigEnvVars } from './config.js';
|
|
|
122
122
|
epoch,
|
|
123
123
|
ts
|
|
124
124
|
});
|
|
125
|
-
// If the committee size is 0, then do not cache
|
|
126
|
-
if (epochData.committee.length
|
|
125
|
+
// If the committee size is 0 or undefined, then do not cache
|
|
126
|
+
if (!epochData.committee || epochData.committee.length === 0) {
|
|
127
127
|
return epochData;
|
|
128
128
|
}
|
|
129
129
|
this.cache.set(epoch, epochData);
|
|
@@ -146,7 +146,7 @@ import { getEpochCacheConfigEnvVars } from './config.js';
|
|
|
146
146
|
this.rollup.getCommitteeAt(ts),
|
|
147
147
|
this.rollup.getSampleSeedAt(ts)
|
|
148
148
|
]);
|
|
149
|
-
const committee = committeeHex
|
|
149
|
+
const committee = committeeHex?.map((v)=>EthAddress.fromString(v));
|
|
150
150
|
return {
|
|
151
151
|
committee,
|
|
152
152
|
seed,
|
|
@@ -197,13 +197,27 @@ import { getEpochCacheConfigEnvVars } from './config.js';
|
|
|
197
197
|
nextSlot: next.slot
|
|
198
198
|
};
|
|
199
199
|
}
|
|
200
|
-
|
|
200
|
+
/**
|
|
201
|
+
* Get the proposer attester address in the next slot
|
|
202
|
+
* @returns The proposer attester address. If the committee does not exist, we throw a NoCommitteeError.
|
|
203
|
+
* If the committee is empty (i.e. target committee size is 0, and anyone can propose), we return undefined.
|
|
204
|
+
*/ getProposerAttesterAddressInNextSlot() {
|
|
201
205
|
const epochAndSlot = this.getEpochAndSlotInNextL1Slot();
|
|
202
206
|
return this.getProposerAttesterAddressAt(epochAndSlot);
|
|
203
207
|
}
|
|
204
|
-
|
|
208
|
+
/**
|
|
209
|
+
* Get the proposer attester address at a given epoch and slot
|
|
210
|
+
* @param when - The epoch and slot to get the proposer attester address at
|
|
211
|
+
* @returns The proposer attester address. If the committee does not exist, we throw a NoCommitteeError.
|
|
212
|
+
* If the committee is empty (i.e. target committee size is 0, and anyone can propose), we return undefined.
|
|
213
|
+
*/ async getProposerAttesterAddressAt(when) {
|
|
205
214
|
const { epoch, slot } = when;
|
|
206
|
-
const {
|
|
215
|
+
const { committee, seed } = await this.getCommittee(slot);
|
|
216
|
+
if (!committee) {
|
|
217
|
+
throw new NoCommitteeError();
|
|
218
|
+
} else if (committee.length === 0) {
|
|
219
|
+
return undefined;
|
|
220
|
+
}
|
|
207
221
|
const proposerIndex = this.computeProposerIndex(slot, epoch, seed, BigInt(committee.length));
|
|
208
222
|
return committee[Number(proposerIndex)];
|
|
209
223
|
}
|
|
@@ -211,10 +225,16 @@ import { getEpochCacheConfigEnvVars } from './config.js';
|
|
|
211
225
|
* Check if a validator is in the current epoch's committee
|
|
212
226
|
*/ async isInCommittee(validator) {
|
|
213
227
|
const { committee } = await this.getCommittee();
|
|
228
|
+
if (!committee) {
|
|
229
|
+
return false;
|
|
230
|
+
}
|
|
214
231
|
return committee.some((v)=>v.equals(validator));
|
|
215
232
|
}
|
|
216
233
|
async filterInCommittee(validators) {
|
|
217
234
|
const { committee } = await this.getCommittee();
|
|
235
|
+
if (!committee) {
|
|
236
|
+
return [];
|
|
237
|
+
}
|
|
218
238
|
const committeeSet = new Set(committee.map((v)=>v.toString()));
|
|
219
239
|
return validators.filter((v)=>committeeSet.has(v.toString()));
|
|
220
240
|
}
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@aztec/epoch-cache",
|
|
3
|
-
"version": "1.0.0-nightly.
|
|
3
|
+
"version": "1.0.0-nightly.20250618",
|
|
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": "1.0.0-nightly.
|
|
30
|
-
"@aztec/foundation": "1.0.0-nightly.
|
|
31
|
-
"@aztec/l1-artifacts": "1.0.0-nightly.
|
|
32
|
-
"@aztec/stdlib": "1.0.0-nightly.
|
|
29
|
+
"@aztec/ethereum": "1.0.0-nightly.20250618",
|
|
30
|
+
"@aztec/foundation": "1.0.0-nightly.20250618",
|
|
31
|
+
"@aztec/l1-artifacts": "1.0.0-nightly.20250618",
|
|
32
|
+
"@aztec/stdlib": "1.0.0-nightly.20250618",
|
|
33
33
|
"@viem/anvil": "^0.0.10",
|
|
34
34
|
"dotenv": "^16.0.3",
|
|
35
35
|
"get-port": "^7.1.0",
|
|
@@ -39,10 +39,10 @@
|
|
|
39
39
|
"zod": "^3.23.8"
|
|
40
40
|
},
|
|
41
41
|
"devDependencies": {
|
|
42
|
-
"@jest/globals": "^
|
|
42
|
+
"@jest/globals": "^30.0.0",
|
|
43
43
|
"@types/jest": "^29.5.0",
|
|
44
44
|
"@types/node": "^22.15.17",
|
|
45
|
-
"jest": "^
|
|
45
|
+
"jest": "^30.0.0",
|
|
46
46
|
"ts-node": "^10.9.1",
|
|
47
47
|
"typescript": "^5.3.3"
|
|
48
48
|
},
|
|
@@ -84,7 +84,10 @@
|
|
|
84
84
|
"setupFiles": [
|
|
85
85
|
"../../foundation/src/jest/setup.mjs"
|
|
86
86
|
],
|
|
87
|
-
"testEnvironment": "../../foundation/src/jest/env.mjs"
|
|
87
|
+
"testEnvironment": "../../foundation/src/jest/env.mjs",
|
|
88
|
+
"setupFilesAfterEnv": [
|
|
89
|
+
"../../foundation/src/jest/setupAfterEnv.mjs"
|
|
90
|
+
]
|
|
88
91
|
},
|
|
89
92
|
"engines": {
|
|
90
93
|
"node": ">=20.10"
|
package/src/epoch_cache.ts
CHANGED
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
import { RollupContract, createEthereumChain } from '@aztec/ethereum';
|
|
1
|
+
import { NoCommitteeError, RollupContract, createEthereumChain } from '@aztec/ethereum';
|
|
2
2
|
import { EthAddress } from '@aztec/foundation/eth-address';
|
|
3
3
|
import { type Logger, createLogger } from '@aztec/foundation/log';
|
|
4
4
|
import { DateProvider } from '@aztec/foundation/timer';
|
|
@@ -24,7 +24,7 @@ type EpochAndSlot = {
|
|
|
24
24
|
};
|
|
25
25
|
|
|
26
26
|
export type EpochCommitteeInfo = {
|
|
27
|
-
committee: EthAddress[];
|
|
27
|
+
committee: EthAddress[] | undefined;
|
|
28
28
|
seed: bigint;
|
|
29
29
|
epoch: bigint;
|
|
30
30
|
};
|
|
@@ -59,14 +59,14 @@ export class EpochCache implements EpochCacheInterface {
|
|
|
59
59
|
constructor(
|
|
60
60
|
private rollup: RollupContract,
|
|
61
61
|
initialEpoch: bigint = 0n,
|
|
62
|
-
initialValidators: EthAddress[] =
|
|
62
|
+
initialValidators: EthAddress[] | undefined = undefined,
|
|
63
63
|
initialSampleSeed: bigint = 0n,
|
|
64
64
|
private readonly l1constants: L1RollupConstants = EmptyL1RollupConstants,
|
|
65
65
|
private readonly dateProvider: DateProvider = new DateProvider(),
|
|
66
66
|
private readonly config = { cacheSize: 12 },
|
|
67
67
|
) {
|
|
68
68
|
this.cache.set(initialEpoch, { epoch: initialEpoch, committee: initialValidators, seed: initialSampleSeed });
|
|
69
|
-
this.log.debug(`Initialized EpochCache with ${initialValidators
|
|
69
|
+
this.log.debug(`Initialized EpochCache with ${initialValidators?.length ?? 'no'} validators`, {
|
|
70
70
|
l1constants,
|
|
71
71
|
initialValidators,
|
|
72
72
|
initialSampleSeed,
|
|
@@ -109,7 +109,7 @@ export class EpochCache implements EpochCacheInterface {
|
|
|
109
109
|
return new EpochCache(
|
|
110
110
|
rollup,
|
|
111
111
|
epochNumber,
|
|
112
|
-
initialValidators
|
|
112
|
+
initialValidators?.map(v => EthAddress.fromString(v)),
|
|
113
113
|
sampleSeed,
|
|
114
114
|
l1RollupConstants,
|
|
115
115
|
deps.dateProvider,
|
|
@@ -168,8 +168,8 @@ export class EpochCache implements EpochCacheInterface {
|
|
|
168
168
|
}
|
|
169
169
|
|
|
170
170
|
const epochData = await this.computeCommittee({ epoch, ts });
|
|
171
|
-
// If the committee size is 0, then do not cache
|
|
172
|
-
if (epochData.committee.length
|
|
171
|
+
// If the committee size is 0 or undefined, then do not cache
|
|
172
|
+
if (!epochData.committee || epochData.committee.length === 0) {
|
|
173
173
|
return epochData;
|
|
174
174
|
}
|
|
175
175
|
this.cache.set(epoch, epochData);
|
|
@@ -195,7 +195,7 @@ export class EpochCache implements EpochCacheInterface {
|
|
|
195
195
|
private async computeCommittee(when: { epoch: bigint; ts: bigint }): Promise<EpochCommitteeInfo> {
|
|
196
196
|
const { ts, epoch } = when;
|
|
197
197
|
const [committeeHex, seed] = await Promise.all([this.rollup.getCommitteeAt(ts), this.rollup.getSampleSeedAt(ts)]);
|
|
198
|
-
const committee = committeeHex
|
|
198
|
+
const committee = committeeHex?.map((v: `0x${string}`) => EthAddress.fromString(v));
|
|
199
199
|
return { committee, seed, epoch };
|
|
200
200
|
}
|
|
201
201
|
|
|
@@ -244,15 +244,31 @@ export class EpochCache implements EpochCacheInterface {
|
|
|
244
244
|
};
|
|
245
245
|
}
|
|
246
246
|
|
|
247
|
+
/**
|
|
248
|
+
* Get the proposer attester address in the next slot
|
|
249
|
+
* @returns The proposer attester address. If the committee does not exist, we throw a NoCommitteeError.
|
|
250
|
+
* If the committee is empty (i.e. target committee size is 0, and anyone can propose), we return undefined.
|
|
251
|
+
*/
|
|
247
252
|
getProposerAttesterAddressInNextSlot(): Promise<EthAddress | undefined> {
|
|
248
253
|
const epochAndSlot = this.getEpochAndSlotInNextL1Slot();
|
|
249
254
|
|
|
250
255
|
return this.getProposerAttesterAddressAt(epochAndSlot);
|
|
251
256
|
}
|
|
252
257
|
|
|
258
|
+
/**
|
|
259
|
+
* Get the proposer attester address at a given epoch and slot
|
|
260
|
+
* @param when - The epoch and slot to get the proposer attester address at
|
|
261
|
+
* @returns The proposer attester address. If the committee does not exist, we throw a NoCommitteeError.
|
|
262
|
+
* If the committee is empty (i.e. target committee size is 0, and anyone can propose), we return undefined.
|
|
263
|
+
*/
|
|
253
264
|
private async getProposerAttesterAddressAt(when: EpochAndSlot) {
|
|
254
265
|
const { epoch, slot } = when;
|
|
255
|
-
const {
|
|
266
|
+
const { committee, seed } = await this.getCommittee(slot);
|
|
267
|
+
if (!committee) {
|
|
268
|
+
throw new NoCommitteeError();
|
|
269
|
+
} else if (committee.length === 0) {
|
|
270
|
+
return undefined;
|
|
271
|
+
}
|
|
256
272
|
|
|
257
273
|
const proposerIndex = this.computeProposerIndex(slot, epoch, seed, BigInt(committee.length));
|
|
258
274
|
return committee[Number(proposerIndex)];
|
|
@@ -263,11 +279,17 @@ export class EpochCache implements EpochCacheInterface {
|
|
|
263
279
|
*/
|
|
264
280
|
async isInCommittee(validator: EthAddress): Promise<boolean> {
|
|
265
281
|
const { committee } = await this.getCommittee();
|
|
282
|
+
if (!committee) {
|
|
283
|
+
return false;
|
|
284
|
+
}
|
|
266
285
|
return committee.some(v => v.equals(validator));
|
|
267
286
|
}
|
|
268
287
|
|
|
269
288
|
async filterInCommittee(validators: EthAddress[]): Promise<EthAddress[]> {
|
|
270
289
|
const { committee } = await this.getCommittee();
|
|
290
|
+
if (!committee) {
|
|
291
|
+
return [];
|
|
292
|
+
}
|
|
271
293
|
const committeeSet = new Set(committee.map(v => v.toString()));
|
|
272
294
|
return validators.filter(v => committeeSet.has(v.toString()));
|
|
273
295
|
}
|