@lodestar/beacon-node 1.44.0-dev.ff43f013ea → 1.44.0-rc.1
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 +13 -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 +1 -1
- package/lib/api/impl/beacon/pool/index.js.map +1 -1
- package/lib/api/impl/config/constants.d.ts +1 -0
- package/lib/api/impl/config/constants.d.ts.map +1 -1
- package/lib/api/impl/config/constants.js +2 -1
- package/lib/api/impl/config/constants.js.map +1 -1
- package/lib/api/impl/debug/index.d.ts.map +1 -1
- package/lib/api/impl/debug/index.js +69 -12
- package/lib/api/impl/debug/index.js.map +1 -1
- package/lib/api/impl/lodestar/index.d.ts.map +1 -1
- package/lib/api/impl/lodestar/index.js +28 -0
- 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 +41 -16
- package/lib/api/impl/validator/index.js.map +1 -1
- package/lib/chain/archiveStore/archiveStore.d.ts +0 -1
- package/lib/chain/archiveStore/archiveStore.d.ts.map +1 -1
- package/lib/chain/archiveStore/archiveStore.js +0 -4
- package/lib/chain/archiveStore/archiveStore.js.map +1 -1
- package/lib/chain/blocks/importBlock.d.ts.map +1 -1
- package/lib/chain/blocks/importBlock.js +1 -1
- package/lib/chain/blocks/importBlock.js.map +1 -1
- package/lib/chain/chain.d.ts.map +1 -1
- package/lib/chain/chain.js +8 -1
- package/lib/chain/chain.js.map +1 -1
- package/lib/chain/emitter.d.ts +2 -1
- package/lib/chain/emitter.d.ts.map +1 -1
- package/lib/chain/emitter.js.map +1 -1
- package/lib/chain/errors/blockError.d.ts +0 -7
- package/lib/chain/errors/blockError.d.ts.map +1 -1
- package/lib/chain/errors/blockError.js +0 -3
- package/lib/chain/errors/blockError.js.map +1 -1
- package/lib/chain/errors/payloadAttestation.d.ts +6 -0
- package/lib/chain/errors/payloadAttestation.d.ts.map +1 -1
- package/lib/chain/errors/payloadAttestation.js +1 -0
- package/lib/chain/errors/payloadAttestation.js.map +1 -1
- package/lib/chain/forkChoice/index.d.ts +4 -4
- package/lib/chain/forkChoice/index.d.ts.map +1 -1
- package/lib/chain/forkChoice/index.js +10 -7
- package/lib/chain/forkChoice/index.js.map +1 -1
- package/lib/chain/options.d.ts.map +1 -1
- package/lib/chain/options.js +1 -0
- package/lib/chain/options.js.map +1 -1
- package/lib/chain/prepareNextSlot.js +1 -1
- package/lib/chain/prepareNextSlot.js.map +1 -1
- package/lib/chain/produceBlock/produceBlockBody.js +3 -3
- package/lib/chain/produceBlock/produceBlockBody.js.map +1 -1
- package/lib/chain/regen/interface.d.ts +1 -1
- 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 +0 -1
- package/lib/chain/regen/queued.d.ts.map +1 -1
- package/lib/chain/regen/queued.js +0 -4
- package/lib/chain/regen/queued.js.map +1 -1
- package/lib/chain/stateCache/fifoBlockStateCache.d.ts +0 -5
- package/lib/chain/stateCache/fifoBlockStateCache.d.ts.map +1 -1
- package/lib/chain/stateCache/fifoBlockStateCache.js +0 -5
- package/lib/chain/stateCache/fifoBlockStateCache.js.map +1 -1
- package/lib/chain/stateCache/persistentCheckpointsCache.d.ts +1 -4
- package/lib/chain/stateCache/persistentCheckpointsCache.d.ts.map +1 -1
- package/lib/chain/stateCache/persistentCheckpointsCache.js +5 -2
- package/lib/chain/stateCache/persistentCheckpointsCache.js.map +1 -1
- package/lib/chain/stateCache/types.d.ts +0 -2
- package/lib/chain/stateCache/types.d.ts.map +1 -1
- package/lib/chain/stateCache/types.js.map +1 -1
- package/lib/chain/validation/block.d.ts +5 -1
- package/lib/chain/validation/block.d.ts.map +1 -1
- package/lib/chain/validation/block.js +4 -14
- package/lib/chain/validation/block.js.map +1 -1
- package/lib/chain/validation/executionPayloadBid.js +22 -5
- package/lib/chain/validation/executionPayloadBid.js.map +1 -1
- package/lib/chain/validation/executionPayloadEnvelope.js +0 -2
- package/lib/chain/validation/executionPayloadEnvelope.js.map +1 -1
- package/lib/chain/validation/payloadAttestationMessage.d.ts.map +1 -1
- package/lib/chain/validation/payloadAttestationMessage.js +24 -4
- package/lib/chain/validation/payloadAttestationMessage.js.map +1 -1
- package/lib/metrics/metrics/lodestar.d.ts +4 -0
- package/lib/metrics/metrics/lodestar.d.ts.map +1 -1
- package/lib/metrics/metrics/lodestar.js +10 -0
- package/lib/metrics/metrics/lodestar.js.map +1 -1
- package/lib/network/processor/gossipHandlers.d.ts.map +1 -1
- package/lib/network/processor/gossipHandlers.js +10 -3
- package/lib/network/processor/gossipHandlers.js.map +1 -1
- package/lib/network/processor/index.d.ts +2 -2
- package/lib/network/processor/index.d.ts.map +1 -1
- package/lib/network/processor/index.js +25 -23
- 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 +9 -5
- package/lib/network/reqresp/handlers/beaconBlocksByRange.js.map +1 -1
- package/lib/network/reqresp/handlers/dataColumnSidecarsByRange.d.ts.map +1 -1
- package/lib/network/reqresp/handlers/dataColumnSidecarsByRange.js +13 -3
- package/lib/network/reqresp/handlers/dataColumnSidecarsByRange.js.map +1 -1
- package/lib/network/reqresp/handlers/dataColumnSidecarsByRoot.js +1 -1
- package/lib/network/reqresp/handlers/dataColumnSidecarsByRoot.js.map +1 -1
- package/lib/network/reqresp/handlers/executionPayloadEnvelopesByRange.d.ts +2 -1
- package/lib/network/reqresp/handlers/executionPayloadEnvelopesByRange.d.ts.map +1 -1
- package/lib/network/reqresp/handlers/executionPayloadEnvelopesByRange.js +16 -6
- package/lib/network/reqresp/handlers/executionPayloadEnvelopesByRange.js.map +1 -1
- package/lib/network/reqresp/handlers/executionPayloadEnvelopesByRoot.d.ts +2 -1
- package/lib/network/reqresp/handlers/executionPayloadEnvelopesByRoot.d.ts.map +1 -1
- package/lib/network/reqresp/handlers/executionPayloadEnvelopesByRoot.js +15 -1
- package/lib/network/reqresp/handlers/executionPayloadEnvelopesByRoot.js.map +1 -1
- package/lib/network/reqresp/handlers/index.js +4 -4
- package/lib/network/reqresp/handlers/index.js.map +1 -1
- package/lib/network/reqresp/utils/dataColumnResponseValidation.d.ts.map +1 -1
- package/lib/network/reqresp/utils/dataColumnResponseValidation.js +22 -3
- package/lib/network/reqresp/utils/dataColumnResponseValidation.js.map +1 -1
- package/lib/sync/types.d.ts +9 -1
- package/lib/sync/types.d.ts.map +1 -1
- package/lib/sync/types.js +9 -2
- package/lib/sync/types.js.map +1 -1
- package/lib/sync/unknownBlock.d.ts.map +1 -1
- package/lib/sync/unknownBlock.js +64 -30
- package/lib/sync/unknownBlock.js.map +1 -1
- package/lib/util/dataColumns.d.ts.map +1 -1
- package/lib/util/dataColumns.js +16 -11
- package/lib/util/dataColumns.js.map +1 -1
- package/package.json +15 -17
- package/src/api/impl/beacon/blocks/index.ts +13 -5
- package/src/api/impl/beacon/pool/index.ts +1 -0
- package/src/api/impl/config/constants.ts +2 -0
- package/src/api/impl/debug/index.ts +73 -12
- package/src/api/impl/lodestar/index.ts +30 -0
- package/src/api/impl/validator/index.ts +52 -22
- package/src/chain/archiveStore/archiveStore.ts +0 -5
- package/src/chain/blocks/importBlock.ts +1 -0
- package/src/chain/chain.ts +10 -1
- package/src/chain/emitter.ts +3 -2
- package/src/chain/errors/blockError.ts +0 -4
- package/src/chain/errors/payloadAttestation.ts +2 -0
- package/src/chain/forkChoice/index.ts +13 -0
- package/src/chain/options.ts +1 -0
- package/src/chain/prepareNextSlot.ts +1 -1
- package/src/chain/produceBlock/produceBlockBody.ts +3 -3
- package/src/chain/regen/interface.ts +1 -1
- package/src/chain/regen/queued.ts +0 -5
- package/src/chain/stateCache/fifoBlockStateCache.ts +0 -6
- package/src/chain/stateCache/persistentCheckpointsCache.ts +6 -2
- package/src/chain/stateCache/types.ts +0 -2
- package/src/chain/validation/block.ts +12 -16
- package/src/chain/validation/executionPayloadBid.ts +23 -5
- package/src/chain/validation/executionPayloadEnvelope.ts +0 -2
- package/src/chain/validation/payloadAttestationMessage.ts +26 -4
- package/src/metrics/metrics/lodestar.ts +11 -0
- package/src/network/processor/gossipHandlers.ts +10 -2
- package/src/network/processor/index.ts +27 -27
- package/src/network/reqresp/handlers/beaconBlocksByRange.ts +12 -5
- package/src/network/reqresp/handlers/dataColumnSidecarsByRange.ts +17 -3
- package/src/network/reqresp/handlers/dataColumnSidecarsByRoot.ts +1 -1
- package/src/network/reqresp/handlers/executionPayloadEnvelopesByRange.ts +22 -6
- package/src/network/reqresp/handlers/executionPayloadEnvelopesByRoot.ts +20 -1
- package/src/network/reqresp/handlers/index.ts +4 -4
- package/src/network/reqresp/utils/dataColumnResponseValidation.ts +21 -3
- package/src/sync/types.ts +11 -2
- package/src/sync/unknownBlock.ts +70 -31
- package/src/util/dataColumns.ts +17 -12
package/src/sync/unknownBlock.ts
CHANGED
|
@@ -3,7 +3,7 @@ import {ChainForkConfig} from "@lodestar/config";
|
|
|
3
3
|
import {ForkSeq} from "@lodestar/params";
|
|
4
4
|
import {RequestError, RequestErrorCode} from "@lodestar/reqresp";
|
|
5
5
|
import {computeTimeAtSlot} from "@lodestar/state-transition";
|
|
6
|
-
import {RootHex, gloas} from "@lodestar/types";
|
|
6
|
+
import {RootHex, Slot, gloas} from "@lodestar/types";
|
|
7
7
|
import {Logger, fromHex, prettyPrintIndices, pruneSetToMax, sleep, toRootHex} from "@lodestar/utils";
|
|
8
8
|
import {isBlockInputBlobs, isBlockInputColumns} from "../chain/blocks/blockInput/blockInput.js";
|
|
9
9
|
import {BlockInputSource, IBlockInput} from "../chain/blocks/blockInput/types.js";
|
|
@@ -215,10 +215,10 @@ export class BlockInputSync {
|
|
|
215
215
|
|
|
216
216
|
private onUnknownEnvelopeBlockRoot = (data: ChainEventData[ChainEvent.unknownEnvelopeBlockRoot]): void => {
|
|
217
217
|
try {
|
|
218
|
-
this.addByPayloadRootHex(data.rootHex, data.peer);
|
|
218
|
+
this.addByPayloadRootHex(data.rootHex, data.peer, data.slot);
|
|
219
219
|
this.triggerUnknownBlockSearch();
|
|
220
|
-
this.metrics?.blockInputSync.requests.inc({type: PendingBlockType.
|
|
221
|
-
this.metrics?.blockInputSync.
|
|
220
|
+
this.metrics?.blockInputSync.requests.inc({type: PendingBlockType.UNKNOWN_PAYLOAD_BLOCK_ROOT});
|
|
221
|
+
this.metrics?.blockInputSync.payloadSource.inc({source: data.source});
|
|
222
222
|
} catch (e) {
|
|
223
223
|
this.logger.debug("Error handling unknownEnvelopeBlockRoot event", {}, e as Error);
|
|
224
224
|
}
|
|
@@ -228,8 +228,8 @@ export class BlockInputSync {
|
|
|
228
228
|
try {
|
|
229
229
|
this.addByPayloadInput(data.payloadInput, data.peer);
|
|
230
230
|
this.triggerUnknownBlockSearch();
|
|
231
|
-
this.metrics?.blockInputSync.requests.inc({type: PendingBlockType.
|
|
232
|
-
this.metrics?.blockInputSync.
|
|
231
|
+
this.metrics?.blockInputSync.requests.inc({type: PendingBlockType.INCOMPLETE_PAYLOAD_ENVELOPE});
|
|
232
|
+
this.metrics?.blockInputSync.payloadSource.inc({source: data.source});
|
|
233
233
|
} catch (e) {
|
|
234
234
|
this.logger.debug("Error handling incompletePayloadEnvelope event", {}, e as Error);
|
|
235
235
|
}
|
|
@@ -331,7 +331,10 @@ export class BlockInputSync {
|
|
|
331
331
|
};
|
|
332
332
|
this.pendingBlocks.set(blockInput.blockRootHex, pendingBlock);
|
|
333
333
|
|
|
334
|
-
this.logger.verbose("Added blockInput to BlockInputSync.pendingBlocks",
|
|
334
|
+
this.logger.verbose("Added blockInput to BlockInputSync.pendingBlocks", {
|
|
335
|
+
...pendingBlock.blockInput.getLogMeta(),
|
|
336
|
+
delaySec: this.chain.clock.secFromSlot(blockInput.slot),
|
|
337
|
+
});
|
|
335
338
|
}
|
|
336
339
|
|
|
337
340
|
if (peerIdStr) {
|
|
@@ -346,13 +349,14 @@ export class BlockInputSync {
|
|
|
346
349
|
}
|
|
347
350
|
};
|
|
348
351
|
|
|
349
|
-
private addByPayloadRootHex = (rootHex: RootHex, peerIdStr?: PeerIdStr): boolean => {
|
|
352
|
+
private addByPayloadRootHex = (rootHex: RootHex, peerIdStr?: PeerIdStr, slot?: Slot): boolean => {
|
|
350
353
|
let pendingPayload = this.pendingPayloads.get(rootHex);
|
|
351
354
|
let added = false;
|
|
352
355
|
if (!pendingPayload) {
|
|
353
356
|
pendingPayload = {
|
|
354
357
|
status: PendingPayloadInputStatus.pending,
|
|
355
358
|
rootHex,
|
|
359
|
+
slot,
|
|
356
360
|
peerIdStrings: new Set(),
|
|
357
361
|
timeAddedSec: Date.now() / 1000,
|
|
358
362
|
};
|
|
@@ -360,6 +364,8 @@ export class BlockInputSync {
|
|
|
360
364
|
added = true;
|
|
361
365
|
|
|
362
366
|
this.logger.verbose("Added new payload rootHex to BlockInputSync.pendingPayloads", {
|
|
367
|
+
slot: slot ?? "unknown",
|
|
368
|
+
delaySec: slot != null ? this.chain.clock.secFromSlot(slot) : "unknown",
|
|
363
369
|
root: rootHex,
|
|
364
370
|
peerIdStr: peerIdStr ?? "unknown peer",
|
|
365
371
|
});
|
|
@@ -392,6 +398,13 @@ export class BlockInputSync {
|
|
|
392
398
|
}
|
|
393
399
|
|
|
394
400
|
this.pendingPayloads.set(payloadInput.blockRootHex, pendingPayload);
|
|
401
|
+
|
|
402
|
+
this.logger.verbose("Added payloadInput to BlockInputSync.pendingPayloads", {
|
|
403
|
+
slot: payloadInput.slot,
|
|
404
|
+
root: payloadInput.blockRootHex,
|
|
405
|
+
delaySec: this.chain.clock.secFromSlot(payloadInput.slot),
|
|
406
|
+
});
|
|
407
|
+
|
|
395
408
|
const prunedItemCount = pruneSetToMax(this.pendingPayloads, this.maxPendingBlocks);
|
|
396
409
|
if (prunedItemCount > 0) {
|
|
397
410
|
this.logger.verbose(`Pruned ${prunedItemCount} items from BlockInputSync.pendingPayloads`);
|
|
@@ -654,10 +667,12 @@ export class BlockInputSync {
|
|
|
654
667
|
}
|
|
655
668
|
|
|
656
669
|
const rootHex = getBlockInputSyncCacheItemRootHex(block);
|
|
670
|
+
const blockSlot = getBlockInputSyncCacheItemSlot(block);
|
|
657
671
|
const logCtx = {
|
|
658
|
-
slot:
|
|
672
|
+
slot: blockSlot,
|
|
659
673
|
root: rootHex,
|
|
660
674
|
pendingBlocks: this.pendingBlocks.size,
|
|
675
|
+
...(typeof blockSlot === "number" && {delaySec: this.chain.clock.secFromSlot(blockSlot)}),
|
|
661
676
|
};
|
|
662
677
|
|
|
663
678
|
this.logger.verbose("BlockInputSync.downloadBlock()", logCtx);
|
|
@@ -679,6 +694,7 @@ export class BlockInputSync {
|
|
|
679
694
|
const logCtx2 = {
|
|
680
695
|
...logCtx,
|
|
681
696
|
slot: blockSlot,
|
|
697
|
+
delaySec,
|
|
682
698
|
parentInForkChoice,
|
|
683
699
|
};
|
|
684
700
|
this.logger.verbose("Downloaded unknown block", logCtx2);
|
|
@@ -748,6 +764,12 @@ export class BlockInputSync {
|
|
|
748
764
|
// this prevents unbundling attack
|
|
749
765
|
// see https://lighthouse-blog.sigmaprime.io/mev-unbundling-rpc.html
|
|
750
766
|
const {slot: blockSlot, proposerIndex} = pendingBlock.blockInput.getBlock().message;
|
|
767
|
+
const logCtx = {
|
|
768
|
+
slot: blockSlot,
|
|
769
|
+
root: pendingBlock.blockInput.blockRootHex,
|
|
770
|
+
delaySec: this.chain.clock.secFromSlot(blockSlot),
|
|
771
|
+
};
|
|
772
|
+
this.logger.verbose("Processing downloaded block", logCtx);
|
|
751
773
|
const fork = this.config.getForkName(blockSlot);
|
|
752
774
|
const proposerBoostWindowMs = this.config.getAttestationDueMs(fork);
|
|
753
775
|
if (
|
|
@@ -783,6 +805,7 @@ export class BlockInputSync {
|
|
|
783
805
|
else this.metrics?.blockInputSync.processedBlocksSuccess.inc();
|
|
784
806
|
|
|
785
807
|
if (!res.err) {
|
|
808
|
+
this.logger.verbose("Processed block from unknown sync", logCtx);
|
|
786
809
|
// no need to update status to "processed", delete anyway
|
|
787
810
|
this.pendingBlocks.delete(pendingBlock.blockInput.blockRootHex);
|
|
788
811
|
// Re-enter the scheduler so descendants blocked on either parent blocks or parent payloads
|
|
@@ -850,25 +873,28 @@ export class BlockInputSync {
|
|
|
850
873
|
}
|
|
851
874
|
|
|
852
875
|
const payloadInput = this.chain.seenPayloadEnvelopeInputCache.get(rootHex);
|
|
853
|
-
if (!
|
|
854
|
-
|
|
855
|
-
|
|
856
|
-
|
|
857
|
-
|
|
858
|
-
|
|
876
|
+
if (!this.chain.forkChoice.hasBlockHex(rootHex)) {
|
|
877
|
+
// Block not in fork choice yet. payloadInput may be seeded from the block body during download, so a
|
|
878
|
+
// non-null payloadInput does not imply the block is imported; defer regardless and pull the block first.
|
|
879
|
+
// onBlockImported re-triggers the search to resume this envelope.
|
|
880
|
+
if (!this.pendingBlocks.has(rootHex)) {
|
|
881
|
+
this.addByRootHex(rootHex);
|
|
882
|
+
}
|
|
859
883
|
|
|
860
|
-
|
|
861
|
-
|
|
862
|
-
|
|
863
|
-
}
|
|
864
|
-
} else {
|
|
865
|
-
this.logger.debug("Missing PayloadEnvelopeInput for known block while reconciling payload envelope", {
|
|
866
|
-
root: rootHex,
|
|
867
|
-
});
|
|
884
|
+
const pendingBlock = this.pendingBlocks.get(rootHex);
|
|
885
|
+
if (pendingBlock && this.network.getConnectedPeers().length > 0) {
|
|
886
|
+
await this.downloadBlock(pendingBlock);
|
|
868
887
|
}
|
|
869
888
|
return;
|
|
870
889
|
}
|
|
871
890
|
|
|
891
|
+
if (!payloadInput) {
|
|
892
|
+
this.logger.debug("Missing PayloadEnvelopeInput for known block while reconciling payload envelope", {
|
|
893
|
+
root: rootHex,
|
|
894
|
+
});
|
|
895
|
+
return;
|
|
896
|
+
}
|
|
897
|
+
|
|
872
898
|
if (!payloadInput.hasPayloadEnvelope()) {
|
|
873
899
|
const validationResult = await wrapError(
|
|
874
900
|
validateGossipExecutionPayloadEnvelope(this.chain, pendingPayload.envelope)
|
|
@@ -922,10 +948,12 @@ export class BlockInputSync {
|
|
|
922
948
|
return;
|
|
923
949
|
}
|
|
924
950
|
|
|
951
|
+
const payloadSlot = getPayloadSyncCacheItemSlot(payload);
|
|
925
952
|
const logCtx = {
|
|
926
|
-
slot:
|
|
953
|
+
slot: payloadSlot,
|
|
927
954
|
root: rootHex,
|
|
928
955
|
pendingPayloads: this.pendingPayloads.size,
|
|
956
|
+
...(typeof payloadSlot === "number" && {delaySec: this.chain.clock.secFromSlot(payloadSlot)}),
|
|
929
957
|
};
|
|
930
958
|
|
|
931
959
|
this.logger.verbose("BlockInputSync.downloadPayload()", logCtx);
|
|
@@ -953,7 +981,11 @@ export class BlockInputSync {
|
|
|
953
981
|
|
|
954
982
|
private async processPayload(pendingPayload: PendingPayloadInput): Promise<void> {
|
|
955
983
|
const rootHex = pendingPayload.payloadInput.blockRootHex;
|
|
956
|
-
const logCtx = {
|
|
984
|
+
const logCtx = {
|
|
985
|
+
slot: pendingPayload.payloadInput.slot,
|
|
986
|
+
root: rootHex,
|
|
987
|
+
delaySec: this.chain.clock.secFromSlot(pendingPayload.payloadInput.slot),
|
|
988
|
+
};
|
|
957
989
|
|
|
958
990
|
if (pendingPayload.status !== PendingPayloadInputStatus.downloaded) {
|
|
959
991
|
this.logger.debug("Skipping payload processing before payload input is downloaded", {
|
|
@@ -980,6 +1012,7 @@ export class BlockInputSync {
|
|
|
980
1012
|
}
|
|
981
1013
|
|
|
982
1014
|
pendingPayload.status = PendingPayloadInputStatus.processing;
|
|
1015
|
+
this.logger.debug("Processing downloaded payload", logCtx);
|
|
983
1016
|
|
|
984
1017
|
const res = await wrapError(this.chain.processExecutionPayload(pendingPayload.payloadInput));
|
|
985
1018
|
if (!res.err) {
|
|
@@ -1073,11 +1106,11 @@ export class BlockInputSync {
|
|
|
1073
1106
|
}
|
|
1074
1107
|
|
|
1075
1108
|
payloadInput ??= this.chain.seenPayloadEnvelopeInputCache.get(rootHex);
|
|
1076
|
-
if (!
|
|
1077
|
-
|
|
1078
|
-
|
|
1079
|
-
|
|
1080
|
-
//
|
|
1109
|
+
if (!this.chain.forkChoice.hasBlockHex(rootHex)) {
|
|
1110
|
+
// Block not in fork choice yet. Validating now would throw BLOCK_ROOT_UNKNOWN, so keep the downloaded
|
|
1111
|
+
// envelope and wait for the block body; reconcilePayloadEnvelope validates once the block lands.
|
|
1112
|
+
// payloadInput may be seeded from the block body during download, so a non-null payloadInput does not
|
|
1113
|
+
// imply the block is imported.
|
|
1081
1114
|
return {
|
|
1082
1115
|
status: PendingPayloadInputStatus.waitingForBlock,
|
|
1083
1116
|
envelope,
|
|
@@ -1086,6 +1119,11 @@ export class BlockInputSync {
|
|
|
1086
1119
|
};
|
|
1087
1120
|
}
|
|
1088
1121
|
|
|
1122
|
+
if (!payloadInput) {
|
|
1123
|
+
// Block is in fork choice but no PayloadEnvelopeInput exists, should have been created during block import.
|
|
1124
|
+
throw new Error(`Missing PayloadEnvelopeInput for known block ${rootHex}`);
|
|
1125
|
+
}
|
|
1126
|
+
|
|
1089
1127
|
if (!payloadInput.hasPayloadEnvelope()) {
|
|
1090
1128
|
await validateGossipExecutionPayloadEnvelope(this.chain, envelope);
|
|
1091
1129
|
}
|
|
@@ -1117,6 +1155,7 @@ export class BlockInputSync {
|
|
|
1117
1155
|
rootHex,
|
|
1118
1156
|
peerId,
|
|
1119
1157
|
peerClient,
|
|
1158
|
+
...(typeof slot === "number" && {delaySec: this.chain.clock.secFromSlot(slot)}),
|
|
1120
1159
|
hasPayload: pendingPayload.payloadInput.hasPayloadEnvelope(),
|
|
1121
1160
|
hasAllData: pendingPayload.payloadInput.hasAllData(),
|
|
1122
1161
|
});
|
|
@@ -1288,7 +1327,7 @@ export class BlockInputSync {
|
|
|
1288
1327
|
this.metrics?.blockInputSync.fetchBegin.observe(this.chain.clock.secFromSlot(slot, fetchStartSec));
|
|
1289
1328
|
}
|
|
1290
1329
|
|
|
1291
|
-
const logCtx = {slot, rootHex, peerId, peerClient};
|
|
1330
|
+
const logCtx = {slot, rootHex, peerId, peerClient, delaySec: this.chain.clock.secFromSlot(slot)};
|
|
1292
1331
|
this.logger.verbose("BlockInputSync.fetchBlockInput: successful download", logCtx);
|
|
1293
1332
|
this.metrics?.blockInputSync.downloadByRoot.success.inc();
|
|
1294
1333
|
const warnings = downloadResult.warnings;
|
package/src/util/dataColumns.ts
CHANGED
|
@@ -470,15 +470,17 @@ export async function recoverDataColumnSidecars(
|
|
|
470
470
|
return DataColumnReconstructionCode.SuccessLate;
|
|
471
471
|
}
|
|
472
472
|
|
|
473
|
-
//
|
|
474
|
-
//
|
|
475
|
-
//
|
|
476
|
-
//
|
|
477
|
-
//
|
|
478
|
-
//
|
|
479
|
-
//
|
|
480
|
-
//
|
|
481
|
-
const
|
|
473
|
+
// Per consensus-specs PR #4657, only publish reconstructed columns the node is
|
|
474
|
+
// subscribed to (custody + sampling). Eagerly cross-seeding non-subscribed
|
|
475
|
+
// columns floods the network with duplicates because the sender has no
|
|
476
|
+
// visibility into which peers already saw the message via the topic mesh.
|
|
477
|
+
// This matches the getBlobsV2 path in `getDataColumnSidecarsFromExecution` and
|
|
478
|
+
// aligns with Lighthouse/Prysm. Capture missing sampled indices before adding
|
|
479
|
+
// any reconstructed columns so they are not filtered out by the subsequent
|
|
480
|
+
// `addColumn` calls.
|
|
481
|
+
const missingSampledColumns = new Set(input.getMissingSampledColumnMeta().missing);
|
|
482
|
+
const sidecarsReconstructed: DataColumnSidecar[] = [];
|
|
483
|
+
const sidecarsToPublish: DataColumnSidecar[] = [];
|
|
482
484
|
for (const columnSidecar of fullSidecars) {
|
|
483
485
|
if (!input.hasColumn(columnSidecar.index)) {
|
|
484
486
|
if (input instanceof PayloadEnvelopeInput) {
|
|
@@ -501,11 +503,14 @@ export async function recoverDataColumnSidecars(
|
|
|
501
503
|
source: BlockInputSource.recovery,
|
|
502
504
|
});
|
|
503
505
|
}
|
|
504
|
-
|
|
506
|
+
sidecarsReconstructed.push(columnSidecar);
|
|
507
|
+
if (missingSampledColumns.has(columnSidecar.index)) {
|
|
508
|
+
sidecarsToPublish.push(columnSidecar);
|
|
509
|
+
}
|
|
505
510
|
}
|
|
506
511
|
}
|
|
507
|
-
metrics?.peerDas.reconstructedColumns.inc(
|
|
508
|
-
metrics?.dataColumns.bySource.inc({source: BlockInputSource.recovery},
|
|
512
|
+
metrics?.peerDas.reconstructedColumns.inc(sidecarsReconstructed.length);
|
|
513
|
+
metrics?.dataColumns.bySource.inc({source: BlockInputSource.recovery}, sidecarsReconstructed.length);
|
|
509
514
|
emitter.emit(ChainEvent.publishDataColumns, sidecarsToPublish);
|
|
510
515
|
// TODO: Can we record dataColumns.sentPeersPerSubnet metric somehow
|
|
511
516
|
return DataColumnReconstructionCode.SuccessResolved;
|