@lodestar/beacon-node 1.43.0-dev.6b7eebbf6d → 1.43.0-dev.6f485b1b61
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 +16 -5
- 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 +45 -2
- package/lib/api/impl/beacon/pool/index.js.map +1 -1
- package/lib/api/impl/debug/index.d.ts.map +1 -1
- package/lib/api/impl/debug/index.js +0 -1
- package/lib/api/impl/debug/index.js.map +1 -1
- package/lib/api/impl/lodestar/index.js +1 -1
- package/lib/api/impl/lodestar/index.js.map +1 -1
- package/lib/api/impl/validator/index.d.ts.map +1 -1
- package/lib/api/impl/validator/index.js +68 -2
- package/lib/api/impl/validator/index.js.map +1 -1
- package/lib/chain/blocks/blockInput/blockInput.d.ts +3 -0
- package/lib/chain/blocks/blockInput/blockInput.d.ts.map +1 -1
- package/lib/chain/blocks/blockInput/blockInput.js +4 -1
- 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 +16 -28
- package/lib/chain/blocks/importBlock.js.map +1 -1
- package/lib/chain/blocks/importExecutionPayload.d.ts +23 -6
- package/lib/chain/blocks/importExecutionPayload.d.ts.map +1 -1
- package/lib/chain/blocks/importExecutionPayload.js +57 -24
- package/lib/chain/blocks/importExecutionPayload.js.map +1 -1
- package/lib/chain/blocks/index.d.ts +5 -3
- package/lib/chain/blocks/index.d.ts.map +1 -1
- package/lib/chain/blocks/index.js +58 -25
- package/lib/chain/blocks/index.js.map +1 -1
- package/lib/chain/blocks/payloadEnvelopeInput/payloadEnvelopeInput.d.ts +12 -1
- package/lib/chain/blocks/payloadEnvelopeInput/payloadEnvelopeInput.d.ts.map +1 -1
- package/lib/chain/blocks/payloadEnvelopeInput/payloadEnvelopeInput.js +28 -2
- package/lib/chain/blocks/payloadEnvelopeInput/payloadEnvelopeInput.js.map +1 -1
- package/lib/chain/blocks/payloadEnvelopeInput/types.d.ts +17 -0
- package/lib/chain/blocks/payloadEnvelopeInput/types.d.ts.map +1 -1
- package/lib/chain/blocks/payloadEnvelopeProcessor.js +2 -2
- package/lib/chain/blocks/payloadEnvelopeProcessor.js.map +1 -1
- package/lib/chain/blocks/types.d.ts +4 -3
- package/lib/chain/blocks/types.d.ts.map +1 -1
- package/lib/chain/blocks/utils/chainSegment.d.ts +23 -2
- package/lib/chain/blocks/utils/chainSegment.d.ts.map +1 -1
- package/lib/chain/blocks/utils/chainSegment.js +89 -12
- package/lib/chain/blocks/utils/chainSegment.js.map +1 -1
- package/lib/chain/blocks/verifyBlock.d.ts +5 -3
- package/lib/chain/blocks/verifyBlock.d.ts.map +1 -1
- package/lib/chain/blocks/verifyBlock.js +50 -7
- package/lib/chain/blocks/verifyBlock.js.map +1 -1
- package/lib/chain/blocks/verifyBlocksExecutionPayloads.d.ts +0 -4
- package/lib/chain/blocks/verifyBlocksExecutionPayloads.d.ts.map +1 -1
- package/lib/chain/blocks/verifyBlocksExecutionPayloads.js +5 -2
- package/lib/chain/blocks/verifyBlocksExecutionPayloads.js.map +1 -1
- package/lib/chain/blocks/verifyBlocksSanityChecks.d.ts +2 -1
- package/lib/chain/blocks/verifyBlocksSanityChecks.d.ts.map +1 -1
- package/lib/chain/blocks/verifyBlocksSanityChecks.js +25 -5
- package/lib/chain/blocks/verifyBlocksSanityChecks.js.map +1 -1
- package/lib/chain/blocks/verifyExecutionPayloadEnvelope.d.ts +2 -2
- package/lib/chain/blocks/verifyExecutionPayloadEnvelope.d.ts.map +1 -1
- package/lib/chain/blocks/verifyExecutionPayloadEnvelope.js +12 -8
- package/lib/chain/blocks/verifyExecutionPayloadEnvelope.js.map +1 -1
- package/lib/chain/blocks/verifyPayloadsDataAvailability.d.ts.map +1 -1
- package/lib/chain/blocks/verifyPayloadsDataAvailability.js +8 -3
- package/lib/chain/blocks/verifyPayloadsDataAvailability.js.map +1 -1
- package/lib/chain/blocks/writePayloadEnvelopeInputToDb.d.ts.map +1 -1
- package/lib/chain/blocks/writePayloadEnvelopeInputToDb.js +1 -10
- package/lib/chain/blocks/writePayloadEnvelopeInputToDb.js.map +1 -1
- package/lib/chain/chain.d.ts +5 -3
- package/lib/chain/chain.d.ts.map +1 -1
- package/lib/chain/chain.js +42 -12
- package/lib/chain/chain.js.map +1 -1
- package/lib/chain/emitter.d.ts +0 -11
- package/lib/chain/emitter.d.ts.map +1 -1
- package/lib/chain/emitter.js +0 -4
- package/lib/chain/emitter.js.map +1 -1
- package/lib/chain/errors/blockError.d.ts +8 -1
- package/lib/chain/errors/blockError.d.ts.map +1 -1
- package/lib/chain/errors/blockError.js +2 -0
- package/lib/chain/errors/blockError.js.map +1 -1
- package/lib/chain/errors/executionPayloadBid.d.ts +5 -0
- package/lib/chain/errors/executionPayloadBid.d.ts.map +1 -1
- package/lib/chain/errors/executionPayloadBid.js +1 -0
- package/lib/chain/errors/executionPayloadBid.js.map +1 -1
- package/lib/chain/errors/index.d.ts +1 -0
- package/lib/chain/errors/index.d.ts.map +1 -1
- package/lib/chain/errors/index.js +1 -0
- package/lib/chain/errors/index.js.map +1 -1
- package/lib/chain/errors/proposerPreferences.d.ts +40 -0
- package/lib/chain/errors/proposerPreferences.d.ts.map +1 -0
- package/lib/chain/errors/proposerPreferences.js +14 -0
- package/lib/chain/errors/proposerPreferences.js.map +1 -0
- package/lib/chain/initState.d.ts.map +1 -1
- package/lib/chain/initState.js +6 -1
- package/lib/chain/initState.js.map +1 -1
- package/lib/chain/interface.d.ts +5 -3
- package/lib/chain/interface.d.ts.map +1 -1
- package/lib/chain/interface.js.map +1 -1
- package/lib/chain/opPools/payloadAttestationPool.d.ts +3 -2
- package/lib/chain/opPools/payloadAttestationPool.d.ts.map +1 -1
- package/lib/chain/opPools/payloadAttestationPool.js +26 -4
- package/lib/chain/opPools/payloadAttestationPool.js.map +1 -1
- package/lib/chain/prepareNextSlot.d.ts.map +1 -1
- package/lib/chain/prepareNextSlot.js +31 -13
- package/lib/chain/prepareNextSlot.js.map +1 -1
- package/lib/chain/produceBlock/produceBlockBody.d.ts +11 -1
- package/lib/chain/produceBlock/produceBlockBody.d.ts.map +1 -1
- package/lib/chain/produceBlock/produceBlockBody.js +47 -15
- package/lib/chain/produceBlock/produceBlockBody.js.map +1 -1
- package/lib/chain/regen/interface.d.ts +1 -0
- package/lib/chain/regen/interface.d.ts.map +1 -1
- package/lib/chain/regen/interface.js +1 -0
- package/lib/chain/regen/interface.js.map +1 -1
- package/lib/chain/regen/queued.d.ts.map +1 -1
- package/lib/chain/regen/queued.js +1 -4
- 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 +1 -4
- package/lib/chain/regen/regen.js.map +1 -1
- package/lib/chain/seenCache/index.d.ts +1 -0
- package/lib/chain/seenCache/index.d.ts.map +1 -1
- package/lib/chain/seenCache/index.js +1 -0
- package/lib/chain/seenCache/index.js.map +1 -1
- package/lib/chain/seenCache/seenPayloadEnvelopeInput.d.ts +24 -7
- package/lib/chain/seenCache/seenPayloadEnvelopeInput.d.ts.map +1 -1
- package/lib/chain/seenCache/seenPayloadEnvelopeInput.js +69 -17
- package/lib/chain/seenCache/seenPayloadEnvelopeInput.js.map +1 -1
- package/lib/chain/seenCache/seenProposerPreferences.d.ts +16 -0
- package/lib/chain/seenCache/seenProposerPreferences.d.ts.map +1 -0
- package/lib/chain/seenCache/seenProposerPreferences.js +26 -0
- package/lib/chain/seenCache/seenProposerPreferences.js.map +1 -0
- package/lib/chain/validation/block.d.ts.map +1 -1
- package/lib/chain/validation/block.js +1 -0
- package/lib/chain/validation/block.js.map +1 -1
- package/lib/chain/validation/executionPayloadBid.d.ts.map +1 -1
- package/lib/chain/validation/executionPayloadBid.js +24 -9
- package/lib/chain/validation/executionPayloadBid.js.map +1 -1
- package/lib/chain/validation/proposerPreferences.d.ts +8 -0
- package/lib/chain/validation/proposerPreferences.d.ts.map +1 -0
- package/lib/chain/validation/proposerPreferences.js +91 -0
- package/lib/chain/validation/proposerPreferences.js.map +1 -0
- package/lib/metrics/metrics/lodestar.d.ts +1 -0
- package/lib/metrics/metrics/lodestar.d.ts.map +1 -1
- package/lib/metrics/metrics/lodestar.js +4 -0
- package/lib/metrics/metrics/lodestar.js.map +1 -1
- package/lib/network/gossip/interface.d.ts +7 -1
- package/lib/network/gossip/interface.d.ts.map +1 -1
- package/lib/network/gossip/interface.js +1 -0
- package/lib/network/gossip/interface.js.map +1 -1
- package/lib/network/gossip/scoringParameters.d.ts.map +1 -1
- package/lib/network/gossip/scoringParameters.js +12 -1
- package/lib/network/gossip/scoringParameters.js.map +1 -1
- package/lib/network/gossip/topic.d.ts +10 -0
- package/lib/network/gossip/topic.d.ts.map +1 -1
- package/lib/network/gossip/topic.js +6 -0
- package/lib/network/gossip/topic.js.map +1 -1
- package/lib/network/interface.d.ts +1 -0
- package/lib/network/interface.d.ts.map +1 -1
- package/lib/network/network.d.ts +1 -0
- package/lib/network/network.d.ts.map +1 -1
- package/lib/network/network.js +5 -0
- package/lib/network/network.js.map +1 -1
- package/lib/network/processor/gossipHandlers.d.ts.map +1 -1
- package/lib/network/processor/gossipHandlers.js +38 -16
- package/lib/network/processor/gossipHandlers.js.map +1 -1
- package/lib/network/processor/gossipQueues/index.d.ts.map +1 -1
- package/lib/network/processor/gossipQueues/index.js +5 -0
- package/lib/network/processor/gossipQueues/index.js.map +1 -1
- package/lib/network/processor/index.d.ts.map +1 -1
- package/lib/network/processor/index.js +6 -5
- package/lib/network/processor/index.js.map +1 -1
- package/lib/network/reqresp/handlers/beaconBlocksByRange.d.ts.map +1 -1
- package/lib/network/reqresp/handlers/beaconBlocksByRange.js +14 -6
- 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 +11 -5
- package/lib/network/reqresp/handlers/blobSidecarsByRange.js.map +1 -1
- package/lib/network/reqresp/handlers/dataColumnSidecarsByRange.d.ts.map +1 -1
- package/lib/network/reqresp/handlers/dataColumnSidecarsByRange.js +17 -5
- package/lib/network/reqresp/handlers/dataColumnSidecarsByRange.js.map +1 -1
- package/lib/network/reqresp/handlers/executionPayloadEnvelopesByRange.d.ts.map +1 -1
- package/lib/network/reqresp/handlers/executionPayloadEnvelopesByRange.js +7 -4
- package/lib/network/reqresp/handlers/executionPayloadEnvelopesByRange.js.map +1 -1
- package/lib/node/nodejs.js +2 -2
- package/lib/node/nodejs.js.map +1 -1
- package/lib/sync/constants.d.ts +3 -1
- package/lib/sync/constants.d.ts.map +1 -1
- package/lib/sync/constants.js +3 -4
- package/lib/sync/constants.js.map +1 -1
- package/lib/sync/range/batch.d.ts +35 -5
- package/lib/sync/range/batch.d.ts.map +1 -1
- package/lib/sync/range/batch.js +240 -59
- package/lib/sync/range/batch.js.map +1 -1
- package/lib/sync/range/chain.d.ts +19 -4
- package/lib/sync/range/chain.d.ts.map +1 -1
- package/lib/sync/range/chain.js +64 -11
- 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 +31 -9
- package/lib/sync/range/range.js.map +1 -1
- package/lib/sync/sync.d.ts.map +1 -1
- package/lib/sync/sync.js +13 -0
- package/lib/sync/sync.js.map +1 -1
- package/lib/sync/types.d.ts +34 -0
- package/lib/sync/types.d.ts.map +1 -1
- package/lib/sync/types.js +34 -0
- package/lib/sync/types.js.map +1 -1
- package/lib/sync/unknownBlock.d.ts +29 -1
- package/lib/sync/unknownBlock.d.ts.map +1 -1
- package/lib/sync/unknownBlock.js +738 -61
- package/lib/sync/unknownBlock.js.map +1 -1
- package/lib/sync/utils/downloadByRange.d.ts +67 -10
- package/lib/sync/utils/downloadByRange.d.ts.map +1 -1
- package/lib/sync/utils/downloadByRange.js +211 -26
- package/lib/sync/utils/downloadByRange.js.map +1 -1
- package/lib/sync/utils/downloadByRoot.d.ts.map +1 -1
- package/lib/sync/utils/downloadByRoot.js +16 -2
- package/lib/sync/utils/downloadByRoot.js.map +1 -1
- package/lib/sync/utils/pendingBlocksTree.d.ts +0 -1
- package/lib/sync/utils/pendingBlocksTree.d.ts.map +1 -1
- package/lib/sync/utils/pendingBlocksTree.js +0 -9
- package/lib/sync/utils/pendingBlocksTree.js.map +1 -1
- package/lib/util/sszBytes.d.ts.map +1 -1
- package/lib/util/sszBytes.js +8 -6
- package/lib/util/sszBytes.js.map +1 -1
- package/package.json +16 -15
- package/src/api/impl/beacon/blocks/index.ts +21 -5
- package/src/api/impl/beacon/pool/index.ts +83 -1
- package/src/api/impl/debug/index.ts +0 -1
- package/src/api/impl/lodestar/index.ts +1 -1
- package/src/api/impl/validator/index.ts +82 -1
- package/src/chain/blocks/blockInput/blockInput.ts +4 -1
- package/src/chain/blocks/importBlock.ts +16 -48
- package/src/chain/blocks/importExecutionPayload.ts +76 -30
- package/src/chain/blocks/index.ts +71 -22
- package/src/chain/blocks/payloadEnvelopeInput/payloadEnvelopeInput.ts +37 -3
- package/src/chain/blocks/payloadEnvelopeInput/types.ts +18 -0
- package/src/chain/blocks/payloadEnvelopeProcessor.ts +2 -2
- package/src/chain/blocks/types.ts +4 -3
- package/src/chain/blocks/utils/chainSegment.ts +114 -17
- package/src/chain/blocks/verifyBlock.ts +70 -9
- package/src/chain/blocks/verifyBlocksExecutionPayloads.ts +6 -4
- package/src/chain/blocks/verifyBlocksSanityChecks.ts +26 -7
- package/src/chain/blocks/verifyExecutionPayloadEnvelope.ts +16 -8
- package/src/chain/blocks/verifyPayloadsDataAvailability.ts +7 -4
- package/src/chain/blocks/writePayloadEnvelopeInputToDb.ts +8 -17
- package/src/chain/chain.ts +55 -10
- package/src/chain/emitter.ts +0 -11
- package/src/chain/errors/blockError.ts +4 -1
- package/src/chain/errors/executionPayloadBid.ts +6 -0
- package/src/chain/errors/index.ts +1 -0
- package/src/chain/errors/proposerPreferences.ts +47 -0
- package/src/chain/initState.ts +9 -1
- package/src/chain/interface.ts +9 -1
- package/src/chain/opPools/payloadAttestationPool.ts +29 -8
- package/src/chain/prepareNextSlot.ts +36 -14
- package/src/chain/produceBlock/produceBlockBody.ts +57 -14
- package/src/chain/regen/interface.ts +1 -0
- package/src/chain/regen/queued.ts +2 -7
- package/src/chain/regen/regen.ts +2 -7
- package/src/chain/seenCache/index.ts +1 -0
- package/src/chain/seenCache/seenPayloadEnvelopeInput.ts +89 -21
- package/src/chain/seenCache/seenProposerPreferences.ts +32 -0
- package/src/chain/validation/block.ts +1 -0
- package/src/chain/validation/executionPayloadBid.ts +25 -8
- package/src/chain/validation/proposerPreferences.ts +110 -0
- package/src/metrics/metrics/lodestar.ts +4 -0
- package/src/network/gossip/interface.ts +6 -0
- package/src/network/gossip/scoringParameters.ts +14 -1
- package/src/network/gossip/topic.ts +6 -0
- package/src/network/interface.ts +1 -0
- package/src/network/network.ts +11 -0
- package/src/network/processor/gossipHandlers.ts +53 -17
- package/src/network/processor/gossipQueues/index.ts +5 -0
- package/src/network/processor/index.ts +6 -5
- package/src/network/reqresp/handlers/beaconBlocksByRange.ts +14 -6
- package/src/network/reqresp/handlers/blobSidecarsByRange.ts +11 -5
- package/src/network/reqresp/handlers/dataColumnSidecarsByRange.ts +17 -5
- package/src/network/reqresp/handlers/executionPayloadEnvelopesByRange.ts +7 -4
- package/src/node/nodejs.ts +2 -2
- package/src/sync/constants.ts +4 -4
- package/src/sync/range/batch.ts +320 -67
- package/src/sync/range/chain.ts +89 -14
- package/src/sync/range/range.ts +34 -9
- package/src/sync/sync.ts +13 -1
- package/src/sync/types.ts +72 -0
- package/src/sync/unknownBlock.ts +928 -65
- package/src/sync/utils/downloadByRange.ts +378 -39
- package/src/sync/utils/downloadByRoot.ts +24 -2
- package/src/sync/utils/pendingBlocksTree.ts +0 -15
- package/src/util/sszBytes.ts +8 -6
package/src/sync/range/chain.ts
CHANGED
|
@@ -1,9 +1,11 @@
|
|
|
1
1
|
import {ChainForkConfig} from "@lodestar/config";
|
|
2
|
-
import {
|
|
3
|
-
import {
|
|
2
|
+
import {RequestErrorCode} from "@lodestar/reqresp";
|
|
3
|
+
import {Epoch, Root, Slot, gloas} from "@lodestar/types";
|
|
4
|
+
import {ErrorAborted, LodestarError, Logger, prettyPrintIndices, toRootHex} from "@lodestar/utils";
|
|
4
5
|
import {isBlockInputBlobs, isBlockInputColumns} from "../../chain/blocks/blockInput/blockInput.js";
|
|
5
6
|
import {BlockInputErrorCode} from "../../chain/blocks/blockInput/errors.js";
|
|
6
7
|
import {IBlockInput} from "../../chain/blocks/blockInput/types.js";
|
|
8
|
+
import {PayloadEnvelopeInput} from "../../chain/blocks/payloadEnvelopeInput/payloadEnvelopeInput.js";
|
|
7
9
|
import {BlobSidecarErrorCode} from "../../chain/errors/blobSidecarError.js";
|
|
8
10
|
import {DataColumnSidecarErrorCode} from "../../chain/errors/dataColumnSidecarError.js";
|
|
9
11
|
import {Metrics} from "../../metrics/metrics.js";
|
|
@@ -14,7 +16,12 @@ import {CustodyConfig} from "../../util/dataColumns.js";
|
|
|
14
16
|
import {ItTrigger} from "../../util/itTrigger.js";
|
|
15
17
|
import {PeerIdStr} from "../../util/peerId.js";
|
|
16
18
|
import {WarnResult, wrapError} from "../../util/wrapError.js";
|
|
17
|
-
import {
|
|
19
|
+
import {
|
|
20
|
+
BATCH_BUFFER_SIZE,
|
|
21
|
+
EPOCHS_PER_BATCH,
|
|
22
|
+
MAX_LOOK_AHEAD_EPOCHS,
|
|
23
|
+
RATE_LIMITED_PEER_BACKOFF_MS,
|
|
24
|
+
} from "../constants.js";
|
|
18
25
|
import {DownloadByRangeError, DownloadByRangeErrorCode} from "../utils/downloadByRange.js";
|
|
19
26
|
import {RangeSyncType} from "../utils/remoteSyncType.js";
|
|
20
27
|
import {Batch, BatchError, BatchErrorCode, BatchMetadata, BatchStatus} from "./batch.js";
|
|
@@ -44,13 +51,19 @@ export type SyncChainFns = {
|
|
|
44
51
|
* Must return if ALL blocks are processed successfully
|
|
45
52
|
* If SOME blocks are processed must throw BlockProcessorError()
|
|
46
53
|
*/
|
|
47
|
-
processChainSegment: (
|
|
54
|
+
processChainSegment: (
|
|
55
|
+
blocks: IBlockInput[],
|
|
56
|
+
payloadEnvelopes: Map<Slot, PayloadEnvelopeInput> | null,
|
|
57
|
+
syncType: RangeSyncType
|
|
58
|
+
) => Promise<void>;
|
|
48
59
|
/** Must download blocks, and validate their range */
|
|
49
60
|
downloadByRange: (
|
|
50
61
|
peer: PeerSyncMeta,
|
|
51
62
|
batch: Batch,
|
|
52
63
|
syncType: RangeSyncType
|
|
53
|
-
) => Promise<
|
|
64
|
+
) => Promise<
|
|
65
|
+
WarnResult<{blocks: IBlockInput[]; payloadEnvelopes: Map<Slot, PayloadEnvelopeInput> | null}, DownloadByRangeError>
|
|
66
|
+
>;
|
|
54
67
|
/** Report peer for negative actions. Decouples from the full network instance */
|
|
55
68
|
reportPeer: (peer: PeerIdStr, action: PeerAction, actionName: string) => void;
|
|
56
69
|
/** Gets current peer custodyColumns and earliestAvailableSlot */
|
|
@@ -132,20 +145,32 @@ export class SyncChain {
|
|
|
132
145
|
private readonly batchProcessor = new ItTrigger();
|
|
133
146
|
/** Sorted map of batches undergoing some kind of processing. */
|
|
134
147
|
private readonly batches = new Map<Epoch, Batch>();
|
|
148
|
+
/**
|
|
149
|
+
* `true` until the first `Batch` is constructed via `includeNextBatch`
|
|
150
|
+
*/
|
|
151
|
+
private isFirstBatch = true;
|
|
135
152
|
private readonly peerset = new Map<PeerIdStr, ChainTarget>();
|
|
153
|
+
/**
|
|
154
|
+
* Tracks peers that have rate-limited us, mapped to the timestamp (ms) until which we should avoid them.
|
|
155
|
+
* This is a sync-layer optimization to avoid assigning batches to backed-off peers.
|
|
156
|
+
* The reqresp SelfRateLimiter independently enforces backoff at the protocol level as a safety net.
|
|
157
|
+
*/
|
|
158
|
+
private readonly rateLimitedPeers = new Map<PeerIdStr, number>();
|
|
136
159
|
|
|
137
160
|
private readonly logger: Logger;
|
|
138
161
|
private readonly config: ChainForkConfig;
|
|
139
162
|
private readonly clock: IClock;
|
|
140
163
|
private readonly metrics: Metrics | null;
|
|
141
164
|
private readonly custodyConfig: CustodyConfig;
|
|
165
|
+
private readonly latestBid: gloas.ExecutionPayloadBid | undefined;
|
|
142
166
|
|
|
143
167
|
constructor(
|
|
144
168
|
initialBatchEpoch: Epoch,
|
|
145
169
|
initialTarget: ChainTarget,
|
|
146
170
|
syncType: RangeSyncType,
|
|
147
171
|
fns: SyncChainFns,
|
|
148
|
-
modules: SyncChainModules
|
|
172
|
+
modules: SyncChainModules,
|
|
173
|
+
latestBid: gloas.ExecutionPayloadBid | undefined
|
|
149
174
|
) {
|
|
150
175
|
const {config, clock, custodyConfig, logger, metrics} = modules;
|
|
151
176
|
this.firstBatchEpoch = initialBatchEpoch;
|
|
@@ -161,6 +186,7 @@ export class SyncChain {
|
|
|
161
186
|
this.clock = clock;
|
|
162
187
|
this.metrics = metrics;
|
|
163
188
|
this.custodyConfig = custodyConfig;
|
|
189
|
+
this.latestBid = latestBid;
|
|
164
190
|
this.logger = logger;
|
|
165
191
|
this.logId = `${syncType}-${nextChainId++}`;
|
|
166
192
|
|
|
@@ -215,12 +241,14 @@ export class SyncChain {
|
|
|
215
241
|
*/
|
|
216
242
|
stopSyncing(): void {
|
|
217
243
|
this.status = SyncChainStatus.Stopped;
|
|
244
|
+
this.logger.debug("SyncChain stopSyncing", {id: this.logId});
|
|
218
245
|
}
|
|
219
246
|
|
|
220
247
|
/**
|
|
221
248
|
* Permanently remove this chain. Throws the main AsyncIterable
|
|
222
249
|
*/
|
|
223
250
|
remove(): void {
|
|
251
|
+
this.logger.debug("SyncChain remove", {id: this.logId});
|
|
224
252
|
this.batchProcessor.end(new ErrorAborted("SyncChain"));
|
|
225
253
|
}
|
|
226
254
|
|
|
@@ -239,6 +267,7 @@ export class SyncChain {
|
|
|
239
267
|
*/
|
|
240
268
|
removePeer(peerId: PeerIdStr): boolean {
|
|
241
269
|
const deleted = this.peerset.delete(peerId);
|
|
270
|
+
this.rateLimitedPeers.delete(peerId);
|
|
242
271
|
this.computeTarget();
|
|
243
272
|
return deleted;
|
|
244
273
|
}
|
|
@@ -374,8 +403,18 @@ export class SyncChain {
|
|
|
374
403
|
return;
|
|
375
404
|
}
|
|
376
405
|
|
|
406
|
+
const now = Date.now();
|
|
377
407
|
const peersSyncInfo: PeerSyncInfo[] = [];
|
|
378
408
|
for (const [peerId, target] of this.peerset.entries()) {
|
|
409
|
+
// Skip peers that are currently in rate-limit backoff
|
|
410
|
+
const rateLimitedUntil = this.rateLimitedPeers.get(peerId);
|
|
411
|
+
if (rateLimitedUntil !== undefined) {
|
|
412
|
+
if (now < rateLimitedUntil) {
|
|
413
|
+
continue;
|
|
414
|
+
}
|
|
415
|
+
this.rateLimitedPeers.delete(peerId);
|
|
416
|
+
}
|
|
417
|
+
|
|
379
418
|
try {
|
|
380
419
|
peersSyncInfo.push({...this.getConnectedPeerSyncMeta(peerId), target});
|
|
381
420
|
} catch (e) {
|
|
@@ -449,7 +488,17 @@ export class SyncChain {
|
|
|
449
488
|
return null;
|
|
450
489
|
}
|
|
451
490
|
|
|
452
|
-
const batch = new Batch(
|
|
491
|
+
const batch = new Batch(
|
|
492
|
+
startEpoch,
|
|
493
|
+
this.config,
|
|
494
|
+
this.clock,
|
|
495
|
+
this.custodyConfig,
|
|
496
|
+
this.isFirstBatch,
|
|
497
|
+
// `latestBid` is only meaningful for the first batch's parent-payload check
|
|
498
|
+
this.isFirstBatch ? this.latestBid : undefined,
|
|
499
|
+
this.target.slot
|
|
500
|
+
);
|
|
501
|
+
this.isFirstBatch = false;
|
|
453
502
|
this.batches.set(startEpoch, batch);
|
|
454
503
|
return batch;
|
|
455
504
|
}
|
|
@@ -507,7 +556,14 @@ export class SyncChain {
|
|
|
507
556
|
{id: this.logId, ...batch.getMetadata(), peer: prettyPrintPeerIdStr(peer.peerId)},
|
|
508
557
|
res.err
|
|
509
558
|
);
|
|
510
|
-
|
|
559
|
+
if (errCode === RequestErrorCode.RESP_RATE_LIMITED || errCode === RequestErrorCode.REQUEST_SELF_RATE_LIMITED) {
|
|
560
|
+
// Peer rate-limited us — don't count as a failed download attempt and mark peer for backoff
|
|
561
|
+
this.rateLimitedPeers.set(peer.peerId, Date.now() + RATE_LIMITED_PEER_BACKOFF_MS);
|
|
562
|
+
batch.downloadingRateLimited();
|
|
563
|
+
this.triggerBatchDownloader();
|
|
564
|
+
} else {
|
|
565
|
+
batch.downloadingError(peer.peerId); // Throws after MAX_DOWNLOAD_ATTEMPTS
|
|
566
|
+
}
|
|
511
567
|
} else {
|
|
512
568
|
this.logger.verbose("Batch download success", {
|
|
513
569
|
id: this.logId,
|
|
@@ -516,7 +572,8 @@ export class SyncChain {
|
|
|
516
572
|
});
|
|
517
573
|
this.metrics?.syncRange.downloadByRange.success.inc();
|
|
518
574
|
const {warnings, result} = res.result;
|
|
519
|
-
const
|
|
575
|
+
const {blocks: downloadedBlocks, payloadEnvelopes} = result;
|
|
576
|
+
const downloadSuccessOutput = batch.downloadingSuccess(peer.peerId, downloadedBlocks, payloadEnvelopes);
|
|
520
577
|
const logMeta: Record<string, number> = {
|
|
521
578
|
blockCount: downloadSuccessOutput.blocks.length,
|
|
522
579
|
};
|
|
@@ -526,7 +583,7 @@ export class SyncChain {
|
|
|
526
583
|
this.metrics?.syncRange.downloadByRange.warn.inc({client: peer.client, code: warning.type.code});
|
|
527
584
|
this.logger.debug(
|
|
528
585
|
"Batch downloaded with warning",
|
|
529
|
-
{id: this.logId,
|
|
586
|
+
{id: this.logId, ...batch.getMetadata(), ...logMeta, peer: prettyPrintPeerIdStr(peer.peerId)},
|
|
530
587
|
warning
|
|
531
588
|
);
|
|
532
589
|
}
|
|
@@ -552,10 +609,17 @@ export class SyncChain {
|
|
|
552
609
|
// the flow will continue to call triggerBatchDownloader() below
|
|
553
610
|
}
|
|
554
611
|
|
|
612
|
+
const blockSlots = downloadSuccessOutput.blocks.map((b) => b.slot);
|
|
613
|
+
const envelopeSlots = downloadSuccessOutput.payloadEnvelopes
|
|
614
|
+
? Array.from(downloadSuccessOutput.payloadEnvelopes.keys())
|
|
615
|
+
: null;
|
|
616
|
+
|
|
555
617
|
this.logger.debug(logMessage, {
|
|
556
618
|
id: this.logId,
|
|
557
|
-
|
|
619
|
+
...batch.getMetadata(),
|
|
558
620
|
...logMeta,
|
|
621
|
+
blockSlots: prettyPrintIndices(blockSlots),
|
|
622
|
+
...(envelopeSlots ? {envelopeSlots: prettyPrintIndices(envelopeSlots)} : {}),
|
|
559
623
|
peer: prettyPrintPeerIdStr(peer.peerId),
|
|
560
624
|
});
|
|
561
625
|
}
|
|
@@ -578,13 +642,24 @@ export class SyncChain {
|
|
|
578
642
|
* Sends `batch` to the processor. Note: batch may be empty
|
|
579
643
|
*/
|
|
580
644
|
private async processBatch(batch: Batch): Promise<void> {
|
|
581
|
-
const blocks = batch.startProcessing();
|
|
645
|
+
const {blocks, payloadEnvelopes, peers} = batch.startProcessing();
|
|
646
|
+
|
|
647
|
+
const logCtx = {
|
|
648
|
+
id: this.logId,
|
|
649
|
+
...batch.getMetadata(),
|
|
650
|
+
blockCount: blocks.length,
|
|
651
|
+
blockSlots: prettyPrintIndices(blocks.map((b) => b.slot)),
|
|
652
|
+
...(payloadEnvelopes ? {envelopeSlots: prettyPrintIndices(Array.from(payloadEnvelopes.keys()))} : {}),
|
|
653
|
+
peers: peers.map(prettyPrintPeerIdStr).join(","),
|
|
654
|
+
};
|
|
655
|
+
this.logger.verbose("Processing batch", logCtx);
|
|
582
656
|
|
|
583
657
|
// wrapError ensures to never call both batch success() and batch error()
|
|
584
|
-
const res = await wrapError(this.processChainSegment(blocks, this.syncType));
|
|
658
|
+
const res = await wrapError(this.processChainSegment(blocks, payloadEnvelopes, this.syncType));
|
|
585
659
|
|
|
586
660
|
if (!res.err) {
|
|
587
661
|
batch.processingSuccess();
|
|
662
|
+
this.logger.verbose("Processed batch", {...logCtx, ...batch.getMetadata()});
|
|
588
663
|
|
|
589
664
|
// If the processed batch is not empty, validate previous AwaitingValidation blocks.
|
|
590
665
|
if (blocks.length > 0) {
|
|
@@ -594,7 +669,7 @@ export class SyncChain {
|
|
|
594
669
|
// Potentially process next AwaitingProcessing batch
|
|
595
670
|
this.triggerBatchProcessor();
|
|
596
671
|
} else {
|
|
597
|
-
this.logger.verbose("Batch process error",
|
|
672
|
+
this.logger.verbose("Batch process error", logCtx, res.err);
|
|
598
673
|
batch.processingError(res.err); // Throws after MAX_BATCH_PROCESSING_ATTEMPTS
|
|
599
674
|
|
|
600
675
|
// At least one block was successfully verified and imported, so we can be sure all
|
package/src/sync/range/range.ts
CHANGED
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
import {EventEmitter} from "node:events";
|
|
2
2
|
import {StrictEventEmitter} from "strict-event-emitter-types";
|
|
3
3
|
import {BeaconConfig} from "@lodestar/config";
|
|
4
|
-
import {computeStartSlotAtEpoch} from "@lodestar/state-transition";
|
|
4
|
+
import {IBeaconStateViewGloas, computeStartSlotAtEpoch, isStatePostGloas} from "@lodestar/state-transition";
|
|
5
5
|
import {Epoch, Status, fulu} from "@lodestar/types";
|
|
6
6
|
import {Logger, toRootHex} from "@lodestar/utils";
|
|
7
7
|
import {IBlockInput} from "../../chain/blocks/blockInput/types.js";
|
|
@@ -172,7 +172,7 @@ export class RangeSync extends (EventEmitter as {new (): RangeSyncEmitter}) {
|
|
|
172
172
|
}
|
|
173
173
|
|
|
174
174
|
/** Convenience method for `SyncChain` */
|
|
175
|
-
private processChainSegment: SyncChainFns["processChainSegment"] = async (blocks, syncType) => {
|
|
175
|
+
private processChainSegment: SyncChainFns["processChainSegment"] = async (blocks, payloadEnvelopes, syncType) => {
|
|
176
176
|
// Not trusted, verify signatures
|
|
177
177
|
const flags: ImportBlockOpts = {
|
|
178
178
|
// Only skip importing attestations for finalized sync. For head sync attestation are valuable.
|
|
@@ -192,30 +192,46 @@ export class RangeSync extends (EventEmitter as {new (): RangeSyncEmitter}) {
|
|
|
192
192
|
|
|
193
193
|
if (this.opts?.disableProcessAsChainSegment) {
|
|
194
194
|
// Should only be used for debugging or testing
|
|
195
|
-
for (const block of blocks)
|
|
195
|
+
for (const block of blocks) {
|
|
196
|
+
await this.chain.processBlock(block, flags);
|
|
197
|
+
const payloadEnvelope = payloadEnvelopes?.get(block.slot);
|
|
198
|
+
if (payloadEnvelope) {
|
|
199
|
+
await this.chain.processExecutionPayload(payloadEnvelope);
|
|
200
|
+
}
|
|
201
|
+
}
|
|
196
202
|
} else {
|
|
197
|
-
await this.chain.processChainSegment(blocks, flags);
|
|
203
|
+
await this.chain.processChainSegment(blocks, payloadEnvelopes, flags);
|
|
198
204
|
}
|
|
199
205
|
};
|
|
200
206
|
|
|
201
207
|
private downloadByRange: SyncChainFns["downloadByRange"] = async (peer, batch) => {
|
|
202
208
|
const batchBlocks = batch.getBlocks();
|
|
209
|
+
const requests = batch.getRequestsForPeer(peer);
|
|
210
|
+
const parentRoot = requests.parentPayloadRequest?.envelopeBlockRoot ?? requests.parentPayloadRequest?.blockRoot;
|
|
211
|
+
const parentPayloadCommitments = parentRoot ? batch.getParentPayloadCommitments(parentRoot) : undefined;
|
|
203
212
|
const {result, warnings} = await downloadByRange({
|
|
204
213
|
config: this.config,
|
|
205
214
|
network: this.network,
|
|
206
215
|
logger: this.logger,
|
|
207
216
|
peerIdStr: peer.peerId,
|
|
208
217
|
batchBlocks,
|
|
218
|
+
parentPayloadCommitments,
|
|
209
219
|
peerDasMetrics: this.chain.metrics?.peerDas,
|
|
210
|
-
...
|
|
220
|
+
...requests,
|
|
211
221
|
});
|
|
212
|
-
const
|
|
222
|
+
const {responses, payloadEnvelopes: downloadedPayloadEnvelopes} = result;
|
|
223
|
+
const {blocks, payloadEnvelopes} = cacheByRangeResponses({
|
|
213
224
|
cache: this.chain.seenBlockInputCache,
|
|
225
|
+
seenPayloadEnvelopeInputCache: this.chain.seenPayloadEnvelopeInputCache,
|
|
214
226
|
peerIdStr: peer.peerId,
|
|
215
|
-
responses
|
|
227
|
+
responses,
|
|
216
228
|
batchBlocks,
|
|
229
|
+
downloadedPayloadEnvelopes,
|
|
230
|
+
existingPayloadEnvelopes: batch.getPayloadEnvelopes(),
|
|
231
|
+
custodyConfig: this.chain.custodyConfig,
|
|
232
|
+
seenTimestampSec: Date.now() / 1000,
|
|
217
233
|
});
|
|
218
|
-
return {result:
|
|
234
|
+
return {result: {blocks, payloadEnvelopes}, warnings};
|
|
219
235
|
};
|
|
220
236
|
|
|
221
237
|
private pruneBlockInputs: SyncChainFns["pruneBlockInputs"] = (blocks: IBlockInput[]) => {
|
|
@@ -246,6 +262,14 @@ export class RangeSync extends (EventEmitter as {new (): RangeSyncEmitter}) {
|
|
|
246
262
|
private addPeerOrCreateChain(startEpoch: Epoch, target: ChainTarget, peer: PeerIdStr, syncType: RangeSyncType): void {
|
|
247
263
|
let syncChain = this.chains.get(syncType);
|
|
248
264
|
if (!syncChain) {
|
|
265
|
+
// The first batch of a new sync chain may need to detect whether the parent block was an
|
|
266
|
+
// gloas "empty" block (no envelope produced). It does so by comparing the first
|
|
267
|
+
// downloaded block's `bid.parentBlockHash` against the head state's `latestExecutionPayloadBid.blockHash`.
|
|
268
|
+
const headState = this.chain.getHeadState();
|
|
269
|
+
const latestBid = isStatePostGloas(headState)
|
|
270
|
+
? (headState as IBeaconStateViewGloas).latestExecutionPayloadBid
|
|
271
|
+
: undefined;
|
|
272
|
+
|
|
249
273
|
syncChain = new SyncChain(
|
|
250
274
|
startEpoch,
|
|
251
275
|
target,
|
|
@@ -264,7 +288,8 @@ export class RangeSync extends (EventEmitter as {new (): RangeSyncEmitter}) {
|
|
|
264
288
|
logger: this.logger,
|
|
265
289
|
custodyConfig: this.chain.custodyConfig,
|
|
266
290
|
metrics: this.metrics,
|
|
267
|
-
}
|
|
291
|
+
},
|
|
292
|
+
latestBid
|
|
268
293
|
);
|
|
269
294
|
this.chains.set(syncType, syncChain);
|
|
270
295
|
|
package/src/sync/sync.ts
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
import {SLOTS_PER_EPOCH} from "@lodestar/params";
|
|
2
2
|
import {Slot} from "@lodestar/types";
|
|
3
|
-
import {Logger} from "@lodestar/utils";
|
|
3
|
+
import {Logger, toRootHex} from "@lodestar/utils";
|
|
4
4
|
import {IBeaconChain} from "../chain/index.js";
|
|
5
5
|
import {GENESIS_SLOT} from "../constants/constants.js";
|
|
6
6
|
import {ExecutionEngineState} from "../execution/index.js";
|
|
@@ -188,6 +188,18 @@ export class BeaconSync implements IBeaconSync {
|
|
|
188
188
|
private addPeer = (data: NetworkEventData[NetworkEvent.peerConnected]): void => {
|
|
189
189
|
const localStatus = this.chain.getStatus();
|
|
190
190
|
const syncType = getPeerSyncType(localStatus, data.status, this.chain.forkChoice, this.slotImportTolerance);
|
|
191
|
+
this.logger.verbose("Peer sync type classified", {
|
|
192
|
+
peer: data.peer,
|
|
193
|
+
syncType,
|
|
194
|
+
localFinalizedEpoch: localStatus.finalizedEpoch,
|
|
195
|
+
localFinalizedRoot: toRootHex(localStatus.finalizedRoot),
|
|
196
|
+
localHeadSlot: localStatus.headSlot,
|
|
197
|
+
localHeadRoot: toRootHex(localStatus.headRoot),
|
|
198
|
+
remoteFinalizedEpoch: data.status.finalizedEpoch,
|
|
199
|
+
remoteFinalizedRoot: toRootHex(data.status.finalizedRoot),
|
|
200
|
+
remoteHeadSlot: data.status.headSlot,
|
|
201
|
+
remoteHeadRoot: toRootHex(data.status.headRoot),
|
|
202
|
+
});
|
|
191
203
|
|
|
192
204
|
// For metrics only
|
|
193
205
|
this.peerSyncType.set(data.peer, syncType);
|
package/src/sync/types.ts
CHANGED
|
@@ -1,5 +1,8 @@
|
|
|
1
1
|
import {RootHex, Slot} from "@lodestar/types";
|
|
2
|
+
import {SignedExecutionPayloadEnvelope} from "@lodestar/types/gloas";
|
|
3
|
+
import {toRootHex} from "@lodestar/utils";
|
|
2
4
|
import {IBlockInput} from "../chain/blocks/blockInput/index.js";
|
|
5
|
+
import {PayloadEnvelopeInput} from "../chain/blocks/payloadEnvelopeInput/payloadEnvelopeInput.js";
|
|
3
6
|
|
|
4
7
|
export enum PendingBlockType {
|
|
5
8
|
/**
|
|
@@ -26,6 +29,14 @@ export enum PendingBlockInputStatus {
|
|
|
26
29
|
processing = "processing",
|
|
27
30
|
}
|
|
28
31
|
|
|
32
|
+
export enum PendingPayloadInputStatus {
|
|
33
|
+
pending = "pending",
|
|
34
|
+
fetching = "fetching",
|
|
35
|
+
waitingForBlock = "waiting_for_block",
|
|
36
|
+
downloaded = "downloaded",
|
|
37
|
+
processing = "processing",
|
|
38
|
+
}
|
|
39
|
+
|
|
29
40
|
export type PendingBlockInput = {
|
|
30
41
|
status: PendingBlockInputStatus;
|
|
31
42
|
blockInput: IBlockInput;
|
|
@@ -44,10 +55,47 @@ export type PendingRootHex = {
|
|
|
44
55
|
|
|
45
56
|
export type BlockInputSyncCacheItem = PendingBlockInput | PendingRootHex;
|
|
46
57
|
|
|
58
|
+
export type PendingPayloadInput = {
|
|
59
|
+
status:
|
|
60
|
+
| PendingPayloadInputStatus.pending
|
|
61
|
+
| PendingPayloadInputStatus.fetching
|
|
62
|
+
| PendingPayloadInputStatus.downloaded
|
|
63
|
+
| PendingPayloadInputStatus.processing;
|
|
64
|
+
payloadInput: PayloadEnvelopeInput;
|
|
65
|
+
timeAddedSec: number;
|
|
66
|
+
timeSyncedSec?: number;
|
|
67
|
+
peerIdStrings: Set<string>;
|
|
68
|
+
};
|
|
69
|
+
|
|
70
|
+
export type PendingPayloadRootHex = {
|
|
71
|
+
status: PendingPayloadInputStatus.pending | PendingPayloadInputStatus.fetching;
|
|
72
|
+
rootHex: RootHex;
|
|
73
|
+
timeAddedSec: number;
|
|
74
|
+
timeSyncedSec?: number;
|
|
75
|
+
peerIdStrings: Set<string>;
|
|
76
|
+
};
|
|
77
|
+
|
|
78
|
+
export type PendingPayloadEnvelope = {
|
|
79
|
+
status: PendingPayloadInputStatus.waitingForBlock;
|
|
80
|
+
envelope: SignedExecutionPayloadEnvelope;
|
|
81
|
+
timeAddedSec: number;
|
|
82
|
+
peerIdStrings: Set<string>;
|
|
83
|
+
};
|
|
84
|
+
|
|
85
|
+
export type PayloadSyncCacheItem = PendingPayloadInput | PendingPayloadRootHex | PendingPayloadEnvelope;
|
|
86
|
+
|
|
47
87
|
export function isPendingBlockInput(pending: BlockInputSyncCacheItem): pending is PendingBlockInput {
|
|
48
88
|
return "blockInput" in pending;
|
|
49
89
|
}
|
|
50
90
|
|
|
91
|
+
export function isPendingPayloadInput(pending: PayloadSyncCacheItem): pending is PendingPayloadInput {
|
|
92
|
+
return "payloadInput" in pending;
|
|
93
|
+
}
|
|
94
|
+
|
|
95
|
+
export function isPendingPayloadEnvelope(pending: PayloadSyncCacheItem): pending is PendingPayloadEnvelope {
|
|
96
|
+
return "envelope" in pending;
|
|
97
|
+
}
|
|
98
|
+
|
|
51
99
|
export function getBlockInputSyncCacheItemRootHex(block: BlockInputSyncCacheItem): RootHex {
|
|
52
100
|
return isPendingBlockInput(block) ? block.blockInput.blockRootHex : block.rootHex;
|
|
53
101
|
}
|
|
@@ -55,3 +103,27 @@ export function getBlockInputSyncCacheItemRootHex(block: BlockInputSyncCacheItem
|
|
|
55
103
|
export function getBlockInputSyncCacheItemSlot(block: BlockInputSyncCacheItem): Slot | string {
|
|
56
104
|
return isPendingBlockInput(block) ? block.blockInput.slot : "unknown";
|
|
57
105
|
}
|
|
106
|
+
|
|
107
|
+
export function getPayloadSyncCacheItemRootHex(payload: PayloadSyncCacheItem): RootHex {
|
|
108
|
+
if (isPendingPayloadInput(payload)) {
|
|
109
|
+
return payload.payloadInput.blockRootHex;
|
|
110
|
+
}
|
|
111
|
+
|
|
112
|
+
if (isPendingPayloadEnvelope(payload)) {
|
|
113
|
+
return toRootHex(payload.envelope.message.beaconBlockRoot);
|
|
114
|
+
}
|
|
115
|
+
|
|
116
|
+
return payload.rootHex;
|
|
117
|
+
}
|
|
118
|
+
|
|
119
|
+
export function getPayloadSyncCacheItemSlot(payload: PayloadSyncCacheItem): Slot | string {
|
|
120
|
+
if (isPendingPayloadInput(payload)) {
|
|
121
|
+
return payload.payloadInput.slot;
|
|
122
|
+
}
|
|
123
|
+
|
|
124
|
+
if (isPendingPayloadEnvelope(payload)) {
|
|
125
|
+
return payload.envelope.message.payload.slotNumber;
|
|
126
|
+
}
|
|
127
|
+
|
|
128
|
+
return "unknown";
|
|
129
|
+
}
|