@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/batch.ts
CHANGED
|
@@ -1,17 +1,19 @@
|
|
|
1
1
|
import {ChainForkConfig} from "@lodestar/config";
|
|
2
|
-
import {ForkName, isForkPostDeneb, isForkPostFulu} from "@lodestar/params";
|
|
3
|
-
import {Epoch, RootHex, Slot, phase0} from "@lodestar/types";
|
|
4
|
-
import {LodestarError} from "@lodestar/utils";
|
|
2
|
+
import {ForkName, isForkPostDeneb, isForkPostFulu, isForkPostGloas} from "@lodestar/params";
|
|
3
|
+
import {Epoch, RootHex, SignedBeaconBlock, Slot, gloas, phase0} from "@lodestar/types";
|
|
4
|
+
import {LodestarError, byteArrayEquals, prettyPrintIndices, toRootHex} from "@lodestar/utils";
|
|
5
5
|
import {isBlockInputColumns} from "../../chain/blocks/blockInput/blockInput.js";
|
|
6
6
|
import {IBlockInput} from "../../chain/blocks/blockInput/types.js";
|
|
7
7
|
import {isDaOutOfRange} from "../../chain/blocks/blockInput/utils.js";
|
|
8
|
+
import {PayloadEnvelopeInput} from "../../chain/blocks/payloadEnvelopeInput/payloadEnvelopeInput.js";
|
|
8
9
|
import {BlockError, BlockErrorCode} from "../../chain/errors/index.js";
|
|
10
|
+
import {ZERO_HASH} from "../../constants/constants.js";
|
|
9
11
|
import {PeerSyncMeta} from "../../network/peers/peersData.js";
|
|
10
12
|
import {IClock} from "../../util/clock.js";
|
|
11
13
|
import {CustodyConfig} from "../../util/dataColumns.js";
|
|
12
14
|
import {PeerIdStr} from "../../util/peerId.js";
|
|
13
15
|
import {MAX_BATCH_DOWNLOAD_ATTEMPTS, MAX_BATCH_PROCESSING_ATTEMPTS} from "../constants.js";
|
|
14
|
-
import {DownloadByRangeRequests} from "../utils/downloadByRange.js";
|
|
16
|
+
import {DownloadByRangeRequests, ParentPayloadCommitments} from "../utils/downloadByRange.js";
|
|
15
17
|
import {getBatchSlotRange, hashBlocks} from "./utils/index.js";
|
|
16
18
|
|
|
17
19
|
/**
|
|
@@ -46,25 +48,68 @@ export type Attempt = {
|
|
|
46
48
|
export type AwaitingDownloadState = {
|
|
47
49
|
status: BatchStatus.AwaitingDownload;
|
|
48
50
|
blocks: IBlockInput[];
|
|
51
|
+
payloadEnvelopes: Map<Slot, PayloadEnvelopeInput> | null;
|
|
49
52
|
};
|
|
50
53
|
|
|
51
54
|
export type DownloadSuccessState = {
|
|
52
55
|
status: BatchStatus.AwaitingProcessing;
|
|
53
56
|
blocks: IBlockInput[];
|
|
57
|
+
payloadEnvelopes: Map<Slot, PayloadEnvelopeInput> | null;
|
|
54
58
|
};
|
|
55
59
|
|
|
56
60
|
export type BatchState =
|
|
57
61
|
| AwaitingDownloadState
|
|
58
|
-
| {
|
|
62
|
+
| {
|
|
63
|
+
status: BatchStatus.Downloading;
|
|
64
|
+
peer: PeerIdStr;
|
|
65
|
+
blocks: IBlockInput[];
|
|
66
|
+
payloadEnvelopes: Map<Slot, PayloadEnvelopeInput> | null;
|
|
67
|
+
}
|
|
59
68
|
| DownloadSuccessState
|
|
60
|
-
| {
|
|
61
|
-
|
|
69
|
+
| {
|
|
70
|
+
status: BatchStatus.Processing;
|
|
71
|
+
blocks: IBlockInput[];
|
|
72
|
+
payloadEnvelopes: Map<Slot, PayloadEnvelopeInput> | null;
|
|
73
|
+
attempt: Attempt;
|
|
74
|
+
}
|
|
75
|
+
| {
|
|
76
|
+
status: BatchStatus.AwaitingValidation;
|
|
77
|
+
blocks: IBlockInput[];
|
|
78
|
+
payloadEnvelopes: Map<Slot, PayloadEnvelopeInput> | null;
|
|
79
|
+
attempt: Attempt;
|
|
80
|
+
};
|
|
62
81
|
|
|
63
82
|
export type BatchMetadata = {
|
|
83
|
+
// Batch-level slot window (always present)
|
|
64
84
|
startEpoch: Epoch;
|
|
85
|
+
startSlot: Slot;
|
|
86
|
+
count: number;
|
|
65
87
|
status: BatchStatus;
|
|
88
|
+
|
|
89
|
+
// Per-type outstanding request shapes; only present when that sub-request exists.
|
|
90
|
+
// Format: "startSlot=<n>,count=<n>" (plus ",cols=<indices>" for columns).
|
|
91
|
+
blocksReq?: string;
|
|
92
|
+
blobsReq?: string;
|
|
93
|
+
columnsReq?: string;
|
|
94
|
+
envelopesReq?: string;
|
|
95
|
+
|
|
96
|
+
// Retry counters
|
|
97
|
+
downloadAttempts: number;
|
|
98
|
+
processingAttempts: number;
|
|
99
|
+
|
|
100
|
+
// Cumulative peer attribution for failed attempts (only present when non-empty)
|
|
101
|
+
failedDownloadPeers?: string;
|
|
102
|
+
failedProcessingPeers?: string;
|
|
66
103
|
};
|
|
67
104
|
|
|
105
|
+
function formatRangeReq(req: {startSlot: Slot; count: number}): string {
|
|
106
|
+
return `startSlot=${req.startSlot},count=${req.count}`;
|
|
107
|
+
}
|
|
108
|
+
|
|
109
|
+
function formatColumnsReq(req: {startSlot: Slot; count: number; columns: number[]}): string {
|
|
110
|
+
return `startSlot=${req.startSlot},count=${req.count},cols=${prettyPrintIndices(req.columns)}`;
|
|
111
|
+
}
|
|
112
|
+
|
|
68
113
|
/**
|
|
69
114
|
* Batches are downloaded at the first block of the epoch.
|
|
70
115
|
*
|
|
@@ -85,7 +130,7 @@ export class Batch {
|
|
|
85
130
|
/** Block, blob and column requests that are used to determine the best peer and are used in downloadByRange */
|
|
86
131
|
requests: DownloadByRangeRequests;
|
|
87
132
|
/** State of the batch. */
|
|
88
|
-
state: BatchState = {status: BatchStatus.AwaitingDownload, blocks: []};
|
|
133
|
+
state: BatchState = {status: BatchStatus.AwaitingDownload, blocks: [], payloadEnvelopes: null};
|
|
89
134
|
/** Peers that provided good data */
|
|
90
135
|
goodPeers: PeerIdStr[] = [];
|
|
91
136
|
/** The `Attempts` that have been made and failed to send us this batch. */
|
|
@@ -97,8 +142,18 @@ export class Batch {
|
|
|
97
142
|
private readonly config: ChainForkConfig;
|
|
98
143
|
private readonly clock: IClock;
|
|
99
144
|
private readonly custodyConfig: CustodyConfig;
|
|
100
|
-
|
|
101
|
-
|
|
145
|
+
private readonly isFirstBatchInChain: boolean;
|
|
146
|
+
private readonly latestBid: gloas.ExecutionPayloadBid | undefined;
|
|
147
|
+
|
|
148
|
+
constructor(
|
|
149
|
+
startEpoch: Epoch,
|
|
150
|
+
config: ChainForkConfig,
|
|
151
|
+
clock: IClock,
|
|
152
|
+
custodyConfig: CustodyConfig,
|
|
153
|
+
isFirstBatchInChain: boolean,
|
|
154
|
+
latestBid: gloas.ExecutionPayloadBid | undefined,
|
|
155
|
+
targetSlot: Slot
|
|
156
|
+
) {
|
|
102
157
|
this.config = config;
|
|
103
158
|
this.clock = clock;
|
|
104
159
|
this.custodyConfig = custodyConfig;
|
|
@@ -107,10 +162,40 @@ export class Batch {
|
|
|
107
162
|
this.forkName = this.config.getForkName(startSlot);
|
|
108
163
|
this.startEpoch = startEpoch;
|
|
109
164
|
this.startSlot = startSlot;
|
|
110
|
-
this.count = count;
|
|
165
|
+
this.count = Math.min(count, targetSlot - startSlot + 1);
|
|
166
|
+
this.isFirstBatchInChain = isFirstBatchInChain;
|
|
167
|
+
this.latestBid = latestBid;
|
|
111
168
|
this.requests = this.getRequests([]);
|
|
112
169
|
}
|
|
113
170
|
|
|
171
|
+
private shouldDownloadParentEnvelope(firstBlock?: SignedBeaconBlock): boolean {
|
|
172
|
+
if (!this.isFirstBatchInChain) return false;
|
|
173
|
+
|
|
174
|
+
if (this.startSlot === 0 || !isForkPostGloas(this.config.getForkName(this.startSlot - 1))) {
|
|
175
|
+
return false;
|
|
176
|
+
}
|
|
177
|
+
|
|
178
|
+
// we only know if we should download parent envelope if firstBlock is downloaded
|
|
179
|
+
if (firstBlock === undefined) return false;
|
|
180
|
+
if (this.latestBid === undefined) return false;
|
|
181
|
+
const firstBlockBidParentHash = (firstBlock.message.body as gloas.BeaconBlockBody).signedExecutionPayloadBid.message
|
|
182
|
+
.parentBlockHash;
|
|
183
|
+
return byteArrayEquals(firstBlockBidParentHash, this.latestBid.blockHash);
|
|
184
|
+
}
|
|
185
|
+
|
|
186
|
+
getParentPayloadCommitments(parentBlockRoot: Uint8Array): ParentPayloadCommitments {
|
|
187
|
+
if (this.latestBid === undefined) {
|
|
188
|
+
throw new Error(
|
|
189
|
+
`Coding error: getParentPayloadCommitments called without latestBid for parentBlockRoot=${toRootHex(parentBlockRoot)}`
|
|
190
|
+
);
|
|
191
|
+
}
|
|
192
|
+
return {
|
|
193
|
+
blockRoot: parentBlockRoot,
|
|
194
|
+
blockRootHex: toRootHex(parentBlockRoot),
|
|
195
|
+
kzgCommitments: this.latestBid.blobKzgCommitments,
|
|
196
|
+
};
|
|
197
|
+
}
|
|
198
|
+
|
|
114
199
|
/**
|
|
115
200
|
* Builds ByRange requests for block, blobs and columns
|
|
116
201
|
*/
|
|
@@ -129,37 +214,36 @@ export class Batch {
|
|
|
129
214
|
count: this.count,
|
|
130
215
|
step: 1,
|
|
131
216
|
};
|
|
132
|
-
|
|
133
|
-
|
|
134
|
-
|
|
135
|
-
|
|
136
|
-
|
|
137
|
-
count: this.count,
|
|
138
|
-
columns: this.custodyConfig.sampledColumns,
|
|
139
|
-
},
|
|
140
|
-
};
|
|
217
|
+
const requests: DownloadByRangeRequests = {blocksRequest};
|
|
218
|
+
|
|
219
|
+
// Post-Gloas envelopes are required for block processing, independent of DA retention window.
|
|
220
|
+
if (isForkPostGloas(this.forkName)) {
|
|
221
|
+
requests.envelopesRequest = {startSlot: this.startSlot, count: this.count};
|
|
141
222
|
}
|
|
142
|
-
|
|
143
|
-
|
|
144
|
-
|
|
145
|
-
|
|
146
|
-
|
|
147
|
-
|
|
148
|
-
},
|
|
223
|
+
|
|
224
|
+
if (isForkPostFulu(this.forkName) && withinValidRequestWindow) {
|
|
225
|
+
requests.columnsRequest = {
|
|
226
|
+
startSlot: this.startSlot,
|
|
227
|
+
count: this.count,
|
|
228
|
+
columns: this.custodyConfig.sampledColumns,
|
|
149
229
|
};
|
|
230
|
+
} else if (isForkPostDeneb(this.forkName) && withinValidRequestWindow) {
|
|
231
|
+
requests.blobsRequest = {startSlot: this.startSlot, count: this.count};
|
|
150
232
|
}
|
|
151
|
-
|
|
152
|
-
|
|
153
|
-
};
|
|
233
|
+
|
|
234
|
+
return requests;
|
|
154
235
|
}
|
|
155
236
|
|
|
156
237
|
// subsequent request where part of the epoch has already been downloaded. Need to figure out what is the beginning
|
|
157
238
|
// of the range where download needs to resume
|
|
158
239
|
let blockStartSlot = this.startSlot;
|
|
159
240
|
let dataStartSlot = this.startSlot;
|
|
241
|
+
let envelopeStartSlot = this.startSlot;
|
|
160
242
|
const neededColumns = new Set<number>();
|
|
243
|
+
const envelopesBySlot = this.state.payloadEnvelopes ?? new Map<Slot, PayloadEnvelopeInput>();
|
|
161
244
|
|
|
162
245
|
// ensure blocks are in slot-wise order
|
|
246
|
+
const isPostGloas = isForkPostGloas(this.forkName);
|
|
163
247
|
for (const blockInput of blocks) {
|
|
164
248
|
const blockSlot = blockInput.slot;
|
|
165
249
|
// check if block/data is present (hasBlock/hasAllData). If present then check if startSlot is the same as
|
|
@@ -175,14 +259,36 @@ export class Batch {
|
|
|
175
259
|
if (blockInput.hasBlock() && blockStartSlot === blockSlot) {
|
|
176
260
|
blockStartSlot = blockSlot + 1;
|
|
177
261
|
}
|
|
178
|
-
|
|
179
|
-
|
|
180
|
-
|
|
262
|
+
|
|
263
|
+
// Range sync uses hasComputedAllData (all sampled columns physically present), not hasAllData
|
|
264
|
+
// which flips at the reconstruction threshold. Sync never triggers reconstruction, so accepting
|
|
265
|
+
// a half-downloaded block here makes writeBlockInputToDb later block on waitForComputedAllData.
|
|
266
|
+
if (isPostGloas) {
|
|
267
|
+
// Post-Gloas: column data lives on PayloadEnvelopeInput, not on BlockInputNoData.
|
|
268
|
+
const payloadInput = envelopesBySlot.get(blockSlot);
|
|
269
|
+
if (blockInput.hasBlock() && envelopeStartSlot === blockSlot && payloadInput?.hasPayloadEnvelope()) {
|
|
270
|
+
envelopeStartSlot = blockSlot + 1;
|
|
271
|
+
}
|
|
272
|
+
if (payloadInput && !payloadInput.hasComputedAllData()) {
|
|
273
|
+
for (const index of payloadInput.getMissingSampledColumnMeta().missing) {
|
|
181
274
|
neededColumns.add(index);
|
|
182
275
|
}
|
|
276
|
+
} else if (payloadInput?.hasComputedAllData() && dataStartSlot === blockSlot) {
|
|
277
|
+
// Only advance dataStartSlot when we know columns for this slot are complete. If
|
|
278
|
+
// payloadInput is missing entirely we cannot tell, so stop here so the next round
|
|
279
|
+
// re-requests columns (and envelopes) starting at this slot.
|
|
280
|
+
dataStartSlot = blockSlot + 1;
|
|
281
|
+
}
|
|
282
|
+
} else {
|
|
283
|
+
if (isBlockInputColumns(blockInput) ? !blockInput.hasComputedAllData() : !blockInput.hasAllData()) {
|
|
284
|
+
if (isBlockInputColumns(blockInput)) {
|
|
285
|
+
for (const index of blockInput.getMissingSampledColumnMeta().missing) {
|
|
286
|
+
neededColumns.add(index);
|
|
287
|
+
}
|
|
288
|
+
}
|
|
289
|
+
} else if (dataStartSlot === blockSlot) {
|
|
290
|
+
dataStartSlot = blockSlot + 1;
|
|
183
291
|
}
|
|
184
|
-
} else if (dataStartSlot === blockSlot) {
|
|
185
|
-
dataStartSlot = blockSlot + 1;
|
|
186
292
|
}
|
|
187
293
|
}
|
|
188
294
|
|
|
@@ -202,11 +308,15 @@ export class Batch {
|
|
|
202
308
|
// range of 40 - 63, startSlot will be inclusive but subtraction will exclusive so need to + 1
|
|
203
309
|
const count = endSlot - dataStartSlot + 1;
|
|
204
310
|
if (isForkPostFulu(this.forkName) && withinValidRequestWindow) {
|
|
205
|
-
|
|
206
|
-
|
|
207
|
-
|
|
208
|
-
|
|
209
|
-
|
|
311
|
+
// Skip the column re-request when we have no specific column indices outstanding.
|
|
312
|
+
// Peer rejects an empty `columns` list
|
|
313
|
+
if (neededColumns.size > 0) {
|
|
314
|
+
requests.columnsRequest = {
|
|
315
|
+
count,
|
|
316
|
+
startSlot: dataStartSlot,
|
|
317
|
+
columns: Array.from(neededColumns),
|
|
318
|
+
};
|
|
319
|
+
}
|
|
210
320
|
} else if (isForkPostDeneb(this.forkName) && withinValidRequestWindow) {
|
|
211
321
|
requests.blobsRequest = {
|
|
212
322
|
count,
|
|
@@ -216,6 +326,43 @@ export class Batch {
|
|
|
216
326
|
// dataSlot will still have a value but do not create a request for preDeneb forks
|
|
217
327
|
}
|
|
218
328
|
|
|
329
|
+
if (isForkPostGloas(this.forkName) && envelopeStartSlot <= endSlot) {
|
|
330
|
+
requests.envelopesRequest = {
|
|
331
|
+
startSlot: envelopeStartSlot,
|
|
332
|
+
count: endSlot - envelopeStartSlot + 1,
|
|
333
|
+
};
|
|
334
|
+
}
|
|
335
|
+
|
|
336
|
+
// Only the first batch of a SyncChain may need the dangling-parent payload by-root.
|
|
337
|
+
if (blocks.length > 0 && this.shouldDownloadParentEnvelope(blocks[0].getBlock())) {
|
|
338
|
+
// shouldDownloadParentEnvelope() = true means there are at least 1 block
|
|
339
|
+
const parentRoot = blocks[0].getBlock().message.parentRoot;
|
|
340
|
+
if (!byteArrayEquals(parentRoot, ZERO_HASH)) {
|
|
341
|
+
const parentRootHex = toRootHex(parentRoot);
|
|
342
|
+
let parentPayloadInput: PayloadEnvelopeInput | undefined;
|
|
343
|
+
if (this.state.payloadEnvelopes) {
|
|
344
|
+
for (const pi of this.state.payloadEnvelopes.values()) {
|
|
345
|
+
if (pi.blockRootHex === parentRootHex) {
|
|
346
|
+
parentPayloadInput = pi;
|
|
347
|
+
break;
|
|
348
|
+
}
|
|
349
|
+
}
|
|
350
|
+
}
|
|
351
|
+
|
|
352
|
+
const needsEnvelope = !parentPayloadInput?.hasPayloadEnvelope();
|
|
353
|
+
const missingColumns = parentPayloadInput
|
|
354
|
+
? parentPayloadInput.getMissingSampledColumnMeta().missing
|
|
355
|
+
: this.custodyConfig.sampledColumns;
|
|
356
|
+
|
|
357
|
+
if (needsEnvelope || missingColumns.length > 0) {
|
|
358
|
+
requests.parentPayloadRequest = {
|
|
359
|
+
...(needsEnvelope ? {envelopeBlockRoot: parentRoot} : {}),
|
|
360
|
+
...(missingColumns.length > 0 ? {blockRoot: parentRoot, columns: missingColumns} : {}),
|
|
361
|
+
};
|
|
362
|
+
}
|
|
363
|
+
}
|
|
364
|
+
}
|
|
365
|
+
|
|
219
366
|
return requests;
|
|
220
367
|
}
|
|
221
368
|
|
|
@@ -227,24 +374,28 @@ export class Batch {
|
|
|
227
374
|
return this.requests;
|
|
228
375
|
}
|
|
229
376
|
|
|
230
|
-
// post-fulu we need to ensure that we only request columns that the peer has advertised
|
|
231
|
-
const {columnsRequest} = this.requests;
|
|
232
|
-
if (columnsRequest == null) {
|
|
233
|
-
return this.requests;
|
|
234
|
-
}
|
|
377
|
+
// post-fulu we need to ensure that we only request columns that the peer has advertised.
|
|
378
|
+
const {columnsRequest, parentPayloadRequest} = this.requests;
|
|
235
379
|
|
|
236
380
|
const peerColumns = new Set(peer.custodyColumns ?? []);
|
|
237
|
-
const
|
|
238
|
-
|
|
239
|
-
|
|
240
|
-
|
|
381
|
+
const filteredColumnsRequest =
|
|
382
|
+
columnsRequest != null ? columnsRequest.columns.filter((c) => peerColumns.has(c)) : null;
|
|
383
|
+
const parentColumns = parentPayloadRequest?.columns;
|
|
384
|
+
const filteredParentColumns = parentColumns != null ? parentColumns.filter((c) => peerColumns.has(c)) : null;
|
|
385
|
+
|
|
386
|
+
const updatedColumnRequest =
|
|
387
|
+
columnsRequest != null && filteredColumnsRequest != null
|
|
388
|
+
? {columnsRequest: {...columnsRequest, columns: filteredColumnsRequest}}
|
|
389
|
+
: {};
|
|
390
|
+
const updatedParentPayloadRequest =
|
|
391
|
+
parentPayloadRequest != null && filteredParentColumns != null
|
|
392
|
+
? {parentPayloadRequest: {...parentPayloadRequest, columns: filteredParentColumns}}
|
|
393
|
+
: {};
|
|
241
394
|
|
|
242
395
|
return {
|
|
243
396
|
...this.requests,
|
|
244
|
-
|
|
245
|
-
|
|
246
|
-
columns: requestedColumns,
|
|
247
|
-
},
|
|
397
|
+
...updatedColumnRequest,
|
|
398
|
+
...updatedParentPayloadRequest,
|
|
248
399
|
};
|
|
249
400
|
}
|
|
250
401
|
|
|
@@ -256,13 +407,36 @@ export class Batch {
|
|
|
256
407
|
}
|
|
257
408
|
|
|
258
409
|
getMetadata(): BatchMetadata {
|
|
259
|
-
|
|
410
|
+
const {blocksRequest, blobsRequest, columnsRequest, envelopesRequest} = this.requests;
|
|
411
|
+
const failedProcessingPeerList = this.failedProcessingAttempts.flatMap((a) => a.peers);
|
|
412
|
+
return {
|
|
413
|
+
startEpoch: this.startEpoch,
|
|
414
|
+
startSlot: this.startSlot,
|
|
415
|
+
count: this.count,
|
|
416
|
+
status: this.state.status,
|
|
417
|
+
...(blocksRequest && {blocksReq: formatRangeReq(blocksRequest)}),
|
|
418
|
+
...(blobsRequest && {blobsReq: formatRangeReq(blobsRequest)}),
|
|
419
|
+
...(columnsRequest && {columnsReq: formatColumnsReq(columnsRequest)}),
|
|
420
|
+
...(envelopesRequest && {envelopesReq: formatRangeReq(envelopesRequest)}),
|
|
421
|
+
downloadAttempts: this.failedDownloadAttempts.length,
|
|
422
|
+
processingAttempts: this.failedProcessingAttempts.length,
|
|
423
|
+
...(this.failedDownloadAttempts.length > 0 && {
|
|
424
|
+
failedDownloadPeers: this.failedDownloadAttempts.join(","),
|
|
425
|
+
}),
|
|
426
|
+
...(failedProcessingPeerList.length > 0 && {
|
|
427
|
+
failedProcessingPeers: failedProcessingPeerList.join(","),
|
|
428
|
+
}),
|
|
429
|
+
};
|
|
260
430
|
}
|
|
261
431
|
|
|
262
432
|
getBlocks(): IBlockInput[] {
|
|
263
433
|
return this.state.blocks;
|
|
264
434
|
}
|
|
265
435
|
|
|
436
|
+
getPayloadEnvelopes(): Map<Slot, PayloadEnvelopeInput> | null {
|
|
437
|
+
return this.state.payloadEnvelopes;
|
|
438
|
+
}
|
|
439
|
+
|
|
266
440
|
/**
|
|
267
441
|
* AwaitingDownload -> Downloading
|
|
268
442
|
*/
|
|
@@ -271,13 +445,22 @@ export class Batch {
|
|
|
271
445
|
throw new BatchError(this.wrongStatusErrorType(BatchStatus.AwaitingDownload));
|
|
272
446
|
}
|
|
273
447
|
|
|
274
|
-
this.state = {
|
|
448
|
+
this.state = {
|
|
449
|
+
status: BatchStatus.Downloading,
|
|
450
|
+
peer,
|
|
451
|
+
blocks: this.state.blocks,
|
|
452
|
+
payloadEnvelopes: this.state.payloadEnvelopes,
|
|
453
|
+
};
|
|
275
454
|
}
|
|
276
455
|
|
|
277
456
|
/**
|
|
278
457
|
* Downloading -> AwaitingProcessing
|
|
279
458
|
*/
|
|
280
|
-
downloadingSuccess(
|
|
459
|
+
downloadingSuccess(
|
|
460
|
+
peer: PeerIdStr,
|
|
461
|
+
blocks: IBlockInput[],
|
|
462
|
+
payloadEnvelopes: Map<Slot, PayloadEnvelopeInput> | null
|
|
463
|
+
): DownloadSuccessState {
|
|
281
464
|
if (this.state.status !== BatchStatus.Downloading) {
|
|
282
465
|
throw new BatchError(this.wrongStatusErrorType(BatchStatus.Downloading));
|
|
283
466
|
}
|
|
@@ -291,7 +474,11 @@ export class Batch {
|
|
|
291
474
|
const slots = new Set<number>();
|
|
292
475
|
for (const block of blocks) {
|
|
293
476
|
slots.add(block.slot);
|
|
294
|
-
|
|
477
|
+
const dataComplete = isBlockInputColumns(block)
|
|
478
|
+
? // by_range needs to download all columns
|
|
479
|
+
block.hasBlock() && block.hasComputedAllData()
|
|
480
|
+
: block.hasBlockAndAllData();
|
|
481
|
+
if (!dataComplete) {
|
|
295
482
|
allComplete = false;
|
|
296
483
|
}
|
|
297
484
|
}
|
|
@@ -305,11 +492,47 @@ export class Batch {
|
|
|
305
492
|
status: this.state.status,
|
|
306
493
|
});
|
|
307
494
|
}
|
|
495
|
+
const newPayloadEnvelopes = payloadEnvelopes ?? this.state.payloadEnvelopes;
|
|
496
|
+
|
|
497
|
+
if (allComplete && isForkPostGloas(this.forkName)) {
|
|
498
|
+
for (const block of blocks) {
|
|
499
|
+
const payloadInput = newPayloadEnvelopes?.get(block.slot);
|
|
500
|
+
// by_range needs every block's envelope and all sampled columns.
|
|
501
|
+
if (!payloadInput?.hasPayloadEnvelope() || !payloadInput.hasComputedAllData()) {
|
|
502
|
+
allComplete = false;
|
|
503
|
+
break;
|
|
504
|
+
}
|
|
505
|
+
}
|
|
506
|
+
}
|
|
507
|
+
|
|
508
|
+
// First batch of a sync chain must additionally have the dangling-parent payload fully
|
|
509
|
+
// present, otherwise `processBlocks` will throw PARENT_PAYLOAD_UNKNOWN. The parent's
|
|
510
|
+
// `PayloadEnvelopeInput` is identified by `blockRootHex` matching `blocks[0].parentRoot`.
|
|
511
|
+
if (allComplete && blocks.length > 0 && this.shouldDownloadParentEnvelope(blocks[0].getBlock())) {
|
|
512
|
+
const parentRoot = blocks[0].getBlock().message.parentRoot;
|
|
513
|
+
// Genesis has no parent payload — nothing to wait for.
|
|
514
|
+
if (!byteArrayEquals(parentRoot, ZERO_HASH)) {
|
|
515
|
+
const parentRootHex = toRootHex(parentRoot);
|
|
516
|
+
let parentPayloadComplete = false;
|
|
517
|
+
if (newPayloadEnvelopes) {
|
|
518
|
+
for (const payloadInput of newPayloadEnvelopes.values()) {
|
|
519
|
+
if (payloadInput.blockRootHex === parentRootHex) {
|
|
520
|
+
parentPayloadComplete = payloadInput.hasPayloadEnvelope() && payloadInput.hasComputedAllData();
|
|
521
|
+
break;
|
|
522
|
+
}
|
|
523
|
+
}
|
|
524
|
+
}
|
|
525
|
+
if (!parentPayloadComplete) {
|
|
526
|
+
allComplete = false;
|
|
527
|
+
}
|
|
528
|
+
}
|
|
529
|
+
}
|
|
530
|
+
|
|
308
531
|
if (allComplete) {
|
|
309
|
-
this.state = {status: BatchStatus.AwaitingProcessing, blocks};
|
|
532
|
+
this.state = {status: BatchStatus.AwaitingProcessing, blocks, payloadEnvelopes: newPayloadEnvelopes};
|
|
310
533
|
} else {
|
|
534
|
+
this.state = {status: BatchStatus.AwaitingDownload, blocks, payloadEnvelopes: newPayloadEnvelopes};
|
|
311
535
|
this.requests = this.getRequests(blocks);
|
|
312
|
-
this.state = {status: BatchStatus.AwaitingDownload, blocks};
|
|
313
536
|
}
|
|
314
537
|
|
|
315
538
|
return this.state as DownloadSuccessState;
|
|
@@ -328,25 +551,50 @@ export class Batch {
|
|
|
328
551
|
throw new BatchError(this.errorType({code: BatchErrorCode.MAX_DOWNLOAD_ATTEMPTS}));
|
|
329
552
|
}
|
|
330
553
|
|
|
331
|
-
this.state = {
|
|
554
|
+
this.state = {
|
|
555
|
+
status: BatchStatus.AwaitingDownload,
|
|
556
|
+
blocks: this.state.blocks,
|
|
557
|
+
payloadEnvelopes: this.state.payloadEnvelopes,
|
|
558
|
+
};
|
|
559
|
+
}
|
|
560
|
+
|
|
561
|
+
/**
|
|
562
|
+
* Downloading -> AwaitingDownload (without counting as a failed attempt).
|
|
563
|
+
* Used when the peer rate-limited us — the request was never actually served.
|
|
564
|
+
*/
|
|
565
|
+
downloadingRateLimited(): void {
|
|
566
|
+
if (this.state.status !== BatchStatus.Downloading) {
|
|
567
|
+
throw new BatchError(this.wrongStatusErrorType(BatchStatus.Downloading));
|
|
568
|
+
}
|
|
569
|
+
|
|
570
|
+
this.state = {
|
|
571
|
+
status: BatchStatus.AwaitingDownload,
|
|
572
|
+
blocks: this.state.blocks,
|
|
573
|
+
payloadEnvelopes: this.state.payloadEnvelopes,
|
|
574
|
+
};
|
|
332
575
|
}
|
|
333
576
|
|
|
334
577
|
/**
|
|
335
578
|
* AwaitingProcessing -> Processing
|
|
336
579
|
*/
|
|
337
|
-
startProcessing():
|
|
580
|
+
startProcessing(): {
|
|
581
|
+
blocks: IBlockInput[];
|
|
582
|
+
payloadEnvelopes: Map<Slot, PayloadEnvelopeInput> | null;
|
|
583
|
+
peers: PeerIdStr[];
|
|
584
|
+
} {
|
|
338
585
|
if (this.state.status !== BatchStatus.AwaitingProcessing) {
|
|
339
586
|
throw new BatchError(this.wrongStatusErrorType(BatchStatus.AwaitingProcessing));
|
|
340
587
|
}
|
|
341
588
|
|
|
342
589
|
const blocks = this.state.blocks;
|
|
590
|
+
const payloadEnvelopes = this.state.payloadEnvelopes;
|
|
343
591
|
const hash = hashBlocks(blocks, this.config); // tracks blocks to report peer on processing error
|
|
344
592
|
// Reset goodPeers in case another download attempt needs to be made. When Attempt is successful or not the peers
|
|
345
593
|
// that the data came from will be handled by the Attempt that goes for processing
|
|
346
594
|
const peers = this.goodPeers;
|
|
347
595
|
this.goodPeers = [];
|
|
348
|
-
this.state = {status: BatchStatus.Processing, blocks, attempt: {peers, hash}};
|
|
349
|
-
return blocks;
|
|
596
|
+
this.state = {status: BatchStatus.Processing, blocks, payloadEnvelopes, attempt: {peers, hash}};
|
|
597
|
+
return {blocks, payloadEnvelopes, peers};
|
|
350
598
|
}
|
|
351
599
|
|
|
352
600
|
/**
|
|
@@ -357,7 +605,12 @@ export class Batch {
|
|
|
357
605
|
throw new BatchError(this.wrongStatusErrorType(BatchStatus.Processing));
|
|
358
606
|
}
|
|
359
607
|
|
|
360
|
-
this.state = {
|
|
608
|
+
this.state = {
|
|
609
|
+
status: BatchStatus.AwaitingValidation,
|
|
610
|
+
blocks: this.state.blocks,
|
|
611
|
+
payloadEnvelopes: this.state.payloadEnvelopes,
|
|
612
|
+
attempt: this.state.attempt,
|
|
613
|
+
};
|
|
361
614
|
}
|
|
362
615
|
|
|
363
616
|
/**
|
|
@@ -408,7 +661,7 @@ export class Batch {
|
|
|
408
661
|
|
|
409
662
|
// remove any downloaded blocks and re-attempt
|
|
410
663
|
// TODO(fulu): need to remove the bad blocks from the SeenBlockInputCache
|
|
411
|
-
this.state = {status: BatchStatus.AwaitingDownload, blocks: []};
|
|
664
|
+
this.state = {status: BatchStatus.AwaitingDownload, blocks: [], payloadEnvelopes: null};
|
|
412
665
|
}
|
|
413
666
|
|
|
414
667
|
private onProcessingError(attempt: Attempt): void {
|
|
@@ -419,12 +672,12 @@ export class Batch {
|
|
|
419
672
|
|
|
420
673
|
// remove any downloaded blocks and re-attempt
|
|
421
674
|
// TODO(fulu): need to remove the bad blocks from the SeenBlockInputCache
|
|
422
|
-
this.state = {status: BatchStatus.AwaitingDownload, blocks: []};
|
|
675
|
+
this.state = {status: BatchStatus.AwaitingDownload, blocks: [], payloadEnvelopes: null};
|
|
423
676
|
}
|
|
424
677
|
|
|
425
678
|
/** Helper to construct typed BatchError. Stack traces are correct as the error is thrown above */
|
|
426
679
|
private errorType(type: BatchErrorType): BatchErrorType & BatchErrorMetadata {
|
|
427
|
-
return {...type,
|
|
680
|
+
return {...type, startEpoch: this.startEpoch, status: this.state.status};
|
|
428
681
|
}
|
|
429
682
|
|
|
430
683
|
private wrongStatusErrorType(expectedStatus: BatchStatus): BatchErrorType & BatchErrorMetadata {
|