@lodestar/beacon-node 1.43.0-dev.78c66bac71 → 1.43.0-dev.87cbe69c66
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/importBlock.d.ts.map +1 -1
- package/lib/chain/blocks/importBlock.js +24 -20
- package/lib/chain/blocks/importBlock.js.map +1 -1
- package/lib/chain/blocks/importExecutionPayload.d.ts +19 -6
- package/lib/chain/blocks/importExecutionPayload.d.ts.map +1 -1
- package/lib/chain/blocks/importExecutionPayload.js +45 -23
- 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 +59 -25
- package/lib/chain/blocks/index.js.map +1 -1
- package/lib/chain/blocks/payloadEnvelopeInput/payloadEnvelopeInput.d.ts +1 -0
- package/lib/chain/blocks/payloadEnvelopeInput/payloadEnvelopeInput.d.ts.map +1 -1
- package/lib/chain/blocks/payloadEnvelopeInput/payloadEnvelopeInput.js +5 -1
- package/lib/chain/blocks/payloadEnvelopeInput/payloadEnvelopeInput.js.map +1 -1
- package/lib/chain/blocks/payloadEnvelopeInput/types.d.ts +1 -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 +7 -4
- 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/chain.d.ts +3 -2
- package/lib/chain/chain.d.ts.map +1 -1
- package/lib/chain/chain.js +12 -4
- 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/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/interface.d.ts +3 -2
- 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 +15 -17
- package/lib/chain/prepareNextSlot.js.map +1 -1
- package/lib/chain/produceBlock/produceBlockBody.d.ts +12 -3
- package/lib/chain/produceBlock/produceBlockBody.d.ts.map +1 -1
- package/lib/chain/produceBlock/produceBlockBody.js +35 -17
- 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 +8 -2
- package/lib/chain/seenCache/seenPayloadEnvelopeInput.d.ts.map +1 -1
- package/lib/chain/seenCache/seenPayloadEnvelopeInput.js +20 -4
- 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 +31 -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.js +11 -8
- 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 +24 -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/range/batch.d.ts +23 -2
- package/lib/sync/range/batch.d.ts.map +1 -1
- package/lib/sync/range/batch.js +84 -33
- package/lib/sync/range/batch.js.map +1 -1
- package/lib/sync/range/chain.d.ts +6 -2
- package/lib/sync/range/chain.d.ts.map +1 -1
- package/lib/sync/range/chain.js +26 -7
- 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 +17 -6
- package/lib/sync/range/range.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 +22 -1
- package/lib/sync/unknownBlock.d.ts.map +1 -1
- package/lib/sync/unknownBlock.js +602 -53
- package/lib/sync/unknownBlock.js.map +1 -1
- package/lib/sync/utils/downloadByRange.d.ts +46 -10
- package/lib/sync/utils/downloadByRange.d.ts.map +1 -1
- package/lib/sync/utils/downloadByRange.js +164 -24
- 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/importBlock.ts +24 -38
- package/src/chain/blocks/importExecutionPayload.ts +59 -25
- package/src/chain/blocks/index.ts +73 -22
- package/src/chain/blocks/payloadEnvelopeInput/payloadEnvelopeInput.ts +6 -1
- package/src/chain/blocks/payloadEnvelopeInput/types.ts +1 -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 +9 -4
- package/src/chain/blocks/verifyPayloadsDataAvailability.ts +7 -4
- package/src/chain/chain.ts +16 -3
- package/src/chain/emitter.ts +0 -11
- package/src/chain/errors/blockError.ts +4 -1
- package/src/chain/errors/index.ts +1 -0
- package/src/chain/errors/proposerPreferences.ts +47 -0
- package/src/chain/interface.ts +7 -1
- package/src/chain/opPools/payloadAttestationPool.ts +29 -8
- package/src/chain/prepareNextSlot.ts +20 -28
- package/src/chain/produceBlock/produceBlockBody.ts +46 -22
- 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 +25 -5
- package/src/chain/seenCache/seenProposerPreferences.ts +37 -0
- package/src/chain/validation/block.ts +1 -0
- package/src/chain/validation/executionPayloadBid.ts +11 -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 +35 -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/range/batch.ts +142 -38
- package/src/sync/range/chain.ts +37 -9
- package/src/sync/range/range.ts +18 -6
- package/src/sync/types.ts +72 -0
- package/src/sync/unknownBlock.ts +760 -57
- package/src/sync/utils/downloadByRange.ts +274 -39
- package/src/sync/utils/downloadByRoot.ts +24 -2
- package/src/sync/utils/pendingBlocksTree.ts +0 -15
- package/src/util/sszBytes.ts +8 -6
|
@@ -1,6 +1,23 @@
|
|
|
1
1
|
import {ChainForkConfig} from "@lodestar/config";
|
|
2
|
-
import {
|
|
3
|
-
|
|
2
|
+
import {
|
|
3
|
+
ForkPostDeneb,
|
|
4
|
+
ForkPostFulu,
|
|
5
|
+
ForkPostGloas,
|
|
6
|
+
ForkPreFulu,
|
|
7
|
+
isForkPostFulu,
|
|
8
|
+
isForkPostGloas,
|
|
9
|
+
} from "@lodestar/params";
|
|
10
|
+
import {
|
|
11
|
+
DataColumnSidecar,
|
|
12
|
+
SignedBeaconBlock,
|
|
13
|
+
Slot,
|
|
14
|
+
deneb,
|
|
15
|
+
fulu,
|
|
16
|
+
gloas,
|
|
17
|
+
isGloasBeaconBlock,
|
|
18
|
+
isGloasDataColumnSidecar,
|
|
19
|
+
phase0,
|
|
20
|
+
} from "@lodestar/types";
|
|
4
21
|
import {LodestarError, Logger, byteArrayEquals, fromHex, prettyPrintIndices, toRootHex} from "@lodestar/utils";
|
|
5
22
|
import {
|
|
6
23
|
BlockInputSource,
|
|
@@ -9,12 +26,18 @@ import {
|
|
|
9
26
|
isBlockInputBlobs,
|
|
10
27
|
isBlockInputColumns,
|
|
11
28
|
} from "../../chain/blocks/blockInput/index.js";
|
|
29
|
+
import {PayloadEnvelopeInput} from "../../chain/blocks/payloadEnvelopeInput/payloadEnvelopeInput.js";
|
|
30
|
+
import {PayloadEnvelopeInputSource} from "../../chain/blocks/payloadEnvelopeInput/types.js";
|
|
12
31
|
import {SeenBlockInput} from "../../chain/seenCache/seenGossipBlockInput.js";
|
|
32
|
+
import {SeenPayloadEnvelopeInput} from "../../chain/seenCache/seenPayloadEnvelopeInput.js";
|
|
13
33
|
import {validateBlockBlobSidecars} from "../../chain/validation/blobSidecar.js";
|
|
14
|
-
import {
|
|
34
|
+
import {
|
|
35
|
+
validateFuluBlockDataColumnSidecars,
|
|
36
|
+
validateGloasBlockDataColumnSidecars,
|
|
37
|
+
} from "../../chain/validation/dataColumnSidecar.js";
|
|
15
38
|
import {BeaconMetrics} from "../../metrics/metrics/beacon.js";
|
|
16
39
|
import {INetwork} from "../../network/index.js";
|
|
17
|
-
import {getBlobKzgCommitments} from "../../util/dataColumns.js";
|
|
40
|
+
import {CustodyConfig, getBlobKzgCommitments} from "../../util/dataColumns.js";
|
|
18
41
|
import {PeerIdStr} from "../../util/peerId.js";
|
|
19
42
|
import {WarnResult} from "../../util/wrapError.js";
|
|
20
43
|
|
|
@@ -22,12 +45,14 @@ export type DownloadByRangeRequests = {
|
|
|
22
45
|
blocksRequest?: phase0.BeaconBlocksByRangeRequest;
|
|
23
46
|
blobsRequest?: deneb.BlobSidecarsByRangeRequest;
|
|
24
47
|
columnsRequest?: fulu.DataColumnSidecarsByRangeRequest;
|
|
48
|
+
envelopesRequest?: gloas.ExecutionPayloadEnvelopesByRangeRequest;
|
|
25
49
|
};
|
|
26
50
|
|
|
27
51
|
export type DownloadByRangeResponses = {
|
|
28
52
|
blocks?: SignedBeaconBlock[];
|
|
29
53
|
blobSidecars?: deneb.BlobSidecars;
|
|
30
|
-
columnSidecars?:
|
|
54
|
+
columnSidecars?: DataColumnSidecar[];
|
|
55
|
+
payloadEnvelopes?: gloas.SignedExecutionPayloadEnvelope[];
|
|
31
56
|
};
|
|
32
57
|
|
|
33
58
|
export type DownloadAndCacheByRangeProps = DownloadByRangeRequests & {
|
|
@@ -41,9 +66,17 @@ export type DownloadAndCacheByRangeProps = DownloadByRangeRequests & {
|
|
|
41
66
|
|
|
42
67
|
export type CacheByRangeResponsesProps = {
|
|
43
68
|
cache: SeenBlockInput;
|
|
69
|
+
seenPayloadEnvelopeInputCache: SeenPayloadEnvelopeInput;
|
|
44
70
|
peerIdStr: string;
|
|
45
71
|
responses: ValidatedResponses;
|
|
46
72
|
batchBlocks: IBlockInput[];
|
|
73
|
+
/** Raw envelopes downloaded in this batch, keyed by slot (from downloadByRange return) */
|
|
74
|
+
downloadedPayloadEnvelopes: Map<Slot, gloas.SignedExecutionPayloadEnvelope> | null;
|
|
75
|
+
/** Envelopes already wrapped from previous partial downloads on this batch */
|
|
76
|
+
existingPayloadEnvelopes: Map<Slot, PayloadEnvelopeInput> | null;
|
|
77
|
+
/** Sampled/custody column indices for building PayloadEnvelopeInputs */
|
|
78
|
+
custodyConfig: Pick<CustodyConfig, "sampledColumns" | "custodyColumns">;
|
|
79
|
+
seenTimestampSec: number;
|
|
47
80
|
};
|
|
48
81
|
|
|
49
82
|
export type ValidatedBlock = {
|
|
@@ -58,7 +91,7 @@ export type ValidatedBlobSidecars = {
|
|
|
58
91
|
|
|
59
92
|
export type ValidatedColumnSidecars = {
|
|
60
93
|
blockRoot: Uint8Array;
|
|
61
|
-
columnSidecars:
|
|
94
|
+
columnSidecars: DataColumnSidecar[];
|
|
62
95
|
};
|
|
63
96
|
|
|
64
97
|
export type ValidatedResponses = {
|
|
@@ -72,12 +105,16 @@ export type ValidatedResponses = {
|
|
|
72
105
|
*/
|
|
73
106
|
export function cacheByRangeResponses({
|
|
74
107
|
cache,
|
|
108
|
+
seenPayloadEnvelopeInputCache,
|
|
75
109
|
peerIdStr,
|
|
76
110
|
responses,
|
|
77
111
|
batchBlocks,
|
|
78
|
-
|
|
112
|
+
downloadedPayloadEnvelopes,
|
|
113
|
+
existingPayloadEnvelopes,
|
|
114
|
+
custodyConfig,
|
|
115
|
+
seenTimestampSec,
|
|
116
|
+
}: CacheByRangeResponsesProps): {blocks: IBlockInput[]; payloadEnvelopes: Map<Slot, PayloadEnvelopeInput> | null} {
|
|
79
117
|
const source = BlockInputSource.byRange;
|
|
80
|
-
const seenTimestampSec = Date.now() / 1000;
|
|
81
118
|
const updatedBatchBlocks = new Map<Slot, IBlockInput>(batchBlocks.map((block) => [block.slot, block]));
|
|
82
119
|
|
|
83
120
|
const blocks = responses.validatedBlocks ?? [];
|
|
@@ -149,16 +186,88 @@ export function cacheByRangeResponses({
|
|
|
149
186
|
}
|
|
150
187
|
}
|
|
151
188
|
|
|
189
|
+
// Seed seenPayloadEnvelopeInputCache for every gloas block in the batch, regardless of whether
|
|
190
|
+
// the peer returned its envelope. Without this, a block returned without its envelope would be
|
|
191
|
+
// imported with no cache entry, and later payload-by-root sync would throw
|
|
192
|
+
// "Missing PayloadEnvelopeInput for known block" (see issue #9306).
|
|
193
|
+
for (const blockInput of updatedBatchBlocks.values()) {
|
|
194
|
+
if (!blockInput.hasBlock() || !isForkPostGloas(blockInput.forkName)) continue;
|
|
195
|
+
seenPayloadEnvelopeInputCache.add({
|
|
196
|
+
blockRootHex: blockInput.blockRootHex,
|
|
197
|
+
block: blockInput.getBlock() as SignedBeaconBlock<ForkPostGloas>,
|
|
198
|
+
forkName: blockInput.forkName,
|
|
199
|
+
sampledColumns: custodyConfig.sampledColumns,
|
|
200
|
+
custodyColumns: custodyConfig.custodyColumns,
|
|
201
|
+
timeCreatedSec: seenTimestampSec,
|
|
202
|
+
});
|
|
203
|
+
}
|
|
204
|
+
|
|
205
|
+
// Attach envelopes to entries whose envelope was returned by the peer. The returned
|
|
206
|
+
// payloadEnvelopes map only contains entries with envelopes ready for importExecutionPayload.
|
|
207
|
+
let payloadEnvelopes: Map<Slot, PayloadEnvelopeInput> | null = null;
|
|
208
|
+
if (downloadedPayloadEnvelopes !== null) {
|
|
209
|
+
payloadEnvelopes = new Map(existingPayloadEnvelopes ?? []);
|
|
210
|
+
|
|
211
|
+
for (const [slot, envelope] of downloadedPayloadEnvelopes) {
|
|
212
|
+
const blockInput = updatedBatchBlocks.get(slot);
|
|
213
|
+
if (!blockInput?.hasBlock() || !isForkPostGloas(blockInput.forkName)) {
|
|
214
|
+
// No block to pair this envelope with; drop silently
|
|
215
|
+
continue;
|
|
216
|
+
}
|
|
217
|
+
|
|
218
|
+
const payloadInput = seenPayloadEnvelopeInputCache.get(blockInput.blockRootHex);
|
|
219
|
+
if (payloadInput === undefined) {
|
|
220
|
+
// Unreachable given the loop above seeded an entry for every gloas block in the batch.
|
|
221
|
+
continue;
|
|
222
|
+
}
|
|
223
|
+
|
|
224
|
+
if (!payloadInput.hasPayloadEnvelope()) {
|
|
225
|
+
payloadInput.addPayloadEnvelope({
|
|
226
|
+
envelope,
|
|
227
|
+
source: PayloadEnvelopeInputSource.byRange,
|
|
228
|
+
seenTimestampSec,
|
|
229
|
+
peerIdStr,
|
|
230
|
+
});
|
|
231
|
+
}
|
|
232
|
+
|
|
233
|
+
payloadEnvelopes.set(slot, payloadInput);
|
|
234
|
+
}
|
|
235
|
+
}
|
|
236
|
+
|
|
152
237
|
for (const {blockRoot, columnSidecars} of responses.validatedColumnSidecars ?? []) {
|
|
153
|
-
const
|
|
154
|
-
if (
|
|
238
|
+
const firstColumn = columnSidecars[0];
|
|
239
|
+
if (!firstColumn) {
|
|
155
240
|
throw new Error(
|
|
156
241
|
`Coding Error: empty columnSidecars returned for blockRoot=${toRootHex(blockRoot)} from validation functions`
|
|
157
242
|
);
|
|
158
243
|
}
|
|
159
|
-
|
|
244
|
+
|
|
160
245
|
const blockRootHex = toRootHex(blockRoot);
|
|
161
246
|
|
|
247
|
+
if (isGloasDataColumnSidecar(firstColumn)) {
|
|
248
|
+
// Gloas columns are attached to the matching PayloadEnvelopeInput, NOT to IBlockInput.
|
|
249
|
+
// Gloas DataColumnSidecar has `slot` directly (no signedBlockHeader).
|
|
250
|
+
const dataSlot = firstColumn.slot;
|
|
251
|
+
const payloadInput = payloadEnvelopes?.get(dataSlot);
|
|
252
|
+
if (!payloadInput) {
|
|
253
|
+
// Should not happen: we built payloadInputs for all gloas blocks above
|
|
254
|
+
continue;
|
|
255
|
+
}
|
|
256
|
+
for (const columnSidecar of columnSidecars as gloas.DataColumnSidecar[]) {
|
|
257
|
+
payloadInput.addColumn({
|
|
258
|
+
columnSidecar,
|
|
259
|
+
seenTimestampSec,
|
|
260
|
+
peerIdStr,
|
|
261
|
+
source: PayloadEnvelopeInputSource.byRange,
|
|
262
|
+
});
|
|
263
|
+
}
|
|
264
|
+
continue;
|
|
265
|
+
}
|
|
266
|
+
|
|
267
|
+
const fuluColumns = columnSidecars as fulu.DataColumnSidecar[];
|
|
268
|
+
const dataSlot = fuluColumns[0].signedBlockHeader.message.slot;
|
|
269
|
+
const existing = updatedBatchBlocks.get(dataSlot);
|
|
270
|
+
|
|
162
271
|
if (!existing) {
|
|
163
272
|
throw new Error("Coding error: blockInput must exist when adding columns");
|
|
164
273
|
}
|
|
@@ -172,7 +281,7 @@ export function cacheByRangeResponses({
|
|
|
172
281
|
actual: existing.type,
|
|
173
282
|
});
|
|
174
283
|
}
|
|
175
|
-
for (const columnSidecar of
|
|
284
|
+
for (const columnSidecar of fuluColumns) {
|
|
176
285
|
// will throw if root hex does not match (meaning we are following the wrong chain)
|
|
177
286
|
existing.addColumn(
|
|
178
287
|
{
|
|
@@ -187,7 +296,7 @@ export function cacheByRangeResponses({
|
|
|
187
296
|
}
|
|
188
297
|
}
|
|
189
298
|
|
|
190
|
-
return Array.from(updatedBatchBlocks.values());
|
|
299
|
+
return {blocks: Array.from(updatedBatchBlocks.values()), payloadEnvelopes};
|
|
191
300
|
}
|
|
192
301
|
|
|
193
302
|
export async function downloadByRange({
|
|
@@ -198,8 +307,14 @@ export async function downloadByRange({
|
|
|
198
307
|
blocksRequest,
|
|
199
308
|
blobsRequest,
|
|
200
309
|
columnsRequest,
|
|
310
|
+
envelopesRequest,
|
|
201
311
|
peerDasMetrics,
|
|
202
|
-
}: DownloadAndCacheByRangeProps): Promise<
|
|
312
|
+
}: DownloadAndCacheByRangeProps): Promise<
|
|
313
|
+
WarnResult<
|
|
314
|
+
{responses: ValidatedResponses; payloadEnvelopes: Map<Slot, gloas.SignedExecutionPayloadEnvelope> | null},
|
|
315
|
+
DownloadByRangeError
|
|
316
|
+
>
|
|
317
|
+
> {
|
|
203
318
|
let response: DownloadByRangeResponses;
|
|
204
319
|
try {
|
|
205
320
|
response = await requestByRange({
|
|
@@ -208,6 +323,7 @@ export async function downloadByRange({
|
|
|
208
323
|
blocksRequest,
|
|
209
324
|
blobsRequest,
|
|
210
325
|
columnsRequest,
|
|
326
|
+
envelopesRequest,
|
|
211
327
|
});
|
|
212
328
|
} catch (err) {
|
|
213
329
|
throw new DownloadByRangeError({
|
|
@@ -217,17 +333,16 @@ export async function downloadByRange({
|
|
|
217
333
|
});
|
|
218
334
|
}
|
|
219
335
|
|
|
220
|
-
|
|
336
|
+
return validateResponses({
|
|
221
337
|
config,
|
|
222
338
|
batchBlocks,
|
|
223
339
|
blocksRequest,
|
|
224
340
|
blobsRequest,
|
|
225
341
|
columnsRequest,
|
|
342
|
+
envelopesRequest,
|
|
226
343
|
peerDasMetrics,
|
|
227
344
|
...response,
|
|
228
345
|
});
|
|
229
|
-
|
|
230
|
-
return validated;
|
|
231
346
|
}
|
|
232
347
|
|
|
233
348
|
/**
|
|
@@ -239,13 +354,15 @@ export async function requestByRange({
|
|
|
239
354
|
blocksRequest,
|
|
240
355
|
blobsRequest,
|
|
241
356
|
columnsRequest,
|
|
357
|
+
envelopesRequest,
|
|
242
358
|
}: DownloadByRangeRequests & {
|
|
243
359
|
network: INetwork;
|
|
244
360
|
peerIdStr: PeerIdStr;
|
|
245
361
|
}): Promise<DownloadByRangeResponses> {
|
|
246
362
|
let blocks: undefined | SignedBeaconBlock[];
|
|
247
363
|
let blobSidecars: undefined | deneb.BlobSidecars;
|
|
248
|
-
let columnSidecars: undefined |
|
|
364
|
+
let columnSidecars: undefined | DataColumnSidecar[];
|
|
365
|
+
const payloadEnvelopes: gloas.SignedExecutionPayloadEnvelope[] = [];
|
|
249
366
|
|
|
250
367
|
const requests: Promise<unknown>[] = [];
|
|
251
368
|
|
|
@@ -253,6 +370,17 @@ export async function requestByRange({
|
|
|
253
370
|
requests.push(
|
|
254
371
|
network.sendBeaconBlocksByRange(peerIdStr, blocksRequest).then((blockResponse) => {
|
|
255
372
|
blocks = blockResponse;
|
|
373
|
+
const firstBlock = blockResponse.at(0);
|
|
374
|
+
if (firstBlock && isGloasBeaconBlock(firstBlock.message)) {
|
|
375
|
+
return network
|
|
376
|
+
.sendExecutionPayloadEnvelopesByRoot(peerIdStr, [
|
|
377
|
+
firstBlock.message.body.signedExecutionPayloadBid.message.parentBlockRoot,
|
|
378
|
+
])
|
|
379
|
+
.then((envelopeResponse) => {
|
|
380
|
+
payloadEnvelopes?.unshift(...envelopeResponse);
|
|
381
|
+
});
|
|
382
|
+
}
|
|
383
|
+
return undefined;
|
|
256
384
|
})
|
|
257
385
|
);
|
|
258
386
|
}
|
|
@@ -268,7 +396,15 @@ export async function requestByRange({
|
|
|
268
396
|
if (columnsRequest) {
|
|
269
397
|
requests.push(
|
|
270
398
|
network.sendDataColumnSidecarsByRange(peerIdStr, columnsRequest).then((columnResponse) => {
|
|
271
|
-
columnSidecars = columnResponse
|
|
399
|
+
columnSidecars = columnResponse;
|
|
400
|
+
})
|
|
401
|
+
);
|
|
402
|
+
}
|
|
403
|
+
|
|
404
|
+
if (envelopesRequest) {
|
|
405
|
+
requests.push(
|
|
406
|
+
network.sendExecutionPayloadEnvelopesByRange(peerIdStr, envelopesRequest).then((envelopeResponse) => {
|
|
407
|
+
payloadEnvelopes?.push(...envelopeResponse);
|
|
272
408
|
})
|
|
273
409
|
);
|
|
274
410
|
}
|
|
@@ -279,6 +415,7 @@ export async function requestByRange({
|
|
|
279
415
|
blocks,
|
|
280
416
|
blobSidecars,
|
|
281
417
|
columnSidecars,
|
|
418
|
+
payloadEnvelopes,
|
|
282
419
|
};
|
|
283
420
|
}
|
|
284
421
|
|
|
@@ -291,16 +428,23 @@ export async function validateResponses({
|
|
|
291
428
|
blocksRequest,
|
|
292
429
|
blobsRequest,
|
|
293
430
|
columnsRequest,
|
|
431
|
+
envelopesRequest,
|
|
294
432
|
blocks,
|
|
295
433
|
blobSidecars,
|
|
296
434
|
columnSidecars,
|
|
435
|
+
payloadEnvelopes,
|
|
297
436
|
peerDasMetrics,
|
|
298
437
|
}: DownloadByRangeRequests &
|
|
299
438
|
DownloadByRangeResponses & {
|
|
300
439
|
config: ChainForkConfig;
|
|
301
440
|
batchBlocks?: IBlockInput[];
|
|
302
441
|
peerDasMetrics?: BeaconMetrics["peerDas"] | null;
|
|
303
|
-
}): Promise<
|
|
442
|
+
}): Promise<
|
|
443
|
+
WarnResult<
|
|
444
|
+
{responses: ValidatedResponses; payloadEnvelopes: Map<Slot, gloas.SignedExecutionPayloadEnvelope> | null},
|
|
445
|
+
DownloadByRangeError
|
|
446
|
+
>
|
|
447
|
+
> {
|
|
304
448
|
// Blocks are always required for blob/column validation
|
|
305
449
|
// If a blocksRequest is provided, blocks have just been downloaded
|
|
306
450
|
// If no blocksRequest is provided, batchBlocks must have been provided from cache
|
|
@@ -326,8 +470,21 @@ export async function validateResponses({
|
|
|
326
470
|
}
|
|
327
471
|
|
|
328
472
|
const dataRequest = blobsRequest ?? columnsRequest;
|
|
473
|
+
if (!dataRequest && !envelopesRequest) {
|
|
474
|
+
return {result: {responses: validatedResponses, payloadEnvelopes: null}, warnings};
|
|
475
|
+
}
|
|
476
|
+
|
|
329
477
|
if (!dataRequest) {
|
|
330
|
-
|
|
478
|
+
// Only envelope validation needed
|
|
479
|
+
let validatedPayloadEnvelopes: Map<Slot, gloas.SignedExecutionPayloadEnvelope> | null = null;
|
|
480
|
+
if (envelopesRequest) {
|
|
481
|
+
validatedPayloadEnvelopes = validateEnvelopesByRangeResponse(
|
|
482
|
+
validatedResponses.validatedBlocks ?? [],
|
|
483
|
+
batchBlocks,
|
|
484
|
+
payloadEnvelopes ?? []
|
|
485
|
+
);
|
|
486
|
+
}
|
|
487
|
+
return {result: {responses: validatedResponses, payloadEnvelopes: validatedPayloadEnvelopes}, warnings};
|
|
331
488
|
}
|
|
332
489
|
|
|
333
490
|
const blocksForDataValidation = getBlocksForDataValidation(
|
|
@@ -385,7 +542,17 @@ export async function validateResponses({
|
|
|
385
542
|
warnings = validatedColumnSidecarsResult.warnings;
|
|
386
543
|
}
|
|
387
544
|
|
|
388
|
-
|
|
545
|
+
// Validate envelopes if an envelopes request was made
|
|
546
|
+
let validatedPayloadEnvelopes: Map<Slot, gloas.SignedExecutionPayloadEnvelope> | null = null;
|
|
547
|
+
if (envelopesRequest) {
|
|
548
|
+
validatedPayloadEnvelopes = validateEnvelopesByRangeResponse(
|
|
549
|
+
validatedResponses.validatedBlocks ?? [],
|
|
550
|
+
batchBlocks,
|
|
551
|
+
payloadEnvelopes ?? []
|
|
552
|
+
);
|
|
553
|
+
}
|
|
554
|
+
|
|
555
|
+
return {result: {responses: validatedResponses, payloadEnvelopes: validatedPayloadEnvelopes}, warnings};
|
|
389
556
|
}
|
|
390
557
|
|
|
391
558
|
/**
|
|
@@ -615,19 +782,19 @@ export async function validateColumnsByRangeResponse(
|
|
|
615
782
|
config: ChainForkConfig,
|
|
616
783
|
request: fulu.DataColumnSidecarsByRangeRequest,
|
|
617
784
|
blocks: ValidatedBlock[],
|
|
618
|
-
columnSidecars:
|
|
785
|
+
columnSidecars: DataColumnSidecar[],
|
|
619
786
|
peerDasMetrics?: BeaconMetrics["peerDas"] | null
|
|
620
787
|
): Promise<WarnResult<ValidatedColumnSidecars[], DownloadByRangeError>> {
|
|
621
788
|
const warnings: DownloadByRangeError[] = [];
|
|
622
789
|
|
|
623
|
-
|
|
624
|
-
// validate against the block bid commitments instead of the fulu signed header shape
|
|
625
|
-
const seenColumns = new Map<Slot, Map<number, fulu.DataColumnSidecar>>();
|
|
790
|
+
const seenColumns = new Map<Slot, Map<number, DataColumnSidecar>>();
|
|
626
791
|
let currentSlot = -1;
|
|
627
792
|
let currentIndex = -1;
|
|
628
793
|
// Check for duplicates and order
|
|
629
794
|
for (const columnSidecar of columnSidecars) {
|
|
630
|
-
const slot = columnSidecar
|
|
795
|
+
const slot = isGloasDataColumnSidecar(columnSidecar)
|
|
796
|
+
? columnSidecar.slot
|
|
797
|
+
: columnSidecar.signedBlockHeader.message.slot;
|
|
631
798
|
let seenSlotColumns = seenColumns.get(slot);
|
|
632
799
|
if (!seenSlotColumns) {
|
|
633
800
|
seenSlotColumns = new Map();
|
|
@@ -686,20 +853,20 @@ export async function validateColumnsByRangeResponse(
|
|
|
686
853
|
const slot = block.message.slot;
|
|
687
854
|
const rootHex = toRootHex(blockRoot);
|
|
688
855
|
const forkName = config.getForkName(slot);
|
|
689
|
-
const columnSidecarsMap: Map<number,
|
|
856
|
+
const columnSidecarsMap: Map<number, DataColumnSidecar> = seenColumns.get(slot) ?? new Map();
|
|
690
857
|
const columnSidecars = Array.from(columnSidecarsMap.values()).sort((a, b) => a.index - b.index);
|
|
691
858
|
|
|
692
859
|
let blobCount: number;
|
|
693
860
|
if (!isForkPostFulu(forkName)) {
|
|
694
|
-
const dataSlot = columnSidecars.at(0)?.signedBlockHeader.message.slot;
|
|
695
861
|
throw new DownloadByRangeError({
|
|
696
862
|
code: DownloadByRangeErrorCode.MISMATCH_BLOCK_FORK,
|
|
697
863
|
slot,
|
|
698
864
|
blockFork: forkName,
|
|
699
|
-
dataFork:
|
|
865
|
+
dataFork: "unknown",
|
|
700
866
|
});
|
|
701
867
|
}
|
|
702
|
-
|
|
868
|
+
const kzgCommitments = getBlobKzgCommitments(forkName, block as SignedBeaconBlock<ForkPostFulu>);
|
|
869
|
+
blobCount = kzgCommitments.length;
|
|
703
870
|
|
|
704
871
|
if (columnSidecars.length === 0) {
|
|
705
872
|
if (!blobCount) {
|
|
@@ -768,15 +935,25 @@ export async function validateColumnsByRangeResponse(
|
|
|
768
935
|
);
|
|
769
936
|
}
|
|
770
937
|
|
|
938
|
+
const validatePromise = isForkPostGloas(forkName)
|
|
939
|
+
? validateGloasBlockDataColumnSidecars(
|
|
940
|
+
slot,
|
|
941
|
+
blockRoot,
|
|
942
|
+
kzgCommitments,
|
|
943
|
+
columnSidecars as gloas.DataColumnSidecar[],
|
|
944
|
+
peerDasMetrics
|
|
945
|
+
)
|
|
946
|
+
: validateFuluBlockDataColumnSidecars(
|
|
947
|
+
null, // do not pass chain here so we do not validate header signature
|
|
948
|
+
slot,
|
|
949
|
+
blockRoot,
|
|
950
|
+
blobCount,
|
|
951
|
+
columnSidecars as fulu.DataColumnSidecar[],
|
|
952
|
+
peerDasMetrics
|
|
953
|
+
);
|
|
954
|
+
|
|
771
955
|
validationPromises.push(
|
|
772
|
-
|
|
773
|
-
null, // do not pass chain here so we do not validate header signature
|
|
774
|
-
slot,
|
|
775
|
-
blockRoot,
|
|
776
|
-
blobCount,
|
|
777
|
-
columnSidecars,
|
|
778
|
-
peerDasMetrics
|
|
779
|
-
).then(() => ({
|
|
956
|
+
validatePromise.then(() => ({
|
|
780
957
|
blockRoot,
|
|
781
958
|
columnSidecars,
|
|
782
959
|
}))
|
|
@@ -882,6 +1059,9 @@ export enum DownloadByRangeErrorCode {
|
|
|
882
1059
|
/** Cached block input type mismatches new data */
|
|
883
1060
|
MISMATCH_BLOCK_FORK = "DOWNLOAD_BY_RANGE_ERROR_MISMATCH_BLOCK_FORK",
|
|
884
1061
|
MISMATCH_BLOCK_INPUT_TYPE = "DOWNLOAD_BY_RANGE_ERROR_MISMATCH_BLOCK_INPUT_TYPE",
|
|
1062
|
+
|
|
1063
|
+
/** Envelope beaconBlockRoot does not match the block's root */
|
|
1064
|
+
INVALID_ENVELOPE_BEACON_BLOCK_ROOT = "DOWNLOAD_BY_RANGE_ERROR_INVALID_ENVELOPE_BEACON_BLOCK_ROOT",
|
|
885
1065
|
}
|
|
886
1066
|
|
|
887
1067
|
export type DownloadByRangeErrorType =
|
|
@@ -973,6 +1153,61 @@ export type DownloadByRangeErrorType =
|
|
|
973
1153
|
blockRoot: string;
|
|
974
1154
|
expected: DAType;
|
|
975
1155
|
actual: DAType;
|
|
1156
|
+
}
|
|
1157
|
+
| {
|
|
1158
|
+
code: DownloadByRangeErrorCode.INVALID_ENVELOPE_BEACON_BLOCK_ROOT;
|
|
1159
|
+
slot: Slot;
|
|
1160
|
+
expected: string;
|
|
1161
|
+
actual: string;
|
|
976
1162
|
};
|
|
977
1163
|
|
|
978
1164
|
export class DownloadByRangeError extends LodestarError<DownloadByRangeErrorType> {}
|
|
1165
|
+
|
|
1166
|
+
/**
|
|
1167
|
+
* Validates SignedExecutionPayloadEnvelopes received for a range request.
|
|
1168
|
+
* For each envelope whose slot appears in the downloaded blocks, verifies that
|
|
1169
|
+
* envelope.message.beaconBlockRoot matches the corresponding block's root.
|
|
1170
|
+
* Envelopes for slots not in the batch (orphaned payloads) are silently ignored.
|
|
1171
|
+
*/
|
|
1172
|
+
export function validateEnvelopesByRangeResponse(
|
|
1173
|
+
validatedBlocks: ValidatedBlock[],
|
|
1174
|
+
batchBlocks: IBlockInput[] | undefined,
|
|
1175
|
+
payloadEnvelopes: gloas.SignedExecutionPayloadEnvelope[]
|
|
1176
|
+
): Map<Slot, gloas.SignedExecutionPayloadEnvelope> {
|
|
1177
|
+
// Build a map of slot -> blockRoot for all blocks in the batch
|
|
1178
|
+
const batchBlockRoots = new Map<Slot, Uint8Array>();
|
|
1179
|
+
if (batchBlocks) {
|
|
1180
|
+
for (const blockInput of batchBlocks) {
|
|
1181
|
+
batchBlockRoots.set(blockInput.slot, fromHex(blockInput.blockRootHex));
|
|
1182
|
+
}
|
|
1183
|
+
}
|
|
1184
|
+
for (const {block, blockRoot} of validatedBlocks) {
|
|
1185
|
+
batchBlockRoots.set(block.message.slot, blockRoot);
|
|
1186
|
+
}
|
|
1187
|
+
|
|
1188
|
+
const payloadEnvelopeMap = new Map<Slot, gloas.SignedExecutionPayloadEnvelope>();
|
|
1189
|
+
|
|
1190
|
+
for (const payloadEnvelope of payloadEnvelopes) {
|
|
1191
|
+
const slot = payloadEnvelope.message.payload.slotNumber;
|
|
1192
|
+
const batchBlockRoot = batchBlockRoots.get(slot);
|
|
1193
|
+
|
|
1194
|
+
// Envelopes for slots not in the batch are silently ignored (orphaned payloads or a parent payload)
|
|
1195
|
+
if (batchBlockRoot === undefined) {
|
|
1196
|
+
continue;
|
|
1197
|
+
}
|
|
1198
|
+
|
|
1199
|
+
// Verify beaconBlockRoot matches the block's root
|
|
1200
|
+
if (!byteArrayEquals(payloadEnvelope.message.beaconBlockRoot, batchBlockRoot)) {
|
|
1201
|
+
throw new DownloadByRangeError({
|
|
1202
|
+
code: DownloadByRangeErrorCode.INVALID_ENVELOPE_BEACON_BLOCK_ROOT,
|
|
1203
|
+
slot,
|
|
1204
|
+
expected: toRootHex(batchBlockRoot),
|
|
1205
|
+
actual: toRootHex(payloadEnvelope.message.beaconBlockRoot),
|
|
1206
|
+
});
|
|
1207
|
+
}
|
|
1208
|
+
|
|
1209
|
+
payloadEnvelopeMap.set(slot, payloadEnvelope);
|
|
1210
|
+
}
|
|
1211
|
+
|
|
1212
|
+
return payloadEnvelopeMap;
|
|
1213
|
+
}
|
|
@@ -1,6 +1,14 @@
|
|
|
1
1
|
import {routes} from "@lodestar/api";
|
|
2
2
|
import {ChainForkConfig} from "@lodestar/config";
|
|
3
|
-
import {
|
|
3
|
+
import {
|
|
4
|
+
ForkPostDeneb,
|
|
5
|
+
ForkPostFulu,
|
|
6
|
+
ForkPostGloas,
|
|
7
|
+
ForkPreFulu,
|
|
8
|
+
isForkPostDeneb,
|
|
9
|
+
isForkPostFulu,
|
|
10
|
+
isForkPostGloas,
|
|
11
|
+
} from "@lodestar/params";
|
|
4
12
|
import {BlobIndex, ColumnIndex, SignedBeaconBlock, Slot, deneb, fulu} from "@lodestar/types";
|
|
5
13
|
import {LodestarError, byteArrayEquals, fromHex, prettyPrintIndices, toHex, toRootHex} from "@lodestar/utils";
|
|
6
14
|
import {isBlockInputBlobs, isBlockInputColumns} from "../../chain/blocks/blockInput/blockInput.js";
|
|
@@ -107,6 +115,17 @@ export async function downloadByRoot({
|
|
|
107
115
|
});
|
|
108
116
|
}
|
|
109
117
|
|
|
118
|
+
if (isForkPostGloas(blockInput.forkName)) {
|
|
119
|
+
chain.seenPayloadEnvelopeInputCache.add({
|
|
120
|
+
blockRootHex: rootHex,
|
|
121
|
+
block: blockInput.getBlock() as SignedBeaconBlock<ForkPostGloas>,
|
|
122
|
+
forkName: blockInput.forkName,
|
|
123
|
+
sampledColumns: chain.custodyConfig.sampledColumns,
|
|
124
|
+
custodyColumns: chain.custodyConfig.custodyColumns,
|
|
125
|
+
timeCreatedSec: Date.now() / 1000,
|
|
126
|
+
});
|
|
127
|
+
}
|
|
128
|
+
|
|
110
129
|
const hasAllDataPreDownload = blockInput.hasBlockAndAllData();
|
|
111
130
|
|
|
112
131
|
if (isBlockInputBlobs(blockInput) && !hasAllDataPreDownload) {
|
|
@@ -263,7 +282,10 @@ export async function fetchByRoot({
|
|
|
263
282
|
blockRoot,
|
|
264
283
|
});
|
|
265
284
|
const forkName = config.getForkName(block.message.slot);
|
|
266
|
-
if (
|
|
285
|
+
if (isForkPostGloas(forkName)) {
|
|
286
|
+
// Post-gloas block sync only needs the block body. Payload columns stay on the
|
|
287
|
+
// payload/envelope path and are queued independently in the network processor.
|
|
288
|
+
} else if (isForkPostFulu(forkName)) {
|
|
267
289
|
columnSidecarResult = await fetchAndValidateColumns({
|
|
268
290
|
config,
|
|
269
291
|
chain,
|
|
@@ -40,21 +40,6 @@ function addToDescendantBlocks(
|
|
|
40
40
|
return descendantBlocks;
|
|
41
41
|
}
|
|
42
42
|
|
|
43
|
-
export function getDescendantBlocks(
|
|
44
|
-
blockRootHex: RootHex,
|
|
45
|
-
blocks: Map<RootHex, BlockInputSyncCacheItem>
|
|
46
|
-
): BlockInputSyncCacheItem[] {
|
|
47
|
-
const descendantBlocks: BlockInputSyncCacheItem[] = [];
|
|
48
|
-
|
|
49
|
-
for (const block of blocks.values()) {
|
|
50
|
-
if ((isPendingBlockInput(block) ? block.blockInput.parentRootHex : undefined) === blockRootHex) {
|
|
51
|
-
descendantBlocks.push(block);
|
|
52
|
-
}
|
|
53
|
-
}
|
|
54
|
-
|
|
55
|
-
return descendantBlocks;
|
|
56
|
-
}
|
|
57
|
-
|
|
58
43
|
export type UnknownAndAncestorBlocks = {
|
|
59
44
|
unknowns: BlockInputSyncCacheItem[];
|
|
60
45
|
ancestors: PendingBlockInput[];
|
package/src/util/sszBytes.ts
CHANGED
|
@@ -558,9 +558,10 @@ export function getBeaconBlockRootFromDataColumnSidecarSerialized(data: Uint8Arr
|
|
|
558
558
|
* └─ ExecutionPayloadEnvelope (starts at byte 100):
|
|
559
559
|
* ├─ 4 bytes: payload offset
|
|
560
560
|
* ├─ 4 bytes: executionRequests offset
|
|
561
|
-
* ├─ 8 bytes: builderIndex
|
|
562
|
-
* ├─ 32 bytes: beaconBlockRoot
|
|
563
|
-
*
|
|
561
|
+
* ├─ 8 bytes: builderIndex (offset 108-115)
|
|
562
|
+
* ├─ 32 bytes: beaconBlockRoot (offset 116-147)
|
|
563
|
+
* ├─ 32 bytes: parentBeaconBlockRoot (offset 148-179) — new in Gloas alpha.6 (consensus-specs#5152)
|
|
564
|
+
* └─ variable: payload data (starts at envelope + 80)
|
|
564
565
|
* └─ ExecutionPayload fixed portion includes slotNumber at offset 532
|
|
565
566
|
*/
|
|
566
567
|
const SIGNED_EXECUTION_PAYLOAD_ENVELOPE_MESSAGE_OFFSET = 4;
|
|
@@ -576,12 +577,13 @@ const BEACON_BLOCK_ROOT_OFFSET_IN_SIGNED_EXECUTION_PAYLOAD_ENVELOPE =
|
|
|
576
577
|
EXECUTION_PAYLOAD_ENVELOPE_REQUESTS_OFFSET +
|
|
577
578
|
EXECUTION_PAYLOAD_ENVELOPE_BUILDER_INDEX_SIZE; // 116
|
|
578
579
|
|
|
579
|
-
// Envelope fixed portion
|
|
580
|
+
// Envelope fixed portion: payload_offset(4) + requests_offset(4) + builderIndex(8) + beaconBlockRoot(32) + parentBeaconBlockRoot(32) = 80
|
|
580
581
|
const EXECUTION_PAYLOAD_ENVELOPE_FIXED_SIZE =
|
|
581
582
|
EXECUTION_PAYLOAD_ENVELOPE_PAYLOAD_OFFSET +
|
|
582
583
|
EXECUTION_PAYLOAD_ENVELOPE_REQUESTS_OFFSET +
|
|
583
584
|
EXECUTION_PAYLOAD_ENVELOPE_BUILDER_INDEX_SIZE +
|
|
584
|
-
ROOT_SIZE
|
|
585
|
+
ROOT_SIZE +
|
|
586
|
+
ROOT_SIZE; // 80
|
|
585
587
|
|
|
586
588
|
// slotNumber offset within ExecutionPayload fixed portion:
|
|
587
589
|
// parentHash(32) + feeRecipient(20) + stateRoot(32) + receiptsRoot(32) + logsBloom(256) +
|
|
@@ -595,7 +597,7 @@ const ENVELOPE_START_IN_SIGNED =
|
|
|
595
597
|
SIGNED_EXECUTION_PAYLOAD_ENVELOPE_MESSAGE_OFFSET + SIGNED_EXECUTION_PAYLOAD_ENVELOPE_SIGNATURE_SIZE; // 100
|
|
596
598
|
|
|
597
599
|
const SLOT_OFFSET_IN_SIGNED_EXECUTION_PAYLOAD_ENVELOPE =
|
|
598
|
-
ENVELOPE_START_IN_SIGNED + EXECUTION_PAYLOAD_ENVELOPE_FIXED_SIZE + SLOT_NUMBER_OFFSET_IN_EXECUTION_PAYLOAD; // 100 +
|
|
600
|
+
ENVELOPE_START_IN_SIGNED + EXECUTION_PAYLOAD_ENVELOPE_FIXED_SIZE + SLOT_NUMBER_OFFSET_IN_EXECUTION_PAYLOAD; // 100 + 80 + 532 = 712
|
|
599
601
|
|
|
600
602
|
export function getSlotFromExecutionPayloadEnvelopeSerialized(data: Uint8Array): Slot | null {
|
|
601
603
|
if (data.length < SLOT_OFFSET_IN_SIGNED_EXECUTION_PAYLOAD_ENVELOPE + SLOT_SIZE) {
|