@lodestar/beacon-node 1.51.0-dev.c99cf49add → 1.51.0-dev.d2b5232209
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/api.js +1 -1
- package/lib/api/impl/api.js.map +1 -1
- package/lib/api/impl/beacon/blocks/index.d.ts +2 -1
- package/lib/api/impl/beacon/blocks/index.d.ts.map +1 -1
- package/lib/api/impl/beacon/blocks/index.js +12 -7
- package/lib/api/impl/beacon/blocks/index.js.map +1 -1
- package/lib/api/impl/beacon/index.d.ts +2 -1
- package/lib/api/impl/beacon/index.d.ts.map +1 -1
- package/lib/api/impl/beacon/index.js +2 -2
- package/lib/api/impl/beacon/index.js.map +1 -1
- package/lib/api/impl/beacon/state/index.d.ts.map +1 -1
- package/lib/api/impl/beacon/state/index.js +8 -2
- package/lib/api/impl/beacon/state/index.js.map +1 -1
- package/lib/api/impl/beacon/state/utils.d.ts +2 -1
- package/lib/api/impl/beacon/state/utils.d.ts.map +1 -1
- package/lib/api/impl/beacon/state/utils.js +17 -9
- package/lib/api/impl/beacon/state/utils.js.map +1 -1
- package/lib/api/impl/debug/index.d.ts.map +1 -1
- package/lib/api/impl/debug/index.js +3 -0
- package/lib/api/impl/debug/index.js.map +1 -1
- package/lib/api/impl/validator/index.d.ts.map +1 -1
- package/lib/api/impl/validator/index.js +105 -10
- package/lib/api/impl/validator/index.js.map +1 -1
- package/lib/api/options.d.ts +2 -0
- package/lib/api/options.d.ts.map +1 -1
- package/lib/api/options.js +1 -0
- package/lib/api/options.js.map +1 -1
- package/lib/chain/ColumnReconstructionTracker.d.ts +11 -11
- package/lib/chain/ColumnReconstructionTracker.d.ts.map +1 -1
- package/lib/chain/ColumnReconstructionTracker.js +46 -40
- package/lib/chain/ColumnReconstructionTracker.js.map +1 -1
- package/lib/chain/GetBlobsTracker.d.ts +11 -0
- package/lib/chain/GetBlobsTracker.d.ts.map +1 -1
- package/lib/chain/GetBlobsTracker.js +83 -27
- package/lib/chain/GetBlobsTracker.js.map +1 -1
- package/lib/chain/archiveStore/utils/archiveBlocks.d.ts +4 -0
- package/lib/chain/archiveStore/utils/archiveBlocks.d.ts.map +1 -1
- package/lib/chain/archiveStore/utils/archiveBlocks.js +61 -97
- package/lib/chain/archiveStore/utils/archiveBlocks.js.map +1 -1
- package/lib/chain/blocks/importBlock.d.ts.map +1 -1
- package/lib/chain/blocks/importBlock.js +9 -7
- package/lib/chain/blocks/importBlock.js.map +1 -1
- package/lib/chain/blocks/importExecutionPayload.d.ts.map +1 -1
- package/lib/chain/blocks/importExecutionPayload.js +51 -3
- package/lib/chain/blocks/importExecutionPayload.js.map +1 -1
- package/lib/chain/blocks/index.js +2 -2
- package/lib/chain/blocks/index.js.map +1 -1
- package/lib/chain/blocks/payloadEnvelopeProcessor.d.ts +5 -5
- package/lib/chain/blocks/payloadEnvelopeProcessor.js +5 -5
- package/lib/chain/blocks/types.d.ts +4 -0
- package/lib/chain/blocks/types.d.ts.map +1 -1
- package/lib/chain/blocks/types.js +5 -0
- package/lib/chain/blocks/types.js.map +1 -1
- package/lib/chain/blocks/verifyBlock.d.ts.map +1 -1
- package/lib/chain/blocks/verifyBlock.js +1 -1
- package/lib/chain/blocks/verifyBlock.js.map +1 -1
- package/lib/chain/blocks/verifyPayloadsDataAvailability.d.ts +3 -3
- package/lib/chain/blocks/verifyPayloadsDataAvailability.d.ts.map +1 -1
- package/lib/chain/blocks/verifyPayloadsDataAvailability.js +6 -6
- package/lib/chain/blocks/verifyPayloadsDataAvailability.js.map +1 -1
- package/lib/chain/chain.d.ts +2 -1
- package/lib/chain/chain.d.ts.map +1 -1
- package/lib/chain/chain.js +9 -5
- package/lib/chain/chain.js.map +1 -1
- package/lib/chain/errors/executionPayloadBid.d.ts +11 -1
- package/lib/chain/errors/executionPayloadBid.d.ts.map +1 -1
- package/lib/chain/errors/executionPayloadBid.js +2 -0
- package/lib/chain/errors/executionPayloadBid.js.map +1 -1
- package/lib/chain/errors/inclusionList.d.ts +60 -0
- package/lib/chain/errors/inclusionList.d.ts.map +1 -0
- package/lib/chain/errors/inclusionList.js +19 -0
- package/lib/chain/errors/inclusionList.js.map +1 -0
- 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/interface.d.ts +2 -1
- package/lib/chain/interface.d.ts.map +1 -1
- package/lib/chain/interface.js.map +1 -1
- package/lib/chain/opPools/inclusionListStore.d.ts +63 -0
- package/lib/chain/opPools/inclusionListStore.d.ts.map +1 -0
- package/lib/chain/opPools/inclusionListStore.js +171 -0
- package/lib/chain/opPools/inclusionListStore.js.map +1 -0
- package/lib/chain/opPools/index.d.ts +1 -0
- package/lib/chain/opPools/index.d.ts.map +1 -1
- package/lib/chain/opPools/index.js +1 -0
- package/lib/chain/opPools/index.js.map +1 -1
- package/lib/chain/produceBlock/produceBlockBody.d.ts +3 -1
- package/lib/chain/produceBlock/produceBlockBody.d.ts.map +1 -1
- package/lib/chain/produceBlock/produceBlockBody.js +30 -10
- 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 -1
- package/lib/chain/regen/interface.js.map +1 -1
- package/lib/chain/validation/executionPayloadBid.d.ts +0 -15
- package/lib/chain/validation/executionPayloadBid.d.ts.map +1 -1
- package/lib/chain/validation/executionPayloadBid.js +24 -145
- package/lib/chain/validation/executionPayloadBid.js.map +1 -1
- package/lib/chain/validation/inclusionList.d.ts +14 -0
- package/lib/chain/validation/inclusionList.d.ts.map +1 -0
- package/lib/chain/validation/inclusionList.js +150 -0
- package/lib/chain/validation/inclusionList.js.map +1 -0
- package/lib/chain/validation/index.d.ts +1 -0
- package/lib/chain/validation/index.d.ts.map +1 -1
- package/lib/chain/validation/index.js +1 -0
- package/lib/chain/validation/index.js.map +1 -1
- package/lib/db/beacon.d.ts +7 -0
- package/lib/db/beacon.d.ts.map +1 -1
- package/lib/db/beacon.js +34 -0
- package/lib/db/beacon.js.map +1 -1
- package/lib/db/dataColumnStore.d.ts +1 -1
- package/lib/db/dataColumnStore.d.ts.map +1 -1
- package/lib/db/dataColumnStore.js +1 -4
- package/lib/db/dataColumnStore.js.map +1 -1
- package/lib/db/interface.d.ts +1 -0
- package/lib/db/interface.d.ts.map +1 -1
- package/lib/db/repositories/dataColumnSidecarArchive.d.ts +6 -0
- package/lib/db/repositories/dataColumnSidecarArchive.d.ts.map +1 -1
- package/lib/db/repositories/dataColumnSidecarArchive.js +19 -0
- package/lib/db/repositories/dataColumnSidecarArchive.js.map +1 -1
- package/lib/execution/builder/validateBid.d.ts.map +1 -1
- package/lib/execution/builder/validateBid.js +14 -1
- package/lib/execution/builder/validateBid.js.map +1 -1
- package/lib/execution/engine/blobVersionedHashes.d.ts +1 -1
- package/lib/execution/engine/blobVersionedHashes.d.ts.map +1 -1
- package/lib/execution/engine/blobVersionedHashes.js.map +1 -1
- package/lib/execution/engine/disabled.d.ts +1 -0
- package/lib/execution/engine/disabled.d.ts.map +1 -1
- package/lib/execution/engine/disabled.js +3 -0
- package/lib/execution/engine/disabled.js.map +1 -1
- package/lib/execution/engine/http.d.ts +8 -2
- package/lib/execution/engine/http.d.ts.map +1 -1
- package/lib/execution/engine/http.js +27 -4
- package/lib/execution/engine/http.js.map +1 -1
- package/lib/execution/engine/interface.d.ts +11 -2
- package/lib/execution/engine/interface.d.ts.map +1 -1
- package/lib/execution/engine/interface.js.map +1 -1
- package/lib/execution/engine/jsonRpcTransport.d.ts +3 -2
- package/lib/execution/engine/jsonRpcTransport.d.ts.map +1 -1
- package/lib/execution/engine/jsonRpcTransport.js +33 -9
- package/lib/execution/engine/jsonRpcTransport.js.map +1 -1
- package/lib/execution/engine/mock.d.ts +1 -0
- package/lib/execution/engine/mock.d.ts.map +1 -1
- package/lib/execution/engine/mock.js +31 -7
- package/lib/execution/engine/mock.js.map +1 -1
- package/lib/execution/engine/payloadIdCache.d.ts +5 -3
- package/lib/execution/engine/payloadIdCache.d.ts.map +1 -1
- package/lib/execution/engine/payloadIdCache.js +15 -4
- package/lib/execution/engine/payloadIdCache.js.map +1 -1
- package/lib/execution/engine/restTransport.d.ts +2 -1
- package/lib/execution/engine/restTransport.d.ts.map +1 -1
- package/lib/execution/engine/restTransport.js +3 -0
- package/lib/execution/engine/restTransport.js.map +1 -1
- package/lib/execution/engine/sszTypes.d.ts +38 -38
- package/lib/execution/engine/transport.d.ts +5 -2
- package/lib/execution/engine/transport.d.ts.map +1 -1
- package/lib/execution/engine/types.d.ts +25 -1
- package/lib/execution/engine/types.d.ts.map +1 -1
- package/lib/execution/engine/types.js +17 -4
- package/lib/execution/engine/types.js.map +1 -1
- package/lib/index.d.ts +1 -0
- package/lib/index.d.ts.map +1 -1
- package/lib/index.js +2 -0
- package/lib/index.js.map +1 -1
- package/lib/metrics/metrics/beacon.d.ts +16 -0
- package/lib/metrics/metrics/beacon.d.ts.map +1 -1
- package/lib/metrics/metrics/beacon.js +35 -0
- package/lib/metrics/metrics/beacon.js.map +1 -1
- package/lib/metrics/metrics/lodestar.d.ts +19 -0
- package/lib/metrics/metrics/lodestar.d.ts.map +1 -1
- package/lib/metrics/metrics/lodestar.js +49 -0
- package/lib/metrics/metrics/lodestar.js.map +1 -1
- package/lib/network/gossip/interface.d.ts +8 -2
- 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/topic.d.ts +13 -5
- package/lib/network/gossip/topic.d.ts.map +1 -1
- package/lib/network/gossip/topic.js +13 -1
- package/lib/network/gossip/topic.js.map +1 -1
- package/lib/network/interface.d.ts +2 -1
- package/lib/network/interface.d.ts.map +1 -1
- package/lib/network/network.d.ts +2 -1
- 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/peers/utils/enrSubnetsDeserialize.d.ts.map +1 -1
- package/lib/network/peers/utils/enrSubnetsDeserialize.js +5 -2
- package/lib/network/peers/utils/enrSubnetsDeserialize.js.map +1 -1
- package/lib/network/processor/gossipHandlers.d.ts.map +1 -1
- package/lib/network/processor/gossipHandlers.js +67 -19
- 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 +6 -0
- package/lib/network/processor/gossipQueues/index.js.map +1 -1
- package/lib/network/processor/gossipValidatorFn.d.ts.map +1 -1
- package/lib/network/processor/gossipValidatorFn.js +5 -1
- package/lib/network/processor/gossipValidatorFn.js.map +1 -1
- package/lib/network/processor/index.d.ts +5 -0
- package/lib/network/processor/index.d.ts.map +1 -1
- package/lib/network/processor/index.js +37 -26
- package/lib/network/processor/index.js.map +1 -1
- package/lib/network/reqresp/ReqRespBeaconNode.d.ts.map +1 -1
- package/lib/network/reqresp/ReqRespBeaconNode.js +6 -0
- package/lib/network/reqresp/ReqRespBeaconNode.js.map +1 -1
- package/lib/network/reqresp/handlers/inclusionListsByIndices.d.ts +10 -0
- package/lib/network/reqresp/handlers/inclusionListsByIndices.d.ts.map +1 -0
- package/lib/network/reqresp/handlers/inclusionListsByIndices.js +30 -0
- package/lib/network/reqresp/handlers/inclusionListsByIndices.js.map +1 -0
- package/lib/network/reqresp/handlers/index.d.ts.map +1 -1
- package/lib/network/reqresp/handlers/index.js +5 -0
- package/lib/network/reqresp/handlers/index.js.map +1 -1
- package/lib/network/reqresp/protocols.d.ts +1 -0
- package/lib/network/reqresp/protocols.d.ts.map +1 -1
- package/lib/network/reqresp/protocols.js +5 -0
- package/lib/network/reqresp/protocols.js.map +1 -1
- package/lib/network/reqresp/rateLimit.d.ts.map +1 -1
- package/lib/network/reqresp/rateLimit.js +4 -0
- package/lib/network/reqresp/rateLimit.js.map +1 -1
- package/lib/network/reqresp/types.d.ts +5 -2
- package/lib/network/reqresp/types.d.ts.map +1 -1
- package/lib/network/reqresp/types.js +3 -0
- package/lib/network/reqresp/types.js.map +1 -1
- package/lib/node/nodejs.d.ts.map +1 -1
- package/lib/node/nodejs.js +9 -1
- package/lib/node/nodejs.js.map +1 -1
- package/lib/sync/unknownBlock.d.ts.map +1 -1
- package/lib/sync/unknownBlock.js +42 -18
- package/lib/sync/unknownBlock.js.map +1 -1
- package/package.json +30 -30
- package/src/api/impl/api.ts +1 -1
- package/src/api/impl/beacon/blocks/index.ts +22 -17
- package/src/api/impl/beacon/index.ts +3 -1
- package/src/api/impl/beacon/state/index.ts +10 -1
- package/src/api/impl/beacon/state/utils.ts +19 -9
- package/src/api/impl/debug/index.ts +4 -0
- package/src/api/impl/validator/index.ts +135 -10
- package/src/api/options.ts +3 -0
- package/src/chain/ColumnReconstructionTracker.ts +60 -41
- package/src/chain/GetBlobsTracker.ts +95 -38
- package/src/chain/archiveStore/utils/archiveBlocks.ts +76 -130
- package/src/chain/blocks/importBlock.ts +11 -14
- package/src/chain/blocks/importExecutionPayload.ts +69 -3
- package/src/chain/blocks/index.ts +6 -2
- package/src/chain/blocks/payloadEnvelopeProcessor.ts +5 -5
- package/src/chain/blocks/types.ts +5 -0
- package/src/chain/blocks/verifyBlock.ts +1 -0
- package/src/chain/blocks/verifyPayloadsDataAvailability.ts +7 -6
- package/src/chain/chain.ts +9 -4
- package/src/chain/errors/executionPayloadBid.ts +12 -0
- package/src/chain/errors/inclusionList.ts +38 -0
- package/src/chain/errors/index.ts +1 -0
- package/src/chain/interface.ts +2 -0
- package/src/chain/opPools/inclusionListStore.ts +208 -0
- package/src/chain/opPools/index.ts +1 -0
- package/src/chain/produceBlock/produceBlockBody.ts +60 -19
- package/src/chain/regen/interface.ts +1 -1
- package/src/chain/validation/executionPayloadBid.ts +40 -170
- package/src/chain/validation/inclusionList.ts +192 -0
- package/src/chain/validation/index.ts +1 -0
- package/src/db/beacon.ts +44 -0
- package/src/db/dataColumnStore.ts +2 -4
- package/src/db/interface.ts +2 -0
- package/src/db/repositories/dataColumnSidecarArchive.ts +20 -0
- package/src/execution/builder/validateBid.ts +23 -2
- package/src/execution/engine/blobVersionedHashes.ts +1 -1
- package/src/execution/engine/disabled.ts +4 -0
- package/src/execution/engine/http.ts +40 -5
- package/src/execution/engine/interface.ts +27 -3
- package/src/execution/engine/jsonRpcTransport.ts +46 -9
- package/src/execution/engine/mock.ts +32 -7
- package/src/execution/engine/payloadIdCache.ts +24 -6
- package/src/execution/engine/restTransport.ts +15 -1
- package/src/execution/engine/transport.ts +7 -2
- package/src/execution/engine/types.ts +41 -6
- package/src/index.ts +2 -0
- package/src/metrics/metrics/beacon.ts +37 -0
- package/src/metrics/metrics/lodestar.ts +51 -0
- package/src/network/gossip/interface.ts +5 -0
- package/src/network/gossip/topic.ts +14 -0
- package/src/network/interface.ts +2 -0
- package/src/network/network.ts +11 -0
- package/src/network/peers/utils/enrSubnetsDeserialize.ts +5 -2
- package/src/network/processor/gossipHandlers.ts +87 -21
- package/src/network/processor/gossipQueues/index.ts +6 -0
- package/src/network/processor/gossipValidatorFn.ts +5 -0
- package/src/network/processor/index.ts +33 -24
- package/src/network/processor/types.ts +1 -1
- package/src/network/reqresp/ReqRespBeaconNode.ts +7 -0
- package/src/network/reqresp/handlers/inclusionListsByIndices.ts +44 -0
- package/src/network/reqresp/handlers/index.ts +5 -0
- package/src/network/reqresp/protocols.ts +6 -0
- package/src/network/reqresp/rateLimit.ts +4 -0
- package/src/network/reqresp/types.ts +6 -0
- package/src/node/nodejs.ts +18 -1
- package/src/sync/unknownBlock.ts +47 -28
|
@@ -1,5 +1,7 @@
|
|
|
1
|
+
import { NUMBER_OF_COLUMNS } from "@lodestar/params";
|
|
1
2
|
import { sleep } from "@lodestar/utils";
|
|
2
3
|
import { DataColumnReconstructionCode, recoverDataColumnSidecars } from "../util/dataColumns.js";
|
|
4
|
+
import { JobItemQueue } from "../util/queue/index.js";
|
|
3
5
|
/**
|
|
4
6
|
* Minimum time to wait before attempting reconstruction
|
|
5
7
|
*/
|
|
@@ -8,67 +10,71 @@ const RECONSTRUCTION_DELAY_MIN_BPS = 667;
|
|
|
8
10
|
* Maximum time to wait before attempting reconstruction
|
|
9
11
|
*/
|
|
10
12
|
const RECONSTRUCTION_DELAY_MAX_BPS = 1000;
|
|
13
|
+
const QUEUE_MAX_LENGTH = 16;
|
|
11
14
|
/**
|
|
12
|
-
*
|
|
15
|
+
* Runs column reconstruction one block root at a time, in trigger order. A trigger for a root that is
|
|
16
|
+
* queued or in flight is a no-op. A root is removed once its attempt finishes so a later column can
|
|
17
|
+
* retry a failed attempt.
|
|
13
18
|
*/
|
|
14
19
|
export class ColumnReconstructionTracker {
|
|
15
20
|
logger;
|
|
16
21
|
emitter;
|
|
17
22
|
metrics;
|
|
18
23
|
config;
|
|
19
|
-
|
|
20
|
-
|
|
21
|
-
|
|
22
|
-
* This is sufficient to avoid duplicate calls since we only call this
|
|
23
|
-
* function when we see a new data column sidecar from gossip.
|
|
24
|
-
*/
|
|
25
|
-
lastBlockRootHex = null;
|
|
26
|
-
/** Track if a reconstruction attempt is in-flight */
|
|
27
|
-
running = false;
|
|
24
|
+
signal;
|
|
25
|
+
pending = new Set();
|
|
26
|
+
queue;
|
|
28
27
|
constructor(init) {
|
|
29
28
|
this.logger = init.logger;
|
|
30
29
|
this.emitter = init.emitter;
|
|
31
30
|
this.metrics = init.metrics;
|
|
32
31
|
this.config = init.config;
|
|
32
|
+
this.signal = init.signal;
|
|
33
|
+
this.queue = new JobItemQueue(this.reconstruct, { maxLength: QUEUE_MAX_LENGTH, signal: init.signal }, init.metrics?.columnReconstructionQueue);
|
|
33
34
|
}
|
|
34
35
|
triggerColumnReconstruction(input) {
|
|
35
|
-
if (this.
|
|
36
|
+
if (this.pending.has(input.blockRootHex)) {
|
|
36
37
|
return;
|
|
37
38
|
}
|
|
38
|
-
if (
|
|
39
|
+
if (input.getAllColumns().length < NUMBER_OF_COLUMNS / 2) {
|
|
39
40
|
return;
|
|
40
41
|
}
|
|
41
|
-
|
|
42
|
-
|
|
43
|
-
|
|
44
|
-
|
|
42
|
+
this.pending.add(input.blockRootHex);
|
|
43
|
+
void this.enqueue(input);
|
|
44
|
+
}
|
|
45
|
+
async enqueue(input) {
|
|
46
|
+
try {
|
|
47
|
+
await this.queue.push(input, Date.now());
|
|
48
|
+
}
|
|
49
|
+
catch (e) {
|
|
50
|
+
this.logger.debug("Data column sidecar reconstruction dropped", { slot: input.slot, root: input.blockRootHex }, e);
|
|
51
|
+
}
|
|
52
|
+
finally {
|
|
53
|
+
this.pending.delete(input.blockRootHex);
|
|
54
|
+
}
|
|
55
|
+
}
|
|
56
|
+
reconstruct = async (input, queuedAtMs) => {
|
|
45
57
|
const fork = this.config.getForkName(input.slot);
|
|
46
58
|
const minDelayMs = this.config.getSlotComponentDurationMs(fork, RECONSTRUCTION_DELAY_MIN_BPS);
|
|
47
59
|
const maxDelayMs = this.config.getSlotComponentDurationMs(fork, RECONSTRUCTION_DELAY_MAX_BPS);
|
|
48
60
|
const delay = minDelayMs + Math.random() * (maxDelayMs - minDelayMs);
|
|
49
|
-
|
|
50
|
-
|
|
51
|
-
|
|
52
|
-
|
|
53
|
-
|
|
54
|
-
|
|
55
|
-
|
|
56
|
-
|
|
57
|
-
})
|
|
58
|
-
|
|
59
|
-
|
|
60
|
-
|
|
61
|
-
|
|
62
|
-
|
|
63
|
-
|
|
64
|
-
|
|
65
|
-
|
|
66
|
-
|
|
67
|
-
});
|
|
68
|
-
})
|
|
69
|
-
.catch((err) => {
|
|
70
|
-
this.logger.debug("ColumnReconstructionTracker unreachable error", {}, err);
|
|
71
|
-
});
|
|
72
|
-
}
|
|
61
|
+
// The delay gives gossip a chance to deliver the remaining columns, so time already spent in the
|
|
62
|
+
// queue behind another root counts towards it
|
|
63
|
+
await sleep(delay - (Date.now() - queuedAtMs), this.signal);
|
|
64
|
+
const logCtx = { slot: input.slot, root: input.blockRootHex };
|
|
65
|
+
this.logger.debug("Attempting data column sidecar reconstruction", logCtx);
|
|
66
|
+
try {
|
|
67
|
+
const result = await recoverDataColumnSidecars(input, this.emitter, this.metrics);
|
|
68
|
+
this.metrics?.recoverDataColumnSidecars.reconstructionResult.inc({ result });
|
|
69
|
+
this.logger.debug("Data column sidecar reconstruction complete", { ...logCtx, result });
|
|
70
|
+
}
|
|
71
|
+
catch (e) {
|
|
72
|
+
this.metrics?.recoverDataColumnSidecars.reconstructionResult.inc({ result: DataColumnReconstructionCode.Failed });
|
|
73
|
+
this.logger.debug("Error during data column sidecar reconstruction", logCtx, e);
|
|
74
|
+
}
|
|
75
|
+
finally {
|
|
76
|
+
this.logger.debug("Data column sidecar reconstruction attempt finished", logCtx);
|
|
77
|
+
}
|
|
78
|
+
};
|
|
73
79
|
}
|
|
74
80
|
//# sourceMappingURL=ColumnReconstructionTracker.js.map
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"ColumnReconstructionTracker.js","sourceRoot":"","sources":["../../src/chain/ColumnReconstructionTracker.ts"],"names":[],"mappings":"AACA,OAAO,EAAS,KAAK,EAAC,MAAM,iBAAiB,CAAC;AAE9C,OAAO,EAAC,4BAA4B,EAAE,yBAAyB,EAAC,MAAM,wBAAwB,CAAC;
|
|
1
|
+
{"version":3,"file":"ColumnReconstructionTracker.js","sourceRoot":"","sources":["../../src/chain/ColumnReconstructionTracker.ts"],"names":[],"mappings":"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"}
|
|
@@ -5,6 +5,9 @@ import { Metrics } from "../metrics/metrics.js";
|
|
|
5
5
|
import { IBlockInput } from "./blocks/blockInput/index.js";
|
|
6
6
|
import { PayloadEnvelopeInput } from "./blocks/payloadEnvelopeInput/index.js";
|
|
7
7
|
import { ChainEventEmitter } from "./emitter.js";
|
|
8
|
+
/** A `null` answer only changes if the EL receives the transactions later, so retries are few and spaced out */
|
|
9
|
+
export declare const MAX_GET_BLOBS_ATTEMPTS = 3;
|
|
10
|
+
export declare const GET_BLOBS_RETRY_INTERVAL_MS = 1000;
|
|
8
11
|
export type GetBlobsTrackerInit = {
|
|
9
12
|
logger: Logger;
|
|
10
13
|
executionEngine: IExecutionEngine;
|
|
@@ -22,11 +25,19 @@ export declare class GetBlobsTracker {
|
|
|
22
25
|
metrics: Metrics | null;
|
|
23
26
|
config: ChainForkConfig;
|
|
24
27
|
activeReconstructions: Set<string>;
|
|
28
|
+
failedAttempts: Map<string, {
|
|
29
|
+
count: number;
|
|
30
|
+
lastAttemptMs: number;
|
|
31
|
+
retryTimer?: NodeJS.Timeout;
|
|
32
|
+
}>;
|
|
33
|
+
pendingTriggers: Set<string>;
|
|
25
34
|
blobsAndProofsBuffers: {
|
|
26
35
|
buffers: Uint8Array[];
|
|
27
36
|
inUse: boolean;
|
|
28
37
|
}[];
|
|
29
38
|
constructor(init: GetBlobsTrackerInit);
|
|
30
39
|
triggerGetBlobs(input: IBlockInput | PayloadEnvelopeInput): void;
|
|
40
|
+
private retryPendingTrigger;
|
|
41
|
+
private recordFailedAttempt;
|
|
31
42
|
}
|
|
32
43
|
//# sourceMappingURL=GetBlobsTracker.d.ts.map
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"GetBlobsTracker.d.ts","sourceRoot":"","sources":["../../src/chain/GetBlobsTracker.ts"],"names":[],"mappings":"AAAA,OAAO,EAAC,eAAe,EAAC,MAAM,kBAAkB,CAAC;AAEjD,OAAO,EAAC,MAAM,
|
|
1
|
+
{"version":3,"file":"GetBlobsTracker.d.ts","sourceRoot":"","sources":["../../src/chain/GetBlobsTracker.ts"],"names":[],"mappings":"AAAA,OAAO,EAAC,eAAe,EAAC,MAAM,kBAAkB,CAAC;AAEjD,OAAO,EAAC,MAAM,EAAgB,MAAM,iBAAiB,CAAC;AAEtD,OAAO,EAAC,gBAAgB,EAAC,MAAM,uBAAuB,CAAC;AACvD,OAAO,EAAC,OAAO,EAAC,MAAM,uBAAuB,CAAC;AAM9C,OAAO,EAAC,WAAW,EAAoB,MAAM,8BAA8B,CAAC;AAC5E,OAAO,EAAC,oBAAoB,EAAC,MAAM,wCAAwC,CAAC;AAC5E,OAAO,EAAC,iBAAiB,EAAC,MAAM,cAAc,CAAC;AAE/C,gHAAgH;AAChH,eAAO,MAAM,sBAAsB,IAAI,CAAC;AACxC,eAAO,MAAM,2BAA2B,OAAO,CAAC;AAGhD,MAAM,MAAM,mBAAmB,GAAG;IAChC,MAAM,EAAE,MAAM,CAAC;IACf,eAAe,EAAE,gBAAgB,CAAC;IAClC,OAAO,EAAE,iBAAiB,CAAC;IAC3B,OAAO,EAAE,OAAO,GAAG,IAAI,CAAC;IACxB,MAAM,EAAE,eAAe,CAAC;CACzB,CAAC;AAEF;;GAEG;AACH,qBAAa,eAAe;IAC1B,MAAM,EAAE,MAAM,CAAC;IACf,eAAe,EAAE,gBAAgB,CAAC;IAClC,OAAO,EAAE,iBAAiB,CAAC;IAC3B,OAAO,EAAE,OAAO,GAAG,IAAI,CAAC;IACxB,MAAM,EAAE,eAAe,CAAC;IACxB,qBAAqB,cAAqB;IAC1C,cAAc;eAA2B,MAAM;uBAAiB,MAAM;qBAAe,MAAM,CAAC,OAAO;OAAK;IACxG,eAAe,cAAqB;IAGpC,qBAAqB,EAAE;QAAC,OAAO,EAAE,UAAU,EAAE,CAAC;QAAC,KAAK,EAAE,OAAO,CAAA;KAAC,EAAE,CAAM;IAEtE,YAAY,IAAI,EAAE,mBAAmB,EAMpC;IAED,eAAe,CAAC,KAAK,EAAE,WAAW,GAAG,oBAAoB,GAAG,IAAI,CAwG/D;IAED,OAAO,CAAC,mBAAmB;IAQ3B,OAAO,CAAC,mBAAmB;CAM5B"}
|
|
@@ -1,9 +1,13 @@
|
|
|
1
1
|
import { computeEpochAtSlot } from "@lodestar/state-transition";
|
|
2
|
+
import { pruneSetToMax } from "@lodestar/utils";
|
|
2
3
|
import { BLOB_AND_PROOF_V2_RPC_BYTES } from "../execution/engine/types.js";
|
|
3
|
-
import { callInNextEventLoop } from "../util/eventLoop.js";
|
|
4
4
|
import { DataColumnEngineResult, getBlobSidecarsFromExecution, getDataColumnSidecarsFromExecution, } from "../util/execution.js";
|
|
5
5
|
import { isBlockInputBlobs } from "./blocks/blockInput/index.js";
|
|
6
6
|
import { PayloadEnvelopeInput } from "./blocks/payloadEnvelopeInput/index.js";
|
|
7
|
+
/** A `null` answer only changes if the EL receives the transactions later, so retries are few and spaced out */
|
|
8
|
+
export const MAX_GET_BLOBS_ATTEMPTS = 3;
|
|
9
|
+
export const GET_BLOBS_RETRY_INTERVAL_MS = 1000;
|
|
10
|
+
const MAX_TRACKED_BLOCK_ROOTS = 64;
|
|
7
11
|
/**
|
|
8
12
|
* Tracks getBlobsV2 calls to the execution engine to avoid duplicate and multiple in-flight calls
|
|
9
13
|
*/
|
|
@@ -14,6 +18,8 @@ export class GetBlobsTracker {
|
|
|
14
18
|
metrics;
|
|
15
19
|
config;
|
|
16
20
|
activeReconstructions = new Set();
|
|
21
|
+
failedAttempts = new Map();
|
|
22
|
+
pendingTriggers = new Set();
|
|
17
23
|
// Preallocate buffers for getBlobsV2 RPC calls
|
|
18
24
|
// See https://github.com/ChainSafe/lodestar/pull/8282 for context
|
|
19
25
|
blobsAndProofsBuffers = [];
|
|
@@ -26,19 +32,52 @@ export class GetBlobsTracker {
|
|
|
26
32
|
}
|
|
27
33
|
triggerGetBlobs(input) {
|
|
28
34
|
if (this.activeReconstructions.has(input.blockRootHex)) {
|
|
35
|
+
this.pendingTriggers.add(input.blockRootHex);
|
|
29
36
|
return;
|
|
30
37
|
}
|
|
38
|
+
const failed = this.failedAttempts.get(input.blockRootHex);
|
|
39
|
+
if (failed) {
|
|
40
|
+
if (failed.count >= MAX_GET_BLOBS_ATTEMPTS) {
|
|
41
|
+
return;
|
|
42
|
+
}
|
|
43
|
+
const waitMs = GET_BLOBS_RETRY_INTERVAL_MS - (Date.now() - failed.lastAttemptMs);
|
|
44
|
+
if (waitMs > 0) {
|
|
45
|
+
// Columns tend to arrive in one burst, so keep a single trailing retry instead of relying on a later trigger
|
|
46
|
+
failed.retryTimer ??= setTimeout(() => {
|
|
47
|
+
failed.retryTimer = undefined;
|
|
48
|
+
if (this.failedAttempts.get(input.blockRootHex) === failed && !input.hasAllData()) {
|
|
49
|
+
this.triggerGetBlobs(input);
|
|
50
|
+
}
|
|
51
|
+
}, waitMs).unref();
|
|
52
|
+
return;
|
|
53
|
+
}
|
|
54
|
+
}
|
|
55
|
+
// The request is sent right away, before block processing issues newPayload: ELs that drop a
|
|
56
|
+
// transaction's blobs once the payload is validated can only answer a request that gets there first
|
|
31
57
|
if (!(input instanceof PayloadEnvelopeInput) && isBlockInputBlobs(input)) {
|
|
32
58
|
// there is not preallocation for blob sidecars like there is for columns sidecars so no need to
|
|
33
59
|
// store the index for the preallocated buffers
|
|
34
60
|
this.activeReconstructions.add(input.blockRootHex);
|
|
35
|
-
|
|
36
|
-
|
|
37
|
-
|
|
38
|
-
|
|
39
|
-
|
|
40
|
-
|
|
41
|
-
|
|
61
|
+
const logCtx = { slot: input.slot, root: input.blockRootHex };
|
|
62
|
+
this.logger.verbose("Trigger getBlobsV1 for block", logCtx);
|
|
63
|
+
let requestFailed = false;
|
|
64
|
+
getBlobSidecarsFromExecution(this.config, this.executionEngine, this.metrics, this.emitter, input)
|
|
65
|
+
.then(() => {
|
|
66
|
+
// EL errors and misses are handled inside the helper, blobs still missing means the attempt failed
|
|
67
|
+
if (!input.hasAllData()) {
|
|
68
|
+
requestFailed = true;
|
|
69
|
+
this.recordFailedAttempt(input.blockRootHex);
|
|
70
|
+
}
|
|
71
|
+
})
|
|
72
|
+
.catch((error) => {
|
|
73
|
+
this.logger.debug("Error during getBlobsV1 for block", logCtx, error);
|
|
74
|
+
requestFailed = true;
|
|
75
|
+
this.recordFailedAttempt(input.blockRootHex);
|
|
76
|
+
})
|
|
77
|
+
.finally(() => {
|
|
78
|
+
this.logger.verbose("Completed getBlobsV1 for block", logCtx);
|
|
79
|
+
this.activeReconstructions.delete(input.blockRootHex);
|
|
80
|
+
this.retryPendingTrigger(input, requestFailed);
|
|
42
81
|
});
|
|
43
82
|
return;
|
|
44
83
|
}
|
|
@@ -56,28 +95,45 @@ export class GetBlobsTracker {
|
|
|
56
95
|
}
|
|
57
96
|
}
|
|
58
97
|
timer?.();
|
|
59
|
-
// We don't care about the outcome of this call,
|
|
60
|
-
// just that it has been triggered for this block root.
|
|
61
98
|
this.activeReconstructions.add(input.blockRootHex);
|
|
62
99
|
this.blobsAndProofsBuffers[freeIndex].inUse = true;
|
|
63
|
-
|
|
64
|
-
|
|
65
|
-
|
|
66
|
-
|
|
67
|
-
|
|
68
|
-
|
|
69
|
-
|
|
70
|
-
|
|
71
|
-
|
|
72
|
-
this.
|
|
73
|
-
|
|
74
|
-
|
|
75
|
-
|
|
76
|
-
|
|
77
|
-
|
|
78
|
-
|
|
79
|
-
|
|
100
|
+
const logCtx = { slot: input.slot, root: input.blockRootHex };
|
|
101
|
+
this.logger.verbose("Trigger getBlobsV2 for block", logCtx);
|
|
102
|
+
let requestFailed = false;
|
|
103
|
+
getDataColumnSidecarsFromExecution(this.config, this.executionEngine, this.emitter, input, this.metrics, this.blobsAndProofsBuffers[freeIndex].buffers)
|
|
104
|
+
.then((result) => {
|
|
105
|
+
this.logger.debug("getBlobsV2 result for block", { ...logCtx, result });
|
|
106
|
+
this.metrics?.dataColumns.dataColumnEngineResult.inc({ result });
|
|
107
|
+
if (result === DataColumnEngineResult.NullResponse) {
|
|
108
|
+
requestFailed = true;
|
|
109
|
+
this.recordFailedAttempt(input.blockRootHex);
|
|
110
|
+
}
|
|
111
|
+
})
|
|
112
|
+
.catch((error) => {
|
|
113
|
+
this.logger.debug("Error during getBlobsV2 for block", logCtx, error);
|
|
114
|
+
this.metrics?.dataColumns.dataColumnEngineResult.inc({ result: DataColumnEngineResult.Failed });
|
|
115
|
+
requestFailed = true;
|
|
116
|
+
this.recordFailedAttempt(input.blockRootHex);
|
|
117
|
+
})
|
|
118
|
+
.finally(() => {
|
|
119
|
+
this.logger.verbose("Completed getBlobsV2 for block", logCtx);
|
|
120
|
+
this.activeReconstructions.delete(input.blockRootHex);
|
|
121
|
+
this.blobsAndProofsBuffers[freeIndex].inUse = false;
|
|
122
|
+
this.retryPendingTrigger(input, requestFailed);
|
|
80
123
|
});
|
|
81
124
|
}
|
|
125
|
+
retryPendingTrigger(input, requestFailed) {
|
|
126
|
+
// Triggers dropped while the request was in flight re-enter once it failed, the attempt that was just
|
|
127
|
+
// recorded makes this arm the trailing retry instead of sending another request right away
|
|
128
|
+
if (this.pendingTriggers.delete(input.blockRootHex) && requestFailed) {
|
|
129
|
+
this.triggerGetBlobs(input);
|
|
130
|
+
}
|
|
131
|
+
}
|
|
132
|
+
recordFailedAttempt(blockRootHex) {
|
|
133
|
+
const failed = this.failedAttempts.get(blockRootHex);
|
|
134
|
+
clearTimeout(failed?.retryTimer);
|
|
135
|
+
this.failedAttempts.set(blockRootHex, { count: (failed?.count ?? 0) + 1, lastAttemptMs: Date.now() });
|
|
136
|
+
pruneSetToMax(this.failedAttempts, MAX_TRACKED_BLOCK_ROOTS);
|
|
137
|
+
}
|
|
82
138
|
}
|
|
83
139
|
//# sourceMappingURL=GetBlobsTracker.js.map
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"GetBlobsTracker.js","sourceRoot":"","sources":["../../src/chain/GetBlobsTracker.ts"],"names":[],"mappings":"AACA,OAAO,EAAC,kBAAkB,EAAC,MAAM,4BAA4B,CAAC;
|
|
1
|
+
{"version":3,"file":"GetBlobsTracker.js","sourceRoot":"","sources":["../../src/chain/GetBlobsTracker.ts"],"names":[],"mappings":"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"}
|
|
@@ -12,6 +12,10 @@ export declare enum LateCanonicalBlockReason {
|
|
|
12
12
|
SlowImport = "slow_import",
|
|
13
13
|
LateReceive = "late_receive"
|
|
14
14
|
}
|
|
15
|
+
/**
|
|
16
|
+
* Oldest epoch for which data column sidecars are kept
|
|
17
|
+
*/
|
|
18
|
+
export declare function getDataColumnSidecarsMinEpoch(config: ChainForkConfig, currentEpoch: Epoch, archiveDataEpochs?: number): Epoch;
|
|
15
19
|
/**
|
|
16
20
|
* Archives finalized blocks from active bucket to archive bucket.
|
|
17
21
|
*
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"archiveBlocks.d.ts","sourceRoot":"","sources":["../../../../src/chain/archiveStore/utils/archiveBlocks.ts"],"names":[],"mappings":"AACA,OAAO,EAAC,eAAe,EAAC,MAAM,kBAAkB,CAAC;AAEjD,OAAO,
|
|
1
|
+
{"version":3,"file":"archiveBlocks.d.ts","sourceRoot":"","sources":["../../../../src/chain/archiveStore/utils/archiveBlocks.ts"],"names":[],"mappings":"AACA,OAAO,EAAC,eAAe,EAAC,MAAM,kBAAkB,CAAC;AAEjD,OAAO,EACL,iBAAiB,EAEjB,WAAW,EAEX,UAAU,EAEX,MAAM,uBAAuB,CAAC;AAG/B,OAAO,EAAC,KAAK,EAAE,IAAI,EAAC,MAAM,iBAAiB,CAAC;AAC5C,OAAO,EAAC,MAAM,EAAyC,MAAM,iBAAiB,CAAC;AAC/E,OAAO,EAAC,SAAS,EAAC,MAAM,sBAAsB,CAAC;AAE/C,OAAO,EAAC,OAAO,EAAC,MAAM,6BAA6B,CAAC;AAIpD,OAAO,EAAC,iBAAiB,EAAC,MAAM,4BAA4B,CAAC;AAU7D;;GAEG;AACH,oBAAY,wBAAwB;IAElC,UAAU,gBAAgB;IAE1B,WAAW,iBAAiB;CAC7B;AAmBD;;GAEG;AACH,wBAAgB,6BAA6B,CAC3C,MAAM,EAAE,eAAe,EACvB,YAAY,EAAE,KAAK,EACnB,iBAAiB,CAAC,EAAE,MAAM,GACzB,KAAK,CAEP;AAED;;;;;;;;GAQG;AACH,wBAAsB,aAAa,CACjC,MAAM,EAAE,eAAe,EACvB,EAAE,EAAE,SAAS,EACb,UAAU,EAAE,WAAW,EACvB,iBAAiB,EAAE,iBAAiB,GAAG,SAAS,EAChD,MAAM,EAAE,MAAM,EACd,mBAAmB,EAAE,iBAAiB,EACtC,YAAY,EAAE,KAAK,EACnB,OAAO,EAAE,OAAO,GAAG,IAAI,EACvB,YAAY,EAAE,OAAO,EACrB,iBAAiB,CAAC,EAAE,MAAM,EAC1B,qBAAqB,CAAC,EAAE,OAAO,EAC/B,wBAAwB,CAAC,EAAE,MAAM,EACjC,cAAc,UAAO,GACpB,OAAO,CAAC,IAAI,CAAC,CA4Nf;AA8GD;;;;;;;GAOG;AACH,wBAAsB,+CAA+C,CACnE,MAAM,EAAE,eAAe,EACvB,EAAE,EAAE,SAAS,EACb,MAAM,EAAE,MAAM,EACd,eAAe,EAAE,UAAU,EAAE,EAC7B,cAAc,EAAE,OAAO,GACtB,OAAO,CAAC,IAAI,EAAE,CAAC,CAmDjB;AAED;;;;;;;;;;;;;;;GAeG;AACH,wBAAgB,4BAA4B,CAAC,KAAK,EAAE,UAAU,GAAG,UAAU,CAE1E;AAED;;;;GAIG;AACH,wBAAgB,sBAAsB,CAAC,CAAC,SAAS;IAAC,IAAI,EAAE,IAAI,CAAA;CAAC,EAAE,MAAM,EAAE,CAAC,EAAE,GAAG,CAAC,EAAE,CA+C/E"}
|
|
@@ -1,8 +1,8 @@
|
|
|
1
1
|
import path from "node:path";
|
|
2
|
-
import { ExecutionStatus, PayloadStatus } from "@lodestar/fork-choice";
|
|
2
|
+
import { ExecutionStatus, PayloadStatus, isGloasBlock, } from "@lodestar/fork-choice";
|
|
3
3
|
import { ForkSeq, SLOTS_PER_EPOCH } from "@lodestar/params";
|
|
4
4
|
import { computeEpochAtSlot, computeStartSlotAtEpoch, getBlobDataRetentionStartEpoch } from "@lodestar/state-transition";
|
|
5
|
-
import {
|
|
5
|
+
import { fromHex, prettyPrintIndices, toRootHex } from "@lodestar/utils";
|
|
6
6
|
import { encodeArchivedHeaderEnvelope } from "../../../db/repositories/index.js";
|
|
7
7
|
import { ensureDir, writeIfNotExist } from "../../../util/file.js";
|
|
8
8
|
import { toSignedHeaderEnvelope } from "../../../util/headerEnvelope.js";
|
|
@@ -30,6 +30,12 @@ async function persistOrphanedBlock(slot, blockRoot, bytes, opts) {
|
|
|
30
30
|
await ensureDir(dirpath);
|
|
31
31
|
await writeIfNotExist(filepath, bytes);
|
|
32
32
|
}
|
|
33
|
+
/**
|
|
34
|
+
* Oldest epoch for which data column sidecars are kept
|
|
35
|
+
*/
|
|
36
|
+
export function getDataColumnSidecarsMinEpoch(config, currentEpoch, archiveDataEpochs) {
|
|
37
|
+
return Math.min(getBlobDataRetentionStartEpoch(config, currentEpoch), currentEpoch - (archiveDataEpochs ?? 0));
|
|
38
|
+
}
|
|
33
39
|
/**
|
|
34
40
|
* Archives finalized blocks from active bucket to archive bucket.
|
|
35
41
|
*
|
|
@@ -90,16 +96,6 @@ export async function archiveBlocks(config, db, forkChoice, lightclientServer, l
|
|
|
90
96
|
const migratedEntries = await migrateBlobSidecarsFromHotToColdDb(config, db, logger, finalizedCanonicalBlockRoots, currentEpoch);
|
|
91
97
|
logger.verbose("Migrated blobSidecars from hot DB to cold DB", { ...logCtx, migratedEntries });
|
|
92
98
|
}
|
|
93
|
-
// Keep the normal LevelDB hot-to-cold flow for legacy columns. New columns are written
|
|
94
|
-
// directly to flat files, so this only moves fallback data left by older versions.
|
|
95
|
-
if (finalizedPostFulu) {
|
|
96
|
-
const migratedSlots = await migrateDataColumnSidecarsFromHotToColdDb(config, db, logger, finalizedCanonicalBlocks, currentEpoch);
|
|
97
|
-
logger.verbose("Migrated legacy dataColumnSidecars from hot DB to cold DB", {
|
|
98
|
-
...logCtx,
|
|
99
|
-
migratedEntries: migratedSlots.length,
|
|
100
|
-
slotRange: prettyPrintIndices(migratedSlots),
|
|
101
|
-
});
|
|
102
|
-
}
|
|
103
99
|
if (finalizedPostGloas) {
|
|
104
100
|
const migratedSlots = await migrateExecutionPayloadEnvelopesFromHotToColdDb(config, db, logger, finalizedCanonicalBlocks, dedupePayloads);
|
|
105
101
|
logger.verbose("Migrated executionPayloadEnvelopes from hot DB to cold DB", {
|
|
@@ -109,38 +105,31 @@ export async function archiveBlocks(config, db, forkChoice, lightclientServer, l
|
|
|
109
105
|
});
|
|
110
106
|
}
|
|
111
107
|
}
|
|
112
|
-
|
|
113
|
-
|
|
114
|
-
const
|
|
115
|
-
|
|
116
|
-
if (
|
|
117
|
-
|
|
118
|
-
|
|
119
|
-
|
|
120
|
-
|
|
121
|
-
|
|
122
|
-
|
|
123
|
-
|
|
124
|
-
persistOrphanedBlocksDir: persistOrphanedBlocksDir ?? "orphaned_blocks",
|
|
125
|
-
});
|
|
126
|
-
logger.verbose("Persisted orphaned block", { ...logCtx, ...blockLogCtx });
|
|
127
|
-
}
|
|
128
|
-
else {
|
|
129
|
-
logger.warn("Tried to persist orphaned block but no block found", { ...logCtx, ...blockLogCtx });
|
|
130
|
-
}
|
|
131
|
-
}));
|
|
108
|
+
const canonicalRoots = new Set(finalizedCanonicalBlocks.map((block) => block.blockRoot));
|
|
109
|
+
const orphanedBlocks = [];
|
|
110
|
+
const orphanedPayloads = [];
|
|
111
|
+
for (const block of finalizedNonCanonicalBlocks) {
|
|
112
|
+
if (block.payloadStatus === PayloadStatus.FULL) {
|
|
113
|
+
orphanedPayloads.push(block);
|
|
114
|
+
}
|
|
115
|
+
// Every Gloas block gets EMPTY before FULL. If only FULL survives pruning, an earlier archive run
|
|
116
|
+
// already handled the root's block-level data.
|
|
117
|
+
const isBlockNode = !isGloasBlock(block) || block.payloadStatus === PayloadStatus.EMPTY;
|
|
118
|
+
if (isBlockNode && !canonicalRoots.has(block.blockRoot)) {
|
|
119
|
+
orphanedBlocks.push(block);
|
|
132
120
|
}
|
|
133
|
-
|
|
134
|
-
|
|
121
|
+
}
|
|
122
|
+
const orphanedBlockRoots = orphanedBlocks.map((block) => fromHex(block.blockRoot));
|
|
123
|
+
if (orphanedPayloads.length > 0) {
|
|
124
|
+
const orphanedPayloadRoots = orphanedPayloads.map((block) => fromHex(block.blockRoot));
|
|
125
|
+
const orphanedPayloadLogCtx = {
|
|
135
126
|
...logCtx,
|
|
136
|
-
count:
|
|
137
|
-
slotRange: prettyPrintIndices(
|
|
127
|
+
count: orphanedPayloads.length,
|
|
128
|
+
slotRange: prettyPrintIndices(orphanedPayloads.map((block) => block.slot).sort((a, b) => a - b)),
|
|
138
129
|
};
|
|
139
|
-
const columnItems =
|
|
140
|
-
|
|
141
|
-
|
|
142
|
-
.filter((summary) => config.getForkSeq(summary.slot) >= ForkSeq.fulu && summary.payloadStatus === PayloadStatus.FULL)
|
|
143
|
-
.map((summary) => ({ slot: summary.slot, blockRoot: summary.blockRoot }));
|
|
130
|
+
const columnItems = orphanedPayloads
|
|
131
|
+
.filter((block) => config.getForkSeq(block.slot) >= ForkSeq.fulu)
|
|
132
|
+
.map((block) => ({ slot: block.slot, blockRoot: block.blockRoot }));
|
|
144
133
|
if (columnItems.length > 0) {
|
|
145
134
|
// Delete sidecars first so their block roots remain available to retry cleanup after a failure or crash.
|
|
146
135
|
await db.dataColumns.deleteMany(columnItems);
|
|
@@ -150,16 +139,38 @@ export async function archiveBlocks(config, db, forkChoice, lightclientServer, l
|
|
|
150
139
|
slotRange: prettyPrintIndices(columnItems.map(({ slot }) => slot).sort((a, b) => a - b)),
|
|
151
140
|
});
|
|
152
141
|
}
|
|
153
|
-
await db.block.batchDelete(nonCanonicalBlockRoots);
|
|
154
|
-
logger.verbose("Deleted non canonical blocks from hot DB", nonCanonicalLogCtx);
|
|
155
142
|
if (finalizedPostDeneb) {
|
|
156
|
-
await db.blobSidecars.batchDelete(
|
|
157
|
-
logger.verbose("Deleted non canonical blobSidecars from hot DB",
|
|
143
|
+
await db.blobSidecars.batchDelete(orphanedPayloadRoots);
|
|
144
|
+
logger.verbose("Deleted non canonical blobSidecars from hot DB", orphanedPayloadLogCtx);
|
|
158
145
|
}
|
|
159
146
|
if (finalizedPostGloas) {
|
|
160
|
-
await db.executionPayloadEnvelope.batchDelete(
|
|
161
|
-
logger.verbose("Deleted non canonical executionPayloadEnvelopes from hot DB",
|
|
147
|
+
await db.executionPayloadEnvelope.batchDelete(orphanedPayloadRoots);
|
|
148
|
+
logger.verbose("Deleted non canonical executionPayloadEnvelopes from hot DB", orphanedPayloadLogCtx);
|
|
149
|
+
}
|
|
150
|
+
}
|
|
151
|
+
if (orphanedBlocks.length > 0) {
|
|
152
|
+
if (persistOrphanedBlocks) {
|
|
153
|
+
// Persist orphaned blocks to disk before deleting them from hot db
|
|
154
|
+
await Promise.all(orphanedBlocks.map(async (block) => {
|
|
155
|
+
const blockBytes = await db.block.getBinary(fromHex(block.blockRoot));
|
|
156
|
+
const blockLogCtx = { slot: block.slot, root: block.blockRoot };
|
|
157
|
+
if (blockBytes) {
|
|
158
|
+
await persistOrphanedBlock(block.slot, block.blockRoot, blockBytes, {
|
|
159
|
+
persistOrphanedBlocksDir: persistOrphanedBlocksDir ?? "orphaned_blocks",
|
|
160
|
+
});
|
|
161
|
+
logger.verbose("Persisted orphaned block", { ...logCtx, ...blockLogCtx });
|
|
162
|
+
}
|
|
163
|
+
else {
|
|
164
|
+
logger.debug("Tried to persist orphaned block but no block found", { ...logCtx, ...blockLogCtx });
|
|
165
|
+
}
|
|
166
|
+
}));
|
|
162
167
|
}
|
|
168
|
+
await db.block.batchDelete(orphanedBlockRoots);
|
|
169
|
+
logger.verbose("Deleted non canonical blocks from hot DB", {
|
|
170
|
+
...logCtx,
|
|
171
|
+
count: orphanedBlocks.length,
|
|
172
|
+
slotRange: prettyPrintIndices(orphanedBlocks.map((block) => block.slot).sort((a, b) => a - b)),
|
|
173
|
+
});
|
|
163
174
|
}
|
|
164
175
|
// Delete expired blobs
|
|
165
176
|
// Keep only `[current_epoch - max(MIN_EPOCHS_FOR_BLOB_SIDECARS_REQUESTS, archiveDataEpochs)]`
|
|
@@ -187,7 +198,7 @@ export async function archiveBlocks(config, db, forkChoice, lightclientServer, l
|
|
|
187
198
|
// Keep only `[min(compute_blob_data_retention_start_epoch(current_epoch), current_epoch - archiveDataEpochs)]`
|
|
188
199
|
if (finalizedPostFulu) {
|
|
189
200
|
if (archiveDataEpochs !== Infinity) {
|
|
190
|
-
const dataColumnSidecarsMinEpoch =
|
|
201
|
+
const dataColumnSidecarsMinEpoch = getDataColumnSidecarsMinEpoch(config, currentEpoch, archiveDataEpochs);
|
|
191
202
|
if (dataColumnSidecarsMinEpoch >= config.FULU_FORK_EPOCH) {
|
|
192
203
|
const columnsPruneSlot = computeStartSlotAtEpoch(dataColumnSidecarsMinEpoch);
|
|
193
204
|
const prunedColumnSlots = await db.dataColumns.pruneBefore(columnsPruneSlot);
|
|
@@ -210,9 +221,9 @@ export async function archiveBlocks(config, db, forkChoice, lightclientServer, l
|
|
|
210
221
|
logger.verbose("dataColumnSidecars pruning skipped: archiveDataEpochs set to Infinity", logCtx);
|
|
211
222
|
}
|
|
212
223
|
}
|
|
213
|
-
//
|
|
224
|
+
// Pruning potential checkpoint data
|
|
214
225
|
const finalizedCanonicalNonCheckpointBlocks = getNonCheckpointBlocks(finalizedCanonicalBlockRoots);
|
|
215
|
-
const nonCheckpointBlockRoots = [...
|
|
226
|
+
const nonCheckpointBlockRoots = [...orphanedBlockRoots];
|
|
216
227
|
for (const block of finalizedCanonicalNonCheckpointBlocks) {
|
|
217
228
|
nonCheckpointBlockRoots.push(block.root);
|
|
218
229
|
}
|
|
@@ -310,53 +321,6 @@ async function migrateBlobSidecarsFromHotToColdDb(config, db, logger, blocks, cu
|
|
|
310
321
|
}
|
|
311
322
|
return migratedWrappedBlobSidecars;
|
|
312
323
|
}
|
|
313
|
-
// TODO: This function can be simplified further by reducing layers of promises in a loop
|
|
314
|
-
/**
|
|
315
|
-
* Post-gloas the data columns of a Gloas block are tied to its execution payload envelope.
|
|
316
|
-
* Columns only exist once the FULL variant of the block is in the proto-array. Pre-Gloas
|
|
317
|
-
* blocks only have a FULL variant, so the payload-status filter passes them all.
|
|
318
|
-
*/
|
|
319
|
-
async function migrateDataColumnSidecarsFromHotToColdDb(config, db, logger, canonicalBlocks, currentEpoch) {
|
|
320
|
-
const columnBlocks = canonicalBlocks.filter((block) => config.getForkSeq(block.slot) < ForkSeq.gloas || block.payloadStatus === PayloadStatus.FULL);
|
|
321
|
-
if (columnBlocks.length === 0)
|
|
322
|
-
return [];
|
|
323
|
-
const blocks = columnBlocks.map((block) => ({ slot: block.slot, root: fromHex(block.blockRoot) }));
|
|
324
|
-
const migratedSlots = [];
|
|
325
|
-
for (let i = 0; i < blocks.length; i += BLOB_SIDECAR_BATCH_SIZE) {
|
|
326
|
-
const toIdx = Math.min(i + BLOB_SIDECAR_BATCH_SIZE, blocks.length);
|
|
327
|
-
const batch = blocks.slice(i, toIdx);
|
|
328
|
-
if (batch.length === 0)
|
|
329
|
-
break;
|
|
330
|
-
const promises = [];
|
|
331
|
-
for (const block of batch) {
|
|
332
|
-
const blockEpoch = computeEpochAtSlot(block.slot);
|
|
333
|
-
if (config.getForkSeq(block.slot) < ForkSeq.fulu ||
|
|
334
|
-
blockEpoch < getBlobDataRetentionStartEpoch(config, currentEpoch)) {
|
|
335
|
-
continue;
|
|
336
|
-
}
|
|
337
|
-
const dataColumnSidecarBytes = await fromAsync(db.dataColumnSidecar.valuesStreamBinary(block.root));
|
|
338
|
-
if (dataColumnSidecarBytes.length === 0) {
|
|
339
|
-
logger.debug("DataColumnSidecars in forkchoice but missing in hot db, could be already archived", {
|
|
340
|
-
slot: block.slot,
|
|
341
|
-
root: toRootHex(block.root),
|
|
342
|
-
});
|
|
343
|
-
continue;
|
|
344
|
-
}
|
|
345
|
-
logger.verbose("Migrated legacy dataColumnSidecars for block", {
|
|
346
|
-
currentEpoch,
|
|
347
|
-
slot: block.slot,
|
|
348
|
-
root: toRootHex(block.root),
|
|
349
|
-
numSidecars: dataColumnSidecarBytes.length,
|
|
350
|
-
});
|
|
351
|
-
promises.push(db.dataColumnSidecarArchive.putManyBinary(block.slot, dataColumnSidecarBytes.map((entry) => ({ key: entry.id, value: entry.value }))));
|
|
352
|
-
migratedSlots.push(block.slot);
|
|
353
|
-
}
|
|
354
|
-
await Promise.all(promises);
|
|
355
|
-
await db.dataColumnSidecar.deleteMany(batch.map((block) => block.root));
|
|
356
|
-
}
|
|
357
|
-
// Ancestor walk is newest to oldest; sort ascending so `prettyPrintIndices` renders cleanly.
|
|
358
|
-
return migratedSlots.sort((a, b) => a - b);
|
|
359
|
-
}
|
|
360
324
|
/**
|
|
361
325
|
* Post-gloas given a finalized checkpoint at a block root, payload of that block root
|
|
362
326
|
* is not considered finalized, hence they are archived in the next run.
|