@lodestar/beacon-node 1.48.0-dev.f22c5ce63e → 1.48.0-dev.f63ac74039
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 +4 -11
- package/lib/api/impl/beacon/blocks/index.js.map +1 -1
- package/lib/api/impl/beacon/state/utils.d.ts.map +1 -1
- package/lib/api/impl/beacon/state/utils.js +14 -0
- package/lib/api/impl/beacon/state/utils.js.map +1 -1
- package/lib/api/impl/config/index.d.ts.map +1 -1
- package/lib/api/impl/config/index.js +4 -1
- package/lib/api/impl/config/index.js.map +1 -1
- package/lib/api/impl/validator/index.d.ts.map +1 -1
- package/lib/api/impl/validator/index.js +39 -39
- package/lib/api/impl/validator/index.js.map +1 -1
- package/lib/chain/archiveStore/archiveStore.d.ts +1 -0
- package/lib/chain/archiveStore/archiveStore.d.ts.map +1 -1
- package/lib/chain/archiveStore/archiveStore.js +5 -1
- package/lib/chain/archiveStore/archiveStore.js.map +1 -1
- package/lib/chain/archiveStore/historicalState/historicalStateRegen.d.ts.map +1 -1
- package/lib/chain/archiveStore/historicalState/historicalStateRegen.js +1 -0
- package/lib/chain/archiveStore/historicalState/historicalStateRegen.js.map +1 -1
- package/lib/chain/archiveStore/historicalState/metrics.d.ts.map +1 -1
- package/lib/chain/archiveStore/historicalState/metrics.js +12 -1
- package/lib/chain/archiveStore/historicalState/metrics.js.map +1 -1
- package/lib/chain/archiveStore/historicalState/types.d.ts +2 -0
- package/lib/chain/archiveStore/historicalState/types.d.ts.map +1 -1
- package/lib/chain/archiveStore/historicalState/types.js.map +1 -1
- package/lib/chain/archiveStore/historicalState/worker.js +4 -1
- package/lib/chain/archiveStore/historicalState/worker.js.map +1 -1
- package/lib/chain/archiveStore/utils/archiveBlocks.d.ts +9 -1
- package/lib/chain/archiveStore/utils/archiveBlocks.d.ts.map +1 -1
- package/lib/chain/archiveStore/utils/archiveBlocks.js +68 -38
- package/lib/chain/archiveStore/utils/archiveBlocks.js.map +1 -1
- package/lib/chain/blocks/importBlock.d.ts +5 -1
- package/lib/chain/blocks/importBlock.d.ts.map +1 -1
- package/lib/chain/blocks/importBlock.js +12 -18
- package/lib/chain/blocks/importBlock.js.map +1 -1
- package/lib/chain/blocks/index.d.ts +8 -4
- package/lib/chain/blocks/index.d.ts.map +1 -1
- package/lib/chain/blocks/index.js +83 -17
- package/lib/chain/blocks/index.js.map +1 -1
- package/lib/chain/blocks/types.d.ts +8 -0
- package/lib/chain/blocks/types.d.ts.map +1 -1
- package/lib/chain/blocks/types.js.map +1 -1
- package/lib/chain/blocks/utils/chainSegment.d.ts +1 -1
- package/lib/chain/blocks/utils/chainSegment.d.ts.map +1 -1
- package/lib/chain/blocks/utils/chainSegment.js +26 -11
- package/lib/chain/blocks/utils/chainSegment.js.map +1 -1
- package/lib/chain/blocks/writeBlockInputToDb.d.ts.map +1 -1
- package/lib/chain/blocks/writeBlockInputToDb.js +9 -16
- package/lib/chain/blocks/writeBlockInputToDb.js.map +1 -1
- package/lib/chain/chain.d.ts +11 -5
- package/lib/chain/chain.d.ts.map +1 -1
- package/lib/chain/chain.js +129 -75
- package/lib/chain/chain.js.map +1 -1
- package/lib/chain/emitter.d.ts +1 -1
- package/lib/chain/emitter.js +1 -1
- package/lib/chain/errors/blockError.d.ts +14 -9
- package/lib/chain/errors/blockError.d.ts.map +1 -1
- package/lib/chain/errors/blockError.js +0 -2
- package/lib/chain/errors/blockError.js.map +1 -1
- package/lib/chain/errors/dataColumnSidecarError.d.ts +15 -2
- package/lib/chain/errors/dataColumnSidecarError.d.ts.map +1 -1
- package/lib/chain/errors/dataColumnSidecarError.js.map +1 -1
- package/lib/chain/errors/executionPayloadBid.d.ts +4 -0
- package/lib/chain/errors/executionPayloadBid.d.ts.map +1 -1
- package/lib/chain/errors/executionPayloadBid.js +1 -0
- package/lib/chain/errors/executionPayloadBid.js.map +1 -1
- package/lib/chain/errors/executionPayloadEnvelope.d.ts +10 -11
- package/lib/chain/errors/executionPayloadEnvelope.d.ts.map +1 -1
- package/lib/chain/errors/executionPayloadEnvelope.js +0 -2
- package/lib/chain/errors/executionPayloadEnvelope.js.map +1 -1
- package/lib/chain/errors/gossipValidation.d.ts +2 -1
- package/lib/chain/errors/gossipValidation.d.ts.map +1 -1
- package/lib/chain/errors/gossipValidation.js +1 -0
- package/lib/chain/errors/gossipValidation.js.map +1 -1
- package/lib/chain/forkChoice/index.d.ts.map +1 -1
- package/lib/chain/forkChoice/index.js +2 -0
- package/lib/chain/forkChoice/index.js.map +1 -1
- package/lib/chain/interface.d.ts +4 -4
- package/lib/chain/interface.d.ts.map +1 -1
- package/lib/chain/lightClient/index.d.ts +3 -3
- package/lib/chain/lightClient/index.d.ts.map +1 -1
- package/lib/chain/lightClient/index.js +21 -23
- package/lib/chain/lightClient/index.js.map +1 -1
- package/lib/chain/lightClient/proofs.d.ts +2 -1
- package/lib/chain/lightClient/proofs.d.ts.map +1 -1
- package/lib/chain/lightClient/proofs.js +5 -1
- package/lib/chain/lightClient/proofs.js.map +1 -1
- package/lib/chain/opPools/aggregatedAttestationPool.js +1 -1
- package/lib/chain/opPools/aggregatedAttestationPool.js.map +1 -1
- package/lib/chain/prepareNextSlot.d.ts.map +1 -1
- package/lib/chain/prepareNextSlot.js +16 -14
- package/lib/chain/prepareNextSlot.js.map +1 -1
- package/lib/chain/produceBlock/produceBlockBody.d.ts +4 -2
- package/lib/chain/produceBlock/produceBlockBody.d.ts.map +1 -1
- package/lib/chain/produceBlock/produceBlockBody.js +57 -72
- package/lib/chain/produceBlock/produceBlockBody.js.map +1 -1
- package/lib/chain/validation/block.d.ts.map +1 -1
- package/lib/chain/validation/block.js +27 -55
- package/lib/chain/validation/block.js.map +1 -1
- package/lib/chain/validation/dataColumnSidecar.d.ts.map +1 -1
- package/lib/chain/validation/dataColumnSidecar.js +38 -13
- package/lib/chain/validation/dataColumnSidecar.js.map +1 -1
- package/lib/chain/validation/executionPayloadBid.d.ts.map +1 -1
- package/lib/chain/validation/executionPayloadBid.js +56 -40
- package/lib/chain/validation/executionPayloadBid.js.map +1 -1
- package/lib/chain/validation/executionPayloadEnvelope.d.ts.map +1 -1
- package/lib/chain/validation/executionPayloadEnvelope.js +10 -29
- 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 +5 -6
- package/lib/chain/validation/payloadAttestationMessage.js.map +1 -1
- package/lib/chain/validatorMonitor.d.ts +7 -1
- package/lib/chain/validatorMonitor.d.ts.map +1 -1
- package/lib/chain/validatorMonitor.js +22 -5
- package/lib/chain/validatorMonitor.js.map +1 -1
- package/lib/db/beacon.d.ts +14 -5
- package/lib/db/beacon.d.ts.map +1 -1
- package/lib/db/beacon.js +17 -3
- package/lib/db/beacon.js.map +1 -1
- package/lib/db/dataColumnStore.d.ts +39 -0
- package/lib/db/dataColumnStore.d.ts.map +1 -0
- package/lib/db/dataColumnStore.js +81 -0
- package/lib/db/dataColumnStore.js.map +1 -0
- package/lib/db/flatFileStore/atomicWrite.d.ts +8 -0
- package/lib/db/flatFileStore/atomicWrite.d.ts.map +1 -0
- package/lib/db/flatFileStore/atomicWrite.js +61 -0
- package/lib/db/flatFileStore/atomicWrite.js.map +1 -0
- package/lib/db/flatFileStore/dcolFormat.d.ts +90 -0
- package/lib/db/flatFileStore/dcolFormat.d.ts.map +1 -0
- package/lib/db/flatFileStore/dcolFormat.js +286 -0
- package/lib/db/flatFileStore/dcolFormat.js.map +1 -0
- package/lib/db/flatFileStore/errors.d.ts +82 -0
- package/lib/db/flatFileStore/errors.d.ts.map +1 -0
- package/lib/db/flatFileStore/errors.js +32 -0
- package/lib/db/flatFileStore/errors.js.map +1 -0
- package/lib/db/flatFileStore/flatFileStore.d.ts +41 -0
- package/lib/db/flatFileStore/flatFileStore.d.ts.map +1 -0
- package/lib/db/flatFileStore/flatFileStore.js +251 -0
- package/lib/db/flatFileStore/flatFileStore.js.map +1 -0
- package/lib/db/flatFileStore/index.d.ts +4 -0
- package/lib/db/flatFileStore/index.d.ts.map +1 -0
- package/lib/db/flatFileStore/index.js +2 -0
- package/lib/db/flatFileStore/index.js.map +1 -0
- package/lib/db/flatFileStore/interface.d.ts +25 -0
- package/lib/db/flatFileStore/interface.d.ts.map +1 -0
- package/lib/db/flatFileStore/interface.js +2 -0
- package/lib/db/flatFileStore/interface.js.map +1 -0
- package/lib/db/flatFileStore/metrics.d.ts +24 -0
- package/lib/db/flatFileStore/metrics.d.ts.map +1 -0
- package/lib/db/flatFileStore/metrics.js +25 -0
- package/lib/db/flatFileStore/metrics.js.map +1 -0
- package/lib/db/flatFileStore/path.d.ts +9 -0
- package/lib/db/flatFileStore/path.d.ts.map +1 -0
- package/lib/db/flatFileStore/path.js +21 -0
- package/lib/db/flatFileStore/path.js.map +1 -0
- package/lib/db/flatFileStore/slotIndex.d.ts +14 -0
- package/lib/db/flatFileStore/slotIndex.d.ts.map +1 -0
- package/lib/db/flatFileStore/slotIndex.js +46 -0
- package/lib/db/flatFileStore/slotIndex.js.map +1 -0
- package/lib/db/flatFileStore/snappy.d.ts +3 -0
- package/lib/db/flatFileStore/snappy.d.ts.map +1 -0
- package/lib/db/flatFileStore/snappy.js +12 -0
- package/lib/db/flatFileStore/snappy.js.map +1 -0
- package/lib/db/index.d.ts +1 -0
- package/lib/db/index.d.ts.map +1 -1
- package/lib/db/interface.d.ts +8 -1
- package/lib/db/interface.d.ts.map +1 -1
- package/lib/db/repositories/blockArchive.d.ts +8 -1
- package/lib/db/repositories/blockArchive.d.ts.map +1 -1
- package/lib/db/repositories/blockArchive.js +65 -28
- package/lib/db/repositories/blockArchive.js.map +1 -1
- package/lib/db/repositories/blockArchiveIndex.d.ts +1 -2
- package/lib/db/repositories/blockArchiveIndex.d.ts.map +1 -1
- package/lib/db/repositories/blockArchiveIndex.js +3 -7
- package/lib/db/repositories/blockArchiveIndex.js.map +1 -1
- package/lib/execution/builder/validateBid.d.ts.map +1 -1
- package/lib/execution/builder/validateBid.js +8 -5
- package/lib/execution/builder/validateBid.js.map +1 -1
- package/lib/execution/engine/mock.d.ts.map +1 -1
- package/lib/execution/engine/mock.js +4 -1
- package/lib/execution/engine/mock.js.map +1 -1
- package/lib/metrics/metrics/lodestar.d.ts +22 -3
- package/lib/metrics/metrics/lodestar.d.ts.map +1 -1
- package/lib/metrics/metrics/lodestar.js +60 -6
- package/lib/metrics/metrics/lodestar.js.map +1 -1
- package/lib/monitoring/clientStats.js +1 -1
- package/lib/monitoring/clientStats.js.map +1 -1
- package/lib/network/gossip/encoding.d.ts.map +1 -1
- package/lib/network/gossip/encoding.js +0 -7
- package/lib/network/gossip/encoding.js.map +1 -1
- package/lib/network/gossip/topic.d.ts +2 -1
- package/lib/network/gossip/topic.d.ts.map +1 -1
- package/lib/network/gossip/topic.js +4 -20
- package/lib/network/gossip/topic.js.map +1 -1
- package/lib/network/libp2p/index.d.ts +9 -1
- package/lib/network/libp2p/index.d.ts.map +1 -1
- package/lib/network/libp2p/index.js +23 -0
- package/lib/network/libp2p/index.js.map +1 -1
- package/lib/network/network.js +2 -2
- package/lib/network/network.js.map +1 -1
- package/lib/network/processor/gossipHandlers.d.ts.map +1 -1
- package/lib/network/processor/gossipHandlers.js +388 -285
- package/lib/network/processor/gossipHandlers.js.map +1 -1
- package/lib/network/processor/index.d.ts +49 -3
- package/lib/network/processor/index.d.ts.map +1 -1
- package/lib/network/processor/index.js +254 -114
- package/lib/network/processor/index.js.map +1 -1
- package/lib/network/reqresp/handlers/dataColumnSidecarsByRange.d.ts.map +1 -1
- package/lib/network/reqresp/handlers/dataColumnSidecarsByRange.js +112 -91
- package/lib/network/reqresp/handlers/dataColumnSidecarsByRange.js.map +1 -1
- package/lib/network/reqresp/handlers/dataColumnSidecarsByRoot.d.ts.map +1 -1
- package/lib/network/reqresp/handlers/dataColumnSidecarsByRoot.js +2 -0
- package/lib/network/reqresp/handlers/dataColumnSidecarsByRoot.js.map +1 -1
- package/lib/network/reqresp/protocols.d.ts.map +1 -1
- package/lib/network/reqresp/protocols.js +6 -22
- package/lib/network/reqresp/protocols.js.map +1 -1
- package/lib/network/reqresp/rateLimit.js +2 -1
- package/lib/network/reqresp/rateLimit.js.map +1 -1
- package/lib/network/reqresp/utils/dataColumnResponseValidation.d.ts +2 -1
- package/lib/network/reqresp/utils/dataColumnResponseValidation.d.ts.map +1 -1
- package/lib/network/reqresp/utils/dataColumnResponseValidation.js +14 -9
- package/lib/network/reqresp/utils/dataColumnResponseValidation.js.map +1 -1
- package/lib/node/nodejs.d.ts +2 -1
- package/lib/node/nodejs.d.ts.map +1 -1
- package/lib/node/nodejs.js +4 -2
- package/lib/node/nodejs.js.map +1 -1
- package/lib/sync/range/range.d.ts.map +1 -1
- package/lib/sync/range/range.js +24 -1
- package/lib/sync/range/range.js.map +1 -1
- package/lib/util/sszBytes.d.ts +6 -0
- package/lib/util/sszBytes.d.ts.map +1 -1
- package/lib/util/sszBytes.js +1 -1
- package/lib/util/sszBytes.js.map +1 -1
- package/package.json +19 -20
- package/src/api/impl/beacon/blocks/index.ts +8 -14
- package/src/api/impl/beacon/state/utils.ts +15 -0
- package/src/api/impl/config/index.ts +4 -1
- package/src/api/impl/validator/index.ts +44 -43
- package/src/chain/archiveStore/archiveStore.ts +12 -1
- package/src/chain/archiveStore/historicalState/historicalStateRegen.ts +1 -0
- package/src/chain/archiveStore/historicalState/metrics.ts +14 -1
- package/src/chain/archiveStore/historicalState/types.ts +2 -0
- package/src/chain/archiveStore/historicalState/worker.ts +4 -1
- package/src/chain/archiveStore/utils/archiveBlocks.ts +73 -42
- package/src/chain/blocks/importBlock.ts +25 -20
- package/src/chain/blocks/index.ts +120 -23
- package/src/chain/blocks/types.ts +9 -0
- package/src/chain/blocks/utils/chainSegment.ts +26 -12
- package/src/chain/blocks/writeBlockInputToDb.ts +10 -17
- package/src/chain/chain.ts +153 -84
- package/src/chain/emitter.ts +1 -1
- package/src/chain/errors/blockError.ts +19 -10
- package/src/chain/errors/dataColumnSidecarError.ts +24 -8
- package/src/chain/errors/executionPayloadBid.ts +2 -0
- package/src/chain/errors/executionPayloadEnvelope.ts +14 -11
- package/src/chain/errors/gossipValidation.ts +1 -0
- package/src/chain/forkChoice/index.ts +2 -0
- package/src/chain/interface.ts +4 -4
- package/src/chain/lightClient/index.ts +32 -36
- package/src/chain/lightClient/proofs.ts +10 -0
- package/src/chain/opPools/aggregatedAttestationPool.ts +1 -1
- package/src/chain/prepareNextSlot.ts +21 -17
- package/src/chain/produceBlock/produceBlockBody.ts +62 -79
- package/src/chain/validation/block.ts +27 -72
- package/src/chain/validation/dataColumnSidecar.ts +47 -14
- package/src/chain/validation/executionPayloadBid.ts +62 -44
- package/src/chain/validation/executionPayloadEnvelope.ts +10 -37
- package/src/chain/validation/payloadAttestationMessage.ts +8 -9
- package/src/chain/validatorMonitor.ts +24 -7
- package/src/db/beacon.ts +33 -6
- package/src/db/dataColumnStore.ts +113 -0
- package/src/db/flatFileStore/atomicWrite.ts +65 -0
- package/src/db/flatFileStore/dcolFormat.ts +389 -0
- package/src/db/flatFileStore/errors.ts +53 -0
- package/src/db/flatFileStore/flatFileStore.ts +310 -0
- package/src/db/flatFileStore/index.ts +3 -0
- package/src/db/flatFileStore/interface.ts +21 -0
- package/src/db/flatFileStore/metrics.ts +48 -0
- package/src/db/flatFileStore/path.ts +32 -0
- package/src/db/flatFileStore/slotIndex.ts +56 -0
- package/src/db/flatFileStore/snappy.ts +14 -0
- package/src/db/index.ts +1 -0
- package/src/db/interface.ts +9 -1
- package/src/db/repositories/blockArchive.ts +89 -30
- package/src/db/repositories/blockArchiveIndex.ts +4 -9
- package/src/execution/builder/validateBid.ts +10 -6
- package/src/execution/engine/mock.ts +4 -1
- package/src/metrics/metrics/lodestar.ts +63 -6
- package/src/monitoring/clientStats.ts +1 -1
- package/src/network/gossip/encoding.ts +0 -7
- package/src/network/gossip/topic.ts +3 -25
- package/src/network/libp2p/index.ts +28 -1
- package/src/network/network.ts +2 -2
- package/src/network/processor/gossipHandlers.ts +500 -355
- package/src/network/processor/index.ts +287 -165
- package/src/network/reqresp/handlers/dataColumnSidecarsByRange.ts +139 -105
- package/src/network/reqresp/handlers/dataColumnSidecarsByRoot.ts +2 -0
- package/src/network/reqresp/protocols.ts +7 -24
- package/src/network/reqresp/rateLimit.ts +2 -1
- package/src/network/reqresp/utils/dataColumnResponseValidation.ts +15 -7
- package/src/node/nodejs.ts +6 -1
- package/src/sync/range/range.ts +23 -1
- package/src/util/sszBytes.ts +1 -1
|
@@ -133,40 +133,37 @@ type BidCandidate = {
|
|
|
133
133
|
};
|
|
134
134
|
|
|
135
135
|
/**
|
|
136
|
-
*
|
|
137
|
-
*
|
|
138
|
-
* p2p bid, and the earlier received bid between builder api bids.
|
|
136
|
+
* Ranking value of a bid, the boosted total payment scaled by 100 as `boostFactor` is a percentage.
|
|
137
|
+
* Kept scaled so bids that differ by less than a percent are not truncated into a tie.
|
|
139
138
|
*/
|
|
140
|
-
function
|
|
141
|
-
|
|
142
|
-
|
|
143
|
-
|
|
144
|
-
|
|
145
|
-
|
|
146
|
-
|
|
147
|
-
|
|
148
|
-
|
|
149
|
-
|
|
150
|
-
|
|
151
|
-
if (candidateIsMaxBoost !== bestIsMaxBoost) {
|
|
152
|
-
if (candidateIsMaxBoost) {
|
|
153
|
-
best = candidate;
|
|
154
|
-
}
|
|
155
|
-
continue;
|
|
156
|
-
}
|
|
157
|
-
const candidateValue = boostedValue(candidate);
|
|
158
|
-
const bestValue = boostedValue(best);
|
|
159
|
-
if (candidateValue > bestValue) {
|
|
160
|
-
best = candidate;
|
|
161
|
-
} else if (
|
|
162
|
-
candidateValue === bestValue &&
|
|
163
|
-
// A tie prefers a builder api bid over the p2p bid, and the earlier received bid otherwise
|
|
164
|
-
(best.url === undefined || (candidate.url !== undefined && candidate.receivedMs < best.receivedMs))
|
|
165
|
-
) {
|
|
166
|
-
best = candidate;
|
|
167
|
-
}
|
|
139
|
+
function getBoostedTotalScaled({totalGwei, boostFactor}: BidCandidate): bigint {
|
|
140
|
+
return boostFactor * totalGwei;
|
|
141
|
+
}
|
|
142
|
+
|
|
143
|
+
/** Order bid candidates by preference, best first, used to select a bid and to log the ranking */
|
|
144
|
+
function compareBidCandidates(a: BidCandidate, b: BidCandidate): number {
|
|
145
|
+
// Preserve max boost preference before comparing bid values
|
|
146
|
+
const aIsMaxBoost = a.boostFactor === MAX_BUILDER_BOOST_FACTOR;
|
|
147
|
+
const bIsMaxBoost = b.boostFactor === MAX_BUILDER_BOOST_FACTOR;
|
|
148
|
+
if (aIsMaxBoost !== bIsMaxBoost) {
|
|
149
|
+
return aIsMaxBoost ? -1 : 1;
|
|
168
150
|
}
|
|
169
|
-
|
|
151
|
+
|
|
152
|
+
const aBoostedTotal = getBoostedTotalScaled(a);
|
|
153
|
+
const bBoostedTotal = getBoostedTotalScaled(b);
|
|
154
|
+
if (aBoostedTotal !== bBoostedTotal) {
|
|
155
|
+
return aBoostedTotal > bBoostedTotal ? -1 : 1;
|
|
156
|
+
}
|
|
157
|
+
|
|
158
|
+
// A tie prefers a builder api bid over the p2p bid
|
|
159
|
+
const aIsBuilderApi = a.url !== undefined;
|
|
160
|
+
const bIsBuilderApi = b.url !== undefined;
|
|
161
|
+
if (aIsBuilderApi !== bIsBuilderApi) {
|
|
162
|
+
return aIsBuilderApi ? -1 : 1;
|
|
163
|
+
}
|
|
164
|
+
|
|
165
|
+
// and the earlier received bid between builder api bids
|
|
166
|
+
return a.receivedMs - b.receivedMs;
|
|
170
167
|
}
|
|
171
168
|
|
|
172
169
|
type ProduceBlockContentsRes = {executionPayloadValue: Wei; consensusBlockValue: Wei} & {
|
|
@@ -1049,20 +1046,24 @@ export function getValidatorApi(
|
|
|
1049
1046
|
});
|
|
1050
1047
|
}
|
|
1051
1048
|
|
|
1052
|
-
|
|
1053
|
-
|
|
1054
|
-
|
|
1049
|
+
if (candidates.length === 0) {
|
|
1050
|
+
return null;
|
|
1051
|
+
}
|
|
1052
|
+
|
|
1053
|
+
const rankedCandidates = candidates.toSorted(compareBidCandidates);
|
|
1054
|
+
for (const [index, candidate] of rankedCandidates.entries()) {
|
|
1055
|
+
logger.debug("Builder bid candidate", {
|
|
1055
1056
|
slot,
|
|
1056
|
-
|
|
1057
|
-
|
|
1058
|
-
|
|
1059
|
-
|
|
1060
|
-
|
|
1061
|
-
|
|
1062
|
-
|
|
1057
|
+
rank: index + 1,
|
|
1058
|
+
source: candidate.url !== undefined ? toPrintableUrl(candidate.url) : "p2p",
|
|
1059
|
+
builder: candidate.signedBid.message.builderIndex,
|
|
1060
|
+
total: prettyGweiToEth(candidate.totalGwei),
|
|
1061
|
+
boost: candidate.boostFactor,
|
|
1062
|
+
boosted: prettyGweiToEth(getBoostedTotalScaled(candidate) / 100n),
|
|
1063
|
+
receivedMs: candidate.receivedMs,
|
|
1063
1064
|
});
|
|
1064
1065
|
}
|
|
1065
|
-
return
|
|
1066
|
+
return rankedCandidates[0];
|
|
1066
1067
|
})();
|
|
1067
1068
|
|
|
1068
1069
|
const commonBlockBodyPromise = chain.produceCommonBlockBody({
|
|
@@ -1,5 +1,6 @@
|
|
|
1
1
|
import {CheckpointWithHex} from "@lodestar/fork-choice";
|
|
2
2
|
import {LoggerNode} from "@lodestar/logger/node";
|
|
3
|
+
import {SLOTS_PER_EPOCH} from "@lodestar/params";
|
|
3
4
|
import {Checkpoint} from "@lodestar/types/phase0";
|
|
4
5
|
import {callFnWhenAwait} from "@lodestar/utils";
|
|
5
6
|
import {IBeaconDb} from "../../db/index.js";
|
|
@@ -24,7 +25,11 @@ type ArchiveStoreModules = {
|
|
|
24
25
|
metrics: Metrics | null;
|
|
25
26
|
};
|
|
26
27
|
|
|
27
|
-
type ArchiveStoreInitOpts = ArchiveStoreOpts & {
|
|
28
|
+
type ArchiveStoreInitOpts = ArchiveStoreOpts & {
|
|
29
|
+
dbName: string;
|
|
30
|
+
dataColumnDir: string;
|
|
31
|
+
anchorState: {finalizedCheckpoint: Checkpoint};
|
|
32
|
+
};
|
|
28
33
|
|
|
29
34
|
export enum ArchiveStoreTask {
|
|
30
35
|
ArchiveBlocks = "archive_blocks",
|
|
@@ -120,6 +125,7 @@ export class ArchiveStore {
|
|
|
120
125
|
opts: {
|
|
121
126
|
genesisTime: this.chain.clock.genesisTime,
|
|
122
127
|
dbLocation: this.opts.dbName,
|
|
128
|
+
dataColumnDir: this.opts.dataColumnDir,
|
|
123
129
|
nativeStateView: this.opts.nativeStateView ?? false,
|
|
124
130
|
},
|
|
125
131
|
config: this.chain.config,
|
|
@@ -208,6 +214,9 @@ export class ArchiveStore {
|
|
|
208
214
|
const finalizedEpoch = finalized.epoch;
|
|
209
215
|
this.logger.verbose("Start processing finalized checkpoint", {epoch: finalizedEpoch, rootHex: finalized.rootHex});
|
|
210
216
|
|
|
217
|
+
// we want to track late imported canonical blocks, but it's not nice to do it at syncig time
|
|
218
|
+
const isNodeSynced = this.chain.clock.currentSlot - this.chain.forkChoice.getHead().slot <= SLOTS_PER_EPOCH;
|
|
219
|
+
|
|
211
220
|
let timer = this.metrics?.processFinalizedCheckpoint.durationByTask.startTimer();
|
|
212
221
|
await archiveBlocks(
|
|
213
222
|
this.chain.config,
|
|
@@ -217,6 +226,8 @@ export class ArchiveStore {
|
|
|
217
226
|
this.logger,
|
|
218
227
|
finalized,
|
|
219
228
|
this.chain.clock.currentEpoch,
|
|
229
|
+
this.metrics,
|
|
230
|
+
isNodeSynced,
|
|
220
231
|
this.archiveDataEpochs,
|
|
221
232
|
this.chain.opts.persistOrphanedBlocks,
|
|
222
233
|
this.chain.opts.persistOrphanedBlocksDir
|
|
@@ -33,6 +33,7 @@ export class HistoricalStateRegen implements HistoricalStateWorkerApi {
|
|
|
33
33
|
maxConcurrency: 1,
|
|
34
34
|
maxLength: 50,
|
|
35
35
|
dbLocation: modules.opts.dbLocation,
|
|
36
|
+
dataColumnDir: modules.opts.dataColumnDir,
|
|
36
37
|
metricsEnabled: Boolean(modules.metrics),
|
|
37
38
|
loggerOpts: modules.logger.toOpts(),
|
|
38
39
|
nativeStateView: modules.opts.nativeStateView,
|
|
@@ -1,7 +1,9 @@
|
|
|
1
1
|
import {ForkName} from "@lodestar/params";
|
|
2
2
|
import {
|
|
3
3
|
BeaconStateTransitionMetrics,
|
|
4
|
+
BlockProcessStep,
|
|
4
5
|
EpochTransitionStep,
|
|
6
|
+
ProcessOperationsStep,
|
|
5
7
|
ProposerRewardType,
|
|
6
8
|
StateCloneSource,
|
|
7
9
|
StateHashTreeRootSource,
|
|
@@ -70,10 +72,21 @@ export function createHistoricalStateTransitionMetrics(
|
|
|
70
72
|
processBlockTime: metricsRegister.histogram({
|
|
71
73
|
name: "lodestar_historical_state_stfn_process_block_seconds",
|
|
72
74
|
help: "Time to process a single block in seconds",
|
|
73
|
-
// TODO: Add metrics for each step
|
|
74
75
|
// Block processing can take 5-40ms, 100ms max
|
|
75
76
|
buckets: [0.005, 0.01, 0.02, 0.05, 0.1, 1],
|
|
76
77
|
}),
|
|
78
|
+
processBlockStepTime: metricsRegister.histogram<{step: BlockProcessStep}>({
|
|
79
|
+
name: "lodestar_historical_state_stfn_process_block_step_seconds",
|
|
80
|
+
help: "Time to call each step of process block in seconds",
|
|
81
|
+
labelNames: ["step"],
|
|
82
|
+
buckets: [0.001, 0.005, 0.01, 0.025, 0.05, 0.1],
|
|
83
|
+
}),
|
|
84
|
+
processOperationsStepTime: metricsRegister.histogram<{step: ProcessOperationsStep}>({
|
|
85
|
+
name: "lodestar_historical_state_stfn_process_operations_step_seconds",
|
|
86
|
+
help: "Time to call each step of process operations in seconds",
|
|
87
|
+
labelNames: ["step"],
|
|
88
|
+
buckets: [0.001, 0.005, 0.01, 0.025, 0.05, 0.1],
|
|
89
|
+
}),
|
|
77
90
|
processBlockCommitTime: metricsRegister.histogram({
|
|
78
91
|
name: "lodestar_historical_state_stfn_process_block_commit_seconds",
|
|
79
92
|
help: "Time to call commit after process a single block in seconds",
|
|
@@ -7,6 +7,7 @@ export type HistoricalStateRegenInitModules = {
|
|
|
7
7
|
opts: {
|
|
8
8
|
genesisTime: number;
|
|
9
9
|
dbLocation: string;
|
|
10
|
+
dataColumnDir: string;
|
|
10
11
|
nativeStateView: boolean;
|
|
11
12
|
};
|
|
12
13
|
config: BeaconConfig;
|
|
@@ -25,6 +26,7 @@ export type HistoricalStateWorkerData = {
|
|
|
25
26
|
maxConcurrency: number;
|
|
26
27
|
maxLength: number;
|
|
27
28
|
dbLocation: string;
|
|
29
|
+
dataColumnDir: string;
|
|
28
30
|
metricsEnabled: boolean;
|
|
29
31
|
loggerOpts: LoggerNodeOpts;
|
|
30
32
|
nativeStateView: boolean;
|
|
@@ -25,7 +25,10 @@ logger.info("Historical state worker started");
|
|
|
25
25
|
|
|
26
26
|
const config = createBeaconConfig(chainConfigFromJson(workerData.chainConfigJson), workerData.genesisValidatorsRoot);
|
|
27
27
|
|
|
28
|
-
const db = new BeaconDb(config, await LevelDbController.create({name: workerData.dbLocation}, {logger})
|
|
28
|
+
const db = new BeaconDb(config, await LevelDbController.create({name: workerData.dbLocation}, {logger}), {
|
|
29
|
+
dataColumnDir: workerData.dataColumnDir,
|
|
30
|
+
logger,
|
|
31
|
+
});
|
|
29
32
|
|
|
30
33
|
const abortController = new AbortController();
|
|
31
34
|
|
|
@@ -8,6 +8,7 @@ import {Epoch, Slot} from "@lodestar/types";
|
|
|
8
8
|
import {Logger, fromAsync, fromHex, prettyPrintIndices, toRootHex} from "@lodestar/utils";
|
|
9
9
|
import {IBeaconDb} from "../../../db/index.js";
|
|
10
10
|
import {BlockArchiveBatchPutBinaryItem} from "../../../db/repositories/index.js";
|
|
11
|
+
import {Metrics} from "../../../metrics/metrics.js";
|
|
11
12
|
import {ensureDir, writeIfNotExist} from "../../../util/file.js";
|
|
12
13
|
import {BlockRootHex} from "../../../util/sszBytes.js";
|
|
13
14
|
import {LightClientServer} from "../../lightClient/index.js";
|
|
@@ -20,6 +21,16 @@ const BLOB_SIDECAR_BATCH_SIZE = 32;
|
|
|
20
21
|
|
|
21
22
|
type BlockRootSlot = {slot: Slot; root: Uint8Array};
|
|
22
23
|
|
|
24
|
+
/**
|
|
25
|
+
* Why a finalized-canonical block was imported after the attestation cutoff.
|
|
26
|
+
*/
|
|
27
|
+
export enum LateCanonicalBlockReason {
|
|
28
|
+
// received on time, but finished importing after the attestation cutoff
|
|
29
|
+
SlowImport = "slow_import",
|
|
30
|
+
// block reached this node late on the network thread
|
|
31
|
+
LateReceive = "late_receive",
|
|
32
|
+
}
|
|
33
|
+
|
|
23
34
|
/**
|
|
24
35
|
* Persist orphaned block to disk
|
|
25
36
|
*/
|
|
@@ -54,6 +65,8 @@ export async function archiveBlocks(
|
|
|
54
65
|
logger: Logger,
|
|
55
66
|
finalizedCheckpoint: CheckpointWithHex,
|
|
56
67
|
currentEpoch: Epoch,
|
|
68
|
+
metrics: Metrics | null,
|
|
69
|
+
isNodeSynced: boolean,
|
|
57
70
|
archiveDataEpochs?: number,
|
|
58
71
|
persistOrphanedBlocks?: boolean,
|
|
59
72
|
persistOrphanedBlocksDir?: string
|
|
@@ -76,6 +89,29 @@ export async function archiveBlocks(
|
|
|
76
89
|
|
|
77
90
|
const logCtx = {currentEpoch, finalizedEpoch: finalizedCheckpoint.epoch, finalizedRoot: finalizedCheckpoint.rootHex};
|
|
78
91
|
|
|
92
|
+
// `finalizedCanonicalBlocks` is newest -> oldest; its LAST element is the previous-finalized
|
|
93
|
+
// boundary block, already audited on the prior run, so exclude it to avoid double counting.
|
|
94
|
+
if (isNodeSynced && finalizedCanonicalBlocks.length > 1) {
|
|
95
|
+
const lateBlocks = finalizedCanonicalBlocks.slice(0, -1).filter((block) => !block.importedTimely);
|
|
96
|
+
if (lateBlocks.length > 0) {
|
|
97
|
+
let slowImport = 0;
|
|
98
|
+
for (const block of lateBlocks) {
|
|
99
|
+
// received late => late_receive; otherwise we had it on time but were slow to import => slow_import
|
|
100
|
+
const reason = block.timeliness ? LateCanonicalBlockReason.SlowImport : LateCanonicalBlockReason.LateReceive;
|
|
101
|
+
if (block.timeliness) slowImport++;
|
|
102
|
+
metrics?.importBlock.lateCanonicalBlock.inc({reason});
|
|
103
|
+
}
|
|
104
|
+
const lateSlots = lateBlocks.map((block) => block.slot).sort((a, b) => a - b);
|
|
105
|
+
logger.verbose("Late imported canonical blocks", {
|
|
106
|
+
...logCtx,
|
|
107
|
+
count: lateBlocks.length,
|
|
108
|
+
slowImport,
|
|
109
|
+
lateReceive: lateBlocks.length - slowImport,
|
|
110
|
+
slotRange: prettyPrintIndices(lateSlots),
|
|
111
|
+
});
|
|
112
|
+
}
|
|
113
|
+
}
|
|
114
|
+
|
|
79
115
|
if (finalizedCanonicalBlockRoots.length > 0) {
|
|
80
116
|
const migratedSlots = await migrateBlocksFromHotToColdDb(db, logger, finalizedCanonicalBlockRoots);
|
|
81
117
|
logger.verbose("Migrated blocks from hot DB to cold DB", {
|
|
@@ -98,6 +134,8 @@ export async function archiveBlocks(
|
|
|
98
134
|
logger.verbose("Migrated blobSidecars from hot DB to cold DB", {...logCtx, migratedEntries});
|
|
99
135
|
}
|
|
100
136
|
|
|
137
|
+
// Keep the normal LevelDB hot-to-cold flow for legacy columns. New columns are written
|
|
138
|
+
// directly to flat files, so this only moves fallback data left by older versions.
|
|
101
139
|
if (finalizedPostFulu) {
|
|
102
140
|
const migratedSlots = await migrateDataColumnSidecarsFromHotToColdDb(
|
|
103
141
|
config,
|
|
@@ -106,7 +144,7 @@ export async function archiveBlocks(
|
|
|
106
144
|
finalizedCanonicalBlocks,
|
|
107
145
|
currentEpoch
|
|
108
146
|
);
|
|
109
|
-
logger.verbose("Migrated dataColumnSidecars from hot DB to cold DB", {
|
|
147
|
+
logger.verbose("Migrated legacy dataColumnSidecars from hot DB to cold DB", {
|
|
110
148
|
...logCtx,
|
|
111
149
|
migratedEntries: migratedSlots.length,
|
|
112
150
|
slotRange: prettyPrintIndices(migratedSlots),
|
|
@@ -159,6 +197,23 @@ export async function archiveBlocks(
|
|
|
159
197
|
slotRange: prettyPrintIndices(nonCanonicalSlots),
|
|
160
198
|
};
|
|
161
199
|
|
|
200
|
+
const columnItems = finalizedNonCanonicalBlocks
|
|
201
|
+
// Gloas EMPTY and FULL variants share a block root. EMPTY has no sidecars, so deleting by its root could
|
|
202
|
+
// remove the canonical FULL variant's columns. Pre-Gloas blocks are always FULL.
|
|
203
|
+
.filter(
|
|
204
|
+
(summary) => config.getForkSeq(summary.slot) >= ForkSeq.fulu && summary.payloadStatus === PayloadStatus.FULL
|
|
205
|
+
)
|
|
206
|
+
.map((summary) => ({slot: summary.slot, blockRoot: summary.blockRoot}));
|
|
207
|
+
if (columnItems.length > 0) {
|
|
208
|
+
// Delete sidecars first so their block roots remain available to retry cleanup after a failure or crash.
|
|
209
|
+
await db.dataColumns.deleteMany(columnItems);
|
|
210
|
+
logger.verbose("Deleted non canonical data columns of blocks", {
|
|
211
|
+
...logCtx,
|
|
212
|
+
blocks: columnItems.length,
|
|
213
|
+
slotRange: prettyPrintIndices(columnItems.map(({slot}) => slot).sort((a, b) => a - b)),
|
|
214
|
+
});
|
|
215
|
+
}
|
|
216
|
+
|
|
162
217
|
await db.block.batchDelete(nonCanonicalBlockRoots);
|
|
163
218
|
logger.verbose("Deleted non canonical blocks from hot DB", nonCanonicalLogCtx);
|
|
164
219
|
|
|
@@ -167,11 +222,6 @@ export async function archiveBlocks(
|
|
|
167
222
|
logger.verbose("Deleted non canonical blobSidecars from hot DB", nonCanonicalLogCtx);
|
|
168
223
|
}
|
|
169
224
|
|
|
170
|
-
if (finalizedPostFulu) {
|
|
171
|
-
await db.dataColumnSidecar.deleteMany(nonCanonicalBlockRoots);
|
|
172
|
-
logger.verbose("Deleted non canonical dataColumnSidecars from hot DB", nonCanonicalLogCtx);
|
|
173
|
-
}
|
|
174
|
-
|
|
175
225
|
if (finalizedPostGloas) {
|
|
176
226
|
await db.executionPayloadEnvelope.batchDelete(nonCanonicalBlockRoots);
|
|
177
227
|
logger.verbose("Deleted non canonical executionPayloadEnvelopes from hot DB", nonCanonicalLogCtx);
|
|
@@ -209,23 +259,16 @@ export async function archiveBlocks(
|
|
|
209
259
|
);
|
|
210
260
|
const dataColumnSidecarsMinEpoch = currentEpoch - dataColumnSidecarsArchiveWindow;
|
|
211
261
|
if (dataColumnSidecarsMinEpoch >= config.FULU_FORK_EPOCH) {
|
|
212
|
-
const
|
|
213
|
-
|
|
214
|
-
|
|
215
|
-
});
|
|
216
|
-
// for each slot there could be multiple dataColumnSidecar, so we need to deduplicate it
|
|
217
|
-
const slotsToDelete = [...new Set(prefixedKeys.map(({prefix}) => prefix))].sort((a, b) => a - b);
|
|
218
|
-
|
|
219
|
-
if (slotsToDelete.length > 0) {
|
|
220
|
-
await db.dataColumnSidecarArchive.deleteMany(slotsToDelete);
|
|
262
|
+
const columnsPruneSlot = computeStartSlotAtEpoch(dataColumnSidecarsMinEpoch);
|
|
263
|
+
const prunedColumnSlots = await db.dataColumns.pruneBefore(columnsPruneSlot);
|
|
264
|
+
if (prunedColumnSlots.length > 0) {
|
|
221
265
|
logger.verbose("dataColumnSidecars prune", {
|
|
222
266
|
...logCtx,
|
|
223
|
-
slotRange: prettyPrintIndices(
|
|
224
|
-
numOfSlots:
|
|
225
|
-
totalNumOfSidecars: prefixedKeys.length,
|
|
267
|
+
slotRange: prettyPrintIndices(prunedColumnSlots),
|
|
268
|
+
numOfSlots: prunedColumnSlots.length,
|
|
226
269
|
});
|
|
227
270
|
} else {
|
|
228
|
-
logger.verbose(
|
|
271
|
+
logger.verbose("dataColumnSidecars prune: no entries before slot", {...logCtx, slot: columnsPruneSlot});
|
|
229
272
|
}
|
|
230
273
|
} else {
|
|
231
274
|
logger.verbose(
|
|
@@ -298,7 +341,7 @@ async function migrateBlocksFromHotToColdDb(db: IBeaconDb, logger: Logger, block
|
|
|
298
341
|
]);
|
|
299
342
|
for (const entry of canonicalBlockEntries) migratedSlots.push(entry.slot);
|
|
300
343
|
}
|
|
301
|
-
// Ancestor walk is newest
|
|
344
|
+
// Ancestor walk is newest to oldest; sort ascending so `prettyPrintIndices` renders cleanly.
|
|
302
345
|
return migratedSlots.sort((a, b) => a - b);
|
|
303
346
|
}
|
|
304
347
|
|
|
@@ -353,7 +396,6 @@ async function migrateBlobSidecarsFromHotToColdDb(
|
|
|
353
396
|
)
|
|
354
397
|
).filter((e): e is KeyValue<Slot, Uint8Array> => e !== null);
|
|
355
398
|
|
|
356
|
-
// put to blockArchive db and delete block db
|
|
357
399
|
await Promise.all([
|
|
358
400
|
db.blobSidecarsArchive.batchPutBinary(canonicalBlobSidecarsEntries),
|
|
359
401
|
db.blobSidecars.batchDelete(canonicalBlocks.map((block) => block.root)),
|
|
@@ -366,11 +408,9 @@ async function migrateBlobSidecarsFromHotToColdDb(
|
|
|
366
408
|
|
|
367
409
|
// TODO: This function can be simplified further by reducing layers of promises in a loop
|
|
368
410
|
/**
|
|
369
|
-
* Post-gloas the data columns of a Gloas block are tied to its execution payload envelope
|
|
370
|
-
*
|
|
371
|
-
* blocks only have a FULL variant, so the
|
|
372
|
-
* Blocks whose canonical variant is PENDING/EMPTY are skipped here — their columns will be picked
|
|
373
|
-
* up on a later run once the FULL variant appears in the ancestor walk.
|
|
411
|
+
* Post-gloas the data columns of a Gloas block are tied to its execution payload envelope.
|
|
412
|
+
* Columns only exist once the FULL variant of the block is in the proto-array. Pre-Gloas
|
|
413
|
+
* blocks only have a FULL variant, so the payload-status filter passes them all.
|
|
374
414
|
*/
|
|
375
415
|
async function migrateDataColumnSidecarsFromHotToColdDb(
|
|
376
416
|
config: ChainForkConfig,
|
|
@@ -392,32 +432,24 @@ async function migrateDataColumnSidecarsFromHotToColdDb(
|
|
|
392
432
|
if (batch.length === 0) break;
|
|
393
433
|
|
|
394
434
|
const promises: Promise<void>[] = [];
|
|
395
|
-
|
|
396
|
-
// load Buffer instead of ssz deserialized to improve performance
|
|
397
435
|
for (const block of batch) {
|
|
398
|
-
const
|
|
399
|
-
const blockEpoch = computeEpochAtSlot(blockSlot);
|
|
400
|
-
|
|
436
|
+
const blockEpoch = computeEpochAtSlot(block.slot);
|
|
401
437
|
if (
|
|
402
|
-
config.getForkSeq(
|
|
403
|
-
// if block is out of ${config.MIN_EPOCHS_FOR_DATA_COLUMN_SIDECARS_REQUESTS}, skip this step
|
|
438
|
+
config.getForkSeq(block.slot) < ForkSeq.fulu ||
|
|
404
439
|
blockEpoch < currentEpoch - config.MIN_EPOCHS_FOR_DATA_COLUMN_SIDECARS_REQUESTS
|
|
405
440
|
) {
|
|
406
441
|
continue;
|
|
407
442
|
}
|
|
408
443
|
|
|
409
|
-
// Here we assume the data column sidecars are already in the hot db
|
|
410
444
|
const dataColumnSidecarBytes = await fromAsync(db.dataColumnSidecar.valuesStreamBinary(block.root));
|
|
411
445
|
if (dataColumnSidecarBytes.length === 0) {
|
|
412
|
-
// Empty stream: either the block has no blobs, or columns were already archived on a
|
|
413
|
-
// previous run (boundary block). Nothing to migrate.
|
|
414
446
|
logger.debug("DataColumnSidecars in forkchoice but missing in hot db, could be already archived", {
|
|
415
447
|
slot: block.slot,
|
|
416
448
|
root: toRootHex(block.root),
|
|
417
449
|
});
|
|
418
450
|
continue;
|
|
419
451
|
}
|
|
420
|
-
logger.verbose("Migrated dataColumnSidecars for block", {
|
|
452
|
+
logger.verbose("Migrated legacy dataColumnSidecars for block", {
|
|
421
453
|
currentEpoch,
|
|
422
454
|
slot: block.slot,
|
|
423
455
|
root: toRootHex(block.root),
|
|
@@ -426,18 +458,17 @@ async function migrateDataColumnSidecarsFromHotToColdDb(
|
|
|
426
458
|
promises.push(
|
|
427
459
|
db.dataColumnSidecarArchive.putManyBinary(
|
|
428
460
|
block.slot,
|
|
429
|
-
dataColumnSidecarBytes.map((
|
|
461
|
+
dataColumnSidecarBytes.map((entry) => ({key: entry.id, value: entry.value}))
|
|
430
462
|
)
|
|
431
463
|
);
|
|
432
464
|
migratedSlots.push(block.slot);
|
|
433
465
|
}
|
|
434
466
|
|
|
435
|
-
promises.push(db.dataColumnSidecar.deleteMany(batch.map((block) => block.root)));
|
|
436
|
-
|
|
437
467
|
await Promise.all(promises);
|
|
468
|
+
await db.dataColumnSidecar.deleteMany(batch.map((block) => block.root));
|
|
438
469
|
}
|
|
439
470
|
|
|
440
|
-
// Ancestor walk is newest
|
|
471
|
+
// Ancestor walk is newest to oldest; sort ascending so `prettyPrintIndices` renders cleanly.
|
|
441
472
|
return migratedSlots.sort((a, b) => a - b);
|
|
442
473
|
}
|
|
443
474
|
|
|
@@ -485,7 +516,7 @@ async function migrateExecutionPayloadEnvelopesFromHotToColdDb(
|
|
|
485
516
|
]);
|
|
486
517
|
|
|
487
518
|
// Slots are ascending in hot-db key order — sort to guarantee `prettyPrintIndices` output is clean
|
|
488
|
-
// regardless of ancestor-walk order (newest
|
|
519
|
+
// regardless of ancestor-walk order (newest to oldest).
|
|
489
520
|
return envelopeEntries.map((entry) => entry.key).sort((a, b) => a - b);
|
|
490
521
|
}
|
|
491
522
|
|
|
@@ -25,7 +25,17 @@ import {
|
|
|
25
25
|
isStatePostAltair,
|
|
26
26
|
isStatePostBellatrix,
|
|
27
27
|
} from "@lodestar/state-transition";
|
|
28
|
-
import {
|
|
28
|
+
import {
|
|
29
|
+
Attestation,
|
|
30
|
+
BeaconBlock,
|
|
31
|
+
Epoch,
|
|
32
|
+
altair,
|
|
33
|
+
capella,
|
|
34
|
+
electra,
|
|
35
|
+
isGloasBeaconBlock,
|
|
36
|
+
phase0,
|
|
37
|
+
ssz,
|
|
38
|
+
} from "@lodestar/types";
|
|
29
39
|
import {isErrorAborted, toRootHex} from "@lodestar/utils";
|
|
30
40
|
import {GENESIS_SLOT, ZERO_HASH_HEX} from "../../constants/index.js";
|
|
31
41
|
import {callInNextEventLoop} from "../../util/eventLoop.js";
|
|
@@ -44,6 +54,15 @@ import {getCheckpointFromState} from "./utils/checkpoint.js";
|
|
|
44
54
|
* Fork-choice allows to import attestations from current (0) or past (1) epoch.
|
|
45
55
|
*/
|
|
46
56
|
const FORK_CHOICE_ATT_EPOCH_LIMIT = 1;
|
|
57
|
+
/**
|
|
58
|
+
* Whether the attestations of a block at `blockEpoch` are imported into fork choice
|
|
59
|
+
*/
|
|
60
|
+
export function importsBlockAttestations(opts: ImportBlockOpts, blockEpoch: Epoch, currentEpoch: Epoch): boolean {
|
|
61
|
+
return (
|
|
62
|
+
opts.importAttestations === AttestationImportOpt.Force ||
|
|
63
|
+
(opts.importAttestations !== AttestationImportOpt.Skip && blockEpoch >= currentEpoch - FORK_CHOICE_ATT_EPOCH_LIMIT)
|
|
64
|
+
);
|
|
65
|
+
}
|
|
47
66
|
/**
|
|
48
67
|
* Emit eventstream events for block contents events only for blocks that are recent enough to clock
|
|
49
68
|
*/
|
|
@@ -85,7 +104,7 @@ export async function importBlock(
|
|
|
85
104
|
const currentEpoch = computeEpochAtSlot(currentSlot);
|
|
86
105
|
const blockEpoch = computeEpochAtSlot(blockSlot);
|
|
87
106
|
const prevFinalizedEpoch = this.forkChoice.getFinalizedCheckpoint().epoch;
|
|
88
|
-
const
|
|
107
|
+
const receiveDelaySec =
|
|
89
108
|
fullyVerifiedBlock.seenTimestampSec - computeTimeAtSlot(this.config, blockSlot, postState.genesisTime);
|
|
90
109
|
const recvToValLatency = Date.now() / 1000 - (opts.seenTimestampSec ?? Date.now() / 1000);
|
|
91
110
|
const fork = this.config.getForkSeq(blockSlot);
|
|
@@ -122,10 +141,12 @@ export async function importBlock(
|
|
|
122
141
|
executionStatus = parentBlock.executionStatus;
|
|
123
142
|
}
|
|
124
143
|
|
|
144
|
+
const importDelaySec = this.clock.secFromSlot(blockSlot);
|
|
125
145
|
const blockSummary = this.forkChoice.onBlock(
|
|
126
146
|
block.message,
|
|
127
147
|
postState,
|
|
128
|
-
|
|
148
|
+
receiveDelaySec,
|
|
149
|
+
importDelaySec,
|
|
129
150
|
currentSlot,
|
|
130
151
|
executionStatus,
|
|
131
152
|
dataAvailabilityStatus
|
|
@@ -147,10 +168,7 @@ export async function importBlock(
|
|
|
147
168
|
// Only process attestations of blocks with relevant attestations for the fork-choice:
|
|
148
169
|
// If current epoch is N, and block is epoch X, block may include attestations for epoch X or X - 1.
|
|
149
170
|
// The latest block that is useful is at epoch N - 1 which may include attestations for epoch N - 1 or N - 2.
|
|
150
|
-
if (
|
|
151
|
-
opts.importAttestations === AttestationImportOpt.Force ||
|
|
152
|
-
(opts.importAttestations !== AttestationImportOpt.Skip && blockEpoch >= currentEpoch - FORK_CHOICE_ATT_EPOCH_LIMIT)
|
|
153
|
-
) {
|
|
171
|
+
if (importsBlockAttestations(opts, blockEpoch, currentEpoch)) {
|
|
154
172
|
const attestations = block.message.body.attestations;
|
|
155
173
|
const rootCache = new RootCache(postState);
|
|
156
174
|
const invalidAttestationErrorsByCode = new Map<string, {error: Error; count: number}>();
|
|
@@ -506,19 +524,6 @@ export async function importBlock(
|
|
|
506
524
|
this.metrics?.previousJustifiedEpoch.set(checkpointState.previousJustifiedCheckpoint.epoch);
|
|
507
525
|
this.metrics?.currentJustifiedEpoch.set(justifiedCheckpoint.epoch);
|
|
508
526
|
}
|
|
509
|
-
const finalizedCheckpoint = checkpointState.finalizedCheckpoint;
|
|
510
|
-
const finalizedEpoch = finalizedCheckpoint.epoch;
|
|
511
|
-
const preFinalizedEpoch = parentBlockSummary.finalizedEpoch;
|
|
512
|
-
if (finalizedEpoch > preFinalizedEpoch) {
|
|
513
|
-
this.emitter.emit(routes.events.EventType.finalizedCheckpoint, {
|
|
514
|
-
block: toRootHex(finalizedCheckpoint.root),
|
|
515
|
-
epoch: finalizedCheckpoint.epoch,
|
|
516
|
-
state: toRootHex(checkpointState.hashTreeRoot()),
|
|
517
|
-
executionOptimistic: false,
|
|
518
|
-
});
|
|
519
|
-
this.logger.verbose("Checkpoint finalized", toCheckpointHex(finalizedCheckpoint));
|
|
520
|
-
this.metrics?.finalizedEpoch.set(finalizedCheckpoint.epoch);
|
|
521
|
-
}
|
|
522
527
|
}
|
|
523
528
|
}
|
|
524
529
|
|