@lodestar/beacon-node 1.39.0 → 1.40.0-dev.1c71f4299a
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/beacon/state/utils.d.ts +2 -7
- package/lib/api/impl/beacon/state/utils.d.ts.map +1 -1
- package/lib/api/impl/beacon/state/utils.js +0 -12
- package/lib/api/impl/beacon/state/utils.js.map +1 -1
- package/lib/api/impl/config/constants.d.ts +3 -0
- package/lib/api/impl/config/constants.d.ts.map +1 -1
- package/lib/api/impl/config/constants.js +5 -1
- package/lib/api/impl/config/constants.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 +6 -1
- package/lib/api/impl/lodestar/index.js.map +1 -1
- package/lib/api/impl/proof/index.d.ts.map +1 -1
- package/lib/api/impl/proof/index.js +1 -2
- package/lib/api/impl/proof/index.js.map +1 -1
- package/lib/api/impl/validator/index.d.ts.map +1 -1
- package/lib/api/impl/validator/index.js +1 -3
- package/lib/api/impl/validator/index.js.map +1 -1
- package/lib/chain/archiveStore/historicalState/getHistoricalState.d.ts.map +1 -1
- package/lib/chain/archiveStore/historicalState/getHistoricalState.js +5 -3
- package/lib/chain/archiveStore/historicalState/getHistoricalState.js.map +1 -1
- package/lib/chain/archiveStore/utils/archiveBlocks.d.ts.map +1 -1
- package/lib/chain/archiveStore/utils/archiveBlocks.js +23 -14
- 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 +14 -9
- 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 +8 -8
- package/lib/chain/blocks/verifyBlock.js.map +1 -1
- package/lib/chain/blocks/verifyBlocksStateTransitionOnly.d.ts.map +1 -1
- package/lib/chain/blocks/verifyBlocksStateTransitionOnly.js +1 -0
- package/lib/chain/blocks/verifyBlocksStateTransitionOnly.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 +16 -3
- package/lib/chain/chain.d.ts.map +1 -1
- package/lib/chain/chain.js +165 -7
- package/lib/chain/chain.js.map +1 -1
- package/lib/chain/initState.d.ts +1 -1
- package/lib/chain/initState.d.ts.map +1 -1
- package/lib/chain/initState.js +5 -3
- package/lib/chain/initState.js.map +1 -1
- package/lib/chain/interface.d.ts +16 -3
- package/lib/chain/interface.d.ts.map +1 -1
- package/lib/chain/interface.js.map +1 -1
- package/lib/chain/lightClient/proofs.d.ts.map +1 -1
- package/lib/chain/lightClient/proofs.js +0 -2
- package/lib/chain/lightClient/proofs.js.map +1 -1
- package/lib/chain/opPools/aggregatedAttestationPool.d.ts +5 -9
- package/lib/chain/opPools/aggregatedAttestationPool.d.ts.map +1 -1
- package/lib/chain/opPools/aggregatedAttestationPool.js +12 -141
- package/lib/chain/opPools/aggregatedAttestationPool.js.map +1 -1
- package/lib/chain/opPools/opPool.js +5 -8
- package/lib/chain/opPools/opPool.js.map +1 -1
- package/lib/chain/prepareNextSlot.d.ts.map +1 -1
- package/lib/chain/prepareNextSlot.js +4 -7
- package/lib/chain/prepareNextSlot.js.map +1 -1
- package/lib/chain/produceBlock/produceBlockBody.d.ts.map +1 -1
- package/lib/chain/produceBlock/produceBlockBody.js +1 -1
- package/lib/chain/produceBlock/produceBlockBody.js.map +1 -1
- package/lib/chain/regen/interface.d.ts +1 -5
- package/lib/chain/regen/interface.d.ts.map +1 -1
- package/lib/chain/regen/queued.d.ts +4 -7
- package/lib/chain/regen/queued.d.ts.map +1 -1
- package/lib/chain/regen/queued.js +15 -25
- package/lib/chain/regen/queued.js.map +1 -1
- package/lib/chain/regen/regen.d.ts +1 -1
- package/lib/chain/regen/regen.d.ts.map +1 -1
- package/lib/chain/regen/regen.js +13 -17
- package/lib/chain/regen/regen.js.map +1 -1
- package/lib/chain/shufflingCache.d.ts +16 -11
- package/lib/chain/shufflingCache.d.ts.map +1 -1
- package/lib/chain/shufflingCache.js +47 -41
- package/lib/chain/shufflingCache.js.map +1 -1
- package/lib/chain/stateCache/blockStateCacheImpl.d.ts +1 -2
- package/lib/chain/stateCache/blockStateCacheImpl.d.ts.map +1 -1
- package/lib/chain/stateCache/blockStateCacheImpl.js +2 -2
- package/lib/chain/stateCache/blockStateCacheImpl.js.map +1 -1
- package/lib/chain/stateCache/fifoBlockStateCache.d.ts +1 -2
- package/lib/chain/stateCache/fifoBlockStateCache.d.ts.map +1 -1
- package/lib/chain/stateCache/fifoBlockStateCache.js +4 -4
- package/lib/chain/stateCache/fifoBlockStateCache.js.map +1 -1
- package/lib/chain/stateCache/inMemoryCheckpointsCache.d.ts +4 -5
- package/lib/chain/stateCache/inMemoryCheckpointsCache.d.ts.map +1 -1
- package/lib/chain/stateCache/inMemoryCheckpointsCache.js +9 -10
- package/lib/chain/stateCache/inMemoryCheckpointsCache.js.map +1 -1
- package/lib/chain/stateCache/persistentCheckpointsCache.d.ts +5 -6
- package/lib/chain/stateCache/persistentCheckpointsCache.d.ts.map +1 -1
- package/lib/chain/stateCache/persistentCheckpointsCache.js +17 -17
- package/lib/chain/stateCache/persistentCheckpointsCache.js.map +1 -1
- package/lib/chain/stateCache/types.d.ts +5 -6
- package/lib/chain/stateCache/types.d.ts.map +1 -1
- package/lib/chain/stateCache/types.js.map +1 -1
- package/lib/chain/validation/attestation.d.ts.map +1 -1
- package/lib/chain/validation/attestation.js +2 -2
- package/lib/chain/validation/attestation.js.map +1 -1
- package/lib/chain/validation/attesterSlashing.d.ts.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.d.ts.map +1 -1
- package/lib/chain/validation/block.js +2 -0
- package/lib/chain/validation/block.js.map +1 -1
- package/lib/chain/validation/blsToExecutionChange.d.ts.map +1 -1
- package/lib/chain/validation/blsToExecutionChange.js +9 -2
- package/lib/chain/validation/blsToExecutionChange.js.map +1 -1
- package/lib/chain/validation/proposerSlashing.js +2 -1
- package/lib/chain/validation/proposerSlashing.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/db/repositories/checkpointState.d.ts +2 -6
- package/lib/db/repositories/checkpointState.d.ts.map +1 -1
- package/lib/db/repositories/checkpointState.js +3 -15
- package/lib/db/repositories/checkpointState.js.map +1 -1
- package/lib/db/repositories/stateArchive.d.ts +9 -9
- package/lib/db/repositories/stateArchive.d.ts.map +1 -1
- package/lib/db/repositories/stateArchive.js +6 -21
- package/lib/db/repositories/stateArchive.js.map +1 -1
- package/lib/execution/engine/mock.d.ts +9 -6
- package/lib/execution/engine/mock.d.ts.map +1 -1
- package/lib/execution/engine/mock.js +34 -7
- package/lib/execution/engine/mock.js.map +1 -1
- package/lib/index.d.ts +1 -1
- package/lib/index.d.ts.map +1 -1
- package/lib/index.js +1 -1
- package/lib/index.js.map +1 -1
- package/lib/metrics/metrics/lodestar.d.ts +8 -6
- package/lib/metrics/metrics/lodestar.d.ts.map +1 -1
- package/lib/metrics/metrics/lodestar.js +27 -17
- 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/network/reqresp/utils/dataColumnResponseValidation.js +1 -1
- package/lib/network/reqresp/utils/dataColumnResponseValidation.js.map +1 -1
- package/lib/node/nodejs.d.ts.map +1 -1
- package/lib/node/nodejs.js +17 -2
- package/lib/node/nodejs.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/lib/util/sszBytes.js +1 -1
- package/lib/util/sszBytes.js.map +1 -1
- package/package.json +15 -15
- package/src/api/impl/beacon/blocks/index.ts +8 -18
- package/src/api/impl/beacon/state/utils.ts +2 -22
- package/src/api/impl/config/constants.ts +8 -0
- package/src/api/impl/debug/index.ts +2 -6
- package/src/api/impl/lodestar/index.ts +7 -1
- package/src/api/impl/proof/index.ts +1 -2
- package/src/api/impl/validator/index.ts +1 -3
- package/src/chain/archiveStore/historicalState/getHistoricalState.ts +5 -3
- package/src/chain/archiveStore/utils/archiveBlocks.ts +25 -14
- package/src/chain/blocks/blockInput/blockInput.ts +8 -0
- package/src/chain/blocks/importBlock.ts +15 -9
- package/src/chain/blocks/index.ts +0 -19
- package/src/chain/blocks/types.ts +0 -2
- package/src/chain/blocks/verifyBlock.ts +9 -11
- package/src/chain/blocks/verifyBlocksStateTransitionOnly.ts +1 -0
- package/src/chain/blocks/writeBlockInputToDb.ts +24 -30
- package/src/chain/chain.ts +191 -10
- package/src/chain/initState.ts +5 -3
- package/src/chain/interface.ts +18 -2
- package/src/chain/lightClient/proofs.ts +0 -2
- package/src/chain/opPools/aggregatedAttestationPool.ts +19 -191
- package/src/chain/opPools/opPool.ts +5 -7
- package/src/chain/prepareNextSlot.ts +2 -6
- package/src/chain/produceBlock/produceBlockBody.ts +6 -1
- package/src/chain/regen/interface.ts +1 -5
- package/src/chain/regen/queued.ts +15 -34
- package/src/chain/regen/regen.ts +12 -18
- package/src/chain/shufflingCache.ts +67 -50
- package/src/chain/stateCache/blockStateCacheImpl.ts +2 -3
- package/src/chain/stateCache/fifoBlockStateCache.ts +4 -5
- package/src/chain/stateCache/inMemoryCheckpointsCache.ts +9 -15
- package/src/chain/stateCache/persistentCheckpointsCache.ts +17 -25
- package/src/chain/stateCache/types.ts +5 -10
- package/src/chain/validation/attestation.ts +3 -3
- package/src/chain/validation/attesterSlashing.ts +8 -1
- package/src/chain/validation/block.ts +3 -0
- package/src/chain/validation/blsToExecutionChange.ts +9 -7
- package/src/chain/validation/proposerSlashing.ts +2 -1
- package/src/chain/validatorMonitor.ts +52 -3
- package/src/db/repositories/checkpointState.ts +3 -19
- package/src/db/repositories/stateArchive.ts +13 -27
- package/src/execution/engine/mock.ts +40 -13
- package/src/index.ts +1 -1
- package/src/metrics/metrics/lodestar.ts +28 -17
- 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/network/reqresp/utils/dataColumnResponseValidation.ts +1 -1
- package/src/node/nodejs.ts +18 -3
- package/src/sync/range/chain.ts +0 -1
- package/src/sync/range/range.ts +0 -3
- package/src/sync/unknownBlock.ts +0 -3
- package/src/util/sszBytes.ts +1 -1
package/src/chain/chain.ts
CHANGED
|
@@ -37,14 +37,19 @@ import {
|
|
|
37
37
|
UintNum64,
|
|
38
38
|
ValidatorIndex,
|
|
39
39
|
Wei,
|
|
40
|
+
deneb,
|
|
41
|
+
fulu,
|
|
40
42
|
isBlindedBeaconBlock,
|
|
41
43
|
phase0,
|
|
42
44
|
rewards,
|
|
45
|
+
ssz,
|
|
46
|
+
sszTypesFor,
|
|
43
47
|
} from "@lodestar/types";
|
|
44
48
|
import {Logger, fromHex, gweiToWei, isErrorAborted, pruneSetToMax, sleep, toRootHex} from "@lodestar/utils";
|
|
45
49
|
import {ProcessShutdownCallback} from "@lodestar/validator";
|
|
46
50
|
import {GENESIS_EPOCH, ZERO_HASH} from "../constants/index.js";
|
|
47
51
|
import {IBeaconDb} from "../db/index.js";
|
|
52
|
+
import {BLOB_SIDECARS_IN_WRAPPER_INDEX} from "../db/repositories/blobSidecars.ts";
|
|
48
53
|
import {BuilderStatus} from "../execution/builder/http.js";
|
|
49
54
|
import {IExecutionBuilder, IExecutionEngine} from "../execution/index.js";
|
|
50
55
|
import {Metrics} from "../metrics/index.js";
|
|
@@ -52,14 +57,18 @@ import {computeNodeIdFromPrivateKey} from "../network/subnets/interface.js";
|
|
|
52
57
|
import {BufferPool} from "../util/bufferPool.js";
|
|
53
58
|
import {Clock, ClockEvent, IClock} from "../util/clock.js";
|
|
54
59
|
import {CustodyConfig, getValidatorsCustodyRequirement} from "../util/dataColumns.js";
|
|
60
|
+
import {callInNextEventLoop} from "../util/eventLoop.js";
|
|
55
61
|
import {ensureDir, writeIfNotExist} from "../util/file.js";
|
|
56
62
|
import {isOptimisticBlock} from "../util/forkChoice.js";
|
|
63
|
+
import {JobItemQueue} from "../util/queue/itemQueue.ts";
|
|
57
64
|
import {SerializedCache} from "../util/serializedCache.js";
|
|
65
|
+
import {getSlotFromSignedBeaconBlockSerialized} from "../util/sszBytes.ts";
|
|
58
66
|
import {ArchiveStore} from "./archiveStore/archiveStore.js";
|
|
59
67
|
import {CheckpointBalancesCache} from "./balancesCache.js";
|
|
60
68
|
import {BeaconProposerCache} from "./beaconProposerCache.js";
|
|
61
|
-
import {IBlockInput} from "./blocks/blockInput/index.js";
|
|
69
|
+
import {IBlockInput, isBlockInputBlobs, isBlockInputColumns} from "./blocks/blockInput/index.js";
|
|
62
70
|
import {BlockProcessor, ImportBlockOpts} from "./blocks/index.js";
|
|
71
|
+
import {persistBlockInputs} from "./blocks/writeBlockInputToDb.ts";
|
|
63
72
|
import {BlsMultiThreadWorkerPool, BlsSingleThreadVerifier, IBlsVerifier} from "./bls/index.js";
|
|
64
73
|
import {ColumnReconstructionTracker} from "./ColumnReconstructionTracker.js";
|
|
65
74
|
import {ChainEvent, ChainEventEmitter} from "./emitter.js";
|
|
@@ -112,6 +121,11 @@ import {ValidatorMonitor} from "./validatorMonitor.js";
|
|
|
112
121
|
*/
|
|
113
122
|
const DEFAULT_MAX_CACHED_PRODUCED_RESULTS = 4;
|
|
114
123
|
|
|
124
|
+
/**
|
|
125
|
+
* The maximum number of pending unfinalized block writes to the database before backpressure is applied.
|
|
126
|
+
*/
|
|
127
|
+
const DEFAULT_MAX_PENDING_UNFINALIZED_BLOCK_WRITES = 32;
|
|
128
|
+
|
|
115
129
|
export class BeaconChain implements IBeaconChain {
|
|
116
130
|
readonly genesisTime: UintNum64;
|
|
117
131
|
readonly genesisValidatorsRoot: Root;
|
|
@@ -135,6 +149,7 @@ export class BeaconChain implements IBeaconChain {
|
|
|
135
149
|
readonly lightClientServer?: LightClientServer;
|
|
136
150
|
readonly reprocessController: ReprocessController;
|
|
137
151
|
readonly archiveStore: ArchiveStore;
|
|
152
|
+
readonly unfinalizedBlockWrites: JobItemQueue<[IBlockInput[]], void>;
|
|
138
153
|
|
|
139
154
|
// Ops pool
|
|
140
155
|
readonly attestationPool: AttestationPool;
|
|
@@ -291,7 +306,8 @@ export class BeaconChain implements IBeaconChain {
|
|
|
291
306
|
});
|
|
292
307
|
|
|
293
308
|
this._earliestAvailableSlot = anchorState.slot;
|
|
294
|
-
|
|
309
|
+
|
|
310
|
+
this.shufflingCache = new ShufflingCache(metrics, logger, this.opts, [
|
|
295
311
|
{
|
|
296
312
|
shuffling: anchorState.epochCtx.previousShuffling,
|
|
297
313
|
decisionRoot: anchorState.epochCtx.previousDecisionRoot,
|
|
@@ -403,6 +419,15 @@ export class BeaconChain implements IBeaconChain {
|
|
|
403
419
|
signal
|
|
404
420
|
);
|
|
405
421
|
|
|
422
|
+
this.unfinalizedBlockWrites = new JobItemQueue(
|
|
423
|
+
persistBlockInputs.bind(this),
|
|
424
|
+
{
|
|
425
|
+
maxLength: DEFAULT_MAX_PENDING_UNFINALIZED_BLOCK_WRITES,
|
|
426
|
+
signal,
|
|
427
|
+
},
|
|
428
|
+
metrics?.unfinalizedBlockWritesQueue
|
|
429
|
+
);
|
|
430
|
+
|
|
406
431
|
// always run PrepareNextSlotScheduler except for fork_choice spec tests
|
|
407
432
|
if (!opts?.disablePrepareNextSlot) {
|
|
408
433
|
new PrepareNextSlotScheduler(this, this.config, metrics, this.logger, signal);
|
|
@@ -417,6 +442,7 @@ export class BeaconChain implements IBeaconChain {
|
|
|
417
442
|
clock.addListener(ClockEvent.epoch, this.onClockEpoch.bind(this));
|
|
418
443
|
emitter.addListener(ChainEvent.forkChoiceFinalized, this.onForkChoiceFinalized.bind(this));
|
|
419
444
|
emitter.addListener(ChainEvent.forkChoiceJustified, this.onForkChoiceJustified.bind(this));
|
|
445
|
+
emitter.addListener(ChainEvent.checkpoint, this.onCheckpoint.bind(this));
|
|
420
446
|
}
|
|
421
447
|
|
|
422
448
|
async init(): Promise<void> {
|
|
@@ -427,6 +453,12 @@ export class BeaconChain implements IBeaconChain {
|
|
|
427
453
|
async close(): Promise<void> {
|
|
428
454
|
await this.archiveStore.close();
|
|
429
455
|
await this.bls.close();
|
|
456
|
+
|
|
457
|
+
// Since we don't persist unfinalized fork-choice,
|
|
458
|
+
// we can abort any ongoing unfinalized block writes.
|
|
459
|
+
// TODO: persist fork choice to disk and allow unfinalized block writes to complete.
|
|
460
|
+
this.unfinalizedBlockWrites.dropAllJobs();
|
|
461
|
+
|
|
430
462
|
this.abortController.abort();
|
|
431
463
|
}
|
|
432
464
|
|
|
@@ -504,7 +536,7 @@ export class BeaconChain implements IBeaconChain {
|
|
|
504
536
|
async getStateBySlot(
|
|
505
537
|
slot: Slot,
|
|
506
538
|
opts?: StateGetOpts
|
|
507
|
-
): Promise<{state:
|
|
539
|
+
): Promise<{state: CachedBeaconStateAllForks; executionOptimistic: boolean; finalized: boolean} | null> {
|
|
508
540
|
const finalizedBlock = this.forkChoice.getFinalizedBlock();
|
|
509
541
|
|
|
510
542
|
if (slot < finalizedBlock.slot) {
|
|
@@ -559,7 +591,7 @@ export class BeaconChain implements IBeaconChain {
|
|
|
559
591
|
async getStateByStateRoot(
|
|
560
592
|
stateRoot: RootHex,
|
|
561
593
|
opts?: StateGetOpts
|
|
562
|
-
): Promise<{state:
|
|
594
|
+
): Promise<{state: CachedBeaconStateAllForks | Uint8Array; executionOptimistic: boolean; finalized: boolean} | null> {
|
|
563
595
|
if (opts?.allowRegen) {
|
|
564
596
|
const state = await this.regen.getState(stateRoot, RegenCaller.restApi);
|
|
565
597
|
const block = this.forkChoice.getBlock(state.latestBlockHeader.hashTreeRoot());
|
|
@@ -587,7 +619,8 @@ export class BeaconChain implements IBeaconChain {
|
|
|
587
619
|
};
|
|
588
620
|
}
|
|
589
621
|
|
|
590
|
-
|
|
622
|
+
// this is mostly useful for a node with `--chain.archiveStateEpochFrequency 1`
|
|
623
|
+
const data = await this.db.stateArchive.getBinaryByRoot(fromHex(stateRoot));
|
|
591
624
|
return data && {state: data, executionOptimistic: false, finalized: true};
|
|
592
625
|
}
|
|
593
626
|
|
|
@@ -648,6 +681,13 @@ export class BeaconChain implements IBeaconChain {
|
|
|
648
681
|
// Unfinalized slot, attempt to find in fork-choice
|
|
649
682
|
const block = this.forkChoice.getCanonicalBlockAtSlot(slot);
|
|
650
683
|
if (block) {
|
|
684
|
+
// Block found in fork-choice.
|
|
685
|
+
// It may be in the block input cache, awaiting full DA reconstruction, check there first
|
|
686
|
+
// Otherwise (most likely), check the hot db
|
|
687
|
+
const blockInput = this.seenBlockInputCache.get(block.blockRoot);
|
|
688
|
+
if (blockInput?.hasBlock()) {
|
|
689
|
+
return {block: blockInput.getBlock(), executionOptimistic: isOptimisticBlock(block), finalized: false};
|
|
690
|
+
}
|
|
651
691
|
const data = await this.db.block.get(fromHex(block.blockRoot));
|
|
652
692
|
if (data) {
|
|
653
693
|
return {block: data, executionOptimistic: isOptimisticBlock(block), finalized: false};
|
|
@@ -667,6 +707,13 @@ export class BeaconChain implements IBeaconChain {
|
|
|
667
707
|
): Promise<{block: SignedBeaconBlock; executionOptimistic: boolean; finalized: boolean} | null> {
|
|
668
708
|
const block = this.forkChoice.getBlockHex(root);
|
|
669
709
|
if (block) {
|
|
710
|
+
// Block found in fork-choice.
|
|
711
|
+
// It may be in the block input cache, awaiting full DA reconstruction, check there first
|
|
712
|
+
// Otherwise (most likely), check the hot db
|
|
713
|
+
const blockInput = this.seenBlockInputCache.get(block.blockRoot);
|
|
714
|
+
if (blockInput?.hasBlock()) {
|
|
715
|
+
return {block: blockInput.getBlock(), executionOptimistic: isOptimisticBlock(block), finalized: false};
|
|
716
|
+
}
|
|
670
717
|
const data = await this.db.block.get(fromHex(root));
|
|
671
718
|
if (data) {
|
|
672
719
|
return {block: data, executionOptimistic: isOptimisticBlock(block), finalized: false};
|
|
@@ -679,6 +726,133 @@ export class BeaconChain implements IBeaconChain {
|
|
|
679
726
|
return data && {block: data, executionOptimistic: false, finalized: true};
|
|
680
727
|
}
|
|
681
728
|
|
|
729
|
+
async getSerializedBlockByRoot(
|
|
730
|
+
root: string
|
|
731
|
+
): Promise<{block: Uint8Array; executionOptimistic: boolean; finalized: boolean; slot: Slot} | null> {
|
|
732
|
+
const block = this.forkChoice.getBlockHex(root);
|
|
733
|
+
if (block) {
|
|
734
|
+
// Block found in fork-choice.
|
|
735
|
+
// It may be in the block input cache, awaiting full DA reconstruction, check there first
|
|
736
|
+
// Otherwise (most likely), check the hot db
|
|
737
|
+
const blockInput = this.seenBlockInputCache.get(block.blockRoot);
|
|
738
|
+
if (blockInput?.hasBlock()) {
|
|
739
|
+
const signedBlock = blockInput.getBlock();
|
|
740
|
+
const serialized = this.serializedCache.get(signedBlock);
|
|
741
|
+
if (serialized) {
|
|
742
|
+
return {
|
|
743
|
+
block: serialized,
|
|
744
|
+
executionOptimistic: isOptimisticBlock(block),
|
|
745
|
+
finalized: false,
|
|
746
|
+
slot: blockInput.slot,
|
|
747
|
+
};
|
|
748
|
+
}
|
|
749
|
+
return {
|
|
750
|
+
block: sszTypesFor(blockInput.forkName).SignedBeaconBlock.serialize(signedBlock),
|
|
751
|
+
executionOptimistic: isOptimisticBlock(block),
|
|
752
|
+
finalized: false,
|
|
753
|
+
slot: blockInput.slot,
|
|
754
|
+
};
|
|
755
|
+
}
|
|
756
|
+
const data = await this.db.block.getBinary(fromHex(root));
|
|
757
|
+
if (data) {
|
|
758
|
+
const slot = getSlotFromSignedBeaconBlockSerialized(data);
|
|
759
|
+
if (slot === null) throw new Error(`Invalid block data stored in DB for root: ${root}`);
|
|
760
|
+
return {block: data, executionOptimistic: isOptimisticBlock(block), finalized: false, slot};
|
|
761
|
+
}
|
|
762
|
+
// If block is not found in hot db, try cold db since there could be an archive cycle happening
|
|
763
|
+
// TODO: Add a lock to the archiver to have deterministic behavior on where are blocks
|
|
764
|
+
}
|
|
765
|
+
|
|
766
|
+
const data = await this.db.blockArchive.getBinaryEntryByRoot(fromHex(root));
|
|
767
|
+
return data && {block: data.value, executionOptimistic: false, finalized: true, slot: data.key};
|
|
768
|
+
}
|
|
769
|
+
|
|
770
|
+
async getBlobSidecars(blockSlot: Slot, blockRootHex: string): Promise<deneb.BlobSidecars | null> {
|
|
771
|
+
const blockInput = this.seenBlockInputCache.get(blockRootHex);
|
|
772
|
+
if (blockInput) {
|
|
773
|
+
if (!isBlockInputBlobs(blockInput)) {
|
|
774
|
+
throw new Error(`Expected block input to have blobs: slot=${blockSlot} root=${blockRootHex}`);
|
|
775
|
+
}
|
|
776
|
+
if (!blockInput.hasAllData()) {
|
|
777
|
+
return null;
|
|
778
|
+
}
|
|
779
|
+
return blockInput.getBlobs();
|
|
780
|
+
}
|
|
781
|
+
const unfinalizedBlobSidecars = (await this.db.blobSidecars.get(fromHex(blockRootHex)))?.blobSidecars ?? null;
|
|
782
|
+
if (unfinalizedBlobSidecars) {
|
|
783
|
+
return unfinalizedBlobSidecars;
|
|
784
|
+
}
|
|
785
|
+
return (await this.db.blobSidecarsArchive.get(blockSlot))?.blobSidecars ?? null;
|
|
786
|
+
}
|
|
787
|
+
|
|
788
|
+
async getSerializedBlobSidecars(blockSlot: Slot, blockRootHex: string): Promise<Uint8Array | null> {
|
|
789
|
+
const blockInput = this.seenBlockInputCache.get(blockRootHex);
|
|
790
|
+
if (blockInput) {
|
|
791
|
+
if (!isBlockInputBlobs(blockInput)) {
|
|
792
|
+
throw new Error(`Expected block input to have blobs: slot=${blockSlot} root=${blockRootHex}`);
|
|
793
|
+
}
|
|
794
|
+
if (!blockInput.hasAllData()) {
|
|
795
|
+
return null;
|
|
796
|
+
}
|
|
797
|
+
return ssz.deneb.BlobSidecars.serialize(blockInput.getBlobs());
|
|
798
|
+
}
|
|
799
|
+
const unfinalizedBlobSidecarsWrapper = await this.db.blobSidecars.getBinary(fromHex(blockRootHex));
|
|
800
|
+
if (unfinalizedBlobSidecarsWrapper) {
|
|
801
|
+
return unfinalizedBlobSidecarsWrapper.slice(BLOB_SIDECARS_IN_WRAPPER_INDEX);
|
|
802
|
+
}
|
|
803
|
+
const finalizedBlobSidecarsWrapper = await this.db.blobSidecarsArchive.getBinary(blockSlot);
|
|
804
|
+
if (finalizedBlobSidecarsWrapper) {
|
|
805
|
+
return finalizedBlobSidecarsWrapper.slice(BLOB_SIDECARS_IN_WRAPPER_INDEX);
|
|
806
|
+
}
|
|
807
|
+
return null;
|
|
808
|
+
}
|
|
809
|
+
|
|
810
|
+
async getDataColumnSidecars(blockSlot: Slot, blockRootHex: string): Promise<fulu.DataColumnSidecars> {
|
|
811
|
+
const blockInput = this.seenBlockInputCache.get(blockRootHex);
|
|
812
|
+
if (blockInput) {
|
|
813
|
+
if (!isBlockInputColumns(blockInput)) {
|
|
814
|
+
throw new Error(`Expected block input to have columns: slot=${blockSlot} root=${blockRootHex}`);
|
|
815
|
+
}
|
|
816
|
+
return blockInput.getAllColumns();
|
|
817
|
+
}
|
|
818
|
+
const sidecarsUnfinalized = await this.db.dataColumnSidecar.values(fromHex(blockRootHex));
|
|
819
|
+
if (sidecarsUnfinalized.length > 0) {
|
|
820
|
+
return sidecarsUnfinalized;
|
|
821
|
+
}
|
|
822
|
+
const sidecarsFinalized = await this.db.dataColumnSidecarArchive.values(blockSlot);
|
|
823
|
+
return sidecarsFinalized;
|
|
824
|
+
}
|
|
825
|
+
|
|
826
|
+
async getSerializedDataColumnSidecars(
|
|
827
|
+
blockSlot: Slot,
|
|
828
|
+
blockRootHex: string,
|
|
829
|
+
indices: number[]
|
|
830
|
+
): Promise<(Uint8Array | undefined)[]> {
|
|
831
|
+
const blockInput = this.seenBlockInputCache.get(blockRootHex);
|
|
832
|
+
if (blockInput) {
|
|
833
|
+
if (!isBlockInputColumns(blockInput)) {
|
|
834
|
+
throw new Error(`Expected block input to have columns: slot=${blockSlot} root=${blockRootHex}`);
|
|
835
|
+
}
|
|
836
|
+
return indices.map((index) => {
|
|
837
|
+
const sidecar = blockInput.getColumn(index);
|
|
838
|
+
if (!sidecar) {
|
|
839
|
+
return undefined;
|
|
840
|
+
}
|
|
841
|
+
const serialized = this.serializedCache.get(sidecar);
|
|
842
|
+
if (serialized) {
|
|
843
|
+
return serialized;
|
|
844
|
+
}
|
|
845
|
+
return ssz.fulu.DataColumnSidecar.serialize(sidecar);
|
|
846
|
+
});
|
|
847
|
+
}
|
|
848
|
+
const sidecarsUnfinalized = await this.db.dataColumnSidecar.getManyBinary(fromHex(blockRootHex), indices);
|
|
849
|
+
if (sidecarsUnfinalized.some((sidecar) => sidecar != null)) {
|
|
850
|
+
return sidecarsUnfinalized;
|
|
851
|
+
}
|
|
852
|
+
const sidecarsFinalized = await this.db.dataColumnSidecarArchive.getManyBinary(blockSlot, indices);
|
|
853
|
+
return sidecarsFinalized;
|
|
854
|
+
}
|
|
855
|
+
|
|
682
856
|
async produceCommonBlockBody(blockAttributes: BlockAttributes): Promise<CommonBlockBody> {
|
|
683
857
|
const {slot, parentBlockRoot} = blockAttributes;
|
|
684
858
|
const state = await this.regen.getBlockSlotState(
|
|
@@ -980,8 +1154,8 @@ export class BeaconChain implements IBeaconChain {
|
|
|
980
1154
|
this.metrics?.gossipAttestation.useHeadBlockState.inc({caller: regenCaller});
|
|
981
1155
|
state = await this.regen.getState(attHeadBlock.stateRoot, regenCaller);
|
|
982
1156
|
}
|
|
983
|
-
|
|
984
|
-
|
|
1157
|
+
// resolve the promise to unblock other calls of the same epoch and dependent root
|
|
1158
|
+
this.shufflingCache.processState(state);
|
|
985
1159
|
return state.epochCtx.getShufflingAtEpoch(attEpoch);
|
|
986
1160
|
}
|
|
987
1161
|
|
|
@@ -1165,6 +1339,13 @@ export class BeaconChain implements IBeaconChain {
|
|
|
1165
1339
|
this.logger.verbose("Fork choice justified", {epoch: cp.epoch, root: cp.rootHex});
|
|
1166
1340
|
}
|
|
1167
1341
|
|
|
1342
|
+
private onCheckpoint(this: BeaconChain, _checkpoint: phase0.Checkpoint, state: CachedBeaconStateAllForks): void {
|
|
1343
|
+
// Defer to not block other checkpoint event handlers, which can cause lightclient update delays
|
|
1344
|
+
callInNextEventLoop(() => {
|
|
1345
|
+
this.shufflingCache.processState(state);
|
|
1346
|
+
});
|
|
1347
|
+
}
|
|
1348
|
+
|
|
1168
1349
|
private async onForkChoiceFinalized(this: BeaconChain, cp: CheckpointWithHex): Promise<void> {
|
|
1169
1350
|
this.logger.verbose("Fork choice finalized", {epoch: cp.epoch, root: cp.rootHex});
|
|
1170
1351
|
this.seenBlockProposers.prune(computeStartSlotAtEpoch(cp.epoch));
|
|
@@ -1295,9 +1476,9 @@ export class BeaconChain implements IBeaconChain {
|
|
|
1295
1476
|
|
|
1296
1477
|
preState = processSlots(preState, block.slot); // Dial preState's slot to block.slot
|
|
1297
1478
|
|
|
1298
|
-
const
|
|
1479
|
+
const proposerRewards = this.regen.getStateSync(toRootHex(block.stateRoot))?.proposerRewards ?? undefined;
|
|
1299
1480
|
|
|
1300
|
-
return computeBlockRewards(this.config, block, preState
|
|
1481
|
+
return computeBlockRewards(this.config, block, preState, proposerRewards);
|
|
1301
1482
|
}
|
|
1302
1483
|
|
|
1303
1484
|
async getAttestationsRewards(
|
|
@@ -1338,6 +1519,6 @@ export class BeaconChain implements IBeaconChain {
|
|
|
1338
1519
|
|
|
1339
1520
|
preState = processSlots(preState, block.slot); // Dial preState's slot to block.slot
|
|
1340
1521
|
|
|
1341
|
-
return computeSyncCommitteeRewards(this.config, this.index2pubkey, block, preState
|
|
1522
|
+
return computeSyncCommitteeRewards(this.config, this.index2pubkey, block, preState, validatorIds);
|
|
1342
1523
|
}
|
|
1343
1524
|
}
|
package/src/chain/initState.ts
CHANGED
|
@@ -6,6 +6,7 @@ import {Logger, toHex, toRootHex} from "@lodestar/utils";
|
|
|
6
6
|
import {GENESIS_SLOT} from "../constants/index.js";
|
|
7
7
|
import {IBeaconDb} from "../db/index.js";
|
|
8
8
|
import {Metrics} from "../metrics/index.js";
|
|
9
|
+
import {getStateTypeFromBytes} from "../util/multifork.js";
|
|
9
10
|
|
|
10
11
|
export async function persistAnchorState(
|
|
11
12
|
config: ChainForkConfig,
|
|
@@ -53,14 +54,15 @@ export function createGenesisBlock(config: ChainForkConfig, genesisState: Beacon
|
|
|
53
54
|
* Restore the latest beacon state from db
|
|
54
55
|
*/
|
|
55
56
|
export async function initStateFromDb(
|
|
56
|
-
|
|
57
|
+
config: ChainForkConfig,
|
|
57
58
|
db: IBeaconDb,
|
|
58
59
|
logger: Logger
|
|
59
60
|
): Promise<BeaconStateAllForks> {
|
|
60
|
-
const
|
|
61
|
-
if (
|
|
61
|
+
const stateBytes = await db.stateArchive.lastBinary();
|
|
62
|
+
if (stateBytes == null) {
|
|
62
63
|
throw new Error("No state exists in database");
|
|
63
64
|
}
|
|
65
|
+
const state = getStateTypeFromBytes(config, stateBytes).deserializeToViewDU(stateBytes);
|
|
64
66
|
|
|
65
67
|
logger.info("Initializing beacon state from db", {
|
|
66
68
|
slot: state.slot,
|
package/src/chain/interface.ts
CHANGED
|
@@ -22,6 +22,8 @@ import {
|
|
|
22
22
|
Wei,
|
|
23
23
|
altair,
|
|
24
24
|
capella,
|
|
25
|
+
deneb,
|
|
26
|
+
fulu,
|
|
25
27
|
phase0,
|
|
26
28
|
rewards,
|
|
27
29
|
} from "@lodestar/types";
|
|
@@ -168,12 +170,12 @@ export interface IBeaconChain {
|
|
|
168
170
|
getStateBySlot(
|
|
169
171
|
slot: Slot,
|
|
170
172
|
opts?: StateGetOpts
|
|
171
|
-
): Promise<{state:
|
|
173
|
+
): Promise<{state: CachedBeaconStateAllForks; executionOptimistic: boolean; finalized: boolean} | null>;
|
|
172
174
|
/** Returns a local state by state root */
|
|
173
175
|
getStateByStateRoot(
|
|
174
176
|
stateRoot: RootHex,
|
|
175
177
|
opts?: StateGetOpts
|
|
176
|
-
): Promise<{state:
|
|
178
|
+
): Promise<{state: CachedBeaconStateAllForks | Uint8Array; executionOptimistic: boolean; finalized: boolean} | null>;
|
|
177
179
|
/** Return serialized bytes of a persisted checkpoint state */
|
|
178
180
|
getPersistedCheckpointState(checkpoint?: phase0.Checkpoint): Promise<Uint8Array | null>;
|
|
179
181
|
/** Returns a cached state by checkpoint */
|
|
@@ -193,12 +195,26 @@ export interface IBeaconChain {
|
|
|
193
195
|
getCanonicalBlockAtSlot(
|
|
194
196
|
slot: Slot
|
|
195
197
|
): Promise<{block: SignedBeaconBlock; executionOptimistic: boolean; finalized: boolean} | null>;
|
|
198
|
+
/**
|
|
199
|
+
* Get local block by root, does not fetch from the network
|
|
200
|
+
*/
|
|
201
|
+
getSerializedBlockByRoot(
|
|
202
|
+
root: RootHex
|
|
203
|
+
): Promise<{block: Uint8Array; executionOptimistic: boolean; finalized: boolean; slot: Slot} | null>;
|
|
196
204
|
/**
|
|
197
205
|
* Get local block by root, does not fetch from the network
|
|
198
206
|
*/
|
|
199
207
|
getBlockByRoot(
|
|
200
208
|
root: RootHex
|
|
201
209
|
): Promise<{block: SignedBeaconBlock; executionOptimistic: boolean; finalized: boolean} | null>;
|
|
210
|
+
getBlobSidecars(blockSlot: Slot, blockRootHex: string): Promise<deneb.BlobSidecars | null>;
|
|
211
|
+
getSerializedBlobSidecars(blockSlot: Slot, blockRootHex: string): Promise<Uint8Array | null>;
|
|
212
|
+
getDataColumnSidecars(blockSlot: Slot, blockRootHex: string): Promise<fulu.DataColumnSidecars>;
|
|
213
|
+
getSerializedDataColumnSidecars(
|
|
214
|
+
blockSlot: Slot,
|
|
215
|
+
blockRootHex: string,
|
|
216
|
+
indices: number[]
|
|
217
|
+
): Promise<(Uint8Array | undefined)[]>;
|
|
202
218
|
|
|
203
219
|
produceCommonBlockBody(blockAttributes: BlockAttributes): Promise<CommonBlockBody>;
|
|
204
220
|
produceBlock(blockAttributes: BlockAttributes & {commonBlockBodyPromise: Promise<CommonBlockBody>}): Promise<{
|
|
@@ -12,7 +12,6 @@ import {BeaconBlockBody, SSZTypesFor, ssz} from "@lodestar/types";
|
|
|
12
12
|
import {SyncCommitteeWitness} from "./types.js";
|
|
13
13
|
|
|
14
14
|
export function getSyncCommitteesWitness(fork: ForkName, state: BeaconStateAllForks): SyncCommitteeWitness {
|
|
15
|
-
state.commit();
|
|
16
15
|
const n1 = state.node;
|
|
17
16
|
let witness: Uint8Array[];
|
|
18
17
|
let currentSyncCommitteeRoot: Uint8Array;
|
|
@@ -71,7 +70,6 @@ export function getCurrentSyncCommitteeBranch(syncCommitteesWitness: SyncCommitt
|
|
|
71
70
|
}
|
|
72
71
|
|
|
73
72
|
export function getFinalizedRootProof(state: CachedBeaconStateAllForks): Uint8Array[] {
|
|
74
|
-
state.commit();
|
|
75
73
|
const finalizedRootGindex = state.epochCtx.isPostElectra() ? FINALIZED_ROOT_GINDEX_ELECTRA : FINALIZED_ROOT_GINDEX;
|
|
76
74
|
return new Tree(state.node).getSingleProof(BigInt(finalizedRootGindex));
|
|
77
75
|
}
|