@lodestar/beacon-node 1.41.0-dev.aeb5a213ee → 1.41.0-dev.b847afb846
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 +3 -2
- package/lib/api/impl/beacon/blocks/index.js.map +1 -1
- package/lib/api/impl/beacon/state/index.js +8 -8
- package/lib/api/impl/beacon/state/index.js.map +1 -1
- package/lib/api/impl/beacon/state/utils.d.ts +3 -4
- package/lib/api/impl/beacon/state/utils.d.ts.map +1 -1
- package/lib/api/impl/beacon/state/utils.js +4 -4
- package/lib/api/impl/beacon/state/utils.js.map +1 -1
- package/lib/api/impl/debug/index.d.ts.map +1 -1
- package/lib/api/impl/debug/index.js +1 -0
- package/lib/api/impl/debug/index.js.map +1 -1
- package/lib/api/impl/node/utils.d.ts +1 -1
- package/lib/api/impl/node/utils.d.ts.map +1 -1
- package/lib/api/impl/node/utils.js.map +1 -1
- package/lib/api/impl/validator/index.d.ts.map +1 -1
- package/lib/api/impl/validator/index.js +29 -15
- package/lib/api/impl/validator/index.js.map +1 -1
- package/lib/chain/archiveStore/archiveStore.d.ts.map +1 -1
- package/lib/chain/archiveStore/archiveStore.js.map +1 -1
- package/lib/chain/archiveStore/historicalState/getHistoricalState.d.ts +5 -6
- package/lib/chain/archiveStore/historicalState/getHistoricalState.d.ts.map +1 -1
- package/lib/chain/archiveStore/historicalState/getHistoricalState.js +9 -10
- package/lib/chain/archiveStore/historicalState/getHistoricalState.js.map +1 -1
- package/lib/chain/archiveStore/historicalState/worker.js +3 -3
- package/lib/chain/archiveStore/historicalState/worker.js.map +1 -1
- package/lib/chain/archiveStore/utils/archiveBlocks.d.ts +3 -8
- package/lib/chain/archiveStore/utils/archiveBlocks.d.ts.map +1 -1
- package/lib/chain/archiveStore/utils/archiveBlocks.js +1 -1
- package/lib/chain/archiveStore/utils/archiveBlocks.js.map +1 -1
- package/lib/chain/archiveStore/utils/updateBackfillRange.js +1 -1
- package/lib/chain/archiveStore/utils/updateBackfillRange.js.map +1 -1
- package/lib/chain/blocks/blockInput/blockInput.d.ts +25 -2
- package/lib/chain/blocks/blockInput/blockInput.d.ts.map +1 -1
- package/lib/chain/blocks/blockInput/blockInput.js +71 -0
- package/lib/chain/blocks/blockInput/blockInput.js.map +1 -1
- package/lib/chain/blocks/blockInput/types.d.ts +18 -1
- package/lib/chain/blocks/blockInput/types.d.ts.map +1 -1
- package/lib/chain/blocks/blockInput/types.js +1 -0
- package/lib/chain/blocks/blockInput/types.js.map +1 -1
- package/lib/chain/blocks/importBlock.d.ts.map +1 -1
- package/lib/chain/blocks/importBlock.js +27 -4
- package/lib/chain/blocks/importBlock.js.map +1 -1
- package/lib/chain/blocks/verifyBlocksDataAvailability.d.ts.map +1 -1
- package/lib/chain/blocks/verifyBlocksDataAvailability.js +3 -0
- package/lib/chain/blocks/verifyBlocksDataAvailability.js.map +1 -1
- package/lib/chain/blocks/verifyBlocksExecutionPayloads.d.ts +4 -0
- package/lib/chain/blocks/verifyBlocksExecutionPayloads.d.ts.map +1 -1
- package/lib/chain/blocks/verifyBlocksExecutionPayloads.js +5 -1
- package/lib/chain/blocks/verifyBlocksExecutionPayloads.js.map +1 -1
- package/lib/chain/blocks/verifyBlocksSanityChecks.d.ts.map +1 -1
- package/lib/chain/blocks/verifyBlocksSanityChecks.js +4 -1
- package/lib/chain/blocks/verifyBlocksSanityChecks.js.map +1 -1
- package/lib/chain/blocks/writeBlockInputToDb.d.ts +12 -3
- package/lib/chain/blocks/writeBlockInputToDb.d.ts.map +1 -1
- package/lib/chain/blocks/writeBlockInputToDb.js +92 -98
- package/lib/chain/blocks/writeBlockInputToDb.js.map +1 -1
- package/lib/chain/bls/multithread/index.d.ts +3 -3
- package/lib/chain/bls/multithread/index.d.ts.map +1 -1
- package/lib/chain/bls/multithread/index.js +5 -5
- package/lib/chain/bls/multithread/index.js.map +1 -1
- package/lib/chain/bls/multithread/jobItem.d.ts +2 -2
- package/lib/chain/bls/multithread/jobItem.d.ts.map +1 -1
- package/lib/chain/bls/multithread/jobItem.js +2 -2
- package/lib/chain/bls/multithread/jobItem.js.map +1 -1
- package/lib/chain/bls/singleThread.d.ts +4 -4
- package/lib/chain/bls/singleThread.d.ts.map +1 -1
- package/lib/chain/bls/singleThread.js +4 -4
- package/lib/chain/bls/singleThread.js.map +1 -1
- package/lib/chain/bls/utils.d.ts +2 -2
- package/lib/chain/bls/utils.d.ts.map +1 -1
- package/lib/chain/bls/utils.js +7 -4
- package/lib/chain/bls/utils.js.map +1 -1
- package/lib/chain/chain.d.ts +5 -8
- package/lib/chain/chain.d.ts.map +1 -1
- package/lib/chain/chain.js +21 -22
- package/lib/chain/chain.js.map +1 -1
- package/lib/chain/emitter.d.ts +3 -3
- package/lib/chain/emitter.d.ts.map +1 -1
- package/lib/chain/errors/executionPayloadEnvelope.d.ts +2 -2
- package/lib/chain/errors/executionPayloadEnvelope.d.ts.map +1 -1
- package/lib/chain/errors/executionPayloadEnvelope.js.map +1 -1
- package/lib/chain/forkChoice/index.d.ts.map +1 -1
- package/lib/chain/forkChoice/index.js +30 -24
- package/lib/chain/forkChoice/index.js.map +1 -1
- package/lib/chain/interface.d.ts +2 -4
- package/lib/chain/interface.d.ts.map +1 -1
- package/lib/chain/interface.js.map +1 -1
- package/lib/chain/opPools/aggregatedAttestationPool.js +1 -1
- package/lib/chain/opPools/aggregatedAttestationPool.js.map +1 -1
- package/lib/chain/produceBlock/produceBlockBody.d.ts.map +1 -1
- package/lib/chain/produceBlock/produceBlockBody.js +1 -2
- package/lib/chain/produceBlock/produceBlockBody.js.map +1 -1
- package/lib/chain/regen/queued.d.ts.map +1 -1
- package/lib/chain/regen/queued.js +4 -1
- package/lib/chain/regen/queued.js.map +1 -1
- package/lib/chain/regen/regen.d.ts.map +1 -1
- package/lib/chain/regen/regen.js +6 -2
- package/lib/chain/regen/regen.js.map +1 -1
- package/lib/chain/seenCache/seenGossipBlockInput.d.ts +5 -1
- package/lib/chain/seenCache/seenGossipBlockInput.d.ts.map +1 -1
- package/lib/chain/seenCache/seenGossipBlockInput.js +36 -15
- package/lib/chain/seenCache/seenGossipBlockInput.js.map +1 -1
- package/lib/chain/validation/aggregateAndProof.js +1 -1
- package/lib/chain/validation/aggregateAndProof.js.map +1 -1
- package/lib/chain/validation/attestation.d.ts.map +1 -1
- package/lib/chain/validation/attestation.js +7 -4
- 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 +9 -2
- package/lib/chain/validation/attesterSlashing.js.map +1 -1
- package/lib/chain/validation/blobSidecar.js +2 -2
- package/lib/chain/validation/blobSidecar.js.map +1 -1
- package/lib/chain/validation/block.d.ts.map +1 -1
- package/lib/chain/validation/block.js +6 -3
- package/lib/chain/validation/block.js.map +1 -1
- package/lib/chain/validation/dataColumnSidecar.js +1 -1
- package/lib/chain/validation/dataColumnSidecar.js.map +1 -1
- package/lib/chain/validation/executionPayloadBid.js +1 -2
- package/lib/chain/validation/executionPayloadBid.js.map +1 -1
- package/lib/chain/validation/executionPayloadEnvelope.js +4 -4
- package/lib/chain/validation/executionPayloadEnvelope.js.map +1 -1
- package/lib/chain/validation/payloadAttestationMessage.js +9 -3
- package/lib/chain/validation/payloadAttestationMessage.js.map +1 -1
- package/lib/chain/validation/proposerSlashing.js +1 -1
- package/lib/chain/validation/proposerSlashing.js.map +1 -1
- package/lib/chain/validation/syncCommitteeContributionAndProof.js +1 -1
- package/lib/db/repositories/blockArchive.d.ts.map +1 -1
- package/lib/db/repositories/blockArchive.js +1 -2
- package/lib/db/repositories/blockArchive.js.map +1 -1
- package/lib/execution/engine/http.d.ts +1 -0
- package/lib/execution/engine/http.d.ts.map +1 -1
- package/lib/execution/engine/http.js +3 -0
- package/lib/execution/engine/http.js.map +1 -1
- package/lib/metrics/metrics/lodestar.d.ts +4 -0
- package/lib/metrics/metrics/lodestar.d.ts.map +1 -1
- package/lib/metrics/metrics/lodestar.js +9 -0
- package/lib/metrics/metrics/lodestar.js.map +1 -1
- package/lib/monitoring/service.d.ts +2 -2
- package/lib/monitoring/service.d.ts.map +1 -1
- package/lib/monitoring/service.js +3 -2
- package/lib/monitoring/service.js.map +1 -1
- package/lib/network/core/networkCore.d.ts +3 -3
- package/lib/network/core/networkCore.d.ts.map +1 -1
- package/lib/network/core/networkCore.js.map +1 -1
- package/lib/network/core/networkCoreWorkerHandler.d.ts +3 -3
- package/lib/network/core/networkCoreWorkerHandler.d.ts.map +1 -1
- package/lib/network/core/types.d.ts +2 -2
- package/lib/network/core/types.d.ts.map +1 -1
- package/lib/network/events.d.ts +2 -1
- package/lib/network/events.d.ts.map +1 -1
- package/lib/network/events.js.map +1 -1
- package/lib/network/gossip/encoding.d.ts +3 -3
- package/lib/network/gossip/encoding.d.ts.map +1 -1
- package/lib/network/gossip/encoding.js.map +1 -1
- package/lib/network/gossip/gossipsub.d.ts +13 -4
- package/lib/network/gossip/gossipsub.d.ts.map +1 -1
- package/lib/network/gossip/gossipsub.js +47 -20
- package/lib/network/gossip/gossipsub.js.map +1 -1
- package/lib/network/gossip/interface.d.ts +3 -3
- package/lib/network/gossip/interface.d.ts.map +1 -1
- package/lib/network/gossip/scoringParameters.d.ts +1 -1
- package/lib/network/gossip/scoringParameters.d.ts.map +1 -1
- package/lib/network/gossip/scoringParameters.js +1 -1
- package/lib/network/gossip/scoringParameters.js.map +1 -1
- package/lib/network/interface.d.ts +3 -3
- package/lib/network/interface.d.ts.map +1 -1
- package/lib/network/libp2p/index.d.ts +1 -1
- package/lib/network/libp2p/index.d.ts.map +1 -1
- package/lib/network/libp2p/index.js +7 -2
- package/lib/network/libp2p/index.js.map +1 -1
- package/lib/network/network.d.ts +2 -2
- package/lib/network/network.d.ts.map +1 -1
- package/lib/network/network.js +1 -1
- package/lib/network/network.js.map +1 -1
- package/lib/network/options.d.ts.map +1 -1
- package/lib/network/options.js +3 -0
- package/lib/network/options.js.map +1 -1
- package/lib/network/peers/datastore.d.ts +7 -5
- package/lib/network/peers/datastore.d.ts.map +1 -1
- package/lib/network/peers/datastore.js +10 -10
- package/lib/network/peers/datastore.js.map +1 -1
- package/lib/network/peers/peerManager.d.ts +3 -0
- package/lib/network/peers/peerManager.d.ts.map +1 -1
- package/lib/network/peers/peerManager.js +103 -53
- package/lib/network/peers/peerManager.js.map +1 -1
- package/lib/network/peers/utils/prioritizePeers.d.ts +3 -3
- package/lib/network/peers/utils/prioritizePeers.d.ts.map +1 -1
- package/lib/network/processor/gossipHandlers.d.ts.map +1 -1
- package/lib/network/processor/gossipHandlers.js +4 -1
- package/lib/network/processor/gossipHandlers.js.map +1 -1
- package/lib/network/processor/gossipValidatorFn.js +1 -1
- package/lib/network/processor/types.d.ts +1 -1
- package/lib/network/processor/types.d.ts.map +1 -1
- package/lib/network/reqresp/handlers/beaconBlocksByRange.d.ts.map +1 -1
- package/lib/network/reqresp/handlers/beaconBlocksByRange.js +3 -2
- package/lib/network/reqresp/handlers/beaconBlocksByRange.js.map +1 -1
- package/lib/network/reqresp/handlers/blobSidecarsByRange.d.ts.map +1 -1
- package/lib/network/reqresp/handlers/blobSidecarsByRange.js +3 -2
- package/lib/network/reqresp/handlers/blobSidecarsByRange.js.map +1 -1
- package/lib/network/reqresp/handlers/blobSidecarsByRoot.js +1 -1
- 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 +3 -2
- package/lib/network/reqresp/handlers/dataColumnSidecarsByRange.js.map +1 -1
- package/lib/network/reqresp/handlers/dataColumnSidecarsByRoot.js +1 -1
- package/lib/network/reqresp/handlers/dataColumnSidecarsByRoot.js.map +1 -1
- package/lib/network/reqresp/score.d.ts.map +1 -1
- package/lib/network/reqresp/score.js +0 -1
- package/lib/network/reqresp/score.js.map +1 -1
- package/lib/network/util.js +2 -2
- package/lib/network/util.js.map +1 -1
- package/lib/node/nodejs.d.ts +3 -5
- package/lib/node/nodejs.d.ts.map +1 -1
- package/lib/node/nodejs.js +6 -4
- package/lib/node/nodejs.js.map +1 -1
- package/lib/util/clock.d.ts +6 -0
- package/lib/util/clock.d.ts.map +1 -1
- package/lib/util/clock.js +9 -3
- package/lib/util/clock.js.map +1 -1
- package/lib/util/serializedCache.d.ts +4 -4
- package/lib/util/serializedCache.d.ts.map +1 -1
- package/lib/util/serializedCache.js +6 -4
- package/lib/util/serializedCache.js.map +1 -1
- package/package.json +39 -42
- package/src/api/impl/beacon/blocks/index.ts +3 -2
- package/src/api/impl/beacon/state/index.ts +8 -8
- package/src/api/impl/beacon/state/utils.ts +5 -6
- package/src/api/impl/debug/index.ts +1 -0
- package/src/api/impl/node/utils.ts +3 -3
- package/src/api/impl/validator/index.ts +29 -16
- package/src/chain/archiveStore/archiveStore.ts +5 -5
- package/src/chain/archiveStore/historicalState/getHistoricalState.ts +10 -11
- package/src/chain/archiveStore/historicalState/worker.ts +3 -3
- package/src/chain/archiveStore/utils/archiveBlocks.ts +4 -5
- package/src/chain/archiveStore/utils/updateBackfillRange.ts +1 -1
- package/src/chain/blocks/blockInput/blockInput.ts +103 -3
- package/src/chain/blocks/blockInput/types.ts +18 -0
- package/src/chain/blocks/importBlock.ts +35 -4
- package/src/chain/blocks/verifyBlocksDataAvailability.ts +3 -0
- package/src/chain/blocks/verifyBlocksExecutionPayloads.ts +9 -2
- package/src/chain/blocks/verifyBlocksSanityChecks.ts +7 -2
- package/src/chain/blocks/writeBlockInputToDb.ts +105 -104
- package/src/chain/bls/multithread/index.ts +7 -7
- package/src/chain/bls/multithread/jobItem.ts +3 -3
- package/src/chain/bls/singleThread.ts +5 -5
- package/src/chain/bls/utils.ts +8 -5
- package/src/chain/chain.ts +38 -31
- package/src/chain/emitter.ts +3 -3
- package/src/chain/errors/executionPayloadEnvelope.ts +6 -2
- package/src/chain/forkChoice/index.ts +39 -21
- package/src/chain/interface.ts +2 -9
- package/src/chain/opPools/aggregatedAttestationPool.ts +1 -1
- package/src/chain/produceBlock/produceBlockBody.ts +1 -2
- package/src/chain/regen/queued.ts +7 -2
- package/src/chain/regen/regen.ts +9 -3
- package/src/chain/seenCache/seenGossipBlockInput.ts +54 -17
- package/src/chain/validation/aggregateAndProof.ts +1 -1
- package/src/chain/validation/attestation.ts +7 -4
- package/src/chain/validation/attesterSlashing.ts +10 -1
- package/src/chain/validation/blobSidecar.ts +2 -2
- package/src/chain/validation/block.ts +9 -4
- package/src/chain/validation/dataColumnSidecar.ts +1 -1
- package/src/chain/validation/executionPayloadBid.ts +1 -2
- package/src/chain/validation/executionPayloadEnvelope.ts +4 -4
- package/src/chain/validation/payloadAttestationMessage.ts +10 -3
- package/src/chain/validation/proposerSlashing.ts +1 -1
- package/src/chain/validation/syncCommitteeContributionAndProof.ts +1 -1
- package/src/db/repositories/blockArchive.ts +1 -2
- package/src/execution/engine/http.ts +3 -0
- package/src/metrics/metrics/lodestar.ts +9 -0
- package/src/monitoring/service.ts +3 -2
- package/src/network/core/networkCore.ts +3 -3
- package/src/network/core/networkCoreWorkerHandler.ts +3 -3
- package/src/network/core/types.ts +2 -2
- package/src/network/events.ts +2 -1
- package/src/network/gossip/encoding.ts +3 -3
- package/src/network/gossip/gossipsub.ts +86 -25
- package/src/network/gossip/interface.ts +3 -3
- package/src/network/gossip/scoringParameters.ts +4 -4
- package/src/network/interface.ts +3 -3
- package/src/network/libp2p/index.ts +8 -3
- package/src/network/network.ts +5 -4
- package/src/network/options.ts +3 -0
- package/src/network/peers/datastore.ts +13 -10
- package/src/network/peers/peerManager.ts +118 -54
- package/src/network/peers/utils/prioritizePeers.ts +3 -3
- package/src/network/processor/gossipHandlers.ts +12 -3
- package/src/network/processor/gossipValidatorFn.ts +1 -1
- package/src/network/processor/types.ts +1 -1
- package/src/network/reqresp/handlers/beaconBlocksByRange.ts +3 -2
- package/src/network/reqresp/handlers/blobSidecarsByRange.ts +3 -2
- package/src/network/reqresp/handlers/blobSidecarsByRoot.ts +1 -1
- package/src/network/reqresp/handlers/dataColumnSidecarsByRange.ts +3 -2
- package/src/network/reqresp/handlers/dataColumnSidecarsByRoot.ts +1 -1
- package/src/network/reqresp/score.ts +0 -1
- package/src/network/util.ts +2 -2
- package/src/node/nodejs.ts +8 -9
- package/src/util/clock.ts +9 -4
- package/src/util/serializedCache.ts +7 -5
- package/src/util/workerEvents.ts +1 -1
|
@@ -1,7 +1,6 @@
|
|
|
1
|
-
import {PubkeyIndexMap} from "@chainsafe/pubkey-index-map";
|
|
2
1
|
import {routes} from "@lodestar/api";
|
|
3
2
|
import {ApplicationMethods} from "@lodestar/api/server";
|
|
4
|
-
import {ExecutionStatus, ProtoBlock} from "@lodestar/fork-choice";
|
|
3
|
+
import {ExecutionStatus, PayloadStatus, ProtoBlock} from "@lodestar/fork-choice";
|
|
5
4
|
import {
|
|
6
5
|
BUILDER_INDEX_SELF_BUILD,
|
|
7
6
|
ForkName,
|
|
@@ -27,6 +26,7 @@ import {
|
|
|
27
26
|
computeStartSlotAtEpoch,
|
|
28
27
|
computeTimeAtSlot,
|
|
29
28
|
createCachedBeaconState,
|
|
29
|
+
createPubkeyCache,
|
|
30
30
|
getBlockRootAtSlot,
|
|
31
31
|
getCurrentSlot,
|
|
32
32
|
loadState,
|
|
@@ -389,7 +389,7 @@ export function getValidatorApi(
|
|
|
389
389
|
*/
|
|
390
390
|
|
|
391
391
|
function notOnOptimisticBlockRoot(beaconBlockRoot: Root): void {
|
|
392
|
-
const protoBeaconBlock = chain.forkChoice.
|
|
392
|
+
const protoBeaconBlock = chain.forkChoice.getBlockDefaultStatus(beaconBlockRoot);
|
|
393
393
|
if (!protoBeaconBlock) {
|
|
394
394
|
throw new ApiError(404, `Block not in forkChoice, beaconBlockRoot=${toRootHex(beaconBlockRoot)}`);
|
|
395
395
|
}
|
|
@@ -401,7 +401,7 @@ export function getValidatorApi(
|
|
|
401
401
|
}
|
|
402
402
|
|
|
403
403
|
function notOnOutOfRangeData(beaconBlockRoot: Root): void {
|
|
404
|
-
const protoBeaconBlock = chain.forkChoice.
|
|
404
|
+
const protoBeaconBlock = chain.forkChoice.getBlockDefaultStatus(beaconBlockRoot);
|
|
405
405
|
if (!protoBeaconBlock) {
|
|
406
406
|
throw new ApiError(404, `Block not in forkChoice, beaconBlockRoot=${toRootHex(beaconBlockRoot)}`);
|
|
407
407
|
}
|
|
@@ -989,8 +989,30 @@ export function getValidatorApi(
|
|
|
989
989
|
const headBlockRoot = fromHex(headBlockRootHex);
|
|
990
990
|
const fork = config.getForkName(slot);
|
|
991
991
|
|
|
992
|
+
const beaconBlockRoot =
|
|
993
|
+
slot >= headSlot
|
|
994
|
+
? // When attesting to the head slot or later, always use the head of the chain.
|
|
995
|
+
headBlockRoot
|
|
996
|
+
: // Permit attesting to slots *prior* to the current head. This is desirable when
|
|
997
|
+
// the VC and BN are out-of-sync due to time issues or overloading.
|
|
998
|
+
getBlockRootAtSlot(headState, slot);
|
|
999
|
+
|
|
992
1000
|
let index: CommitteeIndex;
|
|
993
|
-
if (
|
|
1001
|
+
if (isForkPostGloas(fork)) {
|
|
1002
|
+
const canonicalBlock = chain.forkChoice.getCanonicalBlockByRoot(beaconBlockRoot);
|
|
1003
|
+
if (!canonicalBlock) {
|
|
1004
|
+
// This should never happen
|
|
1005
|
+
throw Error(`Block not found in fork choice for slot=${slot}, root=${toRootHex(beaconBlockRoot)}`);
|
|
1006
|
+
}
|
|
1007
|
+
// After Gloas, attestation.data.index signals payload status in fork-choice:
|
|
1008
|
+
// - 0 = EMPTY / not present, 1 = FULL / present
|
|
1009
|
+
// - same-slot attestations must always use index = 0
|
|
1010
|
+
if (canonicalBlock.slot !== slot) {
|
|
1011
|
+
index = canonicalBlock.payloadStatus === PayloadStatus.FULL ? 1 : 0;
|
|
1012
|
+
} else {
|
|
1013
|
+
index = 0;
|
|
1014
|
+
}
|
|
1015
|
+
} else if (isForkPostElectra(fork)) {
|
|
994
1016
|
index = 0;
|
|
995
1017
|
} else {
|
|
996
1018
|
if (committeeIndex === undefined) {
|
|
@@ -999,14 +1021,6 @@ export function getValidatorApi(
|
|
|
999
1021
|
index = committeeIndex;
|
|
1000
1022
|
}
|
|
1001
1023
|
|
|
1002
|
-
const beaconBlockRoot =
|
|
1003
|
-
slot >= headSlot
|
|
1004
|
-
? // When attesting to the head slot or later, always use the head of the chain.
|
|
1005
|
-
headBlockRoot
|
|
1006
|
-
: // Permit attesting to slots *prior* to the current head. This is desirable when
|
|
1007
|
-
// the VC and BN are out-of-sync due to time issues or overloading.
|
|
1008
|
-
getBlockRootAtSlot(headState, slot);
|
|
1009
|
-
|
|
1010
1024
|
const targetSlot = computeStartSlotAtEpoch(attEpoch);
|
|
1011
1025
|
const targetRoot =
|
|
1012
1026
|
targetSlot >= headSlot
|
|
@@ -1123,8 +1137,7 @@ export function getValidatorApi(
|
|
|
1123
1137
|
{
|
|
1124
1138
|
config: chain.config,
|
|
1125
1139
|
// Not required to compute proposers
|
|
1126
|
-
|
|
1127
|
-
index2pubkey: [],
|
|
1140
|
+
pubkeyCache: createPubkeyCache(),
|
|
1128
1141
|
},
|
|
1129
1142
|
{skipSyncPubkeys: true, skipSyncCommitteeCache: true}
|
|
1130
1143
|
);
|
|
@@ -1585,7 +1598,7 @@ export function getValidatorApi(
|
|
|
1585
1598
|
|
|
1586
1599
|
const filteredRegistrations = registrations.filter((registration) => {
|
|
1587
1600
|
const {pubkey} = registration.message;
|
|
1588
|
-
const validatorIndex = chain.
|
|
1601
|
+
const validatorIndex = chain.pubkeyCache.getIndex(pubkey);
|
|
1589
1602
|
if (validatorIndex === null) return false;
|
|
1590
1603
|
|
|
1591
1604
|
const validator = headState.validators.getReadonly(validatorIndex);
|
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
import {
|
|
1
|
+
import {CheckpointWithPayloadStatus} from "@lodestar/fork-choice";
|
|
2
2
|
import {LoggerNode} from "@lodestar/logger/node";
|
|
3
3
|
import {ForkSeq} from "@lodestar/params";
|
|
4
4
|
import {Checkpoint} from "@lodestar/types/phase0";
|
|
@@ -44,7 +44,7 @@ export enum ArchiveStoreTask {
|
|
|
44
44
|
*/
|
|
45
45
|
export class ArchiveStore {
|
|
46
46
|
private archiveMode: ArchiveMode;
|
|
47
|
-
private jobQueue: JobItemQueue<[
|
|
47
|
+
private jobQueue: JobItemQueue<[CheckpointWithPayloadStatus], void>;
|
|
48
48
|
|
|
49
49
|
private archiveDataEpochs?: number;
|
|
50
50
|
private readonly statesArchiverStrategy: StateArchiveStrategy;
|
|
@@ -67,7 +67,7 @@ export class ArchiveStore {
|
|
|
67
67
|
this.archiveMode = opts.archiveMode;
|
|
68
68
|
this.archiveDataEpochs = opts.archiveDataEpochs;
|
|
69
69
|
|
|
70
|
-
this.jobQueue = new JobItemQueue<[
|
|
70
|
+
this.jobQueue = new JobItemQueue<[CheckpointWithPayloadStatus], void>(this.processFinalizedCheckpoint, {
|
|
71
71
|
maxLength: PROCESS_FINALIZED_CHECKPOINT_QUEUE_LENGTH,
|
|
72
72
|
signal,
|
|
73
73
|
});
|
|
@@ -168,7 +168,7 @@ export class ArchiveStore {
|
|
|
168
168
|
//-------------------------------------------------------------------------
|
|
169
169
|
// Event handlers
|
|
170
170
|
//-------------------------------------------------------------------------
|
|
171
|
-
private onFinalizedCheckpoint = (finalized:
|
|
171
|
+
private onFinalizedCheckpoint = (finalized: CheckpointWithPayloadStatus): void => {
|
|
172
172
|
this.jobQueue.push(finalized).catch((e) => {
|
|
173
173
|
if (!isQueueErrorAborted(e)) {
|
|
174
174
|
this.logger.error("Error queuing finalized checkpoint", {epoch: finalized.epoch}, e as Error);
|
|
@@ -189,7 +189,7 @@ export class ArchiveStore {
|
|
|
189
189
|
});
|
|
190
190
|
};
|
|
191
191
|
|
|
192
|
-
private processFinalizedCheckpoint = async (finalized:
|
|
192
|
+
private processFinalizedCheckpoint = async (finalized: CheckpointWithPayloadStatus): Promise<void> => {
|
|
193
193
|
try {
|
|
194
194
|
const finalizedEpoch = finalized.epoch;
|
|
195
195
|
const finalizedFork = this.chain.config.getForkSeqAtEpoch(finalizedEpoch);
|
|
@@ -1,10 +1,10 @@
|
|
|
1
|
-
import {PubkeyIndexMap} from "@chainsafe/pubkey-index-map";
|
|
2
1
|
import {BeaconConfig} from "@lodestar/config";
|
|
3
2
|
import {
|
|
4
3
|
BeaconStateAllForks,
|
|
5
4
|
CachedBeaconStateAllForks,
|
|
6
5
|
DataAvailabilityStatus,
|
|
7
6
|
ExecutionPayloadStatus,
|
|
7
|
+
PubkeyCache,
|
|
8
8
|
createCachedBeaconState,
|
|
9
9
|
stateTransition,
|
|
10
10
|
} from "@lodestar/state-transition";
|
|
@@ -15,16 +15,16 @@ import {HistoricalStateRegenMetrics} from "./metrics.js";
|
|
|
15
15
|
import {RegenErrorType} from "./types.js";
|
|
16
16
|
|
|
17
17
|
/**
|
|
18
|
-
* Populate a
|
|
18
|
+
* Populate a PubkeyCache with any new entries based on a BeaconState
|
|
19
19
|
*/
|
|
20
|
-
export function syncPubkeyCache(state: BeaconStateAllForks,
|
|
20
|
+
export function syncPubkeyCache(state: BeaconStateAllForks, pubkeyCache: PubkeyCache): void {
|
|
21
21
|
// Get the validators sub tree once for all the loop
|
|
22
22
|
const validators = state.validators;
|
|
23
23
|
|
|
24
24
|
const newCount = state.validators.length;
|
|
25
|
-
for (let i =
|
|
25
|
+
for (let i = pubkeyCache.size; i < newCount; i++) {
|
|
26
26
|
const pubkey = validators.getReadonly(i).pubkey;
|
|
27
|
-
|
|
27
|
+
pubkeyCache.set(i, pubkey);
|
|
28
28
|
}
|
|
29
29
|
}
|
|
30
30
|
|
|
@@ -35,7 +35,7 @@ export async function getNearestState(
|
|
|
35
35
|
slot: number,
|
|
36
36
|
config: BeaconConfig,
|
|
37
37
|
db: IBeaconDb,
|
|
38
|
-
|
|
38
|
+
pubkeyCache: PubkeyCache
|
|
39
39
|
): Promise<CachedBeaconStateAllForks> {
|
|
40
40
|
const stateBytesArr = await db.stateArchive.binaries({limit: 1, lte: slot, reverse: true});
|
|
41
41
|
if (!stateBytesArr.length) {
|
|
@@ -44,14 +44,13 @@ export async function getNearestState(
|
|
|
44
44
|
|
|
45
45
|
const stateBytes = stateBytesArr[0];
|
|
46
46
|
const state = getStateTypeFromBytes(config, stateBytes).deserializeToViewDU(stateBytes);
|
|
47
|
-
syncPubkeyCache(state,
|
|
47
|
+
syncPubkeyCache(state, pubkeyCache);
|
|
48
48
|
|
|
49
49
|
return createCachedBeaconState(
|
|
50
50
|
state,
|
|
51
51
|
{
|
|
52
52
|
config,
|
|
53
|
-
|
|
54
|
-
index2pubkey: [],
|
|
53
|
+
pubkeyCache,
|
|
55
54
|
},
|
|
56
55
|
{
|
|
57
56
|
skipSyncPubkeys: true,
|
|
@@ -66,13 +65,13 @@ export async function getHistoricalState(
|
|
|
66
65
|
slot: number,
|
|
67
66
|
config: BeaconConfig,
|
|
68
67
|
db: IBeaconDb,
|
|
69
|
-
|
|
68
|
+
pubkeyCache: PubkeyCache,
|
|
70
69
|
metrics?: HistoricalStateRegenMetrics
|
|
71
70
|
): Promise<Uint8Array> {
|
|
72
71
|
const regenTimer = metrics?.regenTime.startTimer();
|
|
73
72
|
|
|
74
73
|
const loadStateTimer = metrics?.loadStateTime.startTimer();
|
|
75
|
-
let state = await getNearestState(slot, config, db,
|
|
74
|
+
let state = await getNearestState(slot, config, db, pubkeyCache).catch((e) => {
|
|
76
75
|
metrics?.regenErrorCount.inc({reason: RegenErrorType.loadState});
|
|
77
76
|
throw e;
|
|
78
77
|
});
|
|
@@ -1,9 +1,9 @@
|
|
|
1
1
|
import worker from "node:worker_threads";
|
|
2
|
-
import {PubkeyIndexMap} from "@chainsafe/pubkey-index-map";
|
|
3
2
|
import {Transfer, expose} from "@chainsafe/threads/worker";
|
|
4
3
|
import {chainConfigFromJson, createBeaconConfig} from "@lodestar/config";
|
|
5
4
|
import {LevelDbController} from "@lodestar/db/controller/level";
|
|
6
5
|
import {getNodeLogger} from "@lodestar/logger/node";
|
|
6
|
+
import {createPubkeyCache} from "@lodestar/state-transition";
|
|
7
7
|
import {BeaconDb} from "../../../db/index.js";
|
|
8
8
|
import {RegistryMetricCreator, collectNodeJSMetrics} from "../../../metrics/index.js";
|
|
9
9
|
import {JobFnQueue} from "../../../util/queue/fnQueue.js";
|
|
@@ -52,7 +52,7 @@ const queue = new JobFnQueue(
|
|
|
52
52
|
queueMetrics
|
|
53
53
|
);
|
|
54
54
|
|
|
55
|
-
const
|
|
55
|
+
const pubkeyCache = createPubkeyCache();
|
|
56
56
|
|
|
57
57
|
const api: HistoricalStateWorkerApi = {
|
|
58
58
|
async close() {
|
|
@@ -65,7 +65,7 @@ const api: HistoricalStateWorkerApi = {
|
|
|
65
65
|
historicalStateRegenMetrics?.regenRequestCount.inc();
|
|
66
66
|
|
|
67
67
|
const stateBytes = await queue.push<Uint8Array>(() =>
|
|
68
|
-
getHistoricalState(slot, config, db,
|
|
68
|
+
getHistoricalState(slot, config, db, pubkeyCache, historicalStateRegenMetrics)
|
|
69
69
|
);
|
|
70
70
|
const result = Transfer(stateBytes, [stateBytes.buffer]) as unknown as Uint8Array;
|
|
71
71
|
|
|
@@ -1,10 +1,10 @@
|
|
|
1
1
|
import path from "node:path";
|
|
2
2
|
import {ChainForkConfig} from "@lodestar/config";
|
|
3
3
|
import {KeyValue} from "@lodestar/db";
|
|
4
|
-
import {IForkChoice} from "@lodestar/fork-choice";
|
|
4
|
+
import {CheckpointWithPayloadStatus, IForkChoice} from "@lodestar/fork-choice";
|
|
5
5
|
import {ForkSeq, SLOTS_PER_EPOCH} from "@lodestar/params";
|
|
6
6
|
import {computeEpochAtSlot, computeStartSlotAtEpoch} from "@lodestar/state-transition";
|
|
7
|
-
import {Epoch,
|
|
7
|
+
import {Epoch, Slot} from "@lodestar/types";
|
|
8
8
|
import {Logger, fromAsync, fromHex, prettyPrintIndices, toRootHex} from "@lodestar/utils";
|
|
9
9
|
import {IBeaconDb} from "../../../db/index.js";
|
|
10
10
|
import {BlockArchiveBatchPutBinaryItem} from "../../../db/repositories/index.js";
|
|
@@ -19,7 +19,6 @@ const BLOCK_BATCH_SIZE = 256;
|
|
|
19
19
|
const BLOB_SIDECAR_BATCH_SIZE = 32;
|
|
20
20
|
|
|
21
21
|
type BlockRootSlot = {slot: Slot; root: Uint8Array};
|
|
22
|
-
type CheckpointHex = {epoch: Epoch; rootHex: RootHex};
|
|
23
22
|
|
|
24
23
|
/**
|
|
25
24
|
* Persist orphaned block to disk
|
|
@@ -53,7 +52,7 @@ export async function archiveBlocks(
|
|
|
53
52
|
forkChoice: IForkChoice,
|
|
54
53
|
lightclientServer: LightClientServer | undefined,
|
|
55
54
|
logger: Logger,
|
|
56
|
-
finalizedCheckpoint:
|
|
55
|
+
finalizedCheckpoint: CheckpointWithPayloadStatus,
|
|
57
56
|
currentEpoch: Epoch,
|
|
58
57
|
archiveDataEpochs?: number,
|
|
59
58
|
persistOrphanedBlocks?: boolean,
|
|
@@ -62,7 +61,7 @@ export async function archiveBlocks(
|
|
|
62
61
|
// Use fork choice to determine the blocks to archive and delete
|
|
63
62
|
// getAllAncestorBlocks response includes the finalized block, so it's also moved to the cold db
|
|
64
63
|
const {ancestors: finalizedCanonicalBlocks, nonAncestors: finalizedNonCanonicalBlocks} =
|
|
65
|
-
forkChoice.getAllAncestorAndNonAncestorBlocks(finalizedCheckpoint.rootHex);
|
|
64
|
+
forkChoice.getAllAncestorAndNonAncestorBlocks(finalizedCheckpoint.rootHex, finalizedCheckpoint.payloadStatus);
|
|
66
65
|
|
|
67
66
|
// NOTE: The finalized block will be exactly the first block of `epoch` or previous
|
|
68
67
|
const finalizedPostDeneb = finalizedCheckpoint.epoch >= config.DENEB_FORK_EPOCH;
|
|
@@ -20,7 +20,7 @@ export async function updateBackfillRange(
|
|
|
20
20
|
try {
|
|
21
21
|
// Mark the sequence in backfill db from finalized block's slot till anchor slot as
|
|
22
22
|
// filled.
|
|
23
|
-
const finalizedBlockFC = chain.forkChoice.
|
|
23
|
+
const finalizedBlockFC = chain.forkChoice.getBlockHexDefaultStatus(finalized.rootHex);
|
|
24
24
|
if (finalizedBlockFC && finalizedBlockFC.slot > chain.anchorStateLatestBlockSlot) {
|
|
25
25
|
await db.backfilledRanges.put(finalizedBlockFC.slot, chain.anchorStateLatestBlockSlot);
|
|
26
26
|
|
|
@@ -1,5 +1,5 @@
|
|
|
1
|
-
import {ForkName, ForkPostFulu, ForkPreDeneb, ForkPreGloas, NUMBER_OF_COLUMNS} from "@lodestar/params";
|
|
2
|
-
import {BeaconBlockBody, BlobIndex, ColumnIndex, SignedBeaconBlock, Slot, deneb, fulu} from "@lodestar/types";
|
|
1
|
+
import {ForkName, ForkPostFulu, ForkPostGloas, ForkPreDeneb, ForkPreGloas, NUMBER_OF_COLUMNS} from "@lodestar/params";
|
|
2
|
+
import {BeaconBlockBody, BlobIndex, ColumnIndex, SignedBeaconBlock, Slot, deneb, fulu, gloas} from "@lodestar/types";
|
|
3
3
|
import {byteArrayEquals, fromHex, prettyBytes, toRootHex, withTimeout} from "@lodestar/utils";
|
|
4
4
|
import {VersionedHashes} from "../../../execution/index.js";
|
|
5
5
|
import {kzgCommitmentToVersionedHash} from "../../../util/blobs.js";
|
|
@@ -24,7 +24,7 @@ import {
|
|
|
24
24
|
SourceMeta,
|
|
25
25
|
} from "./types.js";
|
|
26
26
|
|
|
27
|
-
export type BlockInput = BlockInputPreData | BlockInputBlobs | BlockInputColumns;
|
|
27
|
+
export type BlockInput = BlockInputPreData | BlockInputBlobs | BlockInputColumns | BlockInputNoData;
|
|
28
28
|
|
|
29
29
|
export function isBlockInputPreDeneb(blockInput: IBlockInput): blockInput is BlockInputPreData {
|
|
30
30
|
return blockInput.type === DAType.PreData;
|
|
@@ -37,6 +37,10 @@ export function isBlockInputColumns(blockInput: IBlockInput): blockInput is Bloc
|
|
|
37
37
|
return blockInput.type === DAType.Columns;
|
|
38
38
|
}
|
|
39
39
|
|
|
40
|
+
export function isBlockInputNoData(blockInput: IBlockInput): blockInput is BlockInputNoData {
|
|
41
|
+
return blockInput.type === DAType.NoData;
|
|
42
|
+
}
|
|
43
|
+
|
|
40
44
|
function createPromise<T>(): PromiseParts<T> {
|
|
41
45
|
let resolve!: (value: T) => void;
|
|
42
46
|
let reject!: (e: Error) => void;
|
|
@@ -101,6 +105,7 @@ abstract class AbstractBlockInput<F extends ForkName = ForkName, TData extends D
|
|
|
101
105
|
}
|
|
102
106
|
|
|
103
107
|
abstract addBlock(props: AddBlock<F>): void;
|
|
108
|
+
abstract getSerializedCacheKeys(): object[];
|
|
104
109
|
|
|
105
110
|
hasBlock(): boolean {
|
|
106
111
|
return this.state.hasBlock;
|
|
@@ -239,6 +244,10 @@ export class BlockInputPreData extends AbstractBlockInput<ForkPreDeneb, null> {
|
|
|
239
244
|
);
|
|
240
245
|
}
|
|
241
246
|
}
|
|
247
|
+
|
|
248
|
+
getSerializedCacheKeys(): object[] {
|
|
249
|
+
return [this.state.block];
|
|
250
|
+
}
|
|
242
251
|
}
|
|
243
252
|
|
|
244
253
|
// Blobs DA
|
|
@@ -522,6 +531,20 @@ export class BlockInputBlobs extends AbstractBlockInput<ForkBlobsDA, deneb.BlobS
|
|
|
522
531
|
getBlobs(): deneb.BlobSidecars {
|
|
523
532
|
return this.getAllBlobsWithSource().map(({blobSidecar}) => blobSidecar);
|
|
524
533
|
}
|
|
534
|
+
|
|
535
|
+
getSerializedCacheKeys(): object[] {
|
|
536
|
+
const objects: object[] = [];
|
|
537
|
+
|
|
538
|
+
if (this.state.hasBlock) {
|
|
539
|
+
objects.push(this.state.block);
|
|
540
|
+
}
|
|
541
|
+
|
|
542
|
+
for (const {blobSidecar} of this.blobsCache.values()) {
|
|
543
|
+
objects.push(blobSidecar);
|
|
544
|
+
}
|
|
545
|
+
|
|
546
|
+
return objects;
|
|
547
|
+
}
|
|
525
548
|
}
|
|
526
549
|
|
|
527
550
|
function blockAndBlobArePaired(block: SignedBeaconBlock<ForkBlobsDA>, blobSidecar: deneb.BlobSidecar): boolean {
|
|
@@ -902,4 +925,81 @@ export class BlockInputColumns extends AbstractBlockInput<ForkColumnsDA, fulu.Da
|
|
|
902
925
|
}
|
|
903
926
|
return Promise.resolve(this.getSampledColumns());
|
|
904
927
|
}
|
|
928
|
+
|
|
929
|
+
getSerializedCacheKeys(): object[] {
|
|
930
|
+
const objects: object[] = [];
|
|
931
|
+
|
|
932
|
+
if (this.state.hasBlock) {
|
|
933
|
+
objects.push(this.state.block);
|
|
934
|
+
}
|
|
935
|
+
|
|
936
|
+
objects.push(...this.getAllColumns());
|
|
937
|
+
|
|
938
|
+
return objects;
|
|
939
|
+
}
|
|
940
|
+
}
|
|
941
|
+
|
|
942
|
+
type BlockInputNoDataState = {
|
|
943
|
+
hasBlock: true;
|
|
944
|
+
hasAllData: true;
|
|
945
|
+
block: SignedBeaconBlock<ForkPostGloas>;
|
|
946
|
+
source: SourceMeta;
|
|
947
|
+
timeCompleteSec: number;
|
|
948
|
+
};
|
|
949
|
+
|
|
950
|
+
export class BlockInputNoData extends AbstractBlockInput<ForkPostGloas, null> {
|
|
951
|
+
type = DAType.NoData as const;
|
|
952
|
+
|
|
953
|
+
state: BlockInputNoDataState;
|
|
954
|
+
|
|
955
|
+
private constructor(init: BlockInputInit, state: BlockInputNoDataState) {
|
|
956
|
+
super(init);
|
|
957
|
+
this.state = state;
|
|
958
|
+
this.dataPromise.resolve(null);
|
|
959
|
+
this.blockPromise.resolve(state.block);
|
|
960
|
+
}
|
|
961
|
+
|
|
962
|
+
static createFromBlock(props: AddBlock<ForkPostGloas> & CreateBlockInputMeta): BlockInputNoData {
|
|
963
|
+
const init: BlockInputInit = {
|
|
964
|
+
daOutOfRange: props.daOutOfRange,
|
|
965
|
+
timeCreated: props.seenTimestampSec,
|
|
966
|
+
forkName: props.forkName,
|
|
967
|
+
slot: props.block.message.slot,
|
|
968
|
+
blockRootHex: props.blockRootHex,
|
|
969
|
+
parentRootHex: toRootHex(props.block.message.parentRoot),
|
|
970
|
+
};
|
|
971
|
+
const state: BlockInputNoDataState = {
|
|
972
|
+
hasBlock: true,
|
|
973
|
+
hasAllData: true,
|
|
974
|
+
block: props.block,
|
|
975
|
+
source: {
|
|
976
|
+
source: props.source,
|
|
977
|
+
seenTimestampSec: props.seenTimestampSec,
|
|
978
|
+
peerIdStr: props.peerIdStr,
|
|
979
|
+
},
|
|
980
|
+
timeCompleteSec: props.seenTimestampSec,
|
|
981
|
+
};
|
|
982
|
+
return new BlockInputNoData(init, state);
|
|
983
|
+
}
|
|
984
|
+
|
|
985
|
+
addBlock(_: AddBlock<ForkPostGloas>, opts = {throwOnDuplicateAdd: true}): void {
|
|
986
|
+
if (opts.throwOnDuplicateAdd) {
|
|
987
|
+
throw new BlockInputError(
|
|
988
|
+
{
|
|
989
|
+
code: BlockInputErrorCode.INVALID_CONSTRUCTION,
|
|
990
|
+
blockRoot: this.blockRootHex,
|
|
991
|
+
},
|
|
992
|
+
"Cannot addBlock to BlockInputNoData - block already exists"
|
|
993
|
+
);
|
|
994
|
+
}
|
|
995
|
+
}
|
|
996
|
+
|
|
997
|
+
getBlobKzgCommitments(): deneb.BlobKzgCommitments {
|
|
998
|
+
return (this.state.block.message.body as gloas.BeaconBlockBody).signedExecutionPayloadBid.message
|
|
999
|
+
.blobKzgCommitments;
|
|
1000
|
+
}
|
|
1001
|
+
|
|
1002
|
+
getSerializedCacheKeys(): object[] {
|
|
1003
|
+
return [this.state.block];
|
|
1004
|
+
}
|
|
905
1005
|
}
|
|
@@ -6,6 +6,7 @@ export enum DAType {
|
|
|
6
6
|
PreData = "pre-data",
|
|
7
7
|
Blobs = "blobs",
|
|
8
8
|
Columns = "columns",
|
|
9
|
+
NoData = "no-data",
|
|
9
10
|
}
|
|
10
11
|
|
|
11
12
|
export type DAData = null | deneb.BlobSidecars | fulu.DataColumnSidecars;
|
|
@@ -99,6 +100,18 @@ export type MissingColumnMeta = {
|
|
|
99
100
|
versionedHashes: VersionedHashes;
|
|
100
101
|
};
|
|
101
102
|
|
|
103
|
+
/**
|
|
104
|
+
* Minimal interface required to write data columns to the DB.
|
|
105
|
+
* Used by `writeDataColumnsToDb` and designed to be reusable across forks (e.g. Fulu, Gloas).
|
|
106
|
+
*/
|
|
107
|
+
export interface IDataColumnsInput {
|
|
108
|
+
readonly slot: Slot;
|
|
109
|
+
readonly blockRootHex: string;
|
|
110
|
+
getCustodyColumns(): fulu.DataColumnSidecars;
|
|
111
|
+
hasComputedAllData(): boolean;
|
|
112
|
+
waitForComputedAllData(timeout: number, signal?: AbortSignal): Promise<fulu.DataColumnSidecars>;
|
|
113
|
+
}
|
|
114
|
+
|
|
102
115
|
/**
|
|
103
116
|
* This is used to validate that BlockInput implementations follow some minimal subset of operations
|
|
104
117
|
* and that adding a new implementation won't break consumers that rely on this subset.
|
|
@@ -138,6 +151,11 @@ export interface IBlockInput<F extends ForkName = ForkName, TData extends DAData
|
|
|
138
151
|
|
|
139
152
|
/** Only safe to call when `hasBlockAndAllData` is true */
|
|
140
153
|
getTimeComplete(): number;
|
|
154
|
+
/**
|
|
155
|
+
* Return object references used as keys in `SerializedCache` that can be safely removed
|
|
156
|
+
* once this block input lifecycle has completed.
|
|
157
|
+
*/
|
|
158
|
+
getSerializedCacheKeys(): object[];
|
|
141
159
|
|
|
142
160
|
waitForBlock(timeout: number, signal?: AbortSignal): Promise<SignedBeaconBlock<F>>;
|
|
143
161
|
waitForAllData(timeout: number, signal?: AbortSignal): Promise<TData>;
|
|
@@ -20,7 +20,7 @@ import {
|
|
|
20
20
|
isStartSlotOfEpoch,
|
|
21
21
|
isStateValidatorsNodesPopulated,
|
|
22
22
|
} from "@lodestar/state-transition";
|
|
23
|
-
import {Attestation, BeaconBlock, altair, capella, electra, phase0, ssz} from "@lodestar/types";
|
|
23
|
+
import {Attestation, BeaconBlock, altair, capella, electra, isGloasBeaconBlock, phase0, ssz} from "@lodestar/types";
|
|
24
24
|
import {isErrorAborted, toRootHex} from "@lodestar/utils";
|
|
25
25
|
import {ZERO_HASH_HEX} from "../../constants/index.js";
|
|
26
26
|
import {callInNextEventLoop} from "../../util/eventLoop.js";
|
|
@@ -95,7 +95,7 @@ export async function importBlock(
|
|
|
95
95
|
// Without this, a supernode syncing from behind can accumulate many blocks worth of column
|
|
96
96
|
// data in memory (up to 128 columns per block) causing OOM before persistence catches up.
|
|
97
97
|
await this.unfinalizedBlockWrites.waitForSpace();
|
|
98
|
-
this.unfinalizedBlockWrites.push(
|
|
98
|
+
this.unfinalizedBlockWrites.push(blockInput).catch((e) => {
|
|
99
99
|
if (!isQueueErrorAborted(e)) {
|
|
100
100
|
this.logger.error("Error pushing block to unfinalized write queue", {slot: blockSlot}, e as Error);
|
|
101
101
|
}
|
|
@@ -230,6 +230,32 @@ export async function importBlock(
|
|
|
230
230
|
}
|
|
231
231
|
}
|
|
232
232
|
|
|
233
|
+
// 4.5. Import payload attestations to fork choice (Gloas)
|
|
234
|
+
//
|
|
235
|
+
if (isGloasBeaconBlock(block.message)) {
|
|
236
|
+
for (const payloadAttestation of block.message.body.payloadAttestations) {
|
|
237
|
+
try {
|
|
238
|
+
// Extract PTC indices from aggregation bits
|
|
239
|
+
const ptcIndices: number[] = [];
|
|
240
|
+
for (let i = 0; i < payloadAttestation.aggregationBits.bitLen; i++) {
|
|
241
|
+
if (payloadAttestation.aggregationBits.get(i)) {
|
|
242
|
+
ptcIndices.push(i);
|
|
243
|
+
}
|
|
244
|
+
}
|
|
245
|
+
|
|
246
|
+
if (ptcIndices.length > 0) {
|
|
247
|
+
this.forkChoice.notifyPtcMessages(
|
|
248
|
+
toRootHex(payloadAttestation.data.beaconBlockRoot),
|
|
249
|
+
ptcIndices,
|
|
250
|
+
payloadAttestation.data.payloadPresent
|
|
251
|
+
);
|
|
252
|
+
}
|
|
253
|
+
} catch (e) {
|
|
254
|
+
this.logger.warn("Error processing PayloadAttestation from block", {slot: blockSlot}, e as Error);
|
|
255
|
+
}
|
|
256
|
+
}
|
|
257
|
+
}
|
|
258
|
+
|
|
233
259
|
// 5. Compute head. If new head, immediately stateCache.setHeadState()
|
|
234
260
|
|
|
235
261
|
const oldHead = this.forkChoice.getHead();
|
|
@@ -345,7 +371,7 @@ export async function importBlock(
|
|
|
345
371
|
// 3) Proposer boost reorg related flag is turned on (this is checked inside the function)
|
|
346
372
|
// 4) Block meets the criteria of being re-orged out (this is also checked inside the function)
|
|
347
373
|
const result = this.forkChoice.shouldOverrideForkChoiceUpdate(
|
|
348
|
-
blockSummary
|
|
374
|
+
blockSummary,
|
|
349
375
|
this.clock.secFromSlot(currentSlot),
|
|
350
376
|
currentSlot
|
|
351
377
|
);
|
|
@@ -441,7 +467,12 @@ export async function importBlock(
|
|
|
441
467
|
this.metrics?.currentActiveValidators.set(activeValidatorsCount);
|
|
442
468
|
this.metrics?.currentValidators.set({status: "active"}, activeValidatorsCount);
|
|
443
469
|
|
|
444
|
-
const parentBlockSummary =
|
|
470
|
+
const parentBlockSummary = isGloasBeaconBlock(block.message)
|
|
471
|
+
? this.forkChoice.getBlockHexAndBlockHash(
|
|
472
|
+
toRootHex(checkpointState.latestBlockHeader.parentRoot),
|
|
473
|
+
toRootHex(block.message.body.signedExecutionPayloadBid.message.parentBlockHash)
|
|
474
|
+
)
|
|
475
|
+
: this.forkChoice.getBlockDefaultStatus(checkpointState.latestBlockHeader.parentRoot);
|
|
445
476
|
|
|
446
477
|
if (parentBlockSummary) {
|
|
447
478
|
const justifiedCheckpoint = checkpointState.currentJustifiedCheckpoint;
|
|
@@ -29,6 +29,9 @@ export async function verifyBlocksDataAvailability(
|
|
|
29
29
|
|
|
30
30
|
const availableTime = Math.max(0, Math.max(...blocks.map((blockInput) => blockInput.getTimeComplete())));
|
|
31
31
|
const dataAvailabilityStatuses: DataAvailabilityStatus[] = blocks.map((blockInput) => {
|
|
32
|
+
if (blockInput.type === DAType.NoData) {
|
|
33
|
+
return DataAvailabilityStatus.NotRequired;
|
|
34
|
+
}
|
|
32
35
|
if (blockInput.type === DAType.PreData) {
|
|
33
36
|
return DataAvailabilityStatus.PreData;
|
|
34
37
|
}
|
|
@@ -21,7 +21,7 @@ import {Metrics} from "../../metrics/metrics.js";
|
|
|
21
21
|
import {IClock} from "../../util/clock.js";
|
|
22
22
|
import {BlockError, BlockErrorCode} from "../errors/index.js";
|
|
23
23
|
import {BlockProcessOpts} from "../options.js";
|
|
24
|
-
import {isBlockInputBlobs, isBlockInputColumns} from "./blockInput/blockInput.js";
|
|
24
|
+
import {isBlockInputBlobs, isBlockInputColumns, isBlockInputNoData} from "./blockInput/blockInput.js";
|
|
25
25
|
import {IBlockInput} from "./blockInput/types.js";
|
|
26
26
|
import {ImportBlockOpts} from "./types.js";
|
|
27
27
|
|
|
@@ -51,7 +51,8 @@ type VerifyBlockExecutionResponse =
|
|
|
51
51
|
| VerifyExecutionErrorResponse
|
|
52
52
|
| {executionStatus: ExecutionStatus.Valid; lvhResponse: LVHValidResponse; execError: null}
|
|
53
53
|
| {executionStatus: ExecutionStatus.Syncing; lvhResponse?: LVHValidResponse; execError: null}
|
|
54
|
-
| {executionStatus: ExecutionStatus.PreMerge; lvhResponse: undefined; execError: null}
|
|
54
|
+
| {executionStatus: ExecutionStatus.PreMerge; lvhResponse: undefined; execError: null}
|
|
55
|
+
| {executionStatus: ExecutionStatus.PayloadSeparated; lvhResponse: undefined; execError: null};
|
|
55
56
|
|
|
56
57
|
/**
|
|
57
58
|
* Verifies 1 or more execution payloads from a linear sequence of blocks.
|
|
@@ -148,6 +149,12 @@ export async function verifyBlockExecutionPayload(
|
|
|
148
149
|
preState0: CachedBeaconStateAllForks
|
|
149
150
|
): Promise<VerifyBlockExecutionResponse> {
|
|
150
151
|
const block = blockInput.getBlock();
|
|
152
|
+
|
|
153
|
+
// Gloas block doesn't have execution payload. Return right away
|
|
154
|
+
if (isBlockInputNoData(blockInput)) {
|
|
155
|
+
return {executionStatus: ExecutionStatus.PayloadSeparated, lvhResponse: undefined, execError: null};
|
|
156
|
+
}
|
|
157
|
+
|
|
151
158
|
/** Not null if execution is enabled */
|
|
152
159
|
const executionPayloadEnabled =
|
|
153
160
|
isExecutionStateType(preState0) &&
|
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
import {ChainForkConfig} from "@lodestar/config";
|
|
2
2
|
import {IForkChoice, ProtoBlock} from "@lodestar/fork-choice";
|
|
3
3
|
import {computeStartSlotAtEpoch} from "@lodestar/state-transition";
|
|
4
|
-
import {RootHex, Slot} from "@lodestar/types";
|
|
4
|
+
import {RootHex, Slot, isGloasBeaconBlock} from "@lodestar/types";
|
|
5
5
|
import {toRootHex} from "@lodestar/utils";
|
|
6
6
|
import {IClock} from "../../util/clock.js";
|
|
7
7
|
import {BlockError, BlockErrorCode} from "../errors/index.js";
|
|
@@ -90,7 +90,12 @@ export function verifyBlocksSanityChecks(
|
|
|
90
90
|
} else {
|
|
91
91
|
// When importing a block segment, only the first NON-IGNORED block must be known to the fork-choice.
|
|
92
92
|
const parentRoot = toRootHex(block.message.parentRoot);
|
|
93
|
-
parentBlock =
|
|
93
|
+
parentBlock = isGloasBeaconBlock(block.message)
|
|
94
|
+
? chain.forkChoice.getBlockHexAndBlockHash(
|
|
95
|
+
parentRoot,
|
|
96
|
+
toRootHex(block.message.body.signedExecutionPayloadBid.message.parentBlockHash)
|
|
97
|
+
)
|
|
98
|
+
: chain.forkChoice.getBlockHexDefaultStatus(parentRoot);
|
|
94
99
|
if (!parentBlock) {
|
|
95
100
|
throw new BlockError(block, {code: BlockErrorCode.PARENT_UNKNOWN, parentRoot});
|
|
96
101
|
}
|