@lodestar/state-transition 1.47.0-dev.a64cdf7144 → 1.47.0-dev.aa6eaee53a
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/lib/block/isValidIndexedAttestation.d.ts +2 -3
- package/lib/block/isValidIndexedAttestation.d.ts.map +1 -1
- package/lib/block/isValidIndexedAttestation.js +4 -4
- package/lib/block/isValidIndexedAttestation.js.map +1 -1
- package/lib/block/isValidIndexedPayloadAttestation.d.ts.map +1 -1
- package/lib/block/isValidIndexedPayloadAttestation.js +1 -1
- package/lib/block/isValidIndexedPayloadAttestation.js.map +1 -1
- package/lib/block/processAttestationPhase0.d.ts.map +1 -1
- package/lib/block/processAttestationPhase0.js +1 -1
- package/lib/block/processAttestationPhase0.js.map +1 -1
- package/lib/block/processAttestationsAltair.js +1 -1
- package/lib/block/processAttestationsAltair.js.map +1 -1
- package/lib/block/processAttesterSlashing.d.ts +1 -2
- package/lib/block/processAttesterSlashing.d.ts.map +1 -1
- package/lib/block/processAttesterSlashing.js +3 -3
- package/lib/block/processAttesterSlashing.js.map +1 -1
- package/lib/block/processDeposit.d.ts.map +1 -1
- package/lib/block/processDeposit.js +21 -46
- package/lib/block/processDeposit.js.map +1 -1
- package/lib/block/processExecutionPayloadBid.d.ts.map +1 -1
- package/lib/block/processExecutionPayloadBid.js +2 -5
- package/lib/block/processExecutionPayloadBid.js.map +1 -1
- package/lib/block/processProposerSlashing.d.ts +1 -2
- package/lib/block/processProposerSlashing.d.ts.map +1 -1
- package/lib/block/processProposerSlashing.js +3 -3
- package/lib/block/processProposerSlashing.js.map +1 -1
- package/lib/block/processRandao.js +1 -1
- package/lib/block/processRandao.js.map +1 -1
- package/lib/block/processSyncCommittee.js +1 -1
- package/lib/block/processSyncCommittee.js.map +1 -1
- package/lib/block/processVoluntaryExit.d.ts.map +1 -1
- package/lib/block/processVoluntaryExit.js +1 -2
- package/lib/block/processVoluntaryExit.js.map +1 -1
- package/lib/cache/epochCache.d.ts +2 -2
- package/lib/cache/epochCache.d.ts.map +1 -1
- package/lib/cache/epochCache.js +5 -6
- package/lib/cache/epochCache.js.map +1 -1
- package/lib/cache/stateCache.js +1 -1
- package/lib/cache/stateCache.js.map +1 -1
- package/lib/cache/syncCommitteeCache.d.ts +2 -3
- package/lib/cache/syncCommitteeCache.d.ts.map +1 -1
- package/lib/cache/syncCommitteeCache.js.map +1 -1
- package/lib/epoch/processSyncCommitteeUpdates.js +1 -1
- package/lib/epoch/processSyncCommitteeUpdates.js.map +1 -1
- package/lib/index.d.ts +1 -2
- package/lib/index.d.ts.map +1 -1
- package/lib/index.js +1 -2
- package/lib/index.js.map +1 -1
- package/lib/lightClient/spec/store.d.ts +1 -1
- package/lib/lightClient/spec/store.d.ts.map +1 -1
- package/lib/lightClient/spec/utils.js +1 -1
- package/lib/lightClient/spec/utils.js.map +1 -1
- package/lib/lightClient/spec/validateLightClientUpdate.js +1 -1
- package/lib/lightClient/spec/validateLightClientUpdate.js.map +1 -1
- package/lib/rewards/attestationsRewards.d.ts +1 -1
- package/lib/rewards/attestationsRewards.d.ts.map +1 -1
- package/lib/rewards/attestationsRewards.js.map +1 -1
- package/lib/rewards/syncCommitteeRewards.d.ts +1 -1
- package/lib/rewards/syncCommitteeRewards.d.ts.map +1 -1
- package/lib/rewards/syncCommitteeRewards.js +3 -1
- package/lib/rewards/syncCommitteeRewards.js.map +1 -1
- package/lib/signatureSets/blsToExecutionChange.d.ts.map +1 -1
- package/lib/signatureSets/blsToExecutionChange.js +1 -2
- package/lib/signatureSets/blsToExecutionChange.js.map +1 -1
- package/lib/signatureSets/executionPayloadEnvelope.d.ts +2 -3
- package/lib/signatureSets/executionPayloadEnvelope.d.ts.map +1 -1
- package/lib/signatureSets/executionPayloadEnvelope.js +6 -7
- package/lib/signatureSets/executionPayloadEnvelope.js.map +1 -1
- package/lib/signatureSets/proposer.d.ts +1 -2
- package/lib/signatureSets/proposer.d.ts.map +1 -1
- package/lib/signatureSets/proposer.js +2 -2
- package/lib/signatureSets/proposer.js.map +1 -1
- package/lib/signatureSets/randao.d.ts +1 -2
- package/lib/signatureSets/randao.d.ts.map +1 -1
- package/lib/signatureSets/randao.js +2 -2
- package/lib/signatureSets/randao.js.map +1 -1
- package/lib/signatureSets/voluntaryExits.d.ts +1 -2
- package/lib/signatureSets/voluntaryExits.d.ts.map +1 -1
- package/lib/signatureSets/voluntaryExits.js +3 -4
- package/lib/signatureSets/voluntaryExits.js.map +1 -1
- package/lib/stateTransition.js +1 -1
- package/lib/stateTransition.js.map +1 -1
- package/lib/stateView/stateViewFactory.d.ts +1 -1
- package/lib/stateView/stateViewFactory.d.ts.map +1 -1
- package/lib/stateView/stateViewFactory.js +2 -13
- package/lib/stateView/stateViewFactory.js.map +1 -1
- package/lib/testUtils/index.d.ts +1 -0
- package/lib/testUtils/index.d.ts.map +1 -1
- package/lib/testUtils/index.js +1 -0
- package/lib/testUtils/index.js.map +1 -1
- package/lib/testUtils/interopPubkeyCache.d.ts +7 -0
- package/lib/testUtils/interopPubkeyCache.d.ts.map +1 -0
- package/lib/testUtils/interopPubkeyCache.js +92 -0
- package/lib/testUtils/interopPubkeyCache.js.map +1 -0
- package/lib/testUtils/state.d.ts.map +1 -1
- package/lib/testUtils/state.js +5 -5
- package/lib/testUtils/state.js.map +1 -1
- package/lib/testUtils/testFileCache.d.ts.map +1 -1
- package/lib/testUtils/testFileCache.js +3 -0
- package/lib/testUtils/testFileCache.js.map +1 -1
- package/lib/testUtils/util.d.ts +1 -1
- package/lib/testUtils/util.d.ts.map +1 -1
- package/lib/testUtils/util.js +27 -35
- package/lib/testUtils/util.js.map +1 -1
- package/lib/util/gloas.d.ts.map +1 -1
- package/lib/util/gloas.js +2 -4
- package/lib/util/gloas.js.map +1 -1
- package/lib/util/interop.d.ts +1 -1
- package/lib/util/interop.d.ts.map +1 -1
- package/lib/util/interop.js +1 -1
- package/lib/util/interop.js.map +1 -1
- package/lib/util/signatureSets.d.ts +5 -13
- package/lib/util/signatureSets.d.ts.map +1 -1
- package/lib/util/signatureSets.js +30 -39
- package/lib/util/signatureSets.js.map +1 -1
- package/lib/util/syncCommittee.js +1 -1
- package/lib/util/syncCommittee.js.map +1 -1
- package/package.json +11 -12
- package/src/block/isValidIndexedAttestation.ts +2 -8
- package/src/block/isValidIndexedPayloadAttestation.ts +1 -4
- package/src/block/processAttestationPhase0.ts +0 -1
- package/src/block/processAttestationsAltair.ts +1 -1
- package/src/block/processAttesterSlashing.ts +2 -13
- package/src/block/processDeposit.ts +35 -47
- package/src/block/processExecutionPayloadBid.ts +8 -6
- package/src/block/processProposerSlashing.ts +2 -11
- package/src/block/processRandao.ts +1 -1
- package/src/block/processSyncCommittee.ts +1 -1
- package/src/block/processVoluntaryExit.ts +1 -4
- package/src/cache/epochCache.ts +6 -7
- package/src/cache/stateCache.ts +1 -1
- package/src/cache/syncCommitteeCache.ts +3 -2
- package/src/epoch/processSyncCommitteeUpdates.ts +1 -1
- package/src/index.ts +1 -6
- package/src/lightClient/spec/store.ts +1 -1
- package/src/lightClient/spec/utils.ts +1 -1
- package/src/lightClient/spec/validateLightClientUpdate.ts +1 -1
- package/src/rewards/attestationsRewards.ts +1 -1
- package/src/rewards/syncCommitteeRewards.ts +4 -2
- package/src/signatureSets/blsToExecutionChange.ts +1 -2
- package/src/signatureSets/executionPayloadEnvelope.ts +14 -15
- package/src/signatureSets/proposer.ts +1 -3
- package/src/signatureSets/randao.ts +2 -3
- package/src/signatureSets/voluntaryExits.ts +2 -5
- package/src/stateTransition.ts +1 -1
- package/src/stateView/stateViewFactory.ts +2 -14
- package/src/testUtils/index.ts +1 -0
- package/src/testUtils/interopPubkeyCache.ts +100 -0
- package/src/testUtils/state.ts +5 -11
- package/src/testUtils/testFileCache.ts +3 -0
- package/src/testUtils/util.ts +26 -38
- package/src/util/gloas.ts +2 -4
- package/src/util/interop.ts +1 -1
- package/src/util/signatureSets.ts +34 -51
- package/src/util/syncCommittee.ts +1 -1
- package/lib/cache/pubkeyCache.d.ts +0 -28
- package/lib/cache/pubkeyCache.d.ts.map +0 -1
- package/lib/cache/pubkeyCache.js +0 -49
- package/lib/cache/pubkeyCache.js.map +0 -1
- package/src/cache/pubkeyCache.ts +0 -74
|
@@ -0,0 +1,100 @@
|
|
|
1
|
+
import fs from "node:fs";
|
|
2
|
+
import path from "node:path";
|
|
3
|
+
import {pubkeyCache} from "@chainsafe/lodestar-z/pubkeys";
|
|
4
|
+
import {interopSecretKey} from "../util/interop.js";
|
|
5
|
+
import {testCachePath} from "./cache.js";
|
|
6
|
+
|
|
7
|
+
/**
|
|
8
|
+
* This util persists generated keys as a PKIX snapshot in the local test-cache dir, so
|
|
9
|
+
* they are generated once per machine and reloaded for tests.
|
|
10
|
+
*
|
|
11
|
+
* The snapshot grows to satisfy larger requests. Smaller requests may load more entries
|
|
12
|
+
* than they need since cache contents do not define validator-registry membership.
|
|
13
|
+
*/
|
|
14
|
+
|
|
15
|
+
/** Below this count, generating keys is faster than snapshot bookkeeping (~80ms) */
|
|
16
|
+
const MIN_PERSIST_SIZE = 1000;
|
|
17
|
+
const MAX_SNAPSHOT_CAPACITY = 0xffffffff;
|
|
18
|
+
const defaultSnapshotPath = path.join(testCachePath, "interop-pubkeys.pkix");
|
|
19
|
+
|
|
20
|
+
/** Sentinel pubkeys used to verify cache contents, memoized as they are re-checked often */
|
|
21
|
+
const interopPubkeyByIndex = new Map<number, Uint8Array>();
|
|
22
|
+
|
|
23
|
+
function interopPubkey(index: number): Uint8Array {
|
|
24
|
+
let pubkey = interopPubkeyByIndex.get(index);
|
|
25
|
+
if (!pubkey) {
|
|
26
|
+
pubkey = interopSecretKey(index).toPublicKey().toBytes();
|
|
27
|
+
interopPubkeyByIndex.set(index, pubkey);
|
|
28
|
+
}
|
|
29
|
+
return pubkey;
|
|
30
|
+
}
|
|
31
|
+
|
|
32
|
+
function isInteropKeyAt(index: number): boolean {
|
|
33
|
+
const pubkey = pubkeyCache.get(index);
|
|
34
|
+
return pubkey !== undefined && Buffer.compare(pubkey.toBytes(), interopPubkey(index)) === 0;
|
|
35
|
+
}
|
|
36
|
+
|
|
37
|
+
/**
|
|
38
|
+
* True if cache entries [0, count) are the index-matching interop pubkeys. Checking the
|
|
39
|
+
* two endpoints suffices: the native cache is append-only and never remaps an index, so
|
|
40
|
+
* replacing any entry in between would have required a reset() clearing index 0 too.
|
|
41
|
+
*/
|
|
42
|
+
function hasInteropPrefix(count: number): boolean {
|
|
43
|
+
return pubkeyCache.size >= count && isInteropKeyAt(0) && isInteropKeyAt(count - 1);
|
|
44
|
+
}
|
|
45
|
+
|
|
46
|
+
function loadSnapshot(snapshotPath: string): void {
|
|
47
|
+
if (!fs.existsSync(snapshotPath)) return;
|
|
48
|
+
|
|
49
|
+
try {
|
|
50
|
+
pubkeyCache.load(snapshotPath, MAX_SNAPSHOT_CAPACITY);
|
|
51
|
+
} catch {
|
|
52
|
+
// Stale ABI, corrupt or torn file: drop it so future runs regenerate it
|
|
53
|
+
fs.rmSync(snapshotPath, {force: true});
|
|
54
|
+
}
|
|
55
|
+
}
|
|
56
|
+
|
|
57
|
+
function saveSnapshot(snapshotPath: string): void {
|
|
58
|
+
fs.mkdirSync(path.dirname(snapshotPath), {recursive: true});
|
|
59
|
+
// Write-then-rename so concurrent test processes never observe a partial file
|
|
60
|
+
const tmpPath = `${snapshotPath}.tmp-${process.pid}`;
|
|
61
|
+
try {
|
|
62
|
+
pubkeyCache.save(tmpPath);
|
|
63
|
+
fs.renameSync(tmpPath, snapshotPath);
|
|
64
|
+
} catch {
|
|
65
|
+
fs.rmSync(tmpPath, {force: true});
|
|
66
|
+
}
|
|
67
|
+
}
|
|
68
|
+
|
|
69
|
+
/**
|
|
70
|
+
* Ensure the process-wide pubkey cache holds the interop pubkeys for indices [0, vc),
|
|
71
|
+
* loading persisted snapshots and generating as few keys as possible. No-op if the cache
|
|
72
|
+
* already holds them.
|
|
73
|
+
*/
|
|
74
|
+
export function ensureInteropPubkeyCache(vc: number, snapshotPath = defaultSnapshotPath): void {
|
|
75
|
+
if (vc <= 0 || hasInteropPrefix(vc)) return;
|
|
76
|
+
|
|
77
|
+
// The cache is append-only, so extend a shorter interop prefix in place. Otherwise,
|
|
78
|
+
// replace unrelated contents with the persisted interop cache when available.
|
|
79
|
+
const size = pubkeyCache.size;
|
|
80
|
+
const sizeToExtend = size > 0 && size < vc && hasInteropPrefix(size) ? size : 0;
|
|
81
|
+
if (sizeToExtend === 0) {
|
|
82
|
+
pubkeyCache.reset();
|
|
83
|
+
loadSnapshot(snapshotPath);
|
|
84
|
+
}
|
|
85
|
+
|
|
86
|
+
let loadedSize = pubkeyCache.size;
|
|
87
|
+
if (loadedSize > 0 && !hasInteropPrefix(loadedSize)) {
|
|
88
|
+
pubkeyCache.reset();
|
|
89
|
+
loadedSize = 0;
|
|
90
|
+
}
|
|
91
|
+
if (loadedSize >= vc) return;
|
|
92
|
+
|
|
93
|
+
for (let i = loadedSize; i < vc; i++) {
|
|
94
|
+
pubkeyCache.append(i, interopSecretKey(i).toPublicKey().toBytes());
|
|
95
|
+
}
|
|
96
|
+
|
|
97
|
+
if (vc >= MIN_PERSIST_SIZE) {
|
|
98
|
+
saveSnapshot(snapshotPath);
|
|
99
|
+
}
|
|
100
|
+
}
|
package/src/testUtils/state.ts
CHANGED
|
@@ -1,3 +1,4 @@
|
|
|
1
|
+
import {pubkeyCache} from "@chainsafe/lodestar-z/pubkeys";
|
|
1
2
|
import {ChainForkConfig, createBeaconConfig} from "@lodestar/config";
|
|
2
3
|
import {config, config as minimalConfig} from "@lodestar/config/default";
|
|
3
4
|
import {
|
|
@@ -11,13 +12,7 @@ import {phase0, ssz} from "@lodestar/types";
|
|
|
11
12
|
import {EpochCacheOpts} from "../cache/epochCache.js";
|
|
12
13
|
import {BeaconStateCache} from "../cache/stateCache.js";
|
|
13
14
|
import {ZERO_HASH} from "../constants/index.js";
|
|
14
|
-
import {
|
|
15
|
-
BeaconStateAllForks,
|
|
16
|
-
BeaconStatePhase0,
|
|
17
|
-
CachedBeaconStateAllForks,
|
|
18
|
-
createCachedBeaconState,
|
|
19
|
-
createPubkeyCache,
|
|
20
|
-
} from "../index.js";
|
|
15
|
+
import {BeaconStateAllForks, BeaconStatePhase0, CachedBeaconStateAllForks, createCachedBeaconState} from "../index.js";
|
|
21
16
|
import {newZeroedArray} from "../util/index.js";
|
|
22
17
|
|
|
23
18
|
/**
|
|
@@ -86,10 +81,10 @@ export function generateCachedState(
|
|
|
86
81
|
opts: TestBeaconState = {}
|
|
87
82
|
): CachedBeaconStateAllForks {
|
|
88
83
|
const state = generateState(opts);
|
|
84
|
+
pubkeyCache.reset();
|
|
89
85
|
return createCachedBeaconState(state, {
|
|
90
86
|
config: createBeaconConfig(config, state.genesisValidatorsRoot),
|
|
91
|
-
|
|
92
|
-
pubkeyCache: createPubkeyCache(),
|
|
87
|
+
pubkeyCache,
|
|
93
88
|
});
|
|
94
89
|
}
|
|
95
90
|
|
|
@@ -102,8 +97,7 @@ export function createCachedBeaconStateTest<T extends BeaconStateAllForks>(
|
|
|
102
97
|
state,
|
|
103
98
|
{
|
|
104
99
|
config: createBeaconConfig(configCustom, state.genesisValidatorsRoot),
|
|
105
|
-
|
|
106
|
-
pubkeyCache: createPubkeyCache(),
|
|
100
|
+
pubkeyCache,
|
|
107
101
|
},
|
|
108
102
|
opts
|
|
109
103
|
);
|
|
@@ -1,5 +1,6 @@
|
|
|
1
1
|
import fs from "node:fs";
|
|
2
2
|
import path from "node:path";
|
|
3
|
+
import {pubkeyCache} from "@chainsafe/lodestar-z/pubkeys";
|
|
3
4
|
import {getClient} from "@lodestar/api";
|
|
4
5
|
import {ChainForkConfig, createChainForkConfig} from "@lodestar/config";
|
|
5
6
|
import {NetworkName, networksChainConfig} from "@lodestar/config/networks";
|
|
@@ -40,6 +41,7 @@ export async function getNetworkCachedState(
|
|
|
40
41
|
|
|
41
42
|
if (fs.existsSync(filepath)) {
|
|
42
43
|
const stateSsz = fs.readFileSync(filepath);
|
|
44
|
+
pubkeyCache.reset();
|
|
43
45
|
return createCachedBeaconStateTest(config.getForkTypes(slot).BeaconState.deserializeToViewDU(stateSsz), config);
|
|
44
46
|
}
|
|
45
47
|
|
|
@@ -57,6 +59,7 @@ export async function getNetworkCachedState(
|
|
|
57
59
|
]);
|
|
58
60
|
|
|
59
61
|
fs.writeFileSync(filepath, stateSsz);
|
|
62
|
+
pubkeyCache.reset();
|
|
60
63
|
return createCachedBeaconStateTest(config.getForkTypes(slot).BeaconState.deserializeToViewDU(stateSsz), config);
|
|
61
64
|
}
|
|
62
65
|
|
package/src/testUtils/util.ts
CHANGED
|
@@ -1,4 +1,5 @@
|
|
|
1
|
-
import {PublicKey, SecretKey} from "@chainsafe/blst";
|
|
1
|
+
import {PublicKey, SecretKey} from "@chainsafe/lodestar-z/blst";
|
|
2
|
+
import {pubkeyCache} from "@chainsafe/lodestar-z/pubkeys";
|
|
2
3
|
import {BitArray, fromHexString} from "@chainsafe/ssz";
|
|
3
4
|
import {BeaconConfig, createBeaconConfig, createChainForkConfig} from "@lodestar/config";
|
|
4
5
|
import {config} from "@lodestar/config/default";
|
|
@@ -22,7 +23,6 @@ import {
|
|
|
22
23
|
computeCommitteeCount,
|
|
23
24
|
computeEpochAtSlot,
|
|
24
25
|
createCachedBeaconState,
|
|
25
|
-
createPubkeyCache,
|
|
26
26
|
newFilledArray,
|
|
27
27
|
processSlots,
|
|
28
28
|
} from "../index.js";
|
|
@@ -40,7 +40,7 @@ import {interopSecretKey} from "../util/interop.js";
|
|
|
40
40
|
import {computeSigningRoot} from "../util/signingRoot.js";
|
|
41
41
|
import {getNextSyncCommittee} from "../util/syncCommittee.js";
|
|
42
42
|
import {getActiveValidatorIndices} from "../util/validator.js";
|
|
43
|
-
import {
|
|
43
|
+
import {ensureInteropPubkeyCache} from "./interopPubkeyCache.js";
|
|
44
44
|
|
|
45
45
|
let phase0State: BeaconStatePhase0 | null = null;
|
|
46
46
|
let phase0CachedState23637: CachedBeaconStatePhase0 | null = null;
|
|
@@ -69,47 +69,45 @@ export const perfStateId = `${numValidators} vs - 7PWei`;
|
|
|
69
69
|
|
|
70
70
|
/** Cache interop secret keys */
|
|
71
71
|
const secretKeyByModIndex = new Map<number, SecretKey>();
|
|
72
|
+
const pubkeysByCount = new Map<number, Uint8Array[]>();
|
|
72
73
|
const epoch = 23638;
|
|
73
74
|
export const perfStateEpoch = epoch;
|
|
74
75
|
|
|
75
76
|
export function getPubkeys(vc = numValidators) {
|
|
76
|
-
|
|
77
|
-
|
|
78
|
-
|
|
77
|
+
ensureInteropPubkeyCache(vc);
|
|
78
|
+
let pubkeys = pubkeysByCount.get(vc);
|
|
79
|
+
if (!pubkeys) {
|
|
80
|
+
for (const [count, cached] of pubkeysByCount) {
|
|
81
|
+
if (count >= vc) {
|
|
82
|
+
pubkeys = cached.slice(0, vc);
|
|
83
|
+
break;
|
|
84
|
+
}
|
|
85
|
+
}
|
|
86
|
+
pubkeys ??= Array.from({length: vc}, (_, i) => pubkeyCache.getPubkeyBytesOrThrow(i));
|
|
87
|
+
pubkeysByCount.set(vc, pubkeys);
|
|
88
|
+
}
|
|
89
|
+
const pubkeysMod = pubkeys;
|
|
90
|
+
const pubkeysModObj = pubkeys.slice(0, keypairsMod).map((pk) => PublicKey.fromBytes(pk));
|
|
79
91
|
return {pubkeysMod, pubkeysModObj, pubkeys};
|
|
80
92
|
}
|
|
81
93
|
|
|
82
94
|
/** Get secret key of a validatorIndex, if the pubkeys are generated with `getPubkeys()` */
|
|
83
95
|
export function getSecretKeyFromIndex(validatorIndex: number): SecretKey {
|
|
84
|
-
return interopSecretKey(validatorIndex
|
|
96
|
+
return interopSecretKey(validatorIndex);
|
|
85
97
|
}
|
|
86
98
|
|
|
87
99
|
/** Get secret key of a validatorIndex, if the pubkeys are generated with `getPubkeys()` */
|
|
88
100
|
export function getSecretKeyFromIndexCached(validatorIndex: number): SecretKey {
|
|
89
|
-
|
|
90
|
-
let sk = secretKeyByModIndex.get(keyIndex);
|
|
101
|
+
let sk = secretKeyByModIndex.get(validatorIndex);
|
|
91
102
|
if (!sk) {
|
|
92
|
-
sk = interopSecretKey(
|
|
93
|
-
secretKeyByModIndex.set(
|
|
103
|
+
sk = interopSecretKey(validatorIndex);
|
|
104
|
+
secretKeyByModIndex.set(validatorIndex, sk);
|
|
94
105
|
}
|
|
95
106
|
return sk;
|
|
96
107
|
}
|
|
97
108
|
|
|
98
|
-
function getPubkeyCaches({pubkeysMod}: ReturnType<typeof getPubkeys>, vc = numValidators) {
|
|
99
|
-
// Manually sync pubkeys to prevent doing BLS opts 110_000 times
|
|
100
|
-
const pubkeyCache = createPubkeyCache();
|
|
101
|
-
for (let i = 0; i < vc; i++) {
|
|
102
|
-
const pubkey = pubkeysMod[i % keypairsMod];
|
|
103
|
-
pubkeyCache.set(i, pubkey);
|
|
104
|
-
}
|
|
105
|
-
|
|
106
|
-
return {pubkeyCache};
|
|
107
|
-
}
|
|
108
|
-
|
|
109
109
|
export function generatePerfTestCachedStatePhase0(opts?: {goBackOneSlot: boolean}): CachedBeaconStatePhase0 {
|
|
110
|
-
|
|
111
|
-
const {pubkeys, pubkeysMod, pubkeysModObj} = getPubkeys();
|
|
112
|
-
const {pubkeyCache} = getPubkeyCaches({pubkeys, pubkeysMod, pubkeysModObj});
|
|
110
|
+
const {pubkeys} = getPubkeys();
|
|
113
111
|
|
|
114
112
|
if (!phase0State) {
|
|
115
113
|
const state = buildPerformanceStatePhase0();
|
|
@@ -218,8 +216,7 @@ export function generatePerfTestCachedStateAltair(opts?: {
|
|
|
218
216
|
vc?: number;
|
|
219
217
|
}): CachedBeaconStateAltair {
|
|
220
218
|
const vc = opts?.vc ?? numValidators;
|
|
221
|
-
const {pubkeys
|
|
222
|
-
const {pubkeyCache} = getPubkeyCaches({pubkeys, pubkeysMod, pubkeysModObj}, vc);
|
|
219
|
+
const {pubkeys} = getPubkeys(vc);
|
|
223
220
|
|
|
224
221
|
const altairConfig = createChainForkConfig({ALTAIR_FORK_EPOCH: 0});
|
|
225
222
|
|
|
@@ -259,8 +256,7 @@ export function generatePerfTestCachedStateElectra(opts?: {
|
|
|
259
256
|
vc?: number;
|
|
260
257
|
}): CachedBeaconStateElectra {
|
|
261
258
|
const vc = opts?.vc ?? numValidators;
|
|
262
|
-
const {pubkeys
|
|
263
|
-
const {pubkeyCache} = getPubkeyCaches({pubkeys, pubkeysMod, pubkeysModObj}, vc);
|
|
259
|
+
const {pubkeys} = getPubkeys(vc);
|
|
264
260
|
|
|
265
261
|
const electraConfig = createChainForkConfig({
|
|
266
262
|
ALTAIR_FORK_EPOCH: 0,
|
|
@@ -495,15 +491,7 @@ export function generateTestCachedBeaconStateOnlyValidators({
|
|
|
495
491
|
vc: number;
|
|
496
492
|
slot: Slot;
|
|
497
493
|
}): CachedBeaconStateAllForks {
|
|
498
|
-
|
|
499
|
-
const {pubkeys, pubkeysMod} = getPubkeys(vc);
|
|
500
|
-
|
|
501
|
-
// Manually sync pubkeys to prevent doing BLS opts 110_000 times
|
|
502
|
-
const pubkeyCache = createPubkeyCache();
|
|
503
|
-
for (let i = 0; i < vc; i++) {
|
|
504
|
-
const pubkey = pubkeysMod[i % keypairsMod];
|
|
505
|
-
pubkeyCache.set(i, pubkey);
|
|
506
|
-
}
|
|
494
|
+
const {pubkeys} = getPubkeys(vc);
|
|
507
495
|
|
|
508
496
|
const state = ssz.phase0.BeaconState.defaultViewDU();
|
|
509
497
|
state.slot = slot;
|
package/src/util/gloas.ts
CHANGED
|
@@ -1,4 +1,3 @@
|
|
|
1
|
-
import {PublicKey, Signature, verify} from "@chainsafe/blst";
|
|
2
1
|
import {BeaconConfig} from "@lodestar/config";
|
|
3
2
|
import {
|
|
4
3
|
BUILDER_INDEX_FLAG,
|
|
@@ -23,6 +22,7 @@ import {computeEpochAtSlot} from "./epoch.js";
|
|
|
23
22
|
import {computeEpochShuffling} from "./epochShuffling.js";
|
|
24
23
|
import {RootCache} from "./rootCache.js";
|
|
25
24
|
import {computePayloadTimelinessCommitteesForEpoch} from "./seed.js";
|
|
25
|
+
import {createSingleSignatureSetFromComponents, verifySignatureSet} from "./signatureSets.js";
|
|
26
26
|
import {computeSigningRoot} from "./signingRoot.js";
|
|
27
27
|
import {getActiveValidatorIndices} from "./validator.js";
|
|
28
28
|
|
|
@@ -339,9 +339,7 @@ export function isValidBuilderDepositSignature(
|
|
|
339
339
|
const domain = computeDomain(DOMAIN_BUILDER_DEPOSIT, config.GENESIS_FORK_VERSION, ZERO_HASH);
|
|
340
340
|
const signingRoot = computeSigningRoot(ssz.phase0.DepositMessage, depositMessage, domain);
|
|
341
341
|
try {
|
|
342
|
-
|
|
343
|
-
const sig = Signature.fromBytes(signature, true);
|
|
344
|
-
return verify(signingRoot, publicKey, sig);
|
|
342
|
+
return verifySignatureSet(createSingleSignatureSetFromComponents(pubkey, signingRoot, signature));
|
|
345
343
|
} catch (_e) {
|
|
346
344
|
return false;
|
|
347
345
|
}
|
package/src/util/interop.ts
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
import {toBufferBE} from "@vekexasia/bigint-buffer2";
|
|
2
2
|
import {digest} from "@chainsafe/as-sha256";
|
|
3
|
-
import {SecretKey} from "@chainsafe/blst";
|
|
3
|
+
import {SecretKey} from "@chainsafe/lodestar-z/blst";
|
|
4
4
|
import {bytesToBigInt, intToBytes} from "@lodestar/utils";
|
|
5
5
|
|
|
6
6
|
let curveOrder: bigint;
|
|
@@ -1,6 +1,5 @@
|
|
|
1
|
-
import {
|
|
1
|
+
import {BLS_VERIFIER_SET_TYPE, type BlsSignatureSet, verifySignatureSets} from "@chainsafe/lodestar-z/bls-verifier";
|
|
2
2
|
import {Root} from "@lodestar/types";
|
|
3
|
-
import {PubkeyCache} from "../cache/pubkeyCache.js";
|
|
4
3
|
|
|
5
4
|
export enum SignatureSetType {
|
|
6
5
|
single = "single",
|
|
@@ -18,7 +17,7 @@ export enum SignatureSetType {
|
|
|
18
17
|
*/
|
|
19
18
|
export type SingleSignatureSet = {
|
|
20
19
|
type: SignatureSetType.single;
|
|
21
|
-
pubkey:
|
|
20
|
+
pubkey: Uint8Array;
|
|
22
21
|
signingRoot: Root;
|
|
23
22
|
signature: Uint8Array;
|
|
24
23
|
};
|
|
@@ -47,59 +46,39 @@ export type AggregatedSignatureSet = {
|
|
|
47
46
|
|
|
48
47
|
export type ISignatureSet = SingleSignatureSet | IndexedSignatureSet | AggregatedSignatureSet;
|
|
49
48
|
|
|
50
|
-
|
|
51
|
-
* Get the pubkey for a signature set, performing aggregation if necessary.
|
|
52
|
-
* Requires pubkeyCache for indexed and aggregate sets.
|
|
53
|
-
*/
|
|
54
|
-
export function getSignatureSetPubkey(signatureSet: ISignatureSet, pubkeyCache: PubkeyCache): PublicKey {
|
|
49
|
+
export function toBlsSignatureSet(signatureSet: ISignatureSet): BlsSignatureSet {
|
|
55
50
|
switch (signatureSet.type) {
|
|
56
51
|
case SignatureSetType.single:
|
|
57
|
-
return
|
|
58
|
-
|
|
59
|
-
|
|
60
|
-
|
|
61
|
-
|
|
52
|
+
return {
|
|
53
|
+
type: BLS_VERIFIER_SET_TYPE.single,
|
|
54
|
+
pubkey: signatureSet.pubkey,
|
|
55
|
+
message: signatureSet.signingRoot,
|
|
56
|
+
signature: signatureSet.signature,
|
|
57
|
+
};
|
|
58
|
+
|
|
59
|
+
case SignatureSetType.indexed:
|
|
60
|
+
return {
|
|
61
|
+
type: BLS_VERIFIER_SET_TYPE.indexed,
|
|
62
|
+
index: signatureSet.index,
|
|
63
|
+
message: signatureSet.signingRoot,
|
|
64
|
+
signature: signatureSet.signature,
|
|
65
|
+
};
|
|
62
66
|
|
|
63
67
|
case SignatureSetType.aggregate: {
|
|
64
|
-
const
|
|
65
|
-
|
|
66
|
-
|
|
67
|
-
|
|
68
|
-
|
|
69
|
-
|
|
70
|
-
default:
|
|
71
|
-
throw Error("Unknown signature set type");
|
|
72
|
-
}
|
|
73
|
-
}
|
|
74
|
-
|
|
75
|
-
export function verifySignatureSet(signatureSet: SingleSignatureSet, pubkeyCache?: PubkeyCache): boolean;
|
|
76
|
-
export function verifySignatureSet(signatureSet: IndexedSignatureSet, pubkeyCache: PubkeyCache): boolean;
|
|
77
|
-
export function verifySignatureSet(signatureSet: AggregatedSignatureSet, pubkeyCache: PubkeyCache): boolean;
|
|
78
|
-
export function verifySignatureSet(signatureSet: ISignatureSet, pubkeyCache: PubkeyCache): boolean;
|
|
79
|
-
export function verifySignatureSet(signatureSet: ISignatureSet, pubkeyCache?: PubkeyCache): boolean {
|
|
80
|
-
// All signatures are not trusted and must be group checked (p2.subgroup_check)
|
|
81
|
-
const signature = Signature.fromBytes(signatureSet.signature, true);
|
|
82
|
-
|
|
83
|
-
switch (signatureSet.type) {
|
|
84
|
-
case SignatureSetType.single:
|
|
85
|
-
return verify(signatureSet.signingRoot, signatureSet.pubkey, signature);
|
|
86
|
-
|
|
87
|
-
case SignatureSetType.indexed: {
|
|
88
|
-
if (!pubkeyCache) {
|
|
89
|
-
throw Error("pubkeyCache required for indexed signature set");
|
|
68
|
+
const indices = new Uint32Array(signatureSet.indices.length);
|
|
69
|
+
for (const [i, index] of signatureSet.indices.entries()) {
|
|
70
|
+
if (!Number.isInteger(index) || index < 0 || index > 0xffffffff) {
|
|
71
|
+
throw new RangeError(`Invalid validator index ${index}`);
|
|
72
|
+
}
|
|
73
|
+
indices[i] = index;
|
|
90
74
|
}
|
|
91
|
-
const pubkey = pubkeyCache.getOrThrow(signatureSet.index);
|
|
92
|
-
return verify(signatureSet.signingRoot, pubkey, signature);
|
|
93
|
-
}
|
|
94
75
|
|
|
95
|
-
|
|
96
|
-
|
|
97
|
-
|
|
98
|
-
|
|
99
|
-
|
|
100
|
-
|
|
101
|
-
});
|
|
102
|
-
return fastAggregateVerify(signatureSet.signingRoot, pubkeys, signature);
|
|
76
|
+
return {
|
|
77
|
+
type: BLS_VERIFIER_SET_TYPE.aggregate,
|
|
78
|
+
indices,
|
|
79
|
+
message: signatureSet.signingRoot,
|
|
80
|
+
signature: signatureSet.signature,
|
|
81
|
+
};
|
|
103
82
|
}
|
|
104
83
|
|
|
105
84
|
default:
|
|
@@ -107,8 +86,12 @@ export function verifySignatureSet(signatureSet: ISignatureSet, pubkeyCache?: Pu
|
|
|
107
86
|
}
|
|
108
87
|
}
|
|
109
88
|
|
|
89
|
+
export function verifySignatureSet(signatureSet: ISignatureSet): boolean {
|
|
90
|
+
return verifySignatureSets([toBlsSignatureSet(signatureSet)]);
|
|
91
|
+
}
|
|
92
|
+
|
|
110
93
|
export function createSingleSignatureSetFromComponents(
|
|
111
|
-
pubkey:
|
|
94
|
+
pubkey: Uint8Array,
|
|
112
95
|
signingRoot: Root,
|
|
113
96
|
signature: Uint8Array
|
|
114
97
|
): SingleSignatureSet {
|
|
@@ -1,28 +0,0 @@
|
|
|
1
|
-
import { PublicKey } from "@chainsafe/blst";
|
|
2
|
-
import { ValidatorIndex, phase0 } from "@lodestar/types";
|
|
3
|
-
/**
|
|
4
|
-
* Unified pubkey cache coupling index→pubkey and pubkey→index lookups.
|
|
5
|
-
* Both directions are kept in sync atomically via `set()`.
|
|
6
|
-
*/
|
|
7
|
-
export interface PubkeyCache {
|
|
8
|
-
/** Get deserialized PublicKey by validator index */
|
|
9
|
-
get(index: ValidatorIndex): PublicKey | undefined;
|
|
10
|
-
/** Get deserialized PublicKey by validator index or throw if not found */
|
|
11
|
-
getOrThrow(index: ValidatorIndex): PublicKey;
|
|
12
|
-
/** Get validator index by pubkey bytes */
|
|
13
|
-
getIndex(pubkey: Uint8Array): ValidatorIndex | null;
|
|
14
|
-
/** Set both directions atomically. Takes raw pubkey bytes — deserialization is handled internally. */
|
|
15
|
-
set(index: ValidatorIndex, pubkey: Uint8Array): void;
|
|
16
|
-
/** Number of entries */
|
|
17
|
-
readonly size: number;
|
|
18
|
-
}
|
|
19
|
-
export declare function createPubkeyCache(): PubkeyCache;
|
|
20
|
-
/**
|
|
21
|
-
* Checks the pubkey indices against a state and adds missing pubkeys
|
|
22
|
-
*
|
|
23
|
-
* Mutates `pubkeyCache`
|
|
24
|
-
*
|
|
25
|
-
* If pubkey cache is empty: SLOW CODE - 🐢
|
|
26
|
-
*/
|
|
27
|
-
export declare function syncPubkeys(pubkeyCache: PubkeyCache, validators: phase0.Validator[]): void;
|
|
28
|
-
//# sourceMappingURL=pubkeyCache.d.ts.map
|
|
@@ -1 +0,0 @@
|
|
|
1
|
-
{"version":3,"file":"pubkeyCache.d.ts","sourceRoot":"","sources":["../../src/cache/pubkeyCache.ts"],"names":[],"mappings":"AAAA,OAAO,EAAC,SAAS,EAAC,MAAM,iBAAiB,CAAC;AAE1C,OAAO,EAAC,cAAc,EAAE,MAAM,EAAC,MAAM,iBAAiB,CAAC;AAEvD;;;GAGG;AACH,MAAM,WAAW,WAAW;IAC1B,oDAAoD;IACpD,GAAG,CAAC,KAAK,EAAE,cAAc,GAAG,SAAS,GAAG,SAAS,CAAC;IAClD,0EAA0E;IAC1E,UAAU,CAAC,KAAK,EAAE,cAAc,GAAG,SAAS,CAAC;IAC7C,0CAA0C;IAC1C,QAAQ,CAAC,MAAM,EAAE,UAAU,GAAG,cAAc,GAAG,IAAI,CAAC;IACpD,sGAAsG;IACtG,GAAG,CAAC,KAAK,EAAE,cAAc,EAAE,MAAM,EAAE,UAAU,GAAG,IAAI,CAAC;IACrD,wBAAwB;IACxB,QAAQ,CAAC,IAAI,EAAE,MAAM,CAAC;CACvB;AAsCD,wBAAgB,iBAAiB,IAAI,WAAW,CAE/C;AAED;;;;;;GAMG;AACH,wBAAgB,WAAW,CAAC,WAAW,EAAE,WAAW,EAAE,UAAU,EAAE,MAAM,CAAC,SAAS,EAAE,GAAG,IAAI,CAK1F"}
|
package/lib/cache/pubkeyCache.js
DELETED
|
@@ -1,49 +0,0 @@
|
|
|
1
|
-
import { PublicKey } from "@chainsafe/blst";
|
|
2
|
-
import { PubkeyIndexMap } from "@chainsafe/pubkey-index-map";
|
|
3
|
-
class StandardPubkeyCache {
|
|
4
|
-
pubkey2index;
|
|
5
|
-
index2pubkey;
|
|
6
|
-
constructor(pubkey2index, index2pubkey) {
|
|
7
|
-
this.pubkey2index = pubkey2index ?? new PubkeyIndexMap();
|
|
8
|
-
this.index2pubkey = index2pubkey ?? [];
|
|
9
|
-
}
|
|
10
|
-
get size() {
|
|
11
|
-
return this.pubkey2index.size;
|
|
12
|
-
}
|
|
13
|
-
get(index) {
|
|
14
|
-
return this.index2pubkey[index];
|
|
15
|
-
}
|
|
16
|
-
getOrThrow(index) {
|
|
17
|
-
const pubkey = this.get(index);
|
|
18
|
-
if (!pubkey)
|
|
19
|
-
throw Error(`Missing pubkey for validator index ${index}`);
|
|
20
|
-
return pubkey;
|
|
21
|
-
}
|
|
22
|
-
getIndex(pubkey) {
|
|
23
|
-
return this.pubkey2index.get(pubkey);
|
|
24
|
-
}
|
|
25
|
-
set(index, pubkey) {
|
|
26
|
-
this.pubkey2index.set(pubkey, index);
|
|
27
|
-
// Pubkeys must be checked for group + inf. This must be done only once when the validator deposit is processed.
|
|
28
|
-
// Afterwards any public key in the state is considered validated.
|
|
29
|
-
// > Do not do any validation here
|
|
30
|
-
this.index2pubkey[index] = PublicKey.fromBytes(pubkey); // Optimize for aggregation
|
|
31
|
-
}
|
|
32
|
-
}
|
|
33
|
-
export function createPubkeyCache() {
|
|
34
|
-
return new StandardPubkeyCache();
|
|
35
|
-
}
|
|
36
|
-
/**
|
|
37
|
-
* Checks the pubkey indices against a state and adds missing pubkeys
|
|
38
|
-
*
|
|
39
|
-
* Mutates `pubkeyCache`
|
|
40
|
-
*
|
|
41
|
-
* If pubkey cache is empty: SLOW CODE - 🐢
|
|
42
|
-
*/
|
|
43
|
-
export function syncPubkeys(pubkeyCache, validators) {
|
|
44
|
-
const newCount = validators.length;
|
|
45
|
-
for (let i = pubkeyCache.size; i < newCount; i++) {
|
|
46
|
-
pubkeyCache.set(i, validators[i].pubkey);
|
|
47
|
-
}
|
|
48
|
-
}
|
|
49
|
-
//# sourceMappingURL=pubkeyCache.js.map
|
|
@@ -1 +0,0 @@
|
|
|
1
|
-
{"version":3,"file":"pubkeyCache.js","sourceRoot":"","sources":["../../src/cache/pubkeyCache.ts"],"names":[],"mappings":"AAAA,OAAO,EAAC,SAAS,EAAC,MAAM,iBAAiB,CAAC;AAC1C,OAAO,EAAC,cAAc,EAAC,MAAM,6BAA6B,CAAC;AAoB3D,MAAM,mBAAmB;IACN,YAAY,CAAiB;IAC7B,YAAY,CAA4B;IAEzD,YAAY,YAA6B,EAAE,YAAwC;QACjF,IAAI,CAAC,YAAY,GAAG,YAAY,IAAI,IAAI,cAAc,EAAE,CAAC;QACzD,IAAI,CAAC,YAAY,GAAG,YAAY,IAAI,EAAE,CAAC;IACzC,CAAC;IAED,IAAI,IAAI;QACN,OAAO,IAAI,CAAC,YAAY,CAAC,IAAI,CAAC;IAChC,CAAC;IAED,GAAG,CAAC,KAAqB;QACvB,OAAO,IAAI,CAAC,YAAY,CAAC,KAAK,CAAC,CAAC;IAClC,CAAC;IAED,UAAU,CAAC,KAAqB;QAC9B,MAAM,MAAM,GAAG,IAAI,CAAC,GAAG,CAAC,KAAK,CAAC,CAAC;QAC/B,IAAI,CAAC,MAAM;YAAE,MAAM,KAAK,CAAC,sCAAsC,KAAK,EAAE,CAAC,CAAC;QACxE,OAAO,MAAM,CAAC;IAChB,CAAC;IAED,QAAQ,CAAC,MAAkB;QACzB,OAAO,IAAI,CAAC,YAAY,CAAC,GAAG,CAAC,MAAM,CAAC,CAAC;IACvC,CAAC;IAED,GAAG,CAAC,KAAqB,EAAE,MAAkB;QAC3C,IAAI,CAAC,YAAY,CAAC,GAAG,CAAC,MAAM,EAAE,KAAK,CAAC,CAAC;QACrC,gHAAgH;QAChH,kEAAkE;QAClE,kCAAkC;QAClC,IAAI,CAAC,YAAY,CAAC,KAAK,CAAC,GAAG,SAAS,CAAC,SAAS,CAAC,MAAM,CAAC,CAAC,CAAC,2BAA2B;IACrF,CAAC;CACF;AAED,MAAM,UAAU,iBAAiB;IAC/B,OAAO,IAAI,mBAAmB,EAAE,CAAC;AACnC,CAAC;AAED;;;;;;GAMG;AACH,MAAM,UAAU,WAAW,CAAC,WAAwB,EAAE,UAA8B;IAClF,MAAM,QAAQ,GAAG,UAAU,CAAC,MAAM,CAAC;IACnC,KAAK,IAAI,CAAC,GAAG,WAAW,CAAC,IAAI,EAAE,CAAC,GAAG,QAAQ,EAAE,CAAC,EAAE,EAAE,CAAC;QACjD,WAAW,CAAC,GAAG,CAAC,CAAC,EAAE,UAAU,CAAC,CAAC,CAAC,CAAC,MAAM,CAAC,CAAC;IAC3C,CAAC;AACH,CAAC"}
|
package/src/cache/pubkeyCache.ts
DELETED
|
@@ -1,74 +0,0 @@
|
|
|
1
|
-
import {PublicKey} from "@chainsafe/blst";
|
|
2
|
-
import {PubkeyIndexMap} from "@chainsafe/pubkey-index-map";
|
|
3
|
-
import {ValidatorIndex, phase0} from "@lodestar/types";
|
|
4
|
-
|
|
5
|
-
/**
|
|
6
|
-
* Unified pubkey cache coupling index→pubkey and pubkey→index lookups.
|
|
7
|
-
* Both directions are kept in sync atomically via `set()`.
|
|
8
|
-
*/
|
|
9
|
-
export interface PubkeyCache {
|
|
10
|
-
/** Get deserialized PublicKey by validator index */
|
|
11
|
-
get(index: ValidatorIndex): PublicKey | undefined;
|
|
12
|
-
/** Get deserialized PublicKey by validator index or throw if not found */
|
|
13
|
-
getOrThrow(index: ValidatorIndex): PublicKey;
|
|
14
|
-
/** Get validator index by pubkey bytes */
|
|
15
|
-
getIndex(pubkey: Uint8Array): ValidatorIndex | null;
|
|
16
|
-
/** Set both directions atomically. Takes raw pubkey bytes — deserialization is handled internally. */
|
|
17
|
-
set(index: ValidatorIndex, pubkey: Uint8Array): void;
|
|
18
|
-
/** Number of entries */
|
|
19
|
-
readonly size: number;
|
|
20
|
-
}
|
|
21
|
-
|
|
22
|
-
class StandardPubkeyCache implements PubkeyCache {
|
|
23
|
-
private readonly pubkey2index: PubkeyIndexMap;
|
|
24
|
-
private readonly index2pubkey: (PublicKey | undefined)[];
|
|
25
|
-
|
|
26
|
-
constructor(pubkey2index?: PubkeyIndexMap, index2pubkey?: (PublicKey | undefined)[]) {
|
|
27
|
-
this.pubkey2index = pubkey2index ?? new PubkeyIndexMap();
|
|
28
|
-
this.index2pubkey = index2pubkey ?? [];
|
|
29
|
-
}
|
|
30
|
-
|
|
31
|
-
get size(): number {
|
|
32
|
-
return this.pubkey2index.size;
|
|
33
|
-
}
|
|
34
|
-
|
|
35
|
-
get(index: ValidatorIndex): PublicKey | undefined {
|
|
36
|
-
return this.index2pubkey[index];
|
|
37
|
-
}
|
|
38
|
-
|
|
39
|
-
getOrThrow(index: ValidatorIndex): PublicKey {
|
|
40
|
-
const pubkey = this.get(index);
|
|
41
|
-
if (!pubkey) throw Error(`Missing pubkey for validator index ${index}`);
|
|
42
|
-
return pubkey;
|
|
43
|
-
}
|
|
44
|
-
|
|
45
|
-
getIndex(pubkey: Uint8Array): ValidatorIndex | null {
|
|
46
|
-
return this.pubkey2index.get(pubkey);
|
|
47
|
-
}
|
|
48
|
-
|
|
49
|
-
set(index: ValidatorIndex, pubkey: Uint8Array): void {
|
|
50
|
-
this.pubkey2index.set(pubkey, index);
|
|
51
|
-
// Pubkeys must be checked for group + inf. This must be done only once when the validator deposit is processed.
|
|
52
|
-
// Afterwards any public key in the state is considered validated.
|
|
53
|
-
// > Do not do any validation here
|
|
54
|
-
this.index2pubkey[index] = PublicKey.fromBytes(pubkey); // Optimize for aggregation
|
|
55
|
-
}
|
|
56
|
-
}
|
|
57
|
-
|
|
58
|
-
export function createPubkeyCache(): PubkeyCache {
|
|
59
|
-
return new StandardPubkeyCache();
|
|
60
|
-
}
|
|
61
|
-
|
|
62
|
-
/**
|
|
63
|
-
* Checks the pubkey indices against a state and adds missing pubkeys
|
|
64
|
-
*
|
|
65
|
-
* Mutates `pubkeyCache`
|
|
66
|
-
*
|
|
67
|
-
* If pubkey cache is empty: SLOW CODE - 🐢
|
|
68
|
-
*/
|
|
69
|
-
export function syncPubkeys(pubkeyCache: PubkeyCache, validators: phase0.Validator[]): void {
|
|
70
|
-
const newCount = validators.length;
|
|
71
|
-
for (let i = pubkeyCache.size; i < newCount; i++) {
|
|
72
|
-
pubkeyCache.set(i, validators[i].pubkey);
|
|
73
|
-
}
|
|
74
|
-
}
|