@lodestar/beacon-node 1.51.0-dev.f39fad29a1 → 1.51.0-dev.f41cd750ac
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 +17 -27
- package/lib/api/impl/beacon/blocks/index.js.map +1 -1
- package/lib/api/impl/beacon/pool/index.d.ts.map +1 -1
- package/lib/api/impl/beacon/pool/index.js +5 -2
- package/lib/api/impl/beacon/pool/index.js.map +1 -1
- package/lib/api/impl/beacon/state/utils.d.ts +1 -1
- package/lib/api/impl/beacon/state/utils.d.ts.map +1 -1
- package/lib/api/impl/validator/index.d.ts.map +1 -1
- package/lib/api/impl/validator/index.js +4 -1
- package/lib/api/impl/validator/index.js.map +1 -1
- package/lib/chain/GetBlobsTracker.d.ts +11 -0
- package/lib/chain/GetBlobsTracker.d.ts.map +1 -1
- package/lib/chain/GetBlobsTracker.js +85 -27
- package/lib/chain/GetBlobsTracker.js.map +1 -1
- package/lib/chain/archiveStore/archiveStore.d.ts.map +1 -1
- package/lib/chain/archiveStore/archiveStore.js +1 -0
- package/lib/chain/archiveStore/archiveStore.js.map +1 -1
- package/lib/chain/archiveStore/utils/archiveBlocks.d.ts +4 -0
- package/lib/chain/archiveStore/utils/archiveBlocks.d.ts.map +1 -1
- package/lib/chain/archiveStore/utils/archiveBlocks.js +60 -39
- package/lib/chain/archiveStore/utils/archiveBlocks.js.map +1 -1
- package/lib/chain/blocks/importBlock.d.ts.map +1 -1
- package/lib/chain/blocks/importBlock.js +6 -5
- package/lib/chain/blocks/importBlock.js.map +1 -1
- package/lib/chain/blocks/importExecutionPayload.d.ts +6 -11
- package/lib/chain/blocks/importExecutionPayload.d.ts.map +1 -1
- package/lib/chain/blocks/importExecutionPayload.js +8 -15
- package/lib/chain/blocks/importExecutionPayload.js.map +1 -1
- package/lib/chain/blocks/index.js +2 -2
- package/lib/chain/blocks/index.js.map +1 -1
- package/lib/chain/blocks/payloadEnvelopeProcessor.d.ts +12 -9
- package/lib/chain/blocks/payloadEnvelopeProcessor.d.ts.map +1 -1
- package/lib/chain/blocks/payloadEnvelopeProcessor.js +24 -19
- package/lib/chain/blocks/payloadEnvelopeProcessor.js.map +1 -1
- package/lib/chain/blocks/verifyBlock.d.ts.map +1 -1
- package/lib/chain/blocks/verifyBlock.js +1 -1
- package/lib/chain/blocks/verifyBlock.js.map +1 -1
- package/lib/chain/blocks/verifyBlocksDataAvailability.d.ts.map +1 -1
- package/lib/chain/blocks/verifyBlocksDataAvailability.js +8 -1
- package/lib/chain/blocks/verifyBlocksDataAvailability.js.map +1 -1
- package/lib/chain/blocks/verifyPayloadsDataAvailability.d.ts +3 -3
- package/lib/chain/blocks/verifyPayloadsDataAvailability.d.ts.map +1 -1
- package/lib/chain/blocks/verifyPayloadsDataAvailability.js +11 -6
- package/lib/chain/blocks/verifyPayloadsDataAvailability.js.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/types.d.ts +1 -1
- package/lib/chain/bls/multithread/types.d.ts.map +1 -1
- package/lib/chain/bls/multithread/worker.js +1 -1
- package/lib/chain/bls/multithread/worker.js.map +1 -1
- package/lib/chain/bls/singleThread.js +1 -1
- package/lib/chain/bls/singleThread.js.map +1 -1
- package/lib/chain/bls/utils.js +1 -1
- package/lib/chain/bls/utils.js.map +1 -1
- package/lib/chain/chain.d.ts +1 -1
- package/lib/chain/chain.d.ts.map +1 -1
- package/lib/chain/chain.js +4 -4
- package/lib/chain/chain.js.map +1 -1
- package/lib/chain/errors/blockError.d.ts +1 -1
- package/lib/chain/errors/blockError.d.ts.map +1 -1
- package/lib/chain/errors/blockError.js +1 -1
- package/lib/chain/errors/blockError.js.map +1 -1
- package/lib/chain/interface.d.ts +2 -3
- package/lib/chain/interface.d.ts.map +1 -1
- package/lib/chain/interface.js.map +1 -1
- package/lib/chain/opPools/aggregatedAttestationPool.d.ts.map +1 -1
- package/lib/chain/opPools/aggregatedAttestationPool.js +23 -10
- package/lib/chain/opPools/aggregatedAttestationPool.js.map +1 -1
- package/lib/chain/opPools/attestationPool.d.ts +1 -1
- package/lib/chain/opPools/attestationPool.d.ts.map +1 -1
- package/lib/chain/opPools/attestationPool.js +15 -4
- package/lib/chain/opPools/attestationPool.js.map +1 -1
- package/lib/chain/opPools/payloadAttestationPool.d.ts.map +1 -1
- package/lib/chain/opPools/payloadAttestationPool.js +17 -7
- package/lib/chain/opPools/payloadAttestationPool.js.map +1 -1
- package/lib/chain/opPools/syncCommitteeMessagePool.d.ts.map +1 -1
- package/lib/chain/opPools/syncCommitteeMessagePool.js +9 -3
- package/lib/chain/opPools/syncCommitteeMessagePool.js.map +1 -1
- package/lib/chain/opPools/syncContributionAndProofPool.d.ts.map +1 -1
- package/lib/chain/opPools/syncContributionAndProofPool.js +11 -3
- package/lib/chain/opPools/syncContributionAndProofPool.js.map +1 -1
- package/lib/chain/opPools/utils.d.ts +1 -1
- package/lib/chain/opPools/utils.d.ts.map +1 -1
- package/lib/chain/opPools/utils.js +1 -1
- package/lib/chain/opPools/utils.js.map +1 -1
- package/lib/chain/options.d.ts +0 -1
- package/lib/chain/options.d.ts.map +1 -1
- package/lib/chain/options.js +0 -1
- package/lib/chain/options.js.map +1 -1
- package/lib/chain/validation/executionPayloadBid.js +13 -13
- package/lib/chain/validation/executionPayloadBid.js.map +1 -1
- package/lib/db/beacon.d.ts +7 -0
- package/lib/db/beacon.d.ts.map +1 -1
- package/lib/db/beacon.js +32 -0
- package/lib/db/beacon.js.map +1 -1
- package/lib/db/dataColumnStore.d.ts +1 -1
- package/lib/db/dataColumnStore.d.ts.map +1 -1
- package/lib/db/dataColumnStore.js +1 -4
- package/lib/db/dataColumnStore.js.map +1 -1
- package/lib/db/flatFileStore/flatFileStore.js +5 -5
- package/lib/db/flatFileStore/flatFileStore.js.map +1 -1
- package/lib/db/flatFileStore/slotIndex.d.ts.map +1 -1
- package/lib/db/flatFileStore/slotIndex.js +2 -2
- package/lib/db/flatFileStore/slotIndex.js.map +1 -1
- package/lib/db/interface.d.ts +1 -0
- package/lib/db/interface.d.ts.map +1 -1
- package/lib/db/repositories/dataColumnSidecarArchive.d.ts +6 -0
- package/lib/db/repositories/dataColumnSidecarArchive.d.ts.map +1 -1
- package/lib/db/repositories/dataColumnSidecarArchive.js +19 -0
- package/lib/db/repositories/dataColumnSidecarArchive.js.map +1 -1
- package/lib/execution/engine/index.d.ts +1 -1
- package/lib/execution/engine/index.d.ts.map +1 -1
- package/lib/execution/engine/index.js +1 -1
- package/lib/execution/engine/index.js.map +1 -1
- package/lib/execution/engine/interface.d.ts +1 -1
- package/lib/execution/engine/interface.d.ts.map +1 -1
- package/lib/execution/engine/interface.js.map +1 -1
- package/lib/execution/engine/types.d.ts.map +1 -1
- package/lib/execution/engine/types.js +2 -2
- package/lib/execution/engine/types.js.map +1 -1
- package/lib/metrics/metrics/lodestar.d.ts +3 -0
- package/lib/metrics/metrics/lodestar.d.ts.map +1 -1
- package/lib/metrics/metrics/lodestar.js +5 -0
- package/lib/metrics/metrics/lodestar.js.map +1 -1
- package/lib/monitoring/service.js +1 -1
- package/lib/monitoring/service.js.map +1 -1
- package/lib/network/core/networkCore.d.ts +2 -0
- package/lib/network/core/networkCore.d.ts.map +1 -1
- package/lib/network/core/networkCore.js +3 -0
- package/lib/network/core/networkCore.js.map +1 -1
- package/lib/network/core/networkCoreWorker.js +1 -0
- package/lib/network/core/networkCoreWorker.js.map +1 -1
- package/lib/network/core/networkCoreWorkerHandler.d.ts +2 -0
- package/lib/network/core/networkCoreWorkerHandler.d.ts.map +1 -1
- package/lib/network/core/networkCoreWorkerHandler.js +3 -0
- package/lib/network/core/networkCoreWorkerHandler.js.map +1 -1
- package/lib/network/core/types.d.ts +2 -0
- package/lib/network/core/types.d.ts.map +1 -1
- package/lib/network/interface.d.ts +2 -0
- package/lib/network/interface.d.ts.map +1 -1
- package/lib/network/libp2p/index.d.ts.map +1 -1
- package/lib/network/libp2p/index.js +5 -1
- package/lib/network/libp2p/index.js.map +1 -1
- package/lib/network/network.d.ts +2 -0
- package/lib/network/network.d.ts.map +1 -1
- package/lib/network/network.js +6 -1
- package/lib/network/network.js.map +1 -1
- package/lib/network/options.d.ts +2 -0
- package/lib/network/options.d.ts.map +1 -1
- package/lib/network/options.js.map +1 -1
- package/lib/network/peers/peerManager.d.ts +2 -1
- package/lib/network/peers/peerManager.d.ts.map +1 -1
- package/lib/network/peers/peerManager.js.map +1 -1
- package/lib/network/peers/utils/assertPeerRelevance.d.ts +9 -1
- package/lib/network/peers/utils/assertPeerRelevance.d.ts.map +1 -1
- package/lib/network/peers/utils/assertPeerRelevance.js +32 -21
- package/lib/network/peers/utils/assertPeerRelevance.js.map +1 -1
- package/lib/network/processor/gossipHandlers.d.ts.map +1 -1
- package/lib/network/processor/gossipHandlers.js +9 -8
- package/lib/network/processor/gossipHandlers.js.map +1 -1
- package/lib/node/nodejs.d.ts +1 -1
- package/lib/node/nodejs.d.ts.map +1 -1
- package/lib/node/nodejs.js +10 -2
- package/lib/node/nodejs.js.map +1 -1
- package/lib/node/options.d.ts +1 -1
- package/lib/node/options.d.ts.map +1 -1
- package/lib/node/options.js +1 -1
- package/lib/node/options.js.map +1 -1
- package/lib/sync/interface.d.ts.map +1 -1
- package/lib/sync/interface.js.map +1 -1
- package/lib/sync/sync.d.ts +7 -0
- package/lib/sync/sync.d.ts.map +1 -1
- package/lib/sync/sync.js +61 -3
- package/lib/sync/sync.js.map +1 -1
- package/lib/util/file.d.ts.map +1 -1
- package/lib/util/file.js +8 -9
- package/lib/util/file.js.map +1 -1
- package/lib/util/queue/itemQueue.js +1 -1
- package/lib/util/queue/itemQueue.js.map +1 -1
- package/lib/util/sszBytes.js +2 -2
- package/lib/util/sszBytes.js.map +1 -1
- package/package.json +16 -17
- package/src/api/impl/beacon/blocks/index.ts +35 -45
- package/src/api/impl/beacon/pool/index.ts +5 -1
- package/src/api/impl/beacon/state/utils.ts +1 -1
- package/src/api/impl/validator/index.ts +4 -1
- package/src/chain/GetBlobsTracker.ts +97 -38
- package/src/chain/archiveStore/archiveStore.ts +1 -0
- package/src/chain/archiveStore/utils/archiveBlocks.ts +75 -46
- package/src/chain/blocks/importBlock.ts +8 -7
- package/src/chain/blocks/importExecutionPayload.ts +13 -21
- package/src/chain/blocks/index.ts +6 -2
- package/src/chain/blocks/payloadEnvelopeProcessor.ts +35 -24
- package/src/chain/blocks/verifyBlock.ts +1 -0
- package/src/chain/blocks/verifyBlocksDataAvailability.ts +10 -1
- package/src/chain/blocks/verifyPayloadsDataAvailability.ts +14 -6
- package/src/chain/bls/multithread/index.ts +5 -5
- package/src/chain/bls/multithread/types.ts +1 -1
- package/src/chain/bls/multithread/worker.ts +1 -5
- package/src/chain/bls/singleThread.ts +1 -1
- package/src/chain/bls/utils.ts +1 -1
- package/src/chain/chain.ts +5 -5
- package/src/chain/errors/blockError.ts +1 -1
- package/src/chain/interface.ts +2 -3
- package/src/chain/opPools/aggregatedAttestationPool.ts +25 -9
- package/src/chain/opPools/attestationPool.ts +16 -4
- package/src/chain/opPools/payloadAttestationPool.ts +18 -7
- package/src/chain/opPools/syncCommitteeMessagePool.ts +10 -3
- package/src/chain/opPools/syncContributionAndProofPool.ts +13 -3
- package/src/chain/opPools/utils.ts +1 -1
- package/src/chain/options.ts +0 -2
- package/src/chain/validation/executionPayloadBid.ts +14 -13
- package/src/db/beacon.ts +39 -0
- package/src/db/dataColumnStore.ts +2 -4
- package/src/db/flatFileStore/flatFileStore.ts +7 -7
- package/src/db/flatFileStore/slotIndex.ts +4 -3
- package/src/db/interface.ts +2 -0
- package/src/db/repositories/dataColumnSidecarArchive.ts +20 -0
- package/src/execution/engine/index.ts +1 -1
- package/src/execution/engine/interface.ts +1 -1
- package/src/execution/engine/types.ts +3 -1
- package/src/metrics/metrics/lodestar.ts +5 -0
- package/src/monitoring/service.ts +1 -1
- package/src/network/core/networkCore.ts +5 -0
- package/src/network/core/networkCoreWorker.ts +1 -0
- package/src/network/core/networkCoreWorkerHandler.ts +4 -0
- package/src/network/core/types.ts +2 -0
- package/src/network/interface.ts +2 -0
- package/src/network/libp2p/index.ts +5 -1
- package/src/network/network.ts +8 -1
- package/src/network/options.ts +2 -0
- package/src/network/peers/peerManager.ts +1 -1
- package/src/network/peers/utils/assertPeerRelevance.ts +39 -23
- package/src/network/processor/gossipHandlers.ts +9 -8
- package/src/node/nodejs.ts +24 -7
- package/src/node/options.ts +4 -5
- package/src/sync/interface.ts +1 -0
- package/src/sync/sync.ts +65 -4
- package/src/util/file.ts +8 -9
- package/src/util/queue/itemQueue.ts +1 -1
- package/src/util/sszBytes.ts +2 -2
|
@@ -1,5 +1,6 @@
|
|
|
1
|
-
import {ForkName, isForkPostFulu} from "@lodestar/params";
|
|
2
|
-
import {
|
|
1
|
+
import {ForkName, GENESIS_EPOCH, isForkPostFulu} from "@lodestar/params";
|
|
2
|
+
import {computeEpochAtSlot} from "@lodestar/state-transition";
|
|
3
|
+
import {Epoch, ForkDigest, Root, Slot, Status, fulu, ssz} from "@lodestar/types";
|
|
3
4
|
import {toHex, toRootHex} from "@lodestar/utils";
|
|
4
5
|
|
|
5
6
|
// TODO: Why this value? (From Lighthouse)
|
|
@@ -9,6 +10,8 @@ export enum IrrelevantPeerCode {
|
|
|
9
10
|
INCOMPATIBLE_FORKS = "IRRELEVANT_PEER_INCOMPATIBLE_FORKS",
|
|
10
11
|
DIFFERENT_CLOCKS = "IRRELEVANT_PEER_DIFFERENT_CLOCKS",
|
|
11
12
|
DIFFERENT_FINALIZED = "IRRELEVANT_PEER_DIFFERENT_FINALIZED",
|
|
13
|
+
FINALIZED_EPOCH_TOO_HIGH = "IRRELEVANT_PEER_FINALIZED_EPOCH_TOO_HIGH",
|
|
14
|
+
INVALID_FINALIZED_ROOT = "IRRELEVANT_PEER_INVALID_FINALIZED_ROOT",
|
|
12
15
|
NO_EARLIEST_AVAILABLE_SLOT = "NO_EARLIEST_AVAILABLE_SLOT",
|
|
13
16
|
}
|
|
14
17
|
|
|
@@ -16,6 +19,8 @@ type IrrelevantPeerType =
|
|
|
16
19
|
| {code: IrrelevantPeerCode.INCOMPATIBLE_FORKS; ours: ForkDigest; theirs: ForkDigest}
|
|
17
20
|
| {code: IrrelevantPeerCode.DIFFERENT_CLOCKS; slotDiff: number}
|
|
18
21
|
| {code: IrrelevantPeerCode.NO_EARLIEST_AVAILABLE_SLOT}
|
|
22
|
+
| {code: IrrelevantPeerCode.FINALIZED_EPOCH_TOO_HIGH; finalizedEpoch: Epoch; maxFinalizedEpoch: Epoch}
|
|
23
|
+
| {code: IrrelevantPeerCode.INVALID_FINALIZED_ROOT}
|
|
19
24
|
| {code: IrrelevantPeerCode.DIFFERENT_FINALIZED; expectedRoot: Root; remoteRoot: Root};
|
|
20
25
|
|
|
21
26
|
/**
|
|
@@ -45,29 +50,35 @@ export function assertPeerRelevance(
|
|
|
45
50
|
return {code: IrrelevantPeerCode.DIFFERENT_CLOCKS, slotDiff};
|
|
46
51
|
}
|
|
47
52
|
|
|
48
|
-
//
|
|
49
|
-
|
|
50
|
-
|
|
53
|
+
// A checkpoint can be finalized at the earliest at the start of epoch + 2
|
|
54
|
+
const maxFinalizedEpoch = Math.max(
|
|
55
|
+
GENESIS_EPOCH,
|
|
56
|
+
computeEpochAtSlot(Math.max(currentSlot, 0) + FUTURE_SLOT_TOLERANCE) - 2
|
|
57
|
+
);
|
|
58
|
+
if (remote.finalizedEpoch > maxFinalizedEpoch) {
|
|
59
|
+
return {
|
|
60
|
+
code: IrrelevantPeerCode.FINALIZED_EPOCH_TOO_HIGH,
|
|
61
|
+
finalizedEpoch: remote.finalizedEpoch,
|
|
62
|
+
maxFinalizedEpoch,
|
|
63
|
+
};
|
|
64
|
+
}
|
|
65
|
+
|
|
66
|
+
if (remote.finalizedEpoch > GENESIS_EPOCH && isZeroRoot(remote.finalizedRoot)) {
|
|
67
|
+
return {code: IrrelevantPeerCode.INVALID_FINALIZED_ROOT};
|
|
68
|
+
}
|
|
51
69
|
|
|
70
|
+
// The remote's finalized epoch is equal to ours, but the block root is different to the one in our chain.
|
|
71
|
+
// Therefore, the node is on a different chain and we should not communicate with them.
|
|
52
72
|
if (
|
|
53
|
-
remote.finalizedEpoch
|
|
54
|
-
!isZeroRoot(
|
|
55
|
-
!
|
|
73
|
+
remote.finalizedEpoch === local.finalizedEpoch &&
|
|
74
|
+
!isZeroRoot(local.finalizedRoot) &&
|
|
75
|
+
!ssz.Root.equals(remote.finalizedRoot, local.finalizedRoot)
|
|
56
76
|
) {
|
|
57
|
-
|
|
58
|
-
|
|
59
|
-
|
|
60
|
-
|
|
61
|
-
|
|
62
|
-
const expectedRoot = remote.finalizedEpoch === local.finalizedEpoch ? local.finalizedRoot : null;
|
|
63
|
-
|
|
64
|
-
if (expectedRoot !== null && !ssz.Root.equals(remoteRoot, expectedRoot)) {
|
|
65
|
-
return {
|
|
66
|
-
code: IrrelevantPeerCode.DIFFERENT_FINALIZED,
|
|
67
|
-
expectedRoot: expectedRoot, // forkChoice returns Tree BranchNode which the logger prints as {}
|
|
68
|
-
remoteRoot: remoteRoot,
|
|
69
|
-
};
|
|
70
|
-
}
|
|
77
|
+
return {
|
|
78
|
+
code: IrrelevantPeerCode.DIFFERENT_FINALIZED,
|
|
79
|
+
expectedRoot: local.finalizedRoot,
|
|
80
|
+
remoteRoot: remote.finalizedRoot,
|
|
81
|
+
};
|
|
71
82
|
}
|
|
72
83
|
|
|
73
84
|
if (isForkPostFulu(forkName) && (remote as fulu.Status).earliestAvailableSlot === undefined) {
|
|
@@ -76,7 +87,8 @@ export function assertPeerRelevance(
|
|
|
76
87
|
};
|
|
77
88
|
}
|
|
78
89
|
|
|
79
|
-
// Note:
|
|
90
|
+
// Note: for a behind finalized checkpoint, we validate it more on the main thread against our history,
|
|
91
|
+
// see BeaconSync.verifyPastFinalizedCheckpoint
|
|
80
92
|
return null;
|
|
81
93
|
}
|
|
82
94
|
|
|
@@ -93,6 +105,10 @@ export function renderIrrelevantPeerType(type: IrrelevantPeerType): string {
|
|
|
93
105
|
return `DIFFERENT_CLOCKS slotDiff: ${type.slotDiff}`;
|
|
94
106
|
case IrrelevantPeerCode.DIFFERENT_FINALIZED:
|
|
95
107
|
return `DIFFERENT_FINALIZED root: ${toRootHex(type.remoteRoot)} expected: ${toRootHex(type.expectedRoot)}`;
|
|
108
|
+
case IrrelevantPeerCode.FINALIZED_EPOCH_TOO_HIGH:
|
|
109
|
+
return `FINALIZED_EPOCH_TOO_HIGH finalizedEpoch: ${type.finalizedEpoch} max: ${type.maxFinalizedEpoch}`;
|
|
110
|
+
case IrrelevantPeerCode.INVALID_FINALIZED_ROOT:
|
|
111
|
+
return "INVALID_FINALIZED_ROOT zero root for a non-genesis finalized epoch";
|
|
96
112
|
case IrrelevantPeerCode.NO_EARLIEST_AVAILABLE_SLOT:
|
|
97
113
|
return "No earliestAvailableSlot announced via peer Status";
|
|
98
114
|
}
|
|
@@ -705,10 +705,8 @@ function getSequentialHandlers(modules: ValidatorFnsModules, options: GossipHand
|
|
|
705
705
|
|
|
706
706
|
// Immediately attempt fetch of data columns from execution engine as the bid contains kzg commitments
|
|
707
707
|
// which is all the information we need so there is no reason to delay until execution payload arrives
|
|
708
|
-
//
|
|
709
|
-
//
|
|
710
|
-
// Columns fetched here feed payloadInput.addColumn, which resolves waitForAllData for any
|
|
711
|
-
// in-flight importExecutionPayload. No processExecutionPayload trigger needed from this path.
|
|
708
|
+
// Columns fetched here feed payloadInput.addColumn, which resolves the waitForAllData of a
|
|
709
|
+
// pending payload import. No processExecutionPayload trigger needed from this path.
|
|
712
710
|
chain.getBlobsTracker.triggerGetBlobs(payloadInput);
|
|
713
711
|
}
|
|
714
712
|
})
|
|
@@ -718,11 +716,10 @@ function getSequentialHandlers(modules: ValidatorFnsModules, options: GossipHand
|
|
|
718
716
|
|
|
719
717
|
if (e instanceof BlockError) {
|
|
720
718
|
switch (e.type.code) {
|
|
721
|
-
case BlockErrorCode.DATA_UNAVAILABLE:
|
|
722
|
-
//
|
|
719
|
+
case BlockErrorCode.DATA_UNAVAILABLE:
|
|
720
|
+
// Data did not arrive in time, BlockInputSync keeps pulling it and retries the import
|
|
723
721
|
logLevel = LogLevel.debug;
|
|
724
722
|
break;
|
|
725
|
-
}
|
|
726
723
|
// ALREADY_KNOWN should not happen with ignoreIfKnown=true above
|
|
727
724
|
// PARENT_BLOCK_UNKNOWN should not happen, we handled this in validateBeaconBlock() function above
|
|
728
725
|
case BlockErrorCode.ALREADY_KNOWN:
|
|
@@ -930,7 +927,7 @@ function getSequentialHandlers(modules: ValidatorFnsModules, options: GossipHand
|
|
|
930
927
|
}
|
|
931
928
|
|
|
932
929
|
// NOTE: we do NOT call chain.processExecutionPayload here. That is triggered only by
|
|
933
|
-
// envelope arrival (gossip or API).
|
|
930
|
+
// envelope arrival (gossip or API). A pending payload import is awaiting
|
|
934
931
|
// payloadInput.waitForAllData(); addColumn above will resolve it once hasAllData flips.
|
|
935
932
|
|
|
936
933
|
scheduleIncompletePayloadEnvelope(payloadInput, peerIdStr);
|
|
@@ -1358,6 +1355,10 @@ function getSequentialHandlers(modules: ValidatorFnsModules, options: GossipHand
|
|
|
1358
1355
|
|
|
1359
1356
|
if (e instanceof PayloadError) {
|
|
1360
1357
|
switch (e.type.code) {
|
|
1358
|
+
case PayloadErrorCode.DATA_UNAVAILABLE:
|
|
1359
|
+
// Columns did not arrive in time, BlockInputSync keeps pulling them and retries the import
|
|
1360
|
+
logLevel = LogLevel.debug;
|
|
1361
|
+
break;
|
|
1361
1362
|
// BLOCK_NOT_IN_FORK_CHOICE should not happen, validateGossipExecutionPayloadEnvelope above
|
|
1362
1363
|
// already verified the block is in fork choice
|
|
1363
1364
|
case PayloadErrorCode.BLOCK_NOT_IN_FORK_CHOICE:
|
package/src/node/nodejs.ts
CHANGED
|
@@ -1,23 +1,29 @@
|
|
|
1
1
|
import {setMaxListeners} from "node:events";
|
|
2
2
|
import {PrivateKey} from "@libp2p/interface";
|
|
3
3
|
import {Registry} from "prom-client";
|
|
4
|
+
import {hasher} from "@chainsafe/persistent-merkle-tree";
|
|
5
|
+
import {BeaconApiMethods} from "@lodestar/api/beacon/server";
|
|
6
|
+
import {BeaconConfig} from "@lodestar/config";
|
|
7
|
+
import type {LoggerNode} from "@lodestar/logger/node";
|
|
4
8
|
import {
|
|
5
9
|
init as initNativeMetrics,
|
|
6
10
|
registerLocalValidator as registerNativeLocalValidator,
|
|
7
11
|
scrapeMetrics as scrapeNativeMetrics,
|
|
8
12
|
unregisterLocalValidator as unregisterNativeLocalValidator,
|
|
9
|
-
} from "@
|
|
10
|
-
import {type PubkeyCache} from "@
|
|
11
|
-
import {hasher} from "@chainsafe/persistent-merkle-tree";
|
|
12
|
-
import {BeaconApiMethods} from "@lodestar/api/beacon/server";
|
|
13
|
-
import {BeaconConfig} from "@lodestar/config";
|
|
14
|
-
import type {LoggerNode} from "@lodestar/logger/node";
|
|
13
|
+
} from "@lodestar/native/metrics";
|
|
14
|
+
import {type PubkeyCache} from "@lodestar/native/pubkeys";
|
|
15
15
|
import {ZERO_HASH_HEX} from "@lodestar/params";
|
|
16
|
-
import {
|
|
16
|
+
import {
|
|
17
|
+
IBeaconStateView,
|
|
18
|
+
computeStartSlotAtEpoch,
|
|
19
|
+
isStatePostBellatrix,
|
|
20
|
+
isStatePostGloas,
|
|
21
|
+
} from "@lodestar/state-transition";
|
|
17
22
|
import {Slot} from "@lodestar/types";
|
|
18
23
|
import {sleep, toRootHex} from "@lodestar/utils";
|
|
19
24
|
import {ProcessShutdownCallback} from "@lodestar/validator";
|
|
20
25
|
import {BeaconRestApiServer, getApi} from "../api/index.js";
|
|
26
|
+
import {getDataColumnSidecarsMinEpoch} from "../chain/archiveStore/utils/archiveBlocks.js";
|
|
21
27
|
import {BeaconChain, IBeaconChain, initBeaconMetrics} from "../chain/index.js";
|
|
22
28
|
import {ValidatorMonitor, createValidatorMonitor} from "../chain/validatorMonitor.js";
|
|
23
29
|
import {IBeaconDb} from "../db/index.js";
|
|
@@ -212,6 +218,17 @@ export class BeaconNode {
|
|
|
212
218
|
|
|
213
219
|
const clock = new Clock({config, genesisTime: anchorState.genesisTime, signal});
|
|
214
220
|
|
|
221
|
+
// Before any lookup into the legacy column buckets, which can be slow until compacted
|
|
222
|
+
const columnsMinEpoch =
|
|
223
|
+
opts.chain.archiveDataEpochs === Infinity
|
|
224
|
+
? null
|
|
225
|
+
: getDataColumnSidecarsMinEpoch(config, clock.currentEpoch, opts.chain.archiveDataEpochs);
|
|
226
|
+
await db.compactLegacyDataColumns(
|
|
227
|
+
columnsMinEpoch !== null && columnsMinEpoch >= config.FULU_FORK_EPOCH
|
|
228
|
+
? computeStartSlotAtEpoch(columnsMinEpoch)
|
|
229
|
+
: 0
|
|
230
|
+
);
|
|
231
|
+
|
|
215
232
|
await db.init();
|
|
216
233
|
|
|
217
234
|
// Prune hot db repos
|
package/src/node/options.ts
CHANGED
|
@@ -19,16 +19,15 @@ import {SyncOptions, defaultSyncOptions} from "../sync/options.js";
|
|
|
19
19
|
|
|
20
20
|
// Re-export so the CLI doesn't need to depend on lodestar-api
|
|
21
21
|
export {allNamespaces} from "../api/rest/index.js";
|
|
22
|
-
|
|
22
|
+
export type {EngineApiMode};
|
|
23
23
|
// Re-export to use as default values in CLI args
|
|
24
24
|
export {
|
|
25
|
-
defaultExecutionEngineHttpOpts,
|
|
26
|
-
defaultExecutionBuilderHttpOpts,
|
|
27
|
-
engineApiModes,
|
|
28
25
|
ArchiveMode,
|
|
29
26
|
DEFAULT_ARCHIVE_MODE,
|
|
27
|
+
defaultExecutionBuilderHttpOpts,
|
|
28
|
+
defaultExecutionEngineHttpOpts,
|
|
29
|
+
engineApiModes,
|
|
30
30
|
};
|
|
31
|
-
export type {EngineApiMode};
|
|
32
31
|
|
|
33
32
|
export interface IBeaconNodeOptions {
|
|
34
33
|
api: ApiOptions;
|
package/src/sync/interface.ts
CHANGED
|
@@ -7,6 +7,7 @@ import {IBeaconDb} from "../db/index.js";
|
|
|
7
7
|
import {Metrics} from "../metrics/index.js";
|
|
8
8
|
import {INetwork} from "../network/index.js";
|
|
9
9
|
import {SyncChainDebugState} from "./range/chain.js";
|
|
10
|
+
|
|
10
11
|
export type {SyncChainDebugState};
|
|
11
12
|
|
|
12
13
|
export type SyncingStatus = routes.node.SyncingStatus;
|
package/src/sync/sync.ts
CHANGED
|
@@ -1,13 +1,17 @@
|
|
|
1
1
|
import {SLOTS_PER_EPOCH} from "@lodestar/params";
|
|
2
|
-
import {
|
|
2
|
+
import {computeStartSlotAtEpoch} from "@lodestar/state-transition";
|
|
3
|
+
import {Slot, Status} from "@lodestar/types";
|
|
3
4
|
import {Logger, toRootHex} from "@lodestar/utils";
|
|
4
5
|
import {IBeaconChain} from "../chain/index.js";
|
|
5
|
-
import {GENESIS_SLOT} from "../constants/constants.js";
|
|
6
|
+
import {GENESIS_EPOCH, GENESIS_SLOT} from "../constants/constants.js";
|
|
7
|
+
import {GoodByeReasonCode} from "../constants/index.js";
|
|
8
|
+
import {IBeaconDb} from "../db/index.js";
|
|
6
9
|
import {ExecutionEngineState} from "../execution/index.js";
|
|
7
10
|
import {Metrics} from "../metrics/index.js";
|
|
8
|
-
import {INetwork, NetworkEvent, NetworkEventData} from "../network/index.js";
|
|
11
|
+
import {INetwork, NetworkEvent, NetworkEventData, PeerAction} from "../network/index.js";
|
|
9
12
|
import {ClockEvent} from "../util/clock.js";
|
|
10
13
|
import {isOptimisticBlock} from "../util/forkChoice.js";
|
|
14
|
+
import {PeerIdStr} from "../util/peerId.js";
|
|
11
15
|
import {MIN_EPOCH_TO_START_GOSSIP} from "./constants.js";
|
|
12
16
|
import {IBeaconSync, SyncChainDebugState, SyncModules, SyncState, SyncingStatus, syncStateMetric} from "./interface.js";
|
|
13
17
|
import {SyncOptions} from "./options.js";
|
|
@@ -19,6 +23,7 @@ export class BeaconSync implements IBeaconSync {
|
|
|
19
23
|
private readonly logger: Logger;
|
|
20
24
|
private readonly network: INetwork;
|
|
21
25
|
private readonly chain: IBeaconChain;
|
|
26
|
+
private readonly db: IBeaconDb;
|
|
22
27
|
private readonly metrics: Metrics | null;
|
|
23
28
|
private readonly opts: SyncOptions;
|
|
24
29
|
|
|
@@ -30,10 +35,11 @@ export class BeaconSync implements IBeaconSync {
|
|
|
30
35
|
private readonly slotImportTolerance: Slot;
|
|
31
36
|
|
|
32
37
|
constructor(opts: SyncOptions, modules: SyncModules) {
|
|
33
|
-
const {config, chain, metrics, network, logger} = modules;
|
|
38
|
+
const {config, chain, db, metrics, network, logger} = modules;
|
|
34
39
|
this.opts = opts;
|
|
35
40
|
this.network = network;
|
|
36
41
|
this.chain = chain;
|
|
42
|
+
this.db = db;
|
|
37
43
|
this.metrics = metrics;
|
|
38
44
|
this.logger = logger;
|
|
39
45
|
this.rangeSync = new RangeSync(modules, opts);
|
|
@@ -192,6 +198,11 @@ export class BeaconSync implements IBeaconSync {
|
|
|
192
198
|
*/
|
|
193
199
|
private addPeer = (data: NetworkEventData[NetworkEvent.peerConnected]): void => {
|
|
194
200
|
const localStatus = this.chain.getStatus();
|
|
201
|
+
// Genesis and equal finalized epochs are already checked by assertPeerRelevance in the network worker
|
|
202
|
+
if (data.status.finalizedEpoch > GENESIS_EPOCH && data.status.finalizedEpoch < localStatus.finalizedEpoch) {
|
|
203
|
+
void this.verifyPastFinalizedCheckpoint(data.peer, data.status);
|
|
204
|
+
}
|
|
205
|
+
|
|
195
206
|
const syncType = getPeerSyncType(localStatus, data.status, this.chain.forkChoice, this.slotImportTolerance);
|
|
196
207
|
this.logger.verbose("Peer sync type classified", {
|
|
197
208
|
peer: data.peer,
|
|
@@ -216,6 +227,56 @@ export class BeaconSync implements IBeaconSync {
|
|
|
216
227
|
this.updateSyncState();
|
|
217
228
|
};
|
|
218
229
|
|
|
230
|
+
/**
|
|
231
|
+
* A behind peer's finalized checkpoint must be the canonical block in effect at the start slot of its epoch
|
|
232
|
+
*/
|
|
233
|
+
async verifyPastFinalizedCheckpoint(peer: PeerIdStr, remote: Status): Promise<void> {
|
|
234
|
+
const startSlot = computeStartSlotAtEpoch(remote.finalizedEpoch);
|
|
235
|
+
const root = toRootHex(remote.finalizedRoot);
|
|
236
|
+
try {
|
|
237
|
+
let reason: string | null = null;
|
|
238
|
+
// After a finality jump, finalized blocks stay in fork choice until the archiver migrates them.
|
|
239
|
+
// Fork choice is pruned only after archiving, so a miss here means the db already has this range.
|
|
240
|
+
const canonicalBlock = this.chain.forkChoice.getCanonicalBlockClosestLteSlot(startSlot);
|
|
241
|
+
if (canonicalBlock !== null) {
|
|
242
|
+
if (canonicalBlock.blockRoot === root) return;
|
|
243
|
+
reason = "finalized_root_not_canonical";
|
|
244
|
+
} else {
|
|
245
|
+
const slot = await this.db.blockArchive.getSlotByRoot(remote.finalizedRoot);
|
|
246
|
+
if (slot !== null && slot > startSlot) {
|
|
247
|
+
reason = "finalized_root_after_epoch_start";
|
|
248
|
+
} else if (slot !== startSlot) {
|
|
249
|
+
const childSlot = await this.db.blockArchive.getSlotByParentRoot(remote.finalizedRoot);
|
|
250
|
+
if (childSlot !== null) {
|
|
251
|
+
if (childSlot <= startSlot) reason = "finalized_root_not_in_effect_at_epoch_start";
|
|
252
|
+
} else if (slot === null && startSlot > this.chain.earliestAvailableSlot) {
|
|
253
|
+
// childSlot == null too, neither the root nor a child is canonical
|
|
254
|
+
// or they are canonical and both pruned but peer's finalized epoch starts after earliestAvailableSlot
|
|
255
|
+
reason = "unknown_finalized_root";
|
|
256
|
+
}
|
|
257
|
+
}
|
|
258
|
+
}
|
|
259
|
+
|
|
260
|
+
if (reason !== null) {
|
|
261
|
+
this.logger.debug("Peer finalized checkpoint not in our chain", {
|
|
262
|
+
peer,
|
|
263
|
+
finalizedEpoch: remote.finalizedEpoch,
|
|
264
|
+
root,
|
|
265
|
+
reason,
|
|
266
|
+
});
|
|
267
|
+
this.metrics?.syncPeerFinalizedCheckpointMismatch.inc({reason});
|
|
268
|
+
this.network.reportPeer(peer, PeerAction.Fatal, "PeerFinalizedCheckpointMismatch");
|
|
269
|
+
await this.network.goodbyeAndDisconnect(peer, GoodByeReasonCode.IRRELEVANT_NETWORK);
|
|
270
|
+
}
|
|
271
|
+
} catch (e) {
|
|
272
|
+
this.logger.debug(
|
|
273
|
+
"Error verifying peer finalized checkpoint",
|
|
274
|
+
{peer, finalizedEpoch: remote.finalizedEpoch, root},
|
|
275
|
+
e as Error
|
|
276
|
+
);
|
|
277
|
+
}
|
|
278
|
+
}
|
|
279
|
+
|
|
219
280
|
/**
|
|
220
281
|
* Must be called by libp2p when a peer is removed from the peer manager
|
|
221
282
|
*/
|
package/src/util/file.ts
CHANGED
|
@@ -1,25 +1,24 @@
|
|
|
1
|
-
import
|
|
2
|
-
import {promisify} from "node:util";
|
|
1
|
+
import {readFile as fsReadFile, mkdir, readdir, stat, unlink, writeFile} from "node:fs/promises";
|
|
3
2
|
|
|
4
3
|
/** Ensure a directory exists */
|
|
5
4
|
export async function ensureDir(path: string): Promise<void> {
|
|
6
5
|
try {
|
|
7
|
-
await
|
|
6
|
+
await stat(path);
|
|
8
7
|
} catch (_) {
|
|
9
8
|
// not exists
|
|
10
|
-
await
|
|
9
|
+
await mkdir(path, {recursive: true});
|
|
11
10
|
}
|
|
12
11
|
}
|
|
13
12
|
|
|
14
13
|
/** Write data to a file if it does not exist */
|
|
15
14
|
export async function writeIfNotExist(filepath: string, bytes: Uint8Array): Promise<boolean> {
|
|
16
15
|
try {
|
|
17
|
-
await
|
|
16
|
+
await stat(filepath);
|
|
18
17
|
return false;
|
|
19
18
|
// file exists, do nothing
|
|
20
19
|
} catch (_) {
|
|
21
20
|
// not exists
|
|
22
|
-
await
|
|
21
|
+
await writeFile(filepath, bytes);
|
|
23
22
|
return true;
|
|
24
23
|
}
|
|
25
24
|
}
|
|
@@ -27,7 +26,7 @@ export async function writeIfNotExist(filepath: string, bytes: Uint8Array): Prom
|
|
|
27
26
|
/** Remove a file if it exists */
|
|
28
27
|
export async function removeFile(path: string): Promise<boolean> {
|
|
29
28
|
try {
|
|
30
|
-
await
|
|
29
|
+
await unlink(path);
|
|
31
30
|
return true;
|
|
32
31
|
} catch (_) {
|
|
33
32
|
// may not exists
|
|
@@ -37,7 +36,7 @@ export async function removeFile(path: string): Promise<boolean> {
|
|
|
37
36
|
|
|
38
37
|
export async function readFile(path: string): Promise<Uint8Array | null> {
|
|
39
38
|
try {
|
|
40
|
-
return await
|
|
39
|
+
return await fsReadFile(path);
|
|
41
40
|
} catch (_) {
|
|
42
41
|
return null;
|
|
43
42
|
}
|
|
@@ -45,7 +44,7 @@ export async function readFile(path: string): Promise<Uint8Array | null> {
|
|
|
45
44
|
|
|
46
45
|
export async function readFileNames(folderPath: string): Promise<string[]> {
|
|
47
46
|
try {
|
|
48
|
-
return await
|
|
47
|
+
return await readdir(folderPath);
|
|
49
48
|
} catch (_) {
|
|
50
49
|
return [];
|
|
51
50
|
}
|
|
@@ -69,7 +69,7 @@ export class JobItemQueue<Args extends any[], R> {
|
|
|
69
69
|
if (this.jobs.length === 1 && this.opts.noYieldIfOneItem) {
|
|
70
70
|
void this.runJob();
|
|
71
71
|
} else if (this.runningJobs < this.opts.maxConcurrency) {
|
|
72
|
-
callInNextEventLoop(this.runJob);
|
|
72
|
+
callInNextEventLoop(() => void this.runJob());
|
|
73
73
|
}
|
|
74
74
|
});
|
|
75
75
|
}
|
package/src/util/sszBytes.ts
CHANGED
|
@@ -854,7 +854,7 @@ export function getBlobKzgCommitmentsCountFromSignedBeaconBlockSerialized(
|
|
|
854
854
|
|
|
855
855
|
const start = bidMsgStart + commitmentsRange.start;
|
|
856
856
|
const end = bidMsgStart + commitmentsRange.end;
|
|
857
|
-
return Math.round(((end
|
|
857
|
+
return Math.round((Math.min(end, blockBytes.byteLength) - start) / commitmentSize);
|
|
858
858
|
}
|
|
859
859
|
|
|
860
860
|
const {SignedBeaconBlock, BeaconBlock, BeaconBlockBody, KZGCommitment} = ssz[forkName as ForkPostDeneb];
|
|
@@ -880,5 +880,5 @@ export function getBlobKzgCommitmentsCountFromSignedBeaconBlockSerialized(
|
|
|
880
880
|
const end = messageRange.end + bodyRange.end + kzgCommitmentsRange.end;
|
|
881
881
|
const start = messageRange.start + bodyRange.start + kzgCommitmentsRange.start;
|
|
882
882
|
|
|
883
|
-
return Math.round(((end
|
|
883
|
+
return Math.round((Math.min(end, blockBytes.byteLength) - start) / commitmentSize);
|
|
884
884
|
}
|