@lodestar/beacon-node 1.40.0-dev.4acd3ce568 → 1.40.0-dev.63c5c3e7f7
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/api/impl/beacon/blocks/index.d.ts.map +1 -1
- package/lib/api/impl/beacon/blocks/index.js +8 -18
- package/lib/api/impl/beacon/blocks/index.js.map +1 -1
- package/lib/api/impl/debug/index.d.ts +1 -1
- package/lib/api/impl/debug/index.d.ts.map +1 -1
- package/lib/api/impl/debug/index.js +3 -6
- package/lib/api/impl/debug/index.js.map +1 -1
- package/lib/api/impl/lodestar/index.d.ts.map +1 -1
- package/lib/api/impl/lodestar/index.js +5 -2
- package/lib/api/impl/lodestar/index.js.map +1 -1
- package/lib/api/impl/validator/index.d.ts.map +1 -1
- package/lib/api/impl/validator/index.js +9 -8
- package/lib/api/impl/validator/index.js.map +1 -1
- package/lib/chain/archiveStore/utils/archiveBlocks.d.ts.map +1 -1
- package/lib/chain/archiveStore/utils/archiveBlocks.js +4 -0
- package/lib/chain/archiveStore/utils/archiveBlocks.js.map +1 -1
- package/lib/chain/blocks/blockInput/blockInput.d.ts +2 -0
- package/lib/chain/blocks/blockInput/blockInput.d.ts.map +1 -1
- package/lib/chain/blocks/blockInput/blockInput.js +6 -0
- package/lib/chain/blocks/blockInput/blockInput.js.map +1 -1
- package/lib/chain/blocks/importBlock.d.ts.map +1 -1
- package/lib/chain/blocks/importBlock.js +2 -6
- package/lib/chain/blocks/importBlock.js.map +1 -1
- package/lib/chain/blocks/index.d.ts.map +1 -1
- package/lib/chain/blocks/index.js +0 -14
- package/lib/chain/blocks/index.js.map +1 -1
- package/lib/chain/blocks/types.d.ts +0 -2
- package/lib/chain/blocks/types.d.ts.map +1 -1
- package/lib/chain/blocks/verifyBlock.d.ts.map +1 -1
- package/lib/chain/blocks/verifyBlock.js +0 -7
- package/lib/chain/blocks/verifyBlock.js.map +1 -1
- package/lib/chain/blocks/writeBlockInputToDb.d.ts +1 -4
- package/lib/chain/blocks/writeBlockInputToDb.d.ts.map +1 -1
- package/lib/chain/blocks/writeBlockInputToDb.js +20 -28
- package/lib/chain/blocks/writeBlockInputToDb.js.map +1 -1
- package/lib/chain/chain.d.ts +14 -2
- package/lib/chain/chain.d.ts.map +1 -1
- package/lib/chain/chain.js +158 -10
- package/lib/chain/chain.js.map +1 -1
- package/lib/chain/interface.d.ts +14 -1
- package/lib/chain/interface.d.ts.map +1 -1
- package/lib/chain/interface.js.map +1 -1
- package/lib/chain/prepareNextSlot.js +6 -4
- package/lib/chain/prepareNextSlot.js.map +1 -1
- package/lib/chain/produceBlock/produceBlockBody.d.ts +3 -2
- package/lib/chain/produceBlock/produceBlockBody.d.ts.map +1 -1
- package/lib/chain/produceBlock/produceBlockBody.js +5 -3
- package/lib/chain/produceBlock/produceBlockBody.js.map +1 -1
- package/lib/chain/regen/interface.d.ts +2 -8
- package/lib/chain/regen/interface.d.ts.map +1 -1
- package/lib/chain/regen/interface.js +0 -1
- package/lib/chain/regen/interface.js.map +1 -1
- package/lib/chain/regen/queued.d.ts +1 -2
- package/lib/chain/regen/queued.d.ts.map +1 -1
- package/lib/chain/regen/queued.js +2 -16
- package/lib/chain/regen/queued.js.map +1 -1
- package/lib/chain/regen/regen.d.ts +3 -7
- package/lib/chain/regen/regen.d.ts.map +1 -1
- package/lib/chain/regen/regen.js +3 -16
- package/lib/chain/regen/regen.js.map +1 -1
- package/lib/chain/validation/blobSidecar.js +1 -1
- package/lib/chain/validation/blobSidecar.js.map +1 -1
- package/lib/chain/validation/dataColumnSidecar.js +1 -1
- package/lib/chain/validation/dataColumnSidecar.js.map +1 -1
- package/lib/chain/validatorMonitor.d.ts +2 -0
- package/lib/chain/validatorMonitor.d.ts.map +1 -1
- package/lib/chain/validatorMonitor.js +42 -3
- package/lib/chain/validatorMonitor.js.map +1 -1
- package/lib/metrics/metrics/lodestar.d.ts +7 -0
- package/lib/metrics/metrics/lodestar.d.ts.map +1 -1
- package/lib/metrics/metrics/lodestar.js +24 -0
- package/lib/metrics/metrics/lodestar.js.map +1 -1
- package/lib/network/processor/gossipHandlers.d.ts.map +1 -1
- package/lib/network/processor/gossipHandlers.js +0 -3
- package/lib/network/processor/gossipHandlers.js.map +1 -1
- package/lib/network/reqresp/handlers/beaconBlocksByRange.d.ts.map +1 -1
- package/lib/network/reqresp/handlers/beaconBlocksByRange.js +2 -4
- package/lib/network/reqresp/handlers/beaconBlocksByRange.js.map +1 -1
- package/lib/network/reqresp/handlers/beaconBlocksByRoot.d.ts +1 -2
- package/lib/network/reqresp/handlers/beaconBlocksByRoot.d.ts.map +1 -1
- package/lib/network/reqresp/handlers/beaconBlocksByRoot.js +5 -26
- package/lib/network/reqresp/handlers/beaconBlocksByRoot.js.map +1 -1
- package/lib/network/reqresp/handlers/blobSidecarsByRoot.d.ts +1 -2
- package/lib/network/reqresp/handlers/blobSidecarsByRoot.d.ts.map +1 -1
- package/lib/network/reqresp/handlers/blobSidecarsByRoot.js +5 -7
- package/lib/network/reqresp/handlers/blobSidecarsByRoot.js.map +1 -1
- package/lib/network/reqresp/handlers/dataColumnSidecarsByRange.d.ts.map +1 -1
- package/lib/network/reqresp/handlers/dataColumnSidecarsByRange.js +1 -2
- package/lib/network/reqresp/handlers/dataColumnSidecarsByRange.js.map +1 -1
- package/lib/network/reqresp/handlers/dataColumnSidecarsByRoot.d.ts.map +1 -1
- package/lib/network/reqresp/handlers/dataColumnSidecarsByRoot.js +1 -5
- package/lib/network/reqresp/handlers/dataColumnSidecarsByRoot.js.map +1 -1
- package/lib/network/reqresp/handlers/index.js +2 -2
- package/lib/network/reqresp/handlers/index.js.map +1 -1
- package/lib/sync/range/chain.d.ts.map +1 -1
- package/lib/sync/range/chain.js +0 -1
- package/lib/sync/range/chain.js.map +1 -1
- package/lib/sync/range/range.d.ts.map +1 -1
- package/lib/sync/range/range.js +0 -3
- package/lib/sync/range/range.js.map +1 -1
- package/lib/sync/unknownBlock.d.ts.map +1 -1
- package/lib/sync/unknownBlock.js +0 -3
- package/lib/sync/unknownBlock.js.map +1 -1
- package/package.json +15 -15
- package/src/api/impl/beacon/blocks/index.ts +8 -18
- package/src/api/impl/debug/index.ts +2 -6
- package/src/api/impl/lodestar/index.ts +6 -3
- package/src/api/impl/validator/index.ts +12 -11
- package/src/chain/archiveStore/utils/archiveBlocks.ts +4 -0
- package/src/chain/blocks/blockInput/blockInput.ts +8 -0
- package/src/chain/blocks/importBlock.ts +2 -6
- package/src/chain/blocks/index.ts +0 -19
- package/src/chain/blocks/types.ts +0 -2
- package/src/chain/blocks/verifyBlock.ts +0 -8
- package/src/chain/blocks/writeBlockInputToDb.ts +24 -30
- package/src/chain/chain.ts +180 -20
- package/src/chain/interface.ts +16 -0
- package/src/chain/prepareNextSlot.ts +6 -6
- package/src/chain/produceBlock/produceBlockBody.ts +7 -5
- package/src/chain/regen/interface.ts +1 -12
- package/src/chain/regen/queued.ts +3 -23
- package/src/chain/regen/regen.ts +4 -24
- package/src/chain/validation/blobSidecar.ts +1 -1
- package/src/chain/validation/dataColumnSidecar.ts +1 -1
- package/src/chain/validatorMonitor.ts +52 -3
- package/src/metrics/metrics/lodestar.ts +25 -0
- package/src/network/processor/gossipHandlers.ts +0 -3
- package/src/network/reqresp/handlers/beaconBlocksByRange.ts +2 -4
- package/src/network/reqresp/handlers/beaconBlocksByRoot.ts +5 -32
- package/src/network/reqresp/handlers/blobSidecarsByRoot.ts +5 -9
- package/src/network/reqresp/handlers/dataColumnSidecarsByRange.ts +5 -2
- package/src/network/reqresp/handlers/dataColumnSidecarsByRoot.ts +1 -5
- package/src/network/reqresp/handlers/index.ts +2 -2
- package/src/sync/range/chain.ts +0 -1
- package/src/sync/range/range.ts +0 -3
- package/src/sync/unknownBlock.ts +0 -3
|
@@ -80,9 +80,8 @@ export class PrepareNextSlotScheduler {
|
|
|
80
80
|
await sleep(this.config.getSlotComponentDurationMs(PREPARE_NEXT_SLOT_BPS), this.signal);
|
|
81
81
|
|
|
82
82
|
// calling updateHead() here before we produce a block to reduce reorg possibility
|
|
83
|
-
const
|
|
84
|
-
|
|
85
|
-
);
|
|
83
|
+
const headBlock = this.chain.recomputeForkChoiceHead(ForkchoiceCaller.prepareNextSlot);
|
|
84
|
+
const {slot: headSlot, blockRoot: headRoot} = headBlock;
|
|
86
85
|
|
|
87
86
|
// PS: previously this was comparing slots, but that gave no leway on the skipped
|
|
88
87
|
// slots on epoch bounday. Making it more fluid.
|
|
@@ -112,7 +111,7 @@ export class PrepareNextSlotScheduler {
|
|
|
112
111
|
// Pre Bellatrix: we only do precompute state transition for the last slot of epoch
|
|
113
112
|
// For Bellatrix, we always do the `processSlots()` to prepare payload for the next slot
|
|
114
113
|
const prepareState = await this.chain.regen.getBlockSlotState(
|
|
115
|
-
|
|
114
|
+
headBlock,
|
|
116
115
|
prepareSlot,
|
|
117
116
|
// the slot 0 of next epoch will likely use this Previous Root Checkpoint state for state transition so we transfer cache here
|
|
118
117
|
// the resulting state with cache will be cached in Checkpoint State Cache which is used for the upcoming block processing
|
|
@@ -129,7 +128,8 @@ export class PrepareNextSlotScheduler {
|
|
|
129
128
|
|
|
130
129
|
if (feeRecipient) {
|
|
131
130
|
// If we are proposing next slot, we need to predict if we can proposer-boost-reorg or not
|
|
132
|
-
const
|
|
131
|
+
const proposerHead = this.chain.predictProposerHead(clockSlot);
|
|
132
|
+
const {slot: proposerHeadSlot, blockRoot: proposerHeadRoot} = proposerHead;
|
|
133
133
|
|
|
134
134
|
// If we predict we can reorg, update prepareState with proposer head block
|
|
135
135
|
if (proposerHeadRoot !== headRoot || proposerHeadSlot !== headSlot) {
|
|
@@ -141,7 +141,7 @@ export class PrepareNextSlotScheduler {
|
|
|
141
141
|
});
|
|
142
142
|
this.metrics?.weakHeadDetected.inc();
|
|
143
143
|
updatedPrepareState = (await this.chain.regen.getBlockSlotState(
|
|
144
|
-
|
|
144
|
+
proposerHead,
|
|
145
145
|
prepareSlot,
|
|
146
146
|
// only transfer cache if epoch transition because that's the state we will use to stateTransition() the 1st block of epoch
|
|
147
147
|
{dontTransferCache: !isEpochTransition},
|
|
@@ -1,5 +1,5 @@
|
|
|
1
1
|
import {ChainForkConfig} from "@lodestar/config";
|
|
2
|
-
import {getSafeExecutionBlockHash} from "@lodestar/fork-choice";
|
|
2
|
+
import {ProtoBlock, getSafeExecutionBlockHash} from "@lodestar/fork-choice";
|
|
3
3
|
import {
|
|
4
4
|
ForkName,
|
|
5
5
|
ForkPostBellatrix,
|
|
@@ -43,7 +43,7 @@ import {
|
|
|
43
43
|
electra,
|
|
44
44
|
fulu,
|
|
45
45
|
} from "@lodestar/types";
|
|
46
|
-
import {Logger, sleep, toHex, toPubkeyHex, toRootHex} from "@lodestar/utils";
|
|
46
|
+
import {Logger, fromHex, sleep, toHex, toPubkeyHex, toRootHex} from "@lodestar/utils";
|
|
47
47
|
import {ZERO_HASH_HEX} from "../../constants/index.js";
|
|
48
48
|
import {numToQuantity} from "../../execution/engine/utils.js";
|
|
49
49
|
import {
|
|
@@ -86,7 +86,7 @@ export type BlockAttributes = {
|
|
|
86
86
|
randaoReveal: BLSSignature;
|
|
87
87
|
graffiti: Bytes32;
|
|
88
88
|
slot: Slot;
|
|
89
|
-
|
|
89
|
+
parentBlock: ProtoBlock;
|
|
90
90
|
feeRecipient?: string;
|
|
91
91
|
};
|
|
92
92
|
|
|
@@ -155,13 +155,14 @@ export async function produceBlockBody<T extends BlockType>(
|
|
|
155
155
|
const {
|
|
156
156
|
slot: blockSlot,
|
|
157
157
|
feeRecipient: requestedFeeRecipient,
|
|
158
|
-
|
|
158
|
+
parentBlock,
|
|
159
159
|
proposerIndex,
|
|
160
160
|
proposerPubKey,
|
|
161
161
|
commonBlockBodyPromise,
|
|
162
162
|
} = blockAttr;
|
|
163
163
|
let executionPayloadValue: Wei;
|
|
164
164
|
let blockBody: AssembledBodyType<T>;
|
|
165
|
+
const parentBlockRoot = fromHex(parentBlock.blockRoot);
|
|
165
166
|
// even though shouldOverrideBuilder is relevant for the engine response, for simplicity of typing
|
|
166
167
|
// we just return it undefined for the builder which anyway doesn't get consumed downstream
|
|
167
168
|
let shouldOverrideBuilder: boolean | undefined;
|
|
@@ -637,7 +638,7 @@ export async function produceCommonBlockBody<T extends BlockType>(
|
|
|
637
638
|
this: BeaconChain,
|
|
638
639
|
blockType: T,
|
|
639
640
|
currentState: CachedBeaconStateAllForks,
|
|
640
|
-
{randaoReveal, graffiti, slot,
|
|
641
|
+
{randaoReveal, graffiti, slot, parentBlock}: BlockAttributes
|
|
641
642
|
): Promise<CommonBlockBody> {
|
|
642
643
|
const stepsMetrics =
|
|
643
644
|
blockType === BlockType.Full
|
|
@@ -691,6 +692,7 @@ export async function produceCommonBlockBody<T extends BlockType>(
|
|
|
691
692
|
|
|
692
693
|
const endSyncAggregate = stepsMetrics?.startTimer();
|
|
693
694
|
if (ForkSeq[fork] >= ForkSeq.altair) {
|
|
695
|
+
const parentBlockRoot = fromHex(parentBlock.blockRoot);
|
|
694
696
|
const previousSlot = slot - 1;
|
|
695
697
|
const syncAggregate = this.syncContributionAndProofPool.getAggregate(previousSlot, parentBlockRoot);
|
|
696
698
|
this.metrics?.production.producedSyncAggregateParticipants.observe(
|
|
@@ -26,7 +26,6 @@ export enum RegenFnName {
|
|
|
26
26
|
getBlockSlotState = "getBlockSlotState",
|
|
27
27
|
getState = "getState",
|
|
28
28
|
getPreState = "getPreState",
|
|
29
|
-
getCheckpointState = "getCheckpointState",
|
|
30
29
|
}
|
|
31
30
|
|
|
32
31
|
export type StateRegenerationOpts = {
|
|
@@ -63,21 +62,11 @@ export interface IStateRegeneratorInternal {
|
|
|
63
62
|
rCaller: RegenCaller
|
|
64
63
|
): Promise<CachedBeaconStateAllForks>;
|
|
65
64
|
|
|
66
|
-
/**
|
|
67
|
-
* Return a valid checkpoint state
|
|
68
|
-
* This will always return a state with `state.slot % SLOTS_PER_EPOCH === 0`
|
|
69
|
-
*/
|
|
70
|
-
getCheckpointState(
|
|
71
|
-
cp: phase0.Checkpoint,
|
|
72
|
-
opts: StateRegenerationOpts,
|
|
73
|
-
rCaller: RegenCaller
|
|
74
|
-
): Promise<CachedBeaconStateAllForks>;
|
|
75
|
-
|
|
76
65
|
/**
|
|
77
66
|
* Return the state of `blockRoot` processed to slot `slot`
|
|
78
67
|
*/
|
|
79
68
|
getBlockSlotState(
|
|
80
|
-
|
|
69
|
+
block: ProtoBlock,
|
|
81
70
|
slot: Slot,
|
|
82
71
|
opts: StateRegenerationOpts,
|
|
83
72
|
rCaller: RegenCaller
|
|
@@ -5,7 +5,7 @@ import {BeaconBlock, Epoch, RootHex, Slot, phase0} from "@lodestar/types";
|
|
|
5
5
|
import {Logger, toRootHex} from "@lodestar/utils";
|
|
6
6
|
import {Metrics} from "../../metrics/index.js";
|
|
7
7
|
import {JobItemQueue} from "../../util/queue/index.js";
|
|
8
|
-
import {CheckpointHex
|
|
8
|
+
import {CheckpointHex} from "../stateCache/index.js";
|
|
9
9
|
import {BlockStateCache, CheckpointStateCache} from "../stateCache/types.js";
|
|
10
10
|
import {RegenError, RegenErrorCode} from "./errors.js";
|
|
11
11
|
import {
|
|
@@ -220,24 +220,6 @@ export class QueuedStateRegenerator implements IStateRegenerator {
|
|
|
220
220
|
return this.jobQueue.push({key: "getPreState", args: [block, opts, rCaller]});
|
|
221
221
|
}
|
|
222
222
|
|
|
223
|
-
async getCheckpointState(
|
|
224
|
-
cp: phase0.Checkpoint,
|
|
225
|
-
opts: StateRegenerationOpts,
|
|
226
|
-
rCaller: RegenCaller
|
|
227
|
-
): Promise<CachedBeaconStateAllForks> {
|
|
228
|
-
this.metrics?.regenFnCallTotal.inc({caller: rCaller, entrypoint: RegenFnName.getCheckpointState});
|
|
229
|
-
|
|
230
|
-
// First attempt to fetch the state from cache before queueing
|
|
231
|
-
const checkpointState = this.checkpointStateCache.get(toCheckpointHex(cp));
|
|
232
|
-
if (checkpointState) {
|
|
233
|
-
return checkpointState;
|
|
234
|
-
}
|
|
235
|
-
|
|
236
|
-
// The state is not immediately available in the caches, enqueue the job
|
|
237
|
-
this.metrics?.regenFnQueuedTotal.inc({caller: rCaller, entrypoint: RegenFnName.getCheckpointState});
|
|
238
|
-
return this.jobQueue.push({key: "getCheckpointState", args: [cp, opts, rCaller]});
|
|
239
|
-
}
|
|
240
|
-
|
|
241
223
|
/**
|
|
242
224
|
* Get state of provided `blockRoot` and dial forward to `slot`
|
|
243
225
|
* Use this api with care because we don't want the queue to be busy
|
|
@@ -245,7 +227,7 @@ export class QueuedStateRegenerator implements IStateRegenerator {
|
|
|
245
227
|
* @returns
|
|
246
228
|
*/
|
|
247
229
|
async getBlockSlotState(
|
|
248
|
-
|
|
230
|
+
block: ProtoBlock,
|
|
249
231
|
slot: Slot,
|
|
250
232
|
opts: StateRegenerationOpts,
|
|
251
233
|
rCaller: RegenCaller
|
|
@@ -253,7 +235,7 @@ export class QueuedStateRegenerator implements IStateRegenerator {
|
|
|
253
235
|
this.metrics?.regenFnCallTotal.inc({caller: rCaller, entrypoint: RegenFnName.getBlockSlotState});
|
|
254
236
|
|
|
255
237
|
// The state is not immediately available in the caches, enqueue the job
|
|
256
|
-
return this.jobQueue.push({key: "getBlockSlotState", args: [
|
|
238
|
+
return this.jobQueue.push({key: "getBlockSlotState", args: [block, slot, opts, rCaller]});
|
|
257
239
|
}
|
|
258
240
|
|
|
259
241
|
async getState(stateRoot: RootHex, rCaller: RegenCaller): Promise<CachedBeaconStateAllForks> {
|
|
@@ -281,8 +263,6 @@ export class QueuedStateRegenerator implements IStateRegenerator {
|
|
|
281
263
|
switch (regenRequest.key) {
|
|
282
264
|
case "getPreState":
|
|
283
265
|
return await this.regen.getPreState(...regenRequest.args);
|
|
284
|
-
case "getCheckpointState":
|
|
285
|
-
return await this.regen.getCheckpointState(...regenRequest.args);
|
|
286
266
|
case "getBlockSlotState":
|
|
287
267
|
return await this.regen.getBlockSlotState(...regenRequest.args);
|
|
288
268
|
case "getState":
|
package/src/chain/regen/regen.ts
CHANGED
|
@@ -11,7 +11,7 @@ import {
|
|
|
11
11
|
processSlots,
|
|
12
12
|
stateTransition,
|
|
13
13
|
} from "@lodestar/state-transition";
|
|
14
|
-
import {BeaconBlock, RootHex, SignedBeaconBlock, Slot
|
|
14
|
+
import {BeaconBlock, RootHex, SignedBeaconBlock, Slot} from "@lodestar/types";
|
|
15
15
|
import {Logger, fromHex, toRootHex} from "@lodestar/utils";
|
|
16
16
|
import {IBeaconDb} from "../../db/index.js";
|
|
17
17
|
import {Metrics} from "../../metrics/index.js";
|
|
@@ -74,45 +74,24 @@ export class StateRegenerator implements IStateRegeneratorInternal {
|
|
|
74
74
|
// We may have the checkpoint state with parent root inside the checkpoint state cache
|
|
75
75
|
// through gossip validation.
|
|
76
76
|
if (parentEpoch < blockEpoch) {
|
|
77
|
-
return this.
|
|
77
|
+
return this.getBlockSlotState(parentBlock, block.slot, opts, regenCaller, allowDiskReload);
|
|
78
78
|
}
|
|
79
79
|
|
|
80
80
|
// Otherwise, get the state normally.
|
|
81
81
|
return this.getState(parentBlock.stateRoot, regenCaller, allowDiskReload);
|
|
82
82
|
}
|
|
83
83
|
|
|
84
|
-
/**
|
|
85
|
-
* Get state after block `cp.root` dialed forward to first slot of `cp.epoch`
|
|
86
|
-
*/
|
|
87
|
-
async getCheckpointState(
|
|
88
|
-
cp: phase0.Checkpoint,
|
|
89
|
-
opts: StateRegenerationOpts,
|
|
90
|
-
regenCaller: RegenCaller,
|
|
91
|
-
allowDiskReload = false
|
|
92
|
-
): Promise<CachedBeaconStateAllForks> {
|
|
93
|
-
const checkpointStartSlot = computeStartSlotAtEpoch(cp.epoch);
|
|
94
|
-
return this.getBlockSlotState(toRootHex(cp.root), checkpointStartSlot, opts, regenCaller, allowDiskReload);
|
|
95
|
-
}
|
|
96
|
-
|
|
97
84
|
/**
|
|
98
85
|
* Get state after block `blockRoot` dialed forward to `slot`
|
|
99
86
|
* - allowDiskReload should be used with care, as it will cause the state to be reloaded from disk
|
|
100
87
|
*/
|
|
101
88
|
async getBlockSlotState(
|
|
102
|
-
|
|
89
|
+
block: ProtoBlock,
|
|
103
90
|
slot: Slot,
|
|
104
91
|
opts: StateRegenerationOpts,
|
|
105
92
|
regenCaller: RegenCaller,
|
|
106
93
|
allowDiskReload = false
|
|
107
94
|
): Promise<CachedBeaconStateAllForks> {
|
|
108
|
-
const block = this.modules.forkChoice.getBlockHex(blockRoot);
|
|
109
|
-
if (!block) {
|
|
110
|
-
throw new RegenError({
|
|
111
|
-
code: RegenErrorCode.BLOCK_NOT_IN_FORKCHOICE,
|
|
112
|
-
blockRoot,
|
|
113
|
-
});
|
|
114
|
-
}
|
|
115
|
-
|
|
116
95
|
if (slot < block.slot) {
|
|
117
96
|
throw new RegenError({
|
|
118
97
|
code: RegenErrorCode.SLOT_BEFORE_BLOCK_SLOT,
|
|
@@ -121,6 +100,7 @@ export class StateRegenerator implements IStateRegeneratorInternal {
|
|
|
121
100
|
});
|
|
122
101
|
}
|
|
123
102
|
|
|
103
|
+
const {blockRoot} = block;
|
|
124
104
|
const {checkpointStateCache} = this.modules;
|
|
125
105
|
const epoch = computeEpochAtSlot(slot);
|
|
126
106
|
const latestCheckpointStateCtx = allowDiskReload
|
|
@@ -124,7 +124,7 @@ export async function validateGossipBlobSidecar(
|
|
|
124
124
|
// [IGNORE] The block's parent (defined by block.parent_root) has been seen (via both gossip and non-gossip sources) (a client MAY queue blocks for processing once the parent block is retrieved).
|
|
125
125
|
// [REJECT] The block's parent (defined by block.parent_root) passes validation.
|
|
126
126
|
const blockState = await chain.regen
|
|
127
|
-
.getBlockSlotState(
|
|
127
|
+
.getBlockSlotState(parentBlock, blobSlot, {dontTransferCache: true}, RegenCaller.validateGossipBlock)
|
|
128
128
|
.catch(() => {
|
|
129
129
|
throw new BlobSidecarGossipError(GossipAction.IGNORE, {
|
|
130
130
|
code: BlobSidecarErrorCode.PARENT_UNKNOWN,
|
|
@@ -106,7 +106,7 @@ export async function validateGossipDataColumnSidecar(
|
|
|
106
106
|
// this is something we should change this in the future to make the code airtight to the spec.
|
|
107
107
|
// 7) [REJECT] The sidecar's block's parent passes validation.
|
|
108
108
|
const blockState = await chain.regen
|
|
109
|
-
.getBlockSlotState(
|
|
109
|
+
.getBlockSlotState(parentBlock, blockHeader.slot, {dontTransferCache: true}, RegenCaller.validateGossipDataColumn)
|
|
110
110
|
.catch(() => {
|
|
111
111
|
throw new DataColumnSidecarGossipError(GossipAction.IGNORE, {
|
|
112
112
|
code: DataColumnSidecarErrorCode.PARENT_UNKNOWN,
|
|
@@ -24,7 +24,7 @@ import {
|
|
|
24
24
|
altair,
|
|
25
25
|
deneb,
|
|
26
26
|
} from "@lodestar/types";
|
|
27
|
-
import {LogData, LogHandler, LogLevel, Logger, MapDef, MapDefMax, toRootHex} from "@lodestar/utils";
|
|
27
|
+
import {LogData, LogHandler, LogLevel, Logger, MapDef, MapDefMax, prettyPrintIndices, toRootHex} from "@lodestar/utils";
|
|
28
28
|
import {GENESIS_SLOT} from "../constants/constants.js";
|
|
29
29
|
import {RegistryMetricCreator} from "../metrics/index.js";
|
|
30
30
|
|
|
@@ -39,7 +39,8 @@ const MAX_CACHED_DISTINCT_TARGETS = 4;
|
|
|
39
39
|
const LATE_ATTESTATION_SUBMISSION_BPS = 5000;
|
|
40
40
|
const LATE_BLOCK_SUBMISSION_BPS = 2500;
|
|
41
41
|
|
|
42
|
-
|
|
42
|
+
/** Number of epochs to retain registered validators after their last registration */
|
|
43
|
+
const RETAIN_REGISTERED_VALIDATORS_EPOCHS = 2;
|
|
43
44
|
|
|
44
45
|
type Seconds = number;
|
|
45
46
|
export enum OpSource {
|
|
@@ -97,6 +98,8 @@ export type ValidatorMonitor = {
|
|
|
97
98
|
): void;
|
|
98
99
|
onceEveryEndOfEpoch(state: CachedBeaconStateAllForks): void;
|
|
99
100
|
scrapeMetrics(slotClock: Slot): void;
|
|
101
|
+
/** Returns the list of validator indices currently being monitored */
|
|
102
|
+
getMonitoredValidatorIndices(): ValidatorIndex[];
|
|
100
103
|
};
|
|
101
104
|
|
|
102
105
|
export type ValidatorMonitorOpts = {
|
|
@@ -284,6 +287,9 @@ export function createValidatorMonitor(
|
|
|
284
287
|
logger[logLevel](message, context);
|
|
285
288
|
};
|
|
286
289
|
|
|
290
|
+
// Calculate retain time dynamically based on slot duration (2 epochs)
|
|
291
|
+
const retainRegisteredValidatorsMs = SLOTS_PER_EPOCH * config.SLOT_DURATION_MS * RETAIN_REGISTERED_VALIDATORS_EPOCHS;
|
|
292
|
+
|
|
287
293
|
/** The validators that require additional monitoring. */
|
|
288
294
|
const validators = new MapDef<ValidatorIndex, MonitoredValidator>(() => ({
|
|
289
295
|
summaries: new Map<Epoch, EpochSummary>(),
|
|
@@ -306,11 +312,19 @@ export function createValidatorMonitor(
|
|
|
306
312
|
|
|
307
313
|
let lastRegisteredStatusEpoch = -1;
|
|
308
314
|
|
|
315
|
+
// Track validator additions/removals per epoch for logging
|
|
316
|
+
const addedValidatorsInEpoch: Set<ValidatorIndex> = new Set();
|
|
317
|
+
const removedValidatorsInEpoch: Set<ValidatorIndex> = new Set();
|
|
318
|
+
|
|
309
319
|
const validatorMonitorMetrics = metricsRegister ? createValidatorMonitorMetrics(metricsRegister) : null;
|
|
310
320
|
|
|
311
321
|
const validatorMonitor: ValidatorMonitor = {
|
|
312
322
|
registerLocalValidator(index) {
|
|
323
|
+
const isNewValidator = !validators.has(index);
|
|
313
324
|
validators.getOrDefault(index).lastRegisteredTimeMs = Date.now();
|
|
325
|
+
if (isNewValidator) {
|
|
326
|
+
addedValidatorsInEpoch.add(index);
|
|
327
|
+
}
|
|
314
328
|
},
|
|
315
329
|
|
|
316
330
|
registerLocalValidatorInSyncCommittee(index, untilEpoch) {
|
|
@@ -673,11 +687,29 @@ export function createValidatorMonitor(
|
|
|
673
687
|
|
|
674
688
|
// Prune validators not seen in a while
|
|
675
689
|
for (const [index, validator] of validators.entries()) {
|
|
676
|
-
if (Date.now() - validator.lastRegisteredTimeMs >
|
|
690
|
+
if (Date.now() - validator.lastRegisteredTimeMs > retainRegisteredValidatorsMs) {
|
|
677
691
|
validators.delete(index);
|
|
692
|
+
removedValidatorsInEpoch.add(index);
|
|
678
693
|
}
|
|
679
694
|
}
|
|
680
695
|
|
|
696
|
+
// Log validator monitor status every epoch
|
|
697
|
+
const allIndices = Array.from(validators.keys()).sort((a, b) => a - b);
|
|
698
|
+
const addedIndices = Array.from(addedValidatorsInEpoch).sort((a, b) => a - b);
|
|
699
|
+
const removedIndices = Array.from(removedValidatorsInEpoch).sort((a, b) => a - b);
|
|
700
|
+
|
|
701
|
+
log("Validator monitor status", {
|
|
702
|
+
epoch: computeEpochAtSlot(headState.slot),
|
|
703
|
+
added: addedIndices.length > 0 ? prettyPrintIndices(addedIndices) : "none",
|
|
704
|
+
removed: removedIndices.length > 0 ? prettyPrintIndices(removedIndices) : "none",
|
|
705
|
+
total: validators.size,
|
|
706
|
+
indices: prettyPrintIndices(allIndices),
|
|
707
|
+
});
|
|
708
|
+
|
|
709
|
+
// Clear tracking sets for next epoch
|
|
710
|
+
addedValidatorsInEpoch.clear();
|
|
711
|
+
removedValidatorsInEpoch.clear();
|
|
712
|
+
|
|
681
713
|
// Compute summaries of previous epoch attestation performance
|
|
682
714
|
const prevEpoch = computeEpochAtSlot(headState.slot) - 1;
|
|
683
715
|
|
|
@@ -736,6 +768,13 @@ export function createValidatorMonitor(
|
|
|
736
768
|
scrapeMetrics(slotClock) {
|
|
737
769
|
validatorMonitorMetrics?.validatorsConnected.set(validators.size);
|
|
738
770
|
|
|
771
|
+
// Update static metric with connected validator indices
|
|
772
|
+
if (validatorMonitorMetrics?.validatorsConnectedIndices) {
|
|
773
|
+
validatorMonitorMetrics.validatorsConnectedIndices.reset();
|
|
774
|
+
const allIndices = Array.from(validators.keys()).sort((a, b) => a - b);
|
|
775
|
+
validatorMonitorMetrics.validatorsConnectedIndices.set({indices: prettyPrintIndices(allIndices)}, 1);
|
|
776
|
+
}
|
|
777
|
+
|
|
739
778
|
const epoch = computeEpochAtSlot(slotClock);
|
|
740
779
|
const slotInEpoch = slotClock % SLOTS_PER_EPOCH;
|
|
741
780
|
|
|
@@ -815,6 +854,10 @@ export function createValidatorMonitor(
|
|
|
815
854
|
validatorMonitorMetrics?.prevEpochSyncCommitteeHits.set(prevEpochSyncCommitteeHits);
|
|
816
855
|
validatorMonitorMetrics?.prevEpochSyncCommitteeMisses.set(prevEpochSyncCommitteeMisses);
|
|
817
856
|
},
|
|
857
|
+
|
|
858
|
+
getMonitoredValidatorIndices() {
|
|
859
|
+
return Array.from(validators.keys()).sort((a, b) => a - b);
|
|
860
|
+
},
|
|
818
861
|
};
|
|
819
862
|
|
|
820
863
|
// Register a single collect() function to run all validatorMonitor metrics
|
|
@@ -1098,6 +1141,12 @@ function createValidatorMonitorMetrics(register: RegistryMetricCreator) {
|
|
|
1098
1141
|
help: "Count of validators that are specifically monitored by this beacon node",
|
|
1099
1142
|
}),
|
|
1100
1143
|
|
|
1144
|
+
validatorsConnectedIndices: register.gauge<{indices: string}>({
|
|
1145
|
+
name: "validator_monitor_indices",
|
|
1146
|
+
help: "Static metric with connected validator indices as label, value is always 1",
|
|
1147
|
+
labelNames: ["indices"],
|
|
1148
|
+
}),
|
|
1149
|
+
|
|
1101
1150
|
validatorsInSyncCommittee: register.gauge({
|
|
1102
1151
|
name: "validator_monitor_validators_in_sync_committee",
|
|
1103
1152
|
help: "Count of validators monitored by this beacon node that are part of sync committee",
|
|
@@ -212,6 +212,31 @@ export function createLodestarMetrics(
|
|
|
212
212
|
}),
|
|
213
213
|
},
|
|
214
214
|
|
|
215
|
+
unfinalizedBlockWritesQueue: {
|
|
216
|
+
length: register.gauge({
|
|
217
|
+
name: "lodestar_unfinalized_block_writes_queue_length",
|
|
218
|
+
help: "Count of total unfinalized block writes queue length",
|
|
219
|
+
}),
|
|
220
|
+
droppedJobs: register.gauge({
|
|
221
|
+
name: "lodestar_unfinalized_block_writes_queue_dropped_jobs_total",
|
|
222
|
+
help: "Count of total unfinalized block writes queue dropped jobs",
|
|
223
|
+
}),
|
|
224
|
+
jobTime: register.histogram({
|
|
225
|
+
name: "lodestar_unfinalized_block_writes_queue_job_time_seconds",
|
|
226
|
+
help: "Time to process unfinalized block writes queue job in seconds",
|
|
227
|
+
buckets: [0.01, 0.1, 1, 4, 12],
|
|
228
|
+
}),
|
|
229
|
+
jobWaitTime: register.histogram({
|
|
230
|
+
name: "lodestar_unfinalized_block_writes_queue_job_wait_time_seconds",
|
|
231
|
+
help: "Time from job added to the unfinalized block writes queue to starting in seconds",
|
|
232
|
+
buckets: [0.01, 0.1, 1, 4, 12],
|
|
233
|
+
}),
|
|
234
|
+
concurrency: register.gauge({
|
|
235
|
+
name: "lodestar_unfinalized_block_writes_queue_concurrency",
|
|
236
|
+
help: "Current concurrency of unfinalized block writes queue",
|
|
237
|
+
}),
|
|
238
|
+
},
|
|
239
|
+
|
|
215
240
|
engineHttpProcessorQueue: {
|
|
216
241
|
length: register.gauge({
|
|
217
242
|
name: "lodestar_engine_http_processor_queue_length",
|
|
@@ -436,14 +436,11 @@ function getSequentialHandlers(modules: ValidatorFnsModules, options: GossipHand
|
|
|
436
436
|
blsVerifyOnMainThread: true,
|
|
437
437
|
// to track block process steps
|
|
438
438
|
seenTimestampSec,
|
|
439
|
-
// gossip block is validated, we want to process it asap
|
|
440
|
-
eagerPersistBlock: true,
|
|
441
439
|
})
|
|
442
440
|
.then(() => {
|
|
443
441
|
// Returns the delay between the start of `block.slot` and `current time`
|
|
444
442
|
const delaySec = chain.clock.secFromSlot(slot);
|
|
445
443
|
metrics?.gossipBlock.elapsedTimeTillProcessed.observe(delaySec);
|
|
446
|
-
chain.seenBlockInputCache.prune(blockInput.blockRootHex);
|
|
447
444
|
})
|
|
448
445
|
.catch((e) => {
|
|
449
446
|
// Adjust verbosity based on error type
|
|
@@ -4,7 +4,6 @@ import {GENESIS_SLOT, isForkPostDeneb, isForkPostFulu} from "@lodestar/params";
|
|
|
4
4
|
import {RespStatus, ResponseError, ResponseOutgoing} from "@lodestar/reqresp";
|
|
5
5
|
import {computeEpochAtSlot} from "@lodestar/state-transition";
|
|
6
6
|
import {deneb, phase0} from "@lodestar/types";
|
|
7
|
-
import {fromHex} from "@lodestar/utils";
|
|
8
7
|
import {IBeaconChain} from "../../../chain/index.js";
|
|
9
8
|
import {IBeaconDb} from "../../../db/index.js";
|
|
10
9
|
import {prettyPrintPeerId} from "../../util.ts";
|
|
@@ -22,7 +21,6 @@ export async function* onBeaconBlocksByRange(
|
|
|
22
21
|
const endSlot = startSlot + count;
|
|
23
22
|
|
|
24
23
|
const finalized = db.blockArchive;
|
|
25
|
-
const unfinalized = db.block;
|
|
26
24
|
// in the case of initializing from a non-finalized state, we don't have the finalized block so this api does not work
|
|
27
25
|
// chain.forkChoice.getFinalizeBlock().slot
|
|
28
26
|
const finalizedSlot = chain.forkChoice.getFinalizedCheckpointSlot();
|
|
@@ -65,7 +63,7 @@ export async function* onBeaconBlocksByRange(
|
|
|
65
63
|
// re-org there's no need to abort the request
|
|
66
64
|
// Spec: https://github.com/ethereum/consensus-specs/blob/a1e46d1ae47dd9d097725801575b46907c12a1f8/specs/eip4844/p2p-interface.md#blobssidecarsbyrange-v1
|
|
67
65
|
|
|
68
|
-
const blockBytes = await
|
|
66
|
+
const blockBytes = await chain.getSerializedBlockByRoot(block.blockRoot);
|
|
69
67
|
if (!blockBytes) {
|
|
70
68
|
throw new ResponseError(
|
|
71
69
|
RespStatus.SERVER_ERROR,
|
|
@@ -74,7 +72,7 @@ export async function* onBeaconBlocksByRange(
|
|
|
74
72
|
}
|
|
75
73
|
|
|
76
74
|
yield {
|
|
77
|
-
data: blockBytes,
|
|
75
|
+
data: blockBytes.block,
|
|
78
76
|
boundary: chain.config.getForkBoundaryAtEpoch(computeEpochAtSlot(block.slot)),
|
|
79
77
|
};
|
|
80
78
|
}
|
|
@@ -1,48 +1,21 @@
|
|
|
1
1
|
import {ResponseOutgoing} from "@lodestar/reqresp";
|
|
2
2
|
import {computeEpochAtSlot} from "@lodestar/state-transition";
|
|
3
|
-
import {Slot} from "@lodestar/types";
|
|
4
3
|
import {toRootHex} from "@lodestar/utils";
|
|
5
4
|
import {IBeaconChain} from "../../../chain/index.js";
|
|
6
|
-
import {IBeaconDb} from "../../../db/index.js";
|
|
7
|
-
import {getSlotFromSignedBeaconBlockSerialized} from "../../../util/sszBytes.js";
|
|
8
5
|
import {BeaconBlocksByRootRequest} from "../../../util/types.js";
|
|
9
6
|
|
|
10
7
|
export async function* onBeaconBlocksByRoot(
|
|
11
8
|
requestBody: BeaconBlocksByRootRequest,
|
|
12
|
-
chain: IBeaconChain
|
|
13
|
-
db: IBeaconDb
|
|
9
|
+
chain: IBeaconChain
|
|
14
10
|
): AsyncIterable<ResponseOutgoing> {
|
|
15
11
|
for (const blockRoot of requestBody) {
|
|
16
12
|
const root = blockRoot;
|
|
17
|
-
const
|
|
18
|
-
let blockBytes: Uint8Array | null = null;
|
|
19
|
-
|
|
20
|
-
// finalized block has summary in forkchoice but it stays in blockArchive db
|
|
21
|
-
if (summary) {
|
|
22
|
-
blockBytes = await db.block.getBinary(root);
|
|
23
|
-
}
|
|
24
|
-
|
|
25
|
-
let slot: Slot | undefined = undefined;
|
|
26
|
-
if (!blockBytes) {
|
|
27
|
-
const blockEntry = await db.blockArchive.getBinaryEntryByRoot(root);
|
|
28
|
-
if (blockEntry) {
|
|
29
|
-
slot = blockEntry.key;
|
|
30
|
-
blockBytes = blockEntry.value;
|
|
31
|
-
}
|
|
32
|
-
}
|
|
33
|
-
|
|
34
|
-
if (blockBytes) {
|
|
35
|
-
if (slot === undefined) {
|
|
36
|
-
const slotFromBytes = getSlotFromSignedBeaconBlockSerialized(blockBytes);
|
|
37
|
-
if (slotFromBytes === null) {
|
|
38
|
-
throw Error(`Invalid block bytes for block root ${toRootHex(root)}`);
|
|
39
|
-
}
|
|
40
|
-
slot = slotFromBytes;
|
|
41
|
-
}
|
|
13
|
+
const block = await chain.getSerializedBlockByRoot(toRootHex(root));
|
|
42
14
|
|
|
15
|
+
if (block) {
|
|
43
16
|
yield {
|
|
44
|
-
data:
|
|
45
|
-
boundary: chain.config.getForkBoundaryAtEpoch(computeEpochAtSlot(slot)),
|
|
17
|
+
data: block.block,
|
|
18
|
+
boundary: chain.config.getForkBoundaryAtEpoch(computeEpochAtSlot(block.slot)),
|
|
46
19
|
};
|
|
47
20
|
}
|
|
48
21
|
}
|
|
@@ -2,16 +2,13 @@ import {BLOB_SIDECAR_FIXED_SIZE} from "@lodestar/params";
|
|
|
2
2
|
import {RespStatus, ResponseError, ResponseOutgoing} from "@lodestar/reqresp";
|
|
3
3
|
import {computeEpochAtSlot} from "@lodestar/state-transition";
|
|
4
4
|
import {RootHex} from "@lodestar/types";
|
|
5
|
-
import {
|
|
5
|
+
import {toRootHex} from "@lodestar/utils";
|
|
6
6
|
import {IBeaconChain} from "../../../chain/index.js";
|
|
7
|
-
import {IBeaconDb} from "../../../db/index.js";
|
|
8
|
-
import {BLOB_SIDECARS_IN_WRAPPER_INDEX} from "../../../db/repositories/blobSidecars.js";
|
|
9
7
|
import {BlobSidecarsByRootRequest} from "../../../util/types.js";
|
|
10
8
|
|
|
11
9
|
export async function* onBlobSidecarsByRoot(
|
|
12
10
|
requestBody: BlobSidecarsByRootRequest,
|
|
13
|
-
chain: IBeaconChain
|
|
14
|
-
db: IBeaconDb
|
|
11
|
+
chain: IBeaconChain
|
|
15
12
|
): AsyncIterable<ResponseOutgoing> {
|
|
16
13
|
const finalizedSlot = chain.forkChoice.getFinalizedBlock().slot;
|
|
17
14
|
|
|
@@ -34,14 +31,13 @@ export async function* onBlobSidecarsByRoot(
|
|
|
34
31
|
|
|
35
32
|
// Check if we need to load sidecars for a new block root
|
|
36
33
|
if (lastFetchedSideCars === null || lastFetchedSideCars.blockRoot !== blockRootHex) {
|
|
37
|
-
const
|
|
38
|
-
if (!
|
|
34
|
+
const blobSidecarsBytes = await chain.getSerializedBlobSidecars(block.slot, blockRootHex);
|
|
35
|
+
if (!blobSidecarsBytes) {
|
|
39
36
|
// Handle the same to onBeaconBlocksByRange
|
|
40
37
|
throw new ResponseError(RespStatus.SERVER_ERROR, `No item for root ${block.blockRoot} slot ${block.slot}`);
|
|
41
38
|
}
|
|
42
|
-
const blobSideCarsBytes = blobSideCarsBytesWrapped.slice(BLOB_SIDECARS_IN_WRAPPER_INDEX);
|
|
43
39
|
|
|
44
|
-
lastFetchedSideCars = {blockRoot: blockRootHex, bytes:
|
|
40
|
+
lastFetchedSideCars = {blockRoot: blockRootHex, bytes: blobSidecarsBytes};
|
|
45
41
|
}
|
|
46
42
|
|
|
47
43
|
const blobSidecarBytes = lastFetchedSideCars.bytes.slice(
|
|
@@ -38,7 +38,6 @@ export async function* onDataColumnSidecarsByRange(
|
|
|
38
38
|
}
|
|
39
39
|
|
|
40
40
|
const finalized = db.dataColumnSidecarArchive;
|
|
41
|
-
const unfinalized = db.dataColumnSidecar;
|
|
42
41
|
const finalizedSlot = chain.forkChoice.getFinalizedBlock().slot;
|
|
43
42
|
|
|
44
43
|
// Finalized range of columns
|
|
@@ -92,7 +91,11 @@ export async function* onDataColumnSidecarsByRange(
|
|
|
92
91
|
// at the time of the start of the request. Spec is clear the chain of columns must be consistent, but on
|
|
93
92
|
// re-org there's no need to abort the request
|
|
94
93
|
// Spec: https://github.com/ethereum/consensus-specs/blob/ad36024441cf910d428d03f87f331fbbd2b3e5f1/specs/fulu/p2p-interface.md#L425-L429
|
|
95
|
-
const dataColumnSidecars = await
|
|
94
|
+
const dataColumnSidecars = await chain.getSerializedDataColumnSidecars(
|
|
95
|
+
block.slot,
|
|
96
|
+
block.blockRoot,
|
|
97
|
+
availableColumns
|
|
98
|
+
);
|
|
96
99
|
|
|
97
100
|
const unavailableColumnIndices: ColumnIndex[] = [];
|
|
98
101
|
for (let i = 0; i < dataColumnSidecars.length; i++) {
|
|
@@ -61,11 +61,7 @@ export async function* onDataColumnSidecarsByRoot(
|
|
|
61
61
|
continue;
|
|
62
62
|
}
|
|
63
63
|
|
|
64
|
-
const dataColumns =
|
|
65
|
-
? // Non-finalized sidecars are stored by block root
|
|
66
|
-
await db.dataColumnSidecar.getManyBinary(blockRoot, availableColumns)
|
|
67
|
-
: // Finalized sidecars are archived and stored by slot
|
|
68
|
-
await db.dataColumnSidecarArchive.getManyBinary(slot, availableColumns);
|
|
64
|
+
const dataColumns = await chain.getSerializedDataColumnSidecars(slot, blockRootHex, availableColumns);
|
|
69
65
|
|
|
70
66
|
const unavailableColumnIndices: ColumnIndex[] = [];
|
|
71
67
|
for (let i = 0; i < dataColumns.length; i++) {
|
|
@@ -42,12 +42,12 @@ export function getReqRespHandlers({db, chain}: {db: IBeaconDb; chain: IBeaconCh
|
|
|
42
42
|
[ReqRespMethod.BeaconBlocksByRoot]: (req) => {
|
|
43
43
|
const fork = chain.config.getForkName(chain.clock.currentSlot);
|
|
44
44
|
const body = BeaconBlocksByRootRequestType(fork, chain.config).deserialize(req.data);
|
|
45
|
-
return onBeaconBlocksByRoot(body, chain
|
|
45
|
+
return onBeaconBlocksByRoot(body, chain);
|
|
46
46
|
},
|
|
47
47
|
[ReqRespMethod.BlobSidecarsByRoot]: (req) => {
|
|
48
48
|
const fork = chain.config.getForkName(chain.clock.currentSlot);
|
|
49
49
|
const body = BlobSidecarsByRootRequestType(fork, chain.config).deserialize(req.data);
|
|
50
|
-
return onBlobSidecarsByRoot(body, chain
|
|
50
|
+
return onBlobSidecarsByRoot(body, chain);
|
|
51
51
|
},
|
|
52
52
|
[ReqRespMethod.BlobSidecarsByRange]: (req) => {
|
|
53
53
|
const body = ssz.deneb.BlobSidecarsByRangeRequest.deserialize(req.data);
|
package/src/sync/range/chain.ts
CHANGED
package/src/sync/range/range.ts
CHANGED
|
@@ -188,9 +188,6 @@ export class RangeSync extends (EventEmitter as {new (): RangeSyncEmitter}) {
|
|
|
188
188
|
// when this runs, syncing is the most important thing and gossip is not likely to run
|
|
189
189
|
// so we can utilize worker threads to verify signatures
|
|
190
190
|
blsVerifyOnMainThread: false,
|
|
191
|
-
// we want to be safe to only persist blocks after verifying it to avoid any attacks that may cause our DB
|
|
192
|
-
// to grow too much
|
|
193
|
-
eagerPersistBlock: false,
|
|
194
191
|
};
|
|
195
192
|
|
|
196
193
|
if (this.opts?.disableProcessAsChainSegment) {
|