@lodestar/beacon-node 1.39.0-dev.aceb5b7416 → 1.39.0-dev.c151a164f2
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/chain/blocks/verifyBlock.d.ts.map +1 -1
- package/lib/chain/blocks/verifyBlock.js +1 -1
- package/lib/chain/blocks/verifyBlock.js.map +1 -1
- package/lib/chain/blocks/verifyBlocksSignatures.d.ts +2 -1
- package/lib/chain/blocks/verifyBlocksSignatures.d.ts.map +1 -1
- package/lib/chain/blocks/verifyBlocksSignatures.js +2 -2
- package/lib/chain/blocks/verifyBlocksSignatures.js.map +1 -1
- package/lib/chain/chain.d.ts.map +1 -1
- package/lib/chain/chain.js +6 -4
- package/lib/chain/chain.js.map +1 -1
- package/lib/chain/opPools/aggregatedAttestationPool.d.ts +4 -4
- package/lib/chain/opPools/aggregatedAttestationPool.d.ts.map +1 -1
- package/lib/chain/opPools/aggregatedAttestationPool.js +4 -4
- package/lib/chain/opPools/aggregatedAttestationPool.js.map +1 -1
- package/lib/chain/opPools/opPool.d.ts +3 -0
- package/lib/chain/opPools/opPool.d.ts.map +1 -1
- package/lib/chain/opPools/opPool.js +9 -8
- package/lib/chain/opPools/opPool.js.map +1 -1
- package/lib/chain/produceBlock/produceBlockBody.js +2 -2
- package/lib/chain/produceBlock/produceBlockBody.js.map +1 -1
- package/lib/chain/rewards/attestationsRewards.d.ts +2 -1
- package/lib/chain/rewards/attestationsRewards.d.ts.map +1 -1
- package/lib/chain/rewards/attestationsRewards.js +8 -8
- package/lib/chain/rewards/attestationsRewards.js.map +1 -1
- package/lib/chain/rewards/blockRewards.d.ts +2 -1
- package/lib/chain/rewards/blockRewards.d.ts.map +1 -1
- package/lib/chain/rewards/blockRewards.js +5 -5
- package/lib/chain/rewards/blockRewards.js.map +1 -1
- package/lib/chain/rewards/syncCommitteeRewards.d.ts +2 -1
- package/lib/chain/rewards/syncCommitteeRewards.d.ts.map +1 -1
- package/lib/chain/rewards/syncCommitteeRewards.js +2 -2
- package/lib/chain/rewards/syncCommitteeRewards.js.map +1 -1
- package/lib/chain/stateCache/persistentCheckpointsCache.d.ts +4 -1
- package/lib/chain/stateCache/persistentCheckpointsCache.d.ts.map +1 -1
- package/lib/chain/stateCache/persistentCheckpointsCache.js +4 -2
- package/lib/chain/stateCache/persistentCheckpointsCache.js.map +1 -1
- package/lib/chain/validation/attesterSlashing.js +1 -1
- package/lib/chain/validation/attesterSlashing.js.map +1 -1
- package/lib/chain/validation/block.js +1 -1
- package/lib/chain/validation/block.js.map +1 -1
- package/lib/chain/validation/blsToExecutionChange.js +1 -1
- package/lib/chain/validation/proposerSlashing.js +1 -1
- package/lib/chain/validation/proposerSlashing.js.map +1 -1
- package/lib/chain/validation/signatureSets/aggregateAndProof.js +1 -1
- package/lib/chain/validation/signatureSets/aggregateAndProof.js.map +1 -1
- package/lib/chain/validation/signatureSets/contributionAndProof.d.ts +2 -1
- package/lib/chain/validation/signatureSets/contributionAndProof.d.ts.map +1 -1
- package/lib/chain/validation/signatureSets/contributionAndProof.js +2 -2
- package/lib/chain/validation/signatureSets/contributionAndProof.js.map +1 -1
- package/lib/chain/validation/signatureSets/syncCommittee.d.ts +2 -1
- package/lib/chain/validation/signatureSets/syncCommittee.d.ts.map +1 -1
- package/lib/chain/validation/signatureSets/syncCommittee.js +2 -2
- package/lib/chain/validation/signatureSets/syncCommittee.js.map +1 -1
- package/lib/chain/validation/signatureSets/syncCommitteeContribution.d.ts +2 -1
- package/lib/chain/validation/signatureSets/syncCommitteeContribution.d.ts.map +1 -1
- package/lib/chain/validation/signatureSets/syncCommitteeContribution.js +2 -2
- package/lib/chain/validation/signatureSets/syncCommitteeContribution.js.map +1 -1
- package/lib/chain/validation/signatureSets/syncCommitteeSelectionProof.d.ts +2 -1
- package/lib/chain/validation/signatureSets/syncCommitteeSelectionProof.d.ts.map +1 -1
- package/lib/chain/validation/signatureSets/syncCommitteeSelectionProof.js +1 -2
- package/lib/chain/validation/signatureSets/syncCommitteeSelectionProof.js.map +1 -1
- package/lib/chain/validation/syncCommittee.js +1 -1
- package/lib/chain/validation/syncCommittee.js.map +1 -1
- package/lib/chain/validation/syncCommitteeContributionAndProof.d.ts.map +1 -1
- package/lib/chain/validation/syncCommitteeContributionAndProof.js +3 -3
- package/lib/chain/validation/syncCommitteeContributionAndProof.js.map +1 -1
- package/lib/chain/validation/voluntaryExit.js +1 -1
- package/lib/chain/validation/voluntaryExit.js.map +1 -1
- package/lib/db/beacon.d.ts +2 -0
- package/lib/db/beacon.d.ts.map +1 -1
- package/lib/db/beacon.js +32 -0
- package/lib/db/beacon.js.map +1 -1
- package/lib/db/buckets.d.ts +12 -0
- package/lib/db/buckets.d.ts.map +1 -1
- package/lib/db/buckets.js +12 -6
- package/lib/db/buckets.js.map +1 -1
- package/lib/db/interface.d.ts +1 -0
- package/lib/db/interface.d.ts.map +1 -1
- package/lib/db/repositories/blockArchiveIndex.d.ts +2 -2
- package/lib/db/repositories/blockArchiveIndex.d.ts.map +1 -1
- package/lib/node/nodejs.d.ts.map +1 -1
- package/lib/node/nodejs.js +10 -0
- package/lib/node/nodejs.js.map +1 -1
- package/lib/sync/backfill/backfill.d.ts.map +1 -1
- package/lib/sync/backfill/backfill.js +2 -4
- package/lib/sync/backfill/backfill.js.map +1 -1
- package/lib/sync/backfill/verify.d.ts +1 -1
- package/lib/sync/backfill/verify.d.ts.map +1 -1
- package/lib/sync/backfill/verify.js +2 -2
- package/lib/sync/backfill/verify.js.map +1 -1
- package/package.json +14 -14
- package/src/chain/blocks/verifyBlock.ts +1 -0
- package/src/chain/blocks/verifyBlocksSignatures.ts +3 -1
- package/src/chain/chain.ts +6 -4
- package/src/chain/opPools/aggregatedAttestationPool.ts +7 -7
- package/src/chain/opPools/opPool.ts +8 -8
- package/src/chain/produceBlock/produceBlockBody.ts +2 -2
- package/src/chain/rewards/attestationsRewards.ts +13 -4
- package/src/chain/rewards/blockRewards.ts +6 -3
- package/src/chain/rewards/syncCommitteeRewards.ts +3 -1
- package/src/chain/stateCache/persistentCheckpointsCache.ts +15 -2
- package/src/chain/validation/attesterSlashing.ts +1 -1
- package/src/chain/validation/block.ts +1 -1
- package/src/chain/validation/blsToExecutionChange.ts +1 -1
- package/src/chain/validation/proposerSlashing.ts +1 -1
- package/src/chain/validation/signatureSets/aggregateAndProof.ts +1 -1
- package/src/chain/validation/signatureSets/contributionAndProof.ts +3 -1
- package/src/chain/validation/signatureSets/syncCommittee.ts +3 -1
- package/src/chain/validation/signatureSets/syncCommitteeContribution.ts +3 -1
- package/src/chain/validation/signatureSets/syncCommitteeSelectionProof.ts +2 -1
- package/src/chain/validation/syncCommittee.ts +1 -1
- package/src/chain/validation/syncCommitteeContributionAndProof.ts +8 -3
- package/src/chain/validation/voluntaryExit.ts +1 -1
- package/src/db/beacon.ts +38 -1
- package/src/db/buckets.ts +12 -6
- package/src/db/interface.ts +2 -0
- package/src/node/nodejs.ts +11 -0
- package/src/sync/backfill/backfill.ts +8 -3
- package/src/sync/backfill/verify.ts +3 -1
|
@@ -1,3 +1,4 @@
|
|
|
1
|
+
import {BeaconConfig} from "@lodestar/config";
|
|
1
2
|
import {Id, Repository} from "@lodestar/db";
|
|
2
3
|
import {
|
|
3
4
|
BLS_WITHDRAWAL_PREFIX,
|
|
@@ -51,6 +52,8 @@ export class OpPool {
|
|
|
51
52
|
/** Map of validator index -> SignedBLSToExecutionChange */
|
|
52
53
|
private readonly blsToExecutionChanges = new Map<ValidatorIndex, SignedBLSToExecutionChangeVersioned>();
|
|
53
54
|
|
|
55
|
+
constructor(private readonly config: BeaconConfig) {}
|
|
56
|
+
|
|
54
57
|
// Getters for metrics
|
|
55
58
|
|
|
56
59
|
get attesterSlashingsSize(): number {
|
|
@@ -191,9 +194,8 @@ export class OpPool {
|
|
|
191
194
|
phase0.SignedVoluntaryExit[],
|
|
192
195
|
capella.SignedBLSToExecutionChange[],
|
|
193
196
|
] {
|
|
194
|
-
const {config} = state;
|
|
195
197
|
const stateEpoch = computeEpochAtSlot(state.slot);
|
|
196
|
-
const stateFork = config.getForkSeq(state.slot);
|
|
198
|
+
const stateFork = this.config.getForkSeq(state.slot);
|
|
197
199
|
const toBeSlashedIndices = new Set<ValidatorIndex>();
|
|
198
200
|
const proposerSlashings: phase0.ProposerSlashing[] = [];
|
|
199
201
|
|
|
@@ -265,7 +267,7 @@ export class OpPool {
|
|
|
265
267
|
// a future fork.
|
|
266
268
|
isVoluntaryExitSignatureIncludable(
|
|
267
269
|
stateFork,
|
|
268
|
-
config.getForkSeq(computeStartSlotAtEpoch(voluntaryExit.message.epoch))
|
|
270
|
+
this.config.getForkSeq(computeStartSlotAtEpoch(voluntaryExit.message.epoch))
|
|
269
271
|
)
|
|
270
272
|
) {
|
|
271
273
|
voluntaryExits.push(voluntaryExit);
|
|
@@ -368,14 +370,13 @@ export class OpPool {
|
|
|
368
370
|
* Prune if validator has already exited at or before the finalized checkpoint of the head.
|
|
369
371
|
*/
|
|
370
372
|
private pruneVoluntaryExits(headState: CachedBeaconStateAllForks): void {
|
|
371
|
-
const
|
|
372
|
-
const headStateFork = config.getForkSeq(headState.slot);
|
|
373
|
+
const headStateFork = this.config.getForkSeq(headState.slot);
|
|
373
374
|
const finalizedEpoch = headState.finalizedCheckpoint.epoch;
|
|
374
375
|
|
|
375
376
|
for (const [key, voluntaryExit] of this.voluntaryExits.entries()) {
|
|
376
377
|
// VoluntaryExit messages signed in the previous fork become invalid and can never be included in any future
|
|
377
378
|
// block, so just drop as the head state advances into the next fork.
|
|
378
|
-
if (config.getForkSeq(computeStartSlotAtEpoch(voluntaryExit.message.epoch)) < headStateFork) {
|
|
379
|
+
if (this.config.getForkSeq(computeStartSlotAtEpoch(voluntaryExit.message.epoch)) < headStateFork) {
|
|
379
380
|
this.voluntaryExits.delete(key);
|
|
380
381
|
}
|
|
381
382
|
|
|
@@ -392,9 +393,8 @@ export class OpPool {
|
|
|
392
393
|
* to opPool once gossipsub seen cache TTL passes.
|
|
393
394
|
*/
|
|
394
395
|
private pruneBlsToExecutionChanges(headBlock: SignedBeaconBlock, headState: CachedBeaconStateAllForks): void {
|
|
395
|
-
const {config} = headState;
|
|
396
396
|
const recentBlsToExecutionChanges =
|
|
397
|
-
config.getForkSeq(headBlock.message.slot) >= ForkSeq.capella
|
|
397
|
+
this.config.getForkSeq(headBlock.message.slot) >= ForkSeq.capella
|
|
398
398
|
? (headBlock as capella.SignedBeaconBlock).message.body.blsToExecutionChanges
|
|
399
399
|
: [];
|
|
400
400
|
|
|
@@ -165,7 +165,7 @@ export async function produceBlockBody<T extends BlockType>(
|
|
|
165
165
|
// even though shouldOverrideBuilder is relevant for the engine response, for simplicity of typing
|
|
166
166
|
// we just return it undefined for the builder which anyway doesn't get consumed downstream
|
|
167
167
|
let shouldOverrideBuilder: boolean | undefined;
|
|
168
|
-
const fork =
|
|
168
|
+
const fork = this.config.getForkName(blockSlot);
|
|
169
169
|
const produceResult = {
|
|
170
170
|
type: blockType,
|
|
171
171
|
fork,
|
|
@@ -644,7 +644,7 @@ export async function produceCommonBlockBody<T extends BlockType>(
|
|
|
644
644
|
? this.metrics?.executionBlockProductionTimeSteps
|
|
645
645
|
: this.metrics?.builderBlockProductionTimeSteps;
|
|
646
646
|
|
|
647
|
-
const fork =
|
|
647
|
+
const fork = this.config.getForkName(slot);
|
|
648
648
|
|
|
649
649
|
// TODO:
|
|
650
650
|
// Iterate through the naive aggregation pool and ensure all the attestations from there
|
|
@@ -1,5 +1,6 @@
|
|
|
1
1
|
import {PubkeyIndexMap} from "@chainsafe/pubkey-index-map";
|
|
2
2
|
import {routes} from "@lodestar/api";
|
|
3
|
+
import {BeaconConfig} from "@lodestar/config";
|
|
3
4
|
import {
|
|
4
5
|
EFFECTIVE_BALANCE_INCREMENT,
|
|
5
6
|
ForkName,
|
|
@@ -38,11 +39,12 @@ const defaultAttestationsReward = {head: 0, target: 0, source: 0, inclusionDelay
|
|
|
38
39
|
const defaultAttestationsPenalty = {target: 0, source: 0};
|
|
39
40
|
|
|
40
41
|
export async function computeAttestationsRewards(
|
|
42
|
+
config: BeaconConfig,
|
|
41
43
|
pubkey2index: PubkeyIndexMap,
|
|
42
44
|
state: CachedBeaconStateAllForks,
|
|
43
45
|
validatorIds?: (ValidatorIndex | string)[]
|
|
44
46
|
): Promise<AttestationsRewards> {
|
|
45
|
-
const fork =
|
|
47
|
+
const fork = config.getForkName(state.slot);
|
|
46
48
|
if (fork === ForkName.phase0) {
|
|
47
49
|
throw Error("Unsupported fork. Attestations rewards calculation is not available in phase0");
|
|
48
50
|
}
|
|
@@ -50,8 +52,13 @@ export async function computeAttestationsRewards(
|
|
|
50
52
|
const stateAltair = state as CachedBeaconStateAltair;
|
|
51
53
|
const transitionCache = beforeProcessEpoch(stateAltair);
|
|
52
54
|
|
|
53
|
-
const [idealRewards, penalties] = computeIdealAttestationsRewardsAndPenaltiesAltair(
|
|
55
|
+
const [idealRewards, penalties] = computeIdealAttestationsRewardsAndPenaltiesAltair(
|
|
56
|
+
config,
|
|
57
|
+
stateAltair,
|
|
58
|
+
transitionCache
|
|
59
|
+
);
|
|
54
60
|
const totalRewards = computeTotalAttestationsRewardsAltair(
|
|
61
|
+
config,
|
|
55
62
|
pubkey2index,
|
|
56
63
|
stateAltair,
|
|
57
64
|
transitionCache,
|
|
@@ -64,12 +71,13 @@ export async function computeAttestationsRewards(
|
|
|
64
71
|
}
|
|
65
72
|
|
|
66
73
|
function computeIdealAttestationsRewardsAndPenaltiesAltair(
|
|
74
|
+
config: BeaconConfig,
|
|
67
75
|
state: CachedBeaconStateAllForks,
|
|
68
76
|
transitionCache: EpochTransitionCache
|
|
69
77
|
): [IdealAttestationsReward[], AttestationsPenalty[]] {
|
|
70
78
|
const baseRewardPerIncrement = transitionCache.baseRewardPerIncrement;
|
|
71
79
|
const activeBalanceByIncrement = transitionCache.totalActiveStakeByIncrement;
|
|
72
|
-
const fork =
|
|
80
|
+
const fork = config.getForkName(state.slot);
|
|
73
81
|
const maxEffectiveBalance = isForkPostElectra(fork) ? MAX_EFFECTIVE_BALANCE_ELECTRA : MAX_EFFECTIVE_BALANCE;
|
|
74
82
|
const maxEffectiveBalanceByIncrement = Math.floor(maxEffectiveBalance / EFFECTIVE_BALANCE_INCREMENT);
|
|
75
83
|
|
|
@@ -139,6 +147,7 @@ function computeIdealAttestationsRewardsAndPenaltiesAltair(
|
|
|
139
147
|
|
|
140
148
|
// Same calculation as `getRewardsAndPenaltiesAltair` but returns the breakdown of rewards instead of aggregated
|
|
141
149
|
function computeTotalAttestationsRewardsAltair(
|
|
150
|
+
config: BeaconConfig,
|
|
142
151
|
pubkey2index: PubkeyIndexMap,
|
|
143
152
|
state: CachedBeaconStateAltair,
|
|
144
153
|
transitionCache: EpochTransitionCache,
|
|
@@ -148,7 +157,7 @@ function computeTotalAttestationsRewardsAltair(
|
|
|
148
157
|
): TotalAttestationsReward[] {
|
|
149
158
|
const rewards = [];
|
|
150
159
|
const {flags} = transitionCache;
|
|
151
|
-
const {epochCtx
|
|
160
|
+
const {epochCtx} = state;
|
|
152
161
|
const validatorIndices = validatorIds
|
|
153
162
|
.map((id) => (typeof id === "number" ? id : pubkey2index.get(fromHex(id))))
|
|
154
163
|
.filter((index) => index !== undefined); // Validator indices to include in the result
|
|
@@ -1,4 +1,5 @@
|
|
|
1
1
|
import {routes} from "@lodestar/api";
|
|
2
|
+
import {BeaconConfig} from "@lodestar/config";
|
|
2
3
|
import {
|
|
3
4
|
ForkName,
|
|
4
5
|
WHISTLEBLOWER_REWARD_QUOTIENT,
|
|
@@ -26,11 +27,12 @@ type SubRewardValue = number; // All reward values should be integer
|
|
|
26
27
|
* 3) Reporting slashable behaviours from proposer and attester
|
|
27
28
|
*/
|
|
28
29
|
export async function computeBlockRewards(
|
|
30
|
+
config: BeaconConfig,
|
|
29
31
|
block: BeaconBlock,
|
|
30
32
|
preState: CachedBeaconStateAllForks,
|
|
31
33
|
postState?: CachedBeaconStateAllForks
|
|
32
34
|
): Promise<BlockRewards> {
|
|
33
|
-
const fork =
|
|
35
|
+
const fork = config.getForkName(block.slot);
|
|
34
36
|
const {attestations: cachedAttestationsReward = 0, syncAggregate: cachedSyncAggregateReward = 0} =
|
|
35
37
|
postState?.proposerRewards ?? {};
|
|
36
38
|
let blockAttestationReward = cachedAttestationsReward;
|
|
@@ -40,7 +42,7 @@ export async function computeBlockRewards(
|
|
|
40
42
|
blockAttestationReward =
|
|
41
43
|
fork === ForkName.phase0
|
|
42
44
|
? computeBlockAttestationRewardPhase0(block as phase0.BeaconBlock, preState as CachedBeaconStatePhase0)
|
|
43
|
-
: computeBlockAttestationRewardAltair(block as altair.BeaconBlock, preState as CachedBeaconStateAltair);
|
|
45
|
+
: computeBlockAttestationRewardAltair(config, block as altair.BeaconBlock, preState as CachedBeaconStateAltair);
|
|
44
46
|
}
|
|
45
47
|
|
|
46
48
|
if (syncAggregateReward === 0) {
|
|
@@ -78,10 +80,11 @@ function computeBlockAttestationRewardPhase0(
|
|
|
78
80
|
* Reuses `processAttestationsAltair()`. Has dependency on RewardCache
|
|
79
81
|
*/
|
|
80
82
|
function computeBlockAttestationRewardAltair(
|
|
83
|
+
config: BeaconConfig,
|
|
81
84
|
block: altair.BeaconBlock,
|
|
82
85
|
preState: CachedBeaconStateAltair
|
|
83
86
|
): SubRewardValue {
|
|
84
|
-
const fork =
|
|
87
|
+
const fork = config.getForkSeq(block.slot);
|
|
85
88
|
const {attestations} = block.body;
|
|
86
89
|
|
|
87
90
|
processAttestationsAltair(fork, preState, attestations, false);
|
|
@@ -1,4 +1,5 @@
|
|
|
1
1
|
import {routes} from "@lodestar/api";
|
|
2
|
+
import {BeaconConfig} from "@lodestar/config";
|
|
2
3
|
import {ForkName, SYNC_COMMITTEE_SIZE} from "@lodestar/params";
|
|
3
4
|
import {CachedBeaconStateAllForks, CachedBeaconStateAltair, Index2PubkeyCache} from "@lodestar/state-transition";
|
|
4
5
|
import {BeaconBlock, ValidatorIndex, altair} from "@lodestar/types";
|
|
@@ -7,12 +8,13 @@ export type SyncCommitteeRewards = routes.beacon.SyncCommitteeRewards;
|
|
|
7
8
|
type BalanceRecord = {val: number}; // Use val for convenient way to increment/decrement balance
|
|
8
9
|
|
|
9
10
|
export async function computeSyncCommitteeRewards(
|
|
11
|
+
config: BeaconConfig,
|
|
10
12
|
index2pubkey: Index2PubkeyCache,
|
|
11
13
|
block: BeaconBlock,
|
|
12
14
|
preState: CachedBeaconStateAllForks,
|
|
13
15
|
validatorIds: (ValidatorIndex | string)[] = []
|
|
14
16
|
): Promise<SyncCommitteeRewards> {
|
|
15
|
-
const fork =
|
|
17
|
+
const fork = config.getForkName(block.slot);
|
|
16
18
|
if (fork === ForkName.phase0) {
|
|
17
19
|
throw Error("Cannot get sync rewards as phase0 block does not have sync committee");
|
|
18
20
|
}
|
|
@@ -1,4 +1,5 @@
|
|
|
1
1
|
import {routes} from "@lodestar/api";
|
|
2
|
+
import {BeaconConfig} from "@lodestar/config";
|
|
2
3
|
import {
|
|
3
4
|
CachedBeaconStateAllForks,
|
|
4
5
|
computeStartSlotAtEpoch,
|
|
@@ -24,6 +25,7 @@ export type PersistentCheckpointStateCacheOpts = {
|
|
|
24
25
|
};
|
|
25
26
|
|
|
26
27
|
type PersistentCheckpointStateCacheModules = {
|
|
28
|
+
config: BeaconConfig;
|
|
27
29
|
metrics?: Metrics | null;
|
|
28
30
|
logger: Logger;
|
|
29
31
|
clock?: IClock | null;
|
|
@@ -107,6 +109,7 @@ export class PersistentCheckpointStateCache implements CheckpointStateCache {
|
|
|
107
109
|
private readonly cache: MapTracker<CacheKey, CacheItem>;
|
|
108
110
|
/** Epoch -> Set<blockRoot> */
|
|
109
111
|
private readonly epochIndex = new MapDef<Epoch, Set<RootHex>>(() => new Set<string>());
|
|
112
|
+
private readonly config: BeaconConfig;
|
|
110
113
|
private readonly metrics: Metrics | null | undefined;
|
|
111
114
|
private readonly logger: Logger;
|
|
112
115
|
private readonly clock: IClock | null | undefined;
|
|
@@ -120,10 +123,20 @@ export class PersistentCheckpointStateCache implements CheckpointStateCache {
|
|
|
120
123
|
private readonly bufferPool?: BufferPool | null;
|
|
121
124
|
|
|
122
125
|
constructor(
|
|
123
|
-
{
|
|
126
|
+
{
|
|
127
|
+
config,
|
|
128
|
+
metrics,
|
|
129
|
+
logger,
|
|
130
|
+
clock,
|
|
131
|
+
signal,
|
|
132
|
+
datastore,
|
|
133
|
+
blockStateCache,
|
|
134
|
+
bufferPool,
|
|
135
|
+
}: PersistentCheckpointStateCacheModules,
|
|
124
136
|
opts: PersistentCheckpointStateCacheOpts
|
|
125
137
|
) {
|
|
126
138
|
this.cache = new MapTracker(metrics?.cpStateCache);
|
|
139
|
+
this.config = config;
|
|
127
140
|
if (metrics) {
|
|
128
141
|
this.metrics = metrics;
|
|
129
142
|
metrics.cpStateCache.size.addCollect(() => {
|
|
@@ -484,7 +497,7 @@ export class PersistentCheckpointStateCache implements CheckpointStateCache {
|
|
|
484
497
|
}
|
|
485
498
|
|
|
486
499
|
const blockSlot = state.slot;
|
|
487
|
-
const processCPStatesTimeMs =
|
|
500
|
+
const processCPStatesTimeMs = this.config.getSlotComponentDurationMs(PROCESS_CHECKPOINT_STATES_BPS);
|
|
488
501
|
// we always have clock in production, fallback value is only for test
|
|
489
502
|
const msFromSlot = this.clock?.msFromSlot(blockSlot) ?? processCPStatesTimeMs;
|
|
490
503
|
const msToProcessCPStates = processCPStatesTimeMs - msFromSlot;
|
|
@@ -51,7 +51,7 @@ export async function validateAttesterSlashing(
|
|
|
51
51
|
});
|
|
52
52
|
}
|
|
53
53
|
|
|
54
|
-
const signatureSets = getAttesterSlashingSignatureSets(chain.index2pubkey, state, attesterSlashing);
|
|
54
|
+
const signatureSets = getAttesterSlashingSignatureSets(chain.config, chain.index2pubkey, state, attesterSlashing);
|
|
55
55
|
if (!(await chain.bls.verifySignatureSets(signatureSets, {batchable: true, priority: prioritizeBls}))) {
|
|
56
56
|
throw new AttesterSlashingError(GossipAction.REJECT, {
|
|
57
57
|
code: AttesterSlashingErrorCode.INVALID,
|
|
@@ -153,7 +153,7 @@ export async function validateGossipBlock(
|
|
|
153
153
|
|
|
154
154
|
// [REJECT] The proposer signature, signed_beacon_block.signature, is valid with respect to the proposer_index pubkey.
|
|
155
155
|
if (!chain.seenBlockInputCache.isVerifiedProposerSignature(blockSlot, blockRoot, signedBlock.signature)) {
|
|
156
|
-
const signatureSet = getBlockProposerSignatureSet(chain.index2pubkey, blockState, signedBlock);
|
|
156
|
+
const signatureSet = getBlockProposerSignatureSet(chain.config, chain.index2pubkey, blockState, signedBlock);
|
|
157
157
|
// Don't batch so verification is not delayed
|
|
158
158
|
if (!(await chain.bls.verifySignatureSets([signatureSet], {verifyOnMainThread: true}))) {
|
|
159
159
|
throw new BlockGossipError(GossipAction.REJECT, {
|
|
@@ -41,7 +41,7 @@ async function validateBlsToExecutionChange(
|
|
|
41
41
|
// NOTE: No need to advance head state since the signature's fork is handled with `broadcastedOnFork`,
|
|
42
42
|
// and chanes relevant to `isValidBlsToExecutionChange()` happen only on processBlock(), not processEpoch()
|
|
43
43
|
const state = chain.getHeadState();
|
|
44
|
-
const {config} =
|
|
44
|
+
const {config} = chain;
|
|
45
45
|
|
|
46
46
|
// [REJECT] All of the conditions within process_bls_to_execution_change pass validation.
|
|
47
47
|
// verifySignature = false, verified in batch below
|
|
@@ -44,7 +44,7 @@ async function validateProposerSlashing(
|
|
|
44
44
|
});
|
|
45
45
|
}
|
|
46
46
|
|
|
47
|
-
const signatureSets = getProposerSlashingSignatureSets(chain.index2pubkey, state, proposerSlashing);
|
|
47
|
+
const signatureSets = getProposerSlashingSignatureSets(chain.config, chain.index2pubkey, state, proposerSlashing);
|
|
48
48
|
if (!(await chain.bls.verifySignatureSets(signatureSets, {batchable: true, priority: prioritizeBls}))) {
|
|
49
49
|
throw new ProposerSlashingError(GossipAction.REJECT, {
|
|
50
50
|
code: ProposerSlashingErrorCode.INVALID,
|
|
@@ -14,7 +14,7 @@ export function getAggregateAndProofSigningRoot(
|
|
|
14
14
|
epoch: Epoch,
|
|
15
15
|
aggregateAndProof: SignedAggregateAndProof
|
|
16
16
|
): Uint8Array {
|
|
17
|
-
// previously, we call `const aggregatorDomain =
|
|
17
|
+
// previously, we call `const aggregatorDomain = config.getDomain(state.slot, DOMAIN_AGGREGATE_AND_PROOF, slot);`
|
|
18
18
|
// at fork boundary, it's required to dial to target epoch https://github.com/ChainSafe/lodestar/blob/v1.11.3/packages/beacon-node/src/chain/validation/attestation.ts#L573
|
|
19
19
|
// instead of that, just use the fork of slot in the attestation data
|
|
20
20
|
const slot = computeStartSlotAtEpoch(epoch);
|
|
@@ -1,3 +1,4 @@
|
|
|
1
|
+
import {BeaconConfig} from "@lodestar/config";
|
|
1
2
|
import {DOMAIN_CONTRIBUTION_AND_PROOF} from "@lodestar/params";
|
|
2
3
|
import {
|
|
3
4
|
CachedBeaconStateAllForks,
|
|
@@ -9,11 +10,12 @@ import {
|
|
|
9
10
|
import {altair, ssz} from "@lodestar/types";
|
|
10
11
|
|
|
11
12
|
export function getContributionAndProofSignatureSet(
|
|
13
|
+
config: BeaconConfig,
|
|
12
14
|
index2pubkey: Index2PubkeyCache,
|
|
13
15
|
state: CachedBeaconStateAllForks,
|
|
14
16
|
signedContributionAndProof: altair.SignedContributionAndProof
|
|
15
17
|
): ISignatureSet {
|
|
16
|
-
const domain =
|
|
18
|
+
const domain = config.getDomain(
|
|
17
19
|
state.slot,
|
|
18
20
|
DOMAIN_CONTRIBUTION_AND_PROOF,
|
|
19
21
|
signedContributionAndProof.message.contribution.slot
|
|
@@ -1,3 +1,4 @@
|
|
|
1
|
+
import {BeaconConfig} from "@lodestar/config";
|
|
1
2
|
import {DOMAIN_SYNC_COMMITTEE} from "@lodestar/params";
|
|
2
3
|
import {
|
|
3
4
|
CachedBeaconStateAllForks,
|
|
@@ -9,11 +10,12 @@ import {
|
|
|
9
10
|
import {altair, ssz} from "@lodestar/types";
|
|
10
11
|
|
|
11
12
|
export function getSyncCommitteeSignatureSet(
|
|
13
|
+
config: BeaconConfig,
|
|
12
14
|
index2pubkey: Index2PubkeyCache,
|
|
13
15
|
state: CachedBeaconStateAllForks,
|
|
14
16
|
syncCommittee: altair.SyncCommitteeMessage
|
|
15
17
|
): ISignatureSet {
|
|
16
|
-
const domain =
|
|
18
|
+
const domain = config.getDomain(state.slot, DOMAIN_SYNC_COMMITTEE, syncCommittee.slot);
|
|
17
19
|
|
|
18
20
|
return {
|
|
19
21
|
type: SignatureSetType.single,
|
|
@@ -1,14 +1,16 @@
|
|
|
1
1
|
import {PublicKey} from "@chainsafe/blst";
|
|
2
|
+
import {BeaconConfig} from "@lodestar/config";
|
|
2
3
|
import {DOMAIN_SYNC_COMMITTEE} from "@lodestar/params";
|
|
3
4
|
import {CachedBeaconStateAltair, ISignatureSet, SignatureSetType, computeSigningRoot} from "@lodestar/state-transition";
|
|
4
5
|
import {altair, ssz} from "@lodestar/types";
|
|
5
6
|
|
|
6
7
|
export function getSyncCommitteeContributionSignatureSet(
|
|
8
|
+
config: BeaconConfig,
|
|
7
9
|
state: CachedBeaconStateAltair,
|
|
8
10
|
contribution: altair.SyncCommitteeContribution,
|
|
9
11
|
pubkeys: PublicKey[]
|
|
10
12
|
): ISignatureSet {
|
|
11
|
-
const domain =
|
|
13
|
+
const domain = config.getDomain(state.slot, DOMAIN_SYNC_COMMITTEE, contribution.slot);
|
|
12
14
|
return {
|
|
13
15
|
type: SignatureSetType.aggregate,
|
|
14
16
|
pubkeys,
|
|
@@ -1,3 +1,4 @@
|
|
|
1
|
+
import {BeaconConfig} from "@lodestar/config";
|
|
1
2
|
import {DOMAIN_SYNC_COMMITTEE_SELECTION_PROOF} from "@lodestar/params";
|
|
2
3
|
import {
|
|
3
4
|
CachedBeaconStateAllForks,
|
|
@@ -9,11 +10,11 @@ import {
|
|
|
9
10
|
import {altair, ssz} from "@lodestar/types";
|
|
10
11
|
|
|
11
12
|
export function getSyncCommitteeSelectionProofSignatureSet(
|
|
13
|
+
config: BeaconConfig,
|
|
12
14
|
index2pubkey: Index2PubkeyCache,
|
|
13
15
|
state: CachedBeaconStateAllForks,
|
|
14
16
|
contributionAndProof: altair.ContributionAndProof
|
|
15
17
|
): ISignatureSet {
|
|
16
|
-
const {config} = state;
|
|
17
18
|
const slot = contributionAndProof.contribution.slot;
|
|
18
19
|
const domain = config.getDomain(state.slot, DOMAIN_SYNC_COMMITTEE_SELECTION_PROOF, slot);
|
|
19
20
|
const signingData: altair.SyncAggregatorSelectionData = {
|
|
@@ -89,7 +89,7 @@ async function validateSyncCommitteeSigOnly(
|
|
|
89
89
|
syncCommittee: altair.SyncCommitteeMessage,
|
|
90
90
|
prioritizeBls = false
|
|
91
91
|
): Promise<void> {
|
|
92
|
-
const signatureSet = getSyncCommitteeSignatureSet(chain.index2pubkey, headState, syncCommittee);
|
|
92
|
+
const signatureSet = getSyncCommitteeSignatureSet(chain.config, chain.index2pubkey, headState, syncCommittee);
|
|
93
93
|
if (!(await chain.bls.verifySignatureSets([signatureSet], {batchable: true, priority: prioritizeBls}))) {
|
|
94
94
|
throw new SyncCommitteeError(GossipAction.REJECT, {
|
|
95
95
|
code: SyncCommitteeErrorCode.INVALID_SIGNATURE,
|
|
@@ -78,14 +78,19 @@ export async function validateSyncCommitteeGossipContributionAndProof(
|
|
|
78
78
|
const signatureSets = [
|
|
79
79
|
// [REJECT] The contribution_and_proof.selection_proof is a valid signature of the SyncAggregatorSelectionData
|
|
80
80
|
// derived from the contribution by the validator with index contribution_and_proof.aggregator_index.
|
|
81
|
-
getSyncCommitteeSelectionProofSignatureSet(index2pubkey, headState, contributionAndProof),
|
|
81
|
+
getSyncCommitteeSelectionProofSignatureSet(chain.config, index2pubkey, headState, contributionAndProof),
|
|
82
82
|
|
|
83
83
|
// [REJECT] The aggregator signature, signed_contribution_and_proof.signature, is valid.
|
|
84
|
-
getContributionAndProofSignatureSet(index2pubkey, headState, signedContributionAndProof),
|
|
84
|
+
getContributionAndProofSignatureSet(chain.config, index2pubkey, headState, signedContributionAndProof),
|
|
85
85
|
|
|
86
86
|
// [REJECT] The aggregate signature is valid for the message beacon_block_root and aggregate pubkey derived from
|
|
87
87
|
// the participation info in aggregation_bits for the subcommittee specified by the contribution.subcommittee_index.
|
|
88
|
-
getSyncCommitteeContributionSignatureSet(
|
|
88
|
+
getSyncCommitteeContributionSignatureSet(
|
|
89
|
+
chain.config,
|
|
90
|
+
headState as CachedBeaconStateAltair,
|
|
91
|
+
contribution,
|
|
92
|
+
participantPubkeys
|
|
93
|
+
),
|
|
89
94
|
];
|
|
90
95
|
|
|
91
96
|
if (!(await chain.bls.verifySignatureSets(signatureSets, {batchable: true}))) {
|
|
@@ -59,7 +59,7 @@ async function validateVoluntaryExit(
|
|
|
59
59
|
});
|
|
60
60
|
}
|
|
61
61
|
|
|
62
|
-
const signatureSet = getVoluntaryExitSignatureSet(chain.index2pubkey, state, voluntaryExit);
|
|
62
|
+
const signatureSet = getVoluntaryExitSignatureSet(chain.config, chain.index2pubkey, state, voluntaryExit);
|
|
63
63
|
if (!(await chain.bls.verifySignatureSets([signatureSet], {batchable: true, priority: prioritizeBls}))) {
|
|
64
64
|
throw new VoluntaryExitError(GossipAction.REJECT, {
|
|
65
65
|
code: VoluntaryExitErrorCode.INVALID_SIGNATURE,
|
package/src/db/beacon.ts
CHANGED
|
@@ -1,5 +1,6 @@
|
|
|
1
1
|
import {ChainForkConfig} from "@lodestar/config";
|
|
2
|
-
import {Db, LevelDbControllerMetrics} from "@lodestar/db";
|
|
2
|
+
import {Db, LevelDbControllerMetrics, encodeKey} from "@lodestar/db";
|
|
3
|
+
import {Bucket} from "./buckets.js";
|
|
3
4
|
import {IBeaconDb} from "./interface.js";
|
|
4
5
|
import {CheckpointStateRepository} from "./repositories/checkpointState.js";
|
|
5
6
|
import {
|
|
@@ -95,4 +96,40 @@ export class BeaconDb implements IBeaconDb {
|
|
|
95
96
|
// TODO: Enable once it's deemed safe
|
|
96
97
|
// await this.block.batchDelete(await this.block.keys());
|
|
97
98
|
}
|
|
99
|
+
|
|
100
|
+
async deleteDeprecatedEth1Data(): Promise<void> {
|
|
101
|
+
const deprecatedBuckets = [
|
|
102
|
+
Bucket.phase0_eth1Data,
|
|
103
|
+
Bucket.index_depositDataRoot,
|
|
104
|
+
Bucket.phase0_depositData,
|
|
105
|
+
Bucket.phase0_depositEvent,
|
|
106
|
+
Bucket.phase0_preGenesisState,
|
|
107
|
+
Bucket.phase0_preGenesisStateLastProcessedBlock,
|
|
108
|
+
];
|
|
109
|
+
|
|
110
|
+
for (const bucket of deprecatedBuckets) {
|
|
111
|
+
await this.deleteBucketData(bucket);
|
|
112
|
+
}
|
|
113
|
+
}
|
|
114
|
+
|
|
115
|
+
private async deleteBucketData(bucket: Bucket): Promise<void> {
|
|
116
|
+
const minKey = encodeKey(bucket, Buffer.alloc(0));
|
|
117
|
+
const maxKey = encodeKey(bucket + 1, Buffer.alloc(0));
|
|
118
|
+
|
|
119
|
+
// Batch delete to avoid loading all keys into memory at once
|
|
120
|
+
const BATCH_DELETE_SIZE = 1000;
|
|
121
|
+
let keysBatch: Uint8Array[] = [];
|
|
122
|
+
|
|
123
|
+
for await (const key of this.db.keysStream({gte: minKey, lt: maxKey})) {
|
|
124
|
+
keysBatch.push(key);
|
|
125
|
+
if (keysBatch.length >= BATCH_DELETE_SIZE) {
|
|
126
|
+
await this.db.batchDelete(keysBatch);
|
|
127
|
+
keysBatch = [];
|
|
128
|
+
}
|
|
129
|
+
}
|
|
130
|
+
|
|
131
|
+
if (keysBatch.length > 0) {
|
|
132
|
+
await this.db.batchDelete(keysBatch);
|
|
133
|
+
}
|
|
134
|
+
}
|
|
98
135
|
}
|
package/src/db/buckets.ts
CHANGED
|
@@ -16,13 +16,16 @@ export enum Bucket {
|
|
|
16
16
|
index_mainChain = 6, // Slot -> Root<BeaconBlock>
|
|
17
17
|
// justified, finalized state and block hashes
|
|
18
18
|
index_chainInfo = 7, // Key -> Number64 | stateHash | blockHash
|
|
19
|
-
|
|
20
|
-
|
|
19
|
+
/** @deprecated Eth1 deposit tracking is not required since electra, only kept around to delete data from existing databases */
|
|
20
|
+
phase0_eth1Data = 8,
|
|
21
|
+
/** @deprecated Eth1 deposit tracking is not required since electra, only kept around to delete data from existing databases */
|
|
22
|
+
index_depositDataRoot = 9,
|
|
21
23
|
|
|
22
24
|
// op pool
|
|
23
25
|
// phase0_attestation = 10, // DEPRECATED on v0.25.0
|
|
24
26
|
// phase0_aggregateAndProof = 11, // Root -> AggregateAndProof, DEPRECATED on v.27.0
|
|
25
|
-
|
|
27
|
+
/** @deprecated Eth1 deposit tracking is not required since electra, only kept around to delete data from existing databases */
|
|
28
|
+
phase0_depositData = 12,
|
|
26
29
|
phase0_exit = 13, // ValidatorIndex -> VoluntaryExit
|
|
27
30
|
phase0_proposerSlashing = 14, // ValidatorIndex -> ProposerSlashing
|
|
28
31
|
allForks_attesterSlashing = 15, // Root -> AttesterSlashing
|
|
@@ -31,15 +34,18 @@ export enum Bucket {
|
|
|
31
34
|
allForks_checkpointState = 17, // Root -> BeaconState
|
|
32
35
|
|
|
33
36
|
// allForks_pendingBlock = 25, // Root -> SignedBeaconBlock // DEPRECATED on v0.30.0
|
|
34
|
-
|
|
37
|
+
/** @deprecated Eth1 deposit tracking is not required since electra, only kept around to delete data from existing databases */
|
|
38
|
+
phase0_depositEvent = 19,
|
|
35
39
|
|
|
36
40
|
index_stateArchiveRootIndex = 26, // State Root -> slot
|
|
37
41
|
|
|
38
42
|
deneb_blobSidecars = 27, // DENEB BeaconBlockRoot -> BlobSidecars
|
|
39
43
|
deneb_blobSidecarsArchive = 28, // DENEB BeaconBlockSlot -> BlobSidecars
|
|
40
44
|
|
|
41
|
-
|
|
42
|
-
|
|
45
|
+
/** @deprecated Genesis from eth1 is no longer supported, only kept around to delete data from existing databases */
|
|
46
|
+
phase0_preGenesisState = 30,
|
|
47
|
+
/** @deprecated Genesis from eth1 is no longer supported, only kept around to delete data from existing databases */
|
|
48
|
+
phase0_preGenesisStateLastProcessedBlock = 31,
|
|
43
49
|
|
|
44
50
|
// Lightclient server
|
|
45
51
|
// altair_bestUpdatePerCommitteePeriod = 30, // DEPRECATED on v0.32.0
|
package/src/db/interface.ts
CHANGED
|
@@ -56,6 +56,8 @@ export interface IBeaconDb {
|
|
|
56
56
|
|
|
57
57
|
pruneHotDb(): Promise<void>;
|
|
58
58
|
|
|
59
|
+
deleteDeprecatedEth1Data(): Promise<void>;
|
|
60
|
+
|
|
59
61
|
/** Close the connection to the db instance and close the db store. */
|
|
60
62
|
close(): Promise<void>;
|
|
61
63
|
/** To inject metrics after CLI initialization */
|
package/src/node/nodejs.ts
CHANGED
|
@@ -197,6 +197,17 @@ export class BeaconNode {
|
|
|
197
197
|
// TODO: Should this call be awaited?
|
|
198
198
|
await db.pruneHotDb();
|
|
199
199
|
|
|
200
|
+
// Delete deprecated eth1 data to free up disk space for users
|
|
201
|
+
logger.debug("Deleting deprecated eth1 data from database");
|
|
202
|
+
const startTime = Date.now();
|
|
203
|
+
db.deleteDeprecatedEth1Data()
|
|
204
|
+
.then(() => {
|
|
205
|
+
logger.debug("Deleted deprecated eth1 data", {durationMs: Date.now() - startTime});
|
|
206
|
+
})
|
|
207
|
+
.catch((e) => {
|
|
208
|
+
logger.error("Failed to delete deprecated eth1 data", {}, e);
|
|
209
|
+
});
|
|
210
|
+
|
|
200
211
|
const monitoring = opts.monitoring.endpoint
|
|
201
212
|
? new MonitoringService(
|
|
202
213
|
"beacon",
|
|
@@ -750,9 +750,13 @@ export class BackfillSync extends (EventEmitter as {new (): BackfillSyncEmitter}
|
|
|
750
750
|
|
|
751
751
|
// GENESIS_SLOT doesn't has valid signature
|
|
752
752
|
if (anchorBlock.message.slot === GENESIS_SLOT) return;
|
|
753
|
-
await verifyBlockProposerSignature(
|
|
754
|
-
|
|
755
|
-
|
|
753
|
+
await verifyBlockProposerSignature(
|
|
754
|
+
this.chain.config,
|
|
755
|
+
this.chain.index2pubkey,
|
|
756
|
+
this.chain.bls,
|
|
757
|
+
this.chain.getHeadState(),
|
|
758
|
+
[anchorBlock]
|
|
759
|
+
);
|
|
756
760
|
|
|
757
761
|
// We can write to the disk if this is ahead of prevFinalizedCheckpointBlock otherwise
|
|
758
762
|
// we will need to go make checks on the top of sync loop before writing as it might
|
|
@@ -818,6 +822,7 @@ export class BackfillSync extends (EventEmitter as {new (): BackfillSyncEmitter}
|
|
|
818
822
|
// If any of the block's proposer signature fail, we can't trust this peer at all
|
|
819
823
|
if (verifiedBlocks.length > 0) {
|
|
820
824
|
await verifyBlockProposerSignature(
|
|
825
|
+
this.chain.config,
|
|
821
826
|
this.chain.index2pubkey,
|
|
822
827
|
this.chain.bls,
|
|
823
828
|
this.chain.getHeadState(),
|
|
@@ -46,6 +46,7 @@ export function verifyBlockSequence(
|
|
|
46
46
|
}
|
|
47
47
|
|
|
48
48
|
export async function verifyBlockProposerSignature(
|
|
49
|
+
config: BeaconConfig,
|
|
49
50
|
index2pubkey: Index2PubkeyCache,
|
|
50
51
|
bls: IBlsVerifier,
|
|
51
52
|
state: CachedBeaconStateAllForks,
|
|
@@ -54,7 +55,8 @@ export async function verifyBlockProposerSignature(
|
|
|
54
55
|
if (blocks.length === 1 && blocks[0].message.slot === GENESIS_SLOT) return;
|
|
55
56
|
const signatures = blocks.reduce((sigs: ISignatureSet[], block) => {
|
|
56
57
|
// genesis block doesn't have valid signature
|
|
57
|
-
if (block.message.slot !== GENESIS_SLOT)
|
|
58
|
+
if (block.message.slot !== GENESIS_SLOT)
|
|
59
|
+
sigs.push(getBlockProposerSignatureSet(config, index2pubkey, state, block));
|
|
58
60
|
return sigs;
|
|
59
61
|
}, []);
|
|
60
62
|
|