@lodestar/beacon-node 1.50.0-dev.45e4260336 → 1.50.0-dev.4b00f7bf39
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 +7 -2
- package/lib/api/impl/beacon/blocks/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 +28 -6
- package/lib/api/impl/beacon/state/index.js.map +1 -1
- package/lib/api/impl/debug/index.d.ts.map +1 -1
- package/lib/api/impl/debug/index.js +4 -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 +57 -17
- package/lib/api/impl/validator/index.js.map +1 -1
- package/lib/chain/ColumnReconstructionTracker.d.ts +0 -2
- package/lib/chain/ColumnReconstructionTracker.d.ts.map +1 -1
- package/lib/chain/ColumnReconstructionTracker.js +4 -5
- package/lib/chain/ColumnReconstructionTracker.js.map +1 -1
- package/lib/chain/archiveStore/archiveStore.d.ts +5 -0
- package/lib/chain/archiveStore/archiveStore.d.ts.map +1 -1
- package/lib/chain/archiveStore/archiveStore.js +13 -23
- package/lib/chain/archiveStore/archiveStore.js.map +1 -1
- package/lib/chain/archiveStore/utils/pruneHistory.d.ts +1 -1
- package/lib/chain/archiveStore/utils/pruneHistory.d.ts.map +1 -1
- package/lib/chain/archiveStore/utils/pruneHistory.js +2 -1
- package/lib/chain/archiveStore/utils/pruneHistory.js.map +1 -1
- package/lib/chain/beaconProposerCache.d.ts +6 -0
- package/lib/chain/beaconProposerCache.d.ts.map +1 -1
- package/lib/chain/beaconProposerCache.js +16 -0
- package/lib/chain/beaconProposerCache.js.map +1 -1
- package/lib/chain/blocks/blockInput/blockInput.d.ts +1 -1
- package/lib/chain/blocks/blockInput/blockInput.d.ts.map +1 -1
- package/lib/chain/blocks/blockInput/blockInput.js.map +1 -1
- package/lib/chain/blocks/importBlock.d.ts.map +1 -1
- package/lib/chain/blocks/importBlock.js +21 -12
- package/lib/chain/blocks/importBlock.js.map +1 -1
- package/lib/chain/blocks/verifyBlock.d.ts.map +1 -1
- package/lib/chain/blocks/verifyBlock.js +6 -6
- package/lib/chain/blocks/verifyBlock.js.map +1 -1
- package/lib/chain/chain.d.ts +3 -1
- package/lib/chain/chain.d.ts.map +1 -1
- package/lib/chain/chain.js +58 -21
- package/lib/chain/chain.js.map +1 -1
- package/lib/chain/interface.d.ts +3 -1
- package/lib/chain/interface.d.ts.map +1 -1
- package/lib/chain/opPools/aggregatedAttestationPool.d.ts +4 -2
- package/lib/chain/opPools/aggregatedAttestationPool.d.ts.map +1 -1
- package/lib/chain/opPools/aggregatedAttestationPool.js +30 -8
- package/lib/chain/opPools/aggregatedAttestationPool.js.map +1 -1
- package/lib/chain/opPools/opPool.d.ts.map +1 -1
- package/lib/chain/opPools/opPool.js +1 -23
- package/lib/chain/opPools/opPool.js.map +1 -1
- package/lib/chain/opPools/proposerPreferencesPool.d.ts +4 -0
- package/lib/chain/opPools/proposerPreferencesPool.d.ts.map +1 -1
- package/lib/chain/opPools/proposerPreferencesPool.js +13 -1
- package/lib/chain/opPools/proposerPreferencesPool.js.map +1 -1
- package/lib/chain/opPools/utils.d.ts +11 -0
- package/lib/chain/opPools/utils.d.ts.map +1 -1
- package/lib/chain/opPools/utils.js +22 -0
- package/lib/chain/opPools/utils.js.map +1 -1
- package/lib/chain/prepareNextSlot.d.ts.map +1 -1
- package/lib/chain/prepareNextSlot.js +15 -6
- package/lib/chain/prepareNextSlot.js.map +1 -1
- package/lib/chain/produceBlock/computeNewStateRoot.d.ts.map +1 -1
- package/lib/chain/produceBlock/computeNewStateRoot.js.map +1 -1
- package/lib/chain/produceBlock/produceBlockBody.d.ts +8 -0
- package/lib/chain/produceBlock/produceBlockBody.d.ts.map +1 -1
- package/lib/chain/produceBlock/produceBlockBody.js +48 -34
- package/lib/chain/produceBlock/produceBlockBody.js.map +1 -1
- package/lib/chain/reprocess.d.ts +2 -1
- package/lib/chain/reprocess.d.ts.map +1 -1
- package/lib/chain/reprocess.js +2 -1
- package/lib/chain/reprocess.js.map +1 -1
- package/lib/chain/seenCache/seenGossipBlockInput.d.ts +7 -0
- package/lib/chain/seenCache/seenGossipBlockInput.d.ts.map +1 -1
- package/lib/chain/seenCache/seenGossipBlockInput.js +22 -1
- package/lib/chain/seenCache/seenGossipBlockInput.js.map +1 -1
- package/lib/chain/shufflingCache.d.ts +18 -8
- package/lib/chain/shufflingCache.d.ts.map +1 -1
- package/lib/chain/shufflingCache.js +72 -18
- package/lib/chain/shufflingCache.js.map +1 -1
- package/lib/chain/stateCache/persistentCheckpointsCache.d.ts.map +1 -1
- package/lib/chain/stateCache/persistentCheckpointsCache.js +1 -1
- package/lib/chain/stateCache/persistentCheckpointsCache.js.map +1 -1
- package/lib/chain/validatorMonitor.d.ts.map +1 -1
- package/lib/chain/validatorMonitor.js +6 -4
- package/lib/chain/validatorMonitor.js.map +1 -1
- package/lib/constants/constants.d.ts +1 -0
- package/lib/constants/constants.d.ts.map +1 -1
- package/lib/constants/constants.js +1 -0
- package/lib/constants/constants.js.map +1 -1
- package/lib/db/beacon.d.ts +4 -1
- package/lib/db/beacon.d.ts.map +1 -1
- package/lib/db/beacon.js +6 -1
- package/lib/db/beacon.js.map +1 -1
- package/lib/db/buckets.d.ts +3 -1
- package/lib/db/buckets.d.ts.map +1 -1
- package/lib/db/buckets.js +2 -0
- package/lib/db/buckets.js.map +1 -1
- package/lib/db/interface.d.ts +4 -1
- package/lib/db/interface.d.ts.map +1 -1
- package/lib/db/repositories/blockArchive.js +2 -2
- package/lib/db/repositories/blockArchive.js.map +1 -1
- package/lib/db/repositories/blockArchiveIndex.d.ts +3 -3
- package/lib/db/repositories/blockArchiveIndex.d.ts.map +1 -1
- package/lib/db/repositories/blockArchiveIndex.js +1 -2
- package/lib/db/repositories/blockArchiveIndex.js.map +1 -1
- package/lib/db/repositories/earliestAvailableSlot.d.ts +11 -0
- package/lib/db/repositories/earliestAvailableSlot.d.ts.map +1 -0
- package/lib/db/repositories/earliestAvailableSlot.js +19 -0
- package/lib/db/repositories/earliestAvailableSlot.js.map +1 -0
- package/lib/db/repositories/index.d.ts +1 -0
- package/lib/db/repositories/index.d.ts.map +1 -1
- package/lib/db/repositories/index.js +1 -0
- package/lib/db/repositories/index.js.map +1 -1
- package/lib/db/repositories/proposerPreferences.d.ts +14 -0
- package/lib/db/repositories/proposerPreferences.d.ts.map +1 -0
- package/lib/db/repositories/proposerPreferences.js +21 -0
- package/lib/db/repositories/proposerPreferences.js.map +1 -0
- package/lib/execution/engine/blobVersionedHashes.d.ts +9 -0
- package/lib/execution/engine/blobVersionedHashes.d.ts.map +1 -0
- package/lib/execution/engine/blobVersionedHashes.js +74 -0
- package/lib/execution/engine/blobVersionedHashes.js.map +1 -0
- package/lib/execution/engine/http.d.ts +45 -13
- package/lib/execution/engine/http.d.ts.map +1 -1
- package/lib/execution/engine/http.js +236 -198
- package/lib/execution/engine/http.js.map +1 -1
- package/lib/execution/engine/index.d.ts +3 -2
- package/lib/execution/engine/index.d.ts.map +1 -1
- package/lib/execution/engine/index.js +33 -8
- package/lib/execution/engine/index.js.map +1 -1
- package/lib/execution/engine/interface.d.ts +1 -1
- package/lib/execution/engine/interface.d.ts.map +1 -1
- package/lib/execution/engine/jsonRpcHttpClient.d.ts.map +1 -1
- package/lib/execution/engine/jsonRpcHttpClient.js +14 -4
- package/lib/execution/engine/jsonRpcHttpClient.js.map +1 -1
- package/lib/execution/engine/jsonRpcTransport.d.ts +25 -0
- package/lib/execution/engine/jsonRpcTransport.d.ts.map +1 -0
- package/lib/execution/engine/jsonRpcTransport.js +158 -0
- package/lib/execution/engine/jsonRpcTransport.js.map +1 -0
- package/lib/execution/engine/restHttpClient.d.ts +71 -0
- package/lib/execution/engine/restHttpClient.d.ts.map +1 -0
- package/lib/execution/engine/restHttpClient.js +201 -0
- package/lib/execution/engine/restHttpClient.js.map +1 -0
- package/lib/execution/engine/restTransport.d.ts +48 -0
- package/lib/execution/engine/restTransport.d.ts.map +1 -0
- package/lib/execution/engine/restTransport.js +411 -0
- package/lib/execution/engine/restTransport.js.map +1 -0
- package/lib/execution/engine/sszTypes.d.ts +1261 -0
- package/lib/execution/engine/sszTypes.d.ts.map +1 -0
- package/lib/execution/engine/sszTypes.js +216 -0
- package/lib/execution/engine/sszTypes.js.map +1 -0
- package/lib/execution/engine/transport.d.ts +39 -0
- package/lib/execution/engine/transport.d.ts.map +1 -0
- package/lib/execution/engine/transport.js +2 -0
- package/lib/execution/engine/transport.js.map +1 -0
- package/lib/execution/engine/transportMetrics.d.ts +5 -1
- package/lib/execution/engine/transportMetrics.d.ts.map +1 -1
- package/lib/execution/engine/types.d.ts +2 -0
- package/lib/execution/engine/types.d.ts.map +1 -1
- package/lib/execution/engine/types.js +31 -63
- package/lib/execution/engine/types.js.map +1 -1
- package/lib/execution/engine/utils.d.ts.map +1 -1
- package/lib/execution/engine/utils.js +9 -2
- package/lib/execution/engine/utils.js.map +1 -1
- package/lib/metrics/metrics/lodestar.d.ts +14 -0
- package/lib/metrics/metrics/lodestar.d.ts.map +1 -1
- package/lib/metrics/metrics/lodestar.js +29 -1
- package/lib/metrics/metrics/lodestar.js.map +1 -1
- package/lib/network/core/events.d.ts +5 -1
- package/lib/network/core/events.d.ts.map +1 -1
- package/lib/network/core/events.js +8 -0
- package/lib/network/core/events.js.map +1 -1
- package/lib/network/gossip/topic.d.ts +0 -14
- package/lib/network/gossip/topic.d.ts.map +1 -1
- package/lib/network/processor/gossipHandlers.d.ts.map +1 -1
- package/lib/network/processor/gossipHandlers.js +60 -64
- package/lib/network/processor/gossipHandlers.js.map +1 -1
- package/lib/network/processor/index.js +3 -3
- package/lib/network/processor/index.js.map +1 -1
- package/lib/network/reqresp/rateLimit.js +2 -2
- package/lib/network/reqresp/rateLimit.js.map +1 -1
- package/lib/network/subnets/attnetsService.d.ts.map +1 -1
- package/lib/network/subnets/attnetsService.js +3 -1
- package/lib/network/subnets/attnetsService.js.map +1 -1
- package/lib/node/nodejs.d.ts +3 -1
- package/lib/node/nodejs.d.ts.map +1 -1
- package/lib/node/nodejs.js +2 -1
- package/lib/node/nodejs.js.map +1 -1
- package/lib/node/notifier.d.ts.map +1 -1
- package/lib/node/notifier.js +12 -13
- package/lib/node/notifier.js.map +1 -1
- package/lib/node/options.d.ts +3 -2
- package/lib/node/options.d.ts.map +1 -1
- package/lib/node/options.js +2 -2
- package/lib/node/options.js.map +1 -1
- package/lib/sync/range/batch.d.ts +5 -5
- package/lib/sync/range/batch.d.ts.map +1 -1
- package/lib/sync/range/batch.js +11 -17
- package/lib/sync/range/batch.js.map +1 -1
- package/lib/sync/range/chain.d.ts +4 -4
- package/lib/sync/range/chain.d.ts.map +1 -1
- package/lib/sync/range/chain.js +7 -5
- package/lib/sync/range/chain.js.map +1 -1
- package/lib/sync/range/range.d.ts.map +1 -1
- package/lib/sync/range/range.js +25 -11
- package/lib/sync/range/range.js.map +1 -1
- package/lib/sync/unknownBlock.d.ts +5 -2
- package/lib/sync/unknownBlock.d.ts.map +1 -1
- package/lib/sync/unknownBlock.js +47 -22
- package/lib/sync/unknownBlock.js.map +1 -1
- package/lib/sync/utils/downloadByRange.d.ts +38 -14
- package/lib/sync/utils/downloadByRange.d.ts.map +1 -1
- package/lib/sync/utils/downloadByRange.js +84 -39
- package/lib/sync/utils/downloadByRange.js.map +1 -1
- package/lib/util/asyncIterableToEvents.d.ts +10 -2
- package/lib/util/asyncIterableToEvents.d.ts.map +1 -1
- package/lib/util/asyncIterableToEvents.js +29 -3
- package/lib/util/asyncIterableToEvents.js.map +1 -1
- package/lib/util/clock.d.ts.map +1 -1
- package/lib/util/clock.js +3 -4
- package/lib/util/clock.js.map +1 -1
- package/lib/util/metadata.d.ts.map +1 -1
- package/lib/util/metadata.js +2 -1
- package/lib/util/metadata.js.map +1 -1
- package/lib/util/sszBytes.d.ts +2 -2
- package/lib/util/sszBytes.d.ts.map +1 -1
- package/lib/util/sszBytes.js +22 -14
- package/lib/util/sszBytes.js.map +1 -1
- package/package.json +17 -16
- package/src/api/impl/beacon/blocks/index.ts +10 -3
- package/src/api/impl/beacon/state/index.ts +43 -6
- package/src/api/impl/debug/index.ts +4 -0
- package/src/api/impl/validator/index.ts +78 -19
- package/src/chain/ColumnReconstructionTracker.ts +4 -6
- package/src/chain/archiveStore/archiveStore.ts +18 -24
- package/src/chain/archiveStore/utils/pruneHistory.ts +4 -1
- package/src/chain/beaconProposerCache.ts +19 -1
- package/src/chain/blocks/blockInput/blockInput.ts +1 -1
- package/src/chain/blocks/importBlock.ts +25 -11
- package/src/chain/blocks/verifyBlock.ts +7 -6
- package/src/chain/chain.ts +71 -20
- package/src/chain/interface.ts +4 -1
- package/src/chain/opPools/aggregatedAttestationPool.ts +34 -10
- package/src/chain/opPools/opPool.ts +1 -31
- package/src/chain/opPools/proposerPreferencesPool.ts +20 -1
- package/src/chain/opPools/utils.ts +31 -0
- package/src/chain/prepareNextSlot.ts +22 -6
- package/src/chain/produceBlock/computeNewStateRoot.ts +9 -2
- package/src/chain/produceBlock/produceBlockBody.ts +78 -39
- package/src/chain/reprocess.ts +2 -1
- package/src/chain/seenCache/seenGossipBlockInput.ts +25 -1
- package/src/chain/shufflingCache.ts +84 -22
- package/src/chain/stateCache/persistentCheckpointsCache.ts +4 -1
- package/src/chain/validatorMonitor.ts +7 -4
- package/src/constants/constants.ts +1 -0
- package/src/db/beacon.ts +6 -0
- package/src/db/buckets.ts +2 -0
- package/src/db/interface.ts +4 -0
- package/src/db/repositories/blockArchive.ts +2 -2
- package/src/db/repositories/blockArchiveIndex.ts +2 -3
- package/src/db/repositories/earliestAvailableSlot.ts +19 -0
- package/src/db/repositories/index.ts +1 -0
- package/src/db/repositories/proposerPreferences.ts +23 -0
- package/src/execution/engine/blobVersionedHashes.ts +72 -0
- package/src/execution/engine/http.ts +304 -271
- package/src/execution/engine/index.ts +42 -7
- package/src/execution/engine/interface.ts +1 -1
- package/src/execution/engine/jsonRpcHttpClient.ts +12 -5
- package/src/execution/engine/jsonRpcTransport.ts +247 -0
- package/src/execution/engine/restHttpClient.ts +269 -0
- package/src/execution/engine/restTransport.ts +575 -0
- package/src/execution/engine/sszTypes.ts +354 -0
- package/src/execution/engine/transport.ts +61 -0
- package/src/execution/engine/transportMetrics.ts +2 -1
- package/src/execution/engine/types.ts +42 -80
- package/src/execution/engine/utils.ts +12 -2
- package/src/metrics/metrics/lodestar.ts +30 -1
- package/src/network/core/events.ts +16 -1
- package/src/network/processor/gossipHandlers.ts +91 -77
- package/src/network/processor/index.ts +3 -3
- package/src/network/reqresp/rateLimit.ts +2 -2
- package/src/network/subnets/attnetsService.ts +8 -3
- package/src/node/nodejs.ts +4 -0
- package/src/node/notifier.ts +14 -13
- package/src/node/options.ts +10 -1
- package/src/sync/range/batch.ts +14 -19
- package/src/sync/range/chain.ts +9 -7
- package/src/sync/range/range.ts +26 -12
- package/src/sync/unknownBlock.ts +60 -23
- package/src/sync/utils/downloadByRange.ts +123 -58
- package/src/util/asyncIterableToEvents.ts +44 -5
- package/src/util/clock.ts +3 -4
- package/src/util/metadata.ts +2 -1
- package/src/util/sszBytes.ts +25 -12
|
@@ -5,6 +5,8 @@ import {
|
|
|
5
5
|
BUILDER_INDEX_SELF_BUILD,
|
|
6
6
|
ForkName,
|
|
7
7
|
ForkPostBellatrix,
|
|
8
|
+
ForkPostDeneb,
|
|
9
|
+
ForkPreDeneb,
|
|
8
10
|
ForkPreGloas,
|
|
9
11
|
ForkSeq,
|
|
10
12
|
GENESIS_SLOT,
|
|
@@ -111,14 +113,13 @@ import {
|
|
|
111
113
|
* Post this time, race execution and builder to pick whatever resolves first.
|
|
112
114
|
*
|
|
113
115
|
* Empirically the builder block resolves in ~1 second, and execution block resolves in <500 ms.
|
|
114
|
-
* A cutoff of 2 seconds gives enough time and if there are unexpected delays
|
|
115
|
-
* in time as proposals
|
|
116
|
+
* A cutoff of 1667 BPS (2 seconds for 12s slots) gives enough time and if there are unexpected delays
|
|
117
|
+
* it ensures we publish in time as proposals after the attestation deadline will likely be orphaned
|
|
118
|
+
* due to proposer boost reorg.
|
|
116
119
|
*
|
|
117
120
|
* TODO GLOAS: re-evaluate cutoff timing due to attestation deadline changes in gloas
|
|
118
121
|
*/
|
|
119
|
-
const
|
|
120
|
-
/** Overall timeout for execution and block production apis */
|
|
121
|
-
const BLOCK_PRODUCTION_RACE_TIMEOUT_MS = 12_000;
|
|
122
|
+
const BLOCK_PRODUCTION_RACE_CUTOFF_BPS = 1667;
|
|
122
123
|
/** Rejection message of the bid block branch when there is no viable bid to commit to */
|
|
123
124
|
const NO_BID_AVAILABLE = "No builder bid available";
|
|
124
125
|
|
|
@@ -167,8 +168,8 @@ function compareBidCandidates(a: BidCandidate, b: BidCandidate): number {
|
|
|
167
168
|
}
|
|
168
169
|
|
|
169
170
|
type ProduceBlockContentsRes = {executionPayloadValue: Wei; consensusBlockValue: Wei} & {
|
|
170
|
-
data: BlockContents
|
|
171
|
-
version:
|
|
171
|
+
data: BlockContents<ForkPreGloas>;
|
|
172
|
+
version: ForkPreGloas;
|
|
172
173
|
};
|
|
173
174
|
type ProduceBlindedBlockRes = {executionPayloadValue: Wei; consensusBlockValue: Wei} & {
|
|
174
175
|
data: BlindedBeaconBlock;
|
|
@@ -301,8 +302,8 @@ export function getValidatorApi(
|
|
|
301
302
|
*/
|
|
302
303
|
function msToNextEpoch(): number {
|
|
303
304
|
const nextEpoch = chain.clock.currentEpoch + 1;
|
|
304
|
-
const
|
|
305
|
-
const nextEpochStartSec = chain.genesisTime
|
|
305
|
+
const nextEpochSlot = computeStartSlotAtEpoch(nextEpoch);
|
|
306
|
+
const nextEpochStartSec = computeTimeAtSlot(config, nextEpochSlot, chain.genesisTime);
|
|
306
307
|
return nextEpochStartSec * 1000 - Date.now();
|
|
307
308
|
}
|
|
308
309
|
|
|
@@ -511,6 +512,10 @@ export function getValidatorApi(
|
|
|
511
512
|
parentBlock: ProtoBlock;
|
|
512
513
|
}
|
|
513
514
|
): Promise<ProduceBlockContentsRes & {shouldOverrideBuilder?: boolean}> {
|
|
515
|
+
const version = config.getForkName(slot);
|
|
516
|
+
if (isForkPostGloas(version)) {
|
|
517
|
+
throw Error(`produceEngineBlockContents called for post-gloas fork=${version}`);
|
|
518
|
+
}
|
|
514
519
|
const source = ProducedBlockSource.engine;
|
|
515
520
|
metrics?.blockProductionRequests.inc({source});
|
|
516
521
|
|
|
@@ -525,7 +530,6 @@ export function getValidatorApi(
|
|
|
525
530
|
feeRecipient,
|
|
526
531
|
commonBlockBodyPromise,
|
|
527
532
|
});
|
|
528
|
-
const version = config.getForkName(block.slot);
|
|
529
533
|
if (strictFeeRecipientCheck && feeRecipient && isForkPostBellatrix(version)) {
|
|
530
534
|
const blockFeeRecipient = toHex((block as bellatrix.BeaconBlock).body.executionPayload.feeRecipient);
|
|
531
535
|
if (blockFeeRecipient !== feeRecipient) {
|
|
@@ -563,7 +567,7 @@ export function getValidatorApi(
|
|
|
563
567
|
|
|
564
568
|
return {
|
|
565
569
|
data: {
|
|
566
|
-
block
|
|
570
|
+
block: block as BeaconBlock<ForkPostDeneb & ForkPreGloas>,
|
|
567
571
|
blobs: blobsBundle.blobs,
|
|
568
572
|
kzgProofs: blobsBundle.proofs,
|
|
569
573
|
},
|
|
@@ -574,7 +578,13 @@ export function getValidatorApi(
|
|
|
574
578
|
};
|
|
575
579
|
}
|
|
576
580
|
|
|
577
|
-
return {
|
|
581
|
+
return {
|
|
582
|
+
data: {block: block as BeaconBlock<ForkPreDeneb>},
|
|
583
|
+
version,
|
|
584
|
+
executionPayloadValue,
|
|
585
|
+
consensusBlockValue,
|
|
586
|
+
shouldOverrideBuilder,
|
|
587
|
+
};
|
|
578
588
|
} finally {
|
|
579
589
|
if (timer) timer({source});
|
|
580
590
|
}
|
|
@@ -680,17 +690,21 @@ export function getValidatorApi(
|
|
|
680
690
|
});
|
|
681
691
|
|
|
682
692
|
// Calculate cutoff time based on start of the slot
|
|
683
|
-
const cutoffMs = Math.max(
|
|
693
|
+
const cutoffMs = Math.max(
|
|
694
|
+
0,
|
|
695
|
+
config.getSlotComponentDurationMs(fork, BLOCK_PRODUCTION_RACE_CUTOFF_BPS) - chain.clock.msFromSlot(slot)
|
|
696
|
+
);
|
|
697
|
+
const blockProductionTimeoutMs = config.getSlotDurationMs(fork);
|
|
684
698
|
|
|
685
699
|
logger.verbose("Block production race (builder vs execution) starting", {
|
|
686
700
|
...loggerContext,
|
|
687
701
|
cutoffMs,
|
|
688
|
-
timeoutMs:
|
|
702
|
+
timeoutMs: blockProductionTimeoutMs,
|
|
689
703
|
});
|
|
690
704
|
|
|
691
705
|
const blockProductionRacePromise = resolveOrRacePromises([builderPromise, enginePromise], {
|
|
692
706
|
resolveTimeoutMs: cutoffMs,
|
|
693
|
-
raceTimeoutMs:
|
|
707
|
+
raceTimeoutMs: blockProductionTimeoutMs,
|
|
694
708
|
signal: controller.signal,
|
|
695
709
|
});
|
|
696
710
|
|
|
@@ -878,6 +892,10 @@ export function getValidatorApi(
|
|
|
878
892
|
|
|
879
893
|
return {
|
|
880
894
|
async produceBlockV3({slot, randaoReveal, graffiti, skipRandaoVerification, builderBoostFactor, ...opts}) {
|
|
895
|
+
const forkName = config.getForkName(slot);
|
|
896
|
+
if (isForkPostGloas(forkName)) {
|
|
897
|
+
throw new ApiError(400, `produceBlockV3 not supported for post-gloas fork=${forkName}, use produceBlockV4`);
|
|
898
|
+
}
|
|
881
899
|
const {data, ...meta} = await produceEngineOrBuilderBlock(
|
|
882
900
|
slot,
|
|
883
901
|
randaoReveal,
|
|
@@ -1095,7 +1113,10 @@ export function getValidatorApi(
|
|
|
1095
1113
|
|
|
1096
1114
|
// Calculate cutoff time based on start of the slot, ensures a slow local payload build does
|
|
1097
1115
|
// not delay the proposal when a builder bid block is available (and vice versa)
|
|
1098
|
-
const cutoffMs = Math.max(
|
|
1116
|
+
const cutoffMs = Math.max(
|
|
1117
|
+
0,
|
|
1118
|
+
config.getSlotComponentDurationMs(fork, BLOCK_PRODUCTION_RACE_CUTOFF_BPS) - chain.clock.msFromSlot(slot)
|
|
1119
|
+
);
|
|
1099
1120
|
|
|
1100
1121
|
// use abort controller to stop waiting for the bid block if the engine block will be selected
|
|
1101
1122
|
const controller = new AbortController();
|
|
@@ -1123,7 +1144,7 @@ export function getValidatorApi(
|
|
|
1123
1144
|
|
|
1124
1145
|
const [engineResult, bidBlockResult] = await resolveOrRacePromises([enginePromise, bidBlockPromise], {
|
|
1125
1146
|
resolveTimeoutMs: cutoffMs,
|
|
1126
|
-
raceTimeoutMs:
|
|
1147
|
+
raceTimeoutMs: config.getSlotDurationMs(fork),
|
|
1127
1148
|
signal: controller.signal,
|
|
1128
1149
|
});
|
|
1129
1150
|
|
|
@@ -1417,7 +1438,7 @@ export function getValidatorApi(
|
|
|
1417
1438
|
// Spec: set payload_present only if the envelope was seen before get_payload_due_ms()
|
|
1418
1439
|
// into the slot. Use the envelope's own arrival time (getPayloadEnvelopeSource), not
|
|
1419
1440
|
// the input's creation time.
|
|
1420
|
-
const payloadDueSec = config.getPayloadDueMs() / 1000;
|
|
1441
|
+
const payloadDueSec = config.getPayloadDueMs(fork) / 1000;
|
|
1421
1442
|
const payloadSeenSec =
|
|
1422
1443
|
payloadInput?.hasPayloadEnvelope() === true
|
|
1423
1444
|
? chain.clock.secFromSlot(slot, payloadInput.getPayloadEnvelopeSource().seenTimestampSec)
|
|
@@ -1494,8 +1515,9 @@ export function getValidatorApi(
|
|
|
1494
1515
|
const currentEpoch = currentEpochWithDisparity();
|
|
1495
1516
|
const nextEpoch = currentEpoch + 1;
|
|
1496
1517
|
const startSlot = computeStartSlotAtEpoch(epoch);
|
|
1518
|
+
const prepareFork = config.getForkName(computeStartSlotAtEpoch(nextEpoch) - 1);
|
|
1497
1519
|
const prepareNextSlotLookAheadMs =
|
|
1498
|
-
config.
|
|
1520
|
+
config.getSlotDurationMs(prepareFork) - config.getSlotComponentDurationMs(prepareFork, PREPARE_NEXT_SLOT_BPS);
|
|
1499
1521
|
const toNextEpochMs = msToNextEpoch();
|
|
1500
1522
|
const nearNextEpoch = toNextEpochMs < prepareNextSlotLookAheadMs;
|
|
1501
1523
|
// Post-Fulu the proposer lookahead is deterministic and known a full epoch ahead, so
|
|
@@ -1932,6 +1954,17 @@ export function getValidatorApi(
|
|
|
1932
1954
|
},
|
|
1933
1955
|
|
|
1934
1956
|
async prepareBeaconCommitteeSubnet({subscriptions}) {
|
|
1957
|
+
// The subscribing validators use this node for duties regardless of its sync state and
|
|
1958
|
+
// the subscription must not fail on the tracking, e.g. if the finalized state is unavailable
|
|
1959
|
+
try {
|
|
1960
|
+
await chain.updateAttachedValidators(
|
|
1961
|
+
chain.clock.currentEpoch,
|
|
1962
|
+
Array.from(new Set(subscriptions.map(({validatorIndex}) => validatorIndex)))
|
|
1963
|
+
);
|
|
1964
|
+
} catch (e) {
|
|
1965
|
+
logger.warn("Error tracking attached validators", {count: subscriptions.length}, e as Error);
|
|
1966
|
+
}
|
|
1967
|
+
|
|
1935
1968
|
notWhileSyncing(chain, sync.state);
|
|
1936
1969
|
|
|
1937
1970
|
await network.prepareBeaconCommitteeSubnets(
|
|
@@ -1995,6 +2028,13 @@ export function getValidatorApi(
|
|
|
1995
2028
|
},
|
|
1996
2029
|
|
|
1997
2030
|
async prepareBeaconProposer({proposers}) {
|
|
2031
|
+
if (isForkPostGloas(config.getForkName(chain.clock.currentSlot))) {
|
|
2032
|
+
throw new ApiError(
|
|
2033
|
+
410,
|
|
2034
|
+
"prepareBeaconProposer is no longer supported from gloas, submit signed proposer preferences via POST /eth/v1/validator/proposer_preferences instead"
|
|
2035
|
+
);
|
|
2036
|
+
}
|
|
2037
|
+
|
|
1998
2038
|
await chain.updateBeaconProposerData(chain.clock.currentEpoch, proposers);
|
|
1999
2039
|
},
|
|
2000
2040
|
|
|
@@ -2029,6 +2069,13 @@ export function getValidatorApi(
|
|
|
2029
2069
|
},
|
|
2030
2070
|
|
|
2031
2071
|
async registerValidator({registrations}) {
|
|
2072
|
+
if (isForkPostGloas(config.getForkName(chain.clock.currentSlot))) {
|
|
2073
|
+
throw new ApiError(
|
|
2074
|
+
410,
|
|
2075
|
+
"registerValidator is no longer supported from gloas, submit builder preferences via POST /eth/v1/validator/builder_preferences instead"
|
|
2076
|
+
);
|
|
2077
|
+
}
|
|
2078
|
+
|
|
2032
2079
|
if (!chain.executionBuilder) {
|
|
2033
2080
|
throw Error("External builder not configured");
|
|
2034
2081
|
}
|
|
@@ -2064,11 +2111,14 @@ export function getValidatorApi(
|
|
|
2064
2111
|
|
|
2065
2112
|
async submitProposerPreferences({signedProposerPreferences}) {
|
|
2066
2113
|
const failures: FailureList = [];
|
|
2114
|
+
// Preferences submitted here are signed by validators using this node, gossiped ones are not
|
|
2115
|
+
const attachedValidatorIndices: ValidatorIndex[] = [];
|
|
2067
2116
|
|
|
2068
2117
|
await Promise.all(
|
|
2069
2118
|
signedProposerPreferences.map(async (signed, i) => {
|
|
2070
2119
|
try {
|
|
2071
2120
|
await validateGossipProposerPreferences(chain, signed);
|
|
2121
|
+
attachedValidatorIndices.push(signed.message.validatorIndex);
|
|
2072
2122
|
|
|
2073
2123
|
chain.proposerPreferencesPool.add(signed);
|
|
2074
2124
|
await network.publishProposerPreferences(signed);
|
|
@@ -2084,6 +2134,7 @@ export function getValidatorApi(
|
|
|
2084
2134
|
};
|
|
2085
2135
|
|
|
2086
2136
|
if (e instanceof ProposerPreferencesError && e.type.code === ProposerPreferencesErrorCode.ALREADY_KNOWN) {
|
|
2137
|
+
attachedValidatorIndices.push(signed.message.validatorIndex);
|
|
2087
2138
|
logger.debug("Ignoring known signed proposer preferences", logCtx);
|
|
2088
2139
|
return;
|
|
2089
2140
|
}
|
|
@@ -2097,6 +2148,14 @@ export function getValidatorApi(
|
|
|
2097
2148
|
})
|
|
2098
2149
|
);
|
|
2099
2150
|
|
|
2151
|
+
if (attachedValidatorIndices.length > 0) {
|
|
2152
|
+
try {
|
|
2153
|
+
await chain.updateAttachedValidators(chain.clock.currentEpoch, attachedValidatorIndices);
|
|
2154
|
+
} catch (e) {
|
|
2155
|
+
logger.warn("Error tracking attached validators", {count: attachedValidatorIndices.length}, e as Error);
|
|
2156
|
+
}
|
|
2157
|
+
}
|
|
2158
|
+
|
|
2100
2159
|
if (failures.length > 0) {
|
|
2101
2160
|
throw new IndexedError("Error processing signed proposer preferences", failures);
|
|
2102
2161
|
}
|
|
@@ -42,16 +42,11 @@ export class ColumnReconstructionTracker {
|
|
|
42
42
|
/** Track if a reconstruction attempt is in-flight */
|
|
43
43
|
running = false;
|
|
44
44
|
|
|
45
|
-
private readonly minDelayMs: number;
|
|
46
|
-
private readonly maxDelayMs: number;
|
|
47
|
-
|
|
48
45
|
constructor(init: ColumnReconstructionTrackerInit) {
|
|
49
46
|
this.logger = init.logger;
|
|
50
47
|
this.emitter = init.emitter;
|
|
51
48
|
this.metrics = init.metrics;
|
|
52
49
|
this.config = init.config;
|
|
53
|
-
this.minDelayMs = this.config.getSlotComponentDurationMs(RECONSTRUCTION_DELAY_MIN_BPS);
|
|
54
|
-
this.maxDelayMs = this.config.getSlotComponentDurationMs(RECONSTRUCTION_DELAY_MAX_BPS);
|
|
55
50
|
}
|
|
56
51
|
|
|
57
52
|
triggerColumnReconstruction(input: BlockInputColumns | PayloadEnvelopeInput): void {
|
|
@@ -67,7 +62,10 @@ export class ColumnReconstructionTracker {
|
|
|
67
62
|
// just that it has been triggered for this block root.
|
|
68
63
|
this.running = true;
|
|
69
64
|
this.lastBlockRootHex = input.blockRootHex;
|
|
70
|
-
const
|
|
65
|
+
const fork = this.config.getForkName(input.slot);
|
|
66
|
+
const minDelayMs = this.config.getSlotComponentDurationMs(fork, RECONSTRUCTION_DELAY_MIN_BPS);
|
|
67
|
+
const maxDelayMs = this.config.getSlotComponentDurationMs(fork, RECONSTRUCTION_DELAY_MAX_BPS);
|
|
68
|
+
const delay = minDelayMs + Math.random() * (maxDelayMs - minDelayMs);
|
|
71
69
|
sleep(delay)
|
|
72
70
|
.then(() => {
|
|
73
71
|
const logCtx = {slot: input.slot, root: input.blockRootHex};
|
|
@@ -113,7 +113,9 @@ export class ArchiveStore {
|
|
|
113
113
|
this.logger,
|
|
114
114
|
this.metrics,
|
|
115
115
|
this.opts.anchorState.finalizedCheckpoint.epoch,
|
|
116
|
-
this.chain.clock.currentEpoch
|
|
116
|
+
this.chain.clock.currentEpoch,
|
|
117
|
+
this.statePruneFromSlot,
|
|
118
|
+
this.advanceEarliestAvailableSlot
|
|
117
119
|
),
|
|
118
120
|
() => this.logger.info("Still pruning historical data, please wait..."),
|
|
119
121
|
30_000,
|
|
@@ -122,26 +124,6 @@ export class ArchiveStore {
|
|
|
122
124
|
this.statePruneFromSlot = stateCutoffSlot;
|
|
123
125
|
}
|
|
124
126
|
|
|
125
|
-
// Initialize earliestAvailableSlot from the earliest block actually retained (after any pruning
|
|
126
|
-
// above), rather than the anchor state slot set in the constructor. On an in-place restart the DB
|
|
127
|
-
// still holds finalized history below the anchor; leaving the value at the anchor makes the node
|
|
128
|
-
// reject by_range requests (beacon_blocks, execution_payload_envelopes and data_column_sidecars
|
|
129
|
-
// all gate on this slot) for data it still retains. An empty archive (e.g. a fresh checkpoint
|
|
130
|
-
// sync with nothing below the anchor) leaves the constructor's anchor slot in place.
|
|
131
|
-
const earliestArchivedBlockSlot = await this.db.blockArchive.firstKey();
|
|
132
|
-
if (earliestArchivedBlockSlot != null) {
|
|
133
|
-
const oldEarliestAvailableSlot = this.chain.earliestAvailableSlot;
|
|
134
|
-
this.chain.earliestAvailableSlot = earliestArchivedBlockSlot;
|
|
135
|
-
this.logger.verbose("Initialized earliestAvailableSlot from retained block archive", {
|
|
136
|
-
oldEarliestAvailableSlot,
|
|
137
|
-
newEarliestAvailableSlot: earliestArchivedBlockSlot,
|
|
138
|
-
});
|
|
139
|
-
} else {
|
|
140
|
-
this.logger.verbose("Empty block archive on init, keeping anchor earliestAvailableSlot", {
|
|
141
|
-
earliestAvailableSlot: this.chain.earliestAvailableSlot,
|
|
142
|
-
});
|
|
143
|
-
}
|
|
144
|
-
|
|
145
127
|
if (this.opts.serveHistoricalState) {
|
|
146
128
|
this.historicalStateRegen = await HistoricalStateRegen.init({
|
|
147
129
|
opts: {
|
|
@@ -158,6 +140,18 @@ export class ArchiveStore {
|
|
|
158
140
|
}
|
|
159
141
|
}
|
|
160
142
|
|
|
143
|
+
/**
|
|
144
|
+
* The CLI owns the initial value; this only advances it during pruneHistory.
|
|
145
|
+
* Persisted before any deletion so a crash mid-prune never leaves the floor below deleted data.
|
|
146
|
+
*/
|
|
147
|
+
private advanceEarliestAvailableSlot = async (blockCutoffSlot: Slot): Promise<void> => {
|
|
148
|
+
const earliestAvailableSlot = Math.max(this.chain.earliestAvailableSlot, blockCutoffSlot);
|
|
149
|
+
if (earliestAvailableSlot !== this.chain.earliestAvailableSlot) {
|
|
150
|
+
await this.db.earliestAvailableSlot.set(earliestAvailableSlot);
|
|
151
|
+
this.chain.earliestAvailableSlot = earliestAvailableSlot;
|
|
152
|
+
}
|
|
153
|
+
};
|
|
154
|
+
|
|
161
155
|
async close(): Promise<void> {
|
|
162
156
|
await this.historicalStateRegen?.close();
|
|
163
157
|
}
|
|
@@ -259,17 +253,17 @@ export class ArchiveStore {
|
|
|
259
253
|
|
|
260
254
|
if (this.opts.pruneHistory) {
|
|
261
255
|
timer = this.metrics?.processFinalizedCheckpoint.durationByTask.startTimer();
|
|
262
|
-
const {
|
|
256
|
+
const {stateCutoffSlot} = await pruneHistory(
|
|
263
257
|
this.chain.config,
|
|
264
258
|
this.db,
|
|
265
259
|
this.logger,
|
|
266
260
|
this.metrics,
|
|
267
261
|
finalizedEpoch,
|
|
268
262
|
this.chain.clock.currentEpoch,
|
|
269
|
-
this.statePruneFromSlot
|
|
263
|
+
this.statePruneFromSlot,
|
|
264
|
+
this.advanceEarliestAvailableSlot
|
|
270
265
|
);
|
|
271
266
|
this.statePruneFromSlot = stateCutoffSlot;
|
|
272
|
-
this.chain.earliestAvailableSlot = Math.max(this.chain.earliestAvailableSlot, blockCutoffSlot);
|
|
273
267
|
timer?.({source: ArchiveStoreTask.PruneHistory});
|
|
274
268
|
}
|
|
275
269
|
|
|
@@ -12,7 +12,8 @@ export async function pruneHistory(
|
|
|
12
12
|
metrics: Metrics | null | undefined,
|
|
13
13
|
finalizedEpoch: Epoch,
|
|
14
14
|
currentEpoch: Epoch,
|
|
15
|
-
statePruneFromSlot: Slot
|
|
15
|
+
statePruneFromSlot: Slot,
|
|
16
|
+
beforePrune: (blockCutoffSlot: Slot) => Promise<void>
|
|
16
17
|
): Promise<{blockCutoffSlot: Slot; stateCutoffSlot: Slot}> {
|
|
17
18
|
const blockCutoffEpoch = Math.min(
|
|
18
19
|
// set by config, with underflow protection
|
|
@@ -51,6 +52,8 @@ export async function pruneHistory(
|
|
|
51
52
|
stateSlots: prettyPrintIndices(states),
|
|
52
53
|
});
|
|
53
54
|
|
|
55
|
+
await beforePrune(blockCutoffSlot);
|
|
56
|
+
|
|
54
57
|
const step1 = metrics?.pruneHistory.pruneKeys.startTimer();
|
|
55
58
|
await Promise.all([
|
|
56
59
|
// ->
|
|
@@ -6,7 +6,7 @@ const PROPOSER_PRESERVE_EPOCHS = 2;
|
|
|
6
6
|
export type ProposerPreparationData = routes.validator.ProposerPreparationData;
|
|
7
7
|
|
|
8
8
|
export class BeaconProposerCache {
|
|
9
|
-
private readonly feeRecipientByValidatorIndex: Map<number, {epoch: Epoch; feeRecipient
|
|
9
|
+
private readonly feeRecipientByValidatorIndex: Map<number, {epoch: Epoch; feeRecipient?: string}>;
|
|
10
10
|
constructor(readonly opts: {suggestedFeeRecipient: string}) {
|
|
11
11
|
this.feeRecipientByValidatorIndex = new Map();
|
|
12
12
|
}
|
|
@@ -15,6 +15,24 @@ export class BeaconProposerCache {
|
|
|
15
15
|
this.feeRecipientByValidatorIndex.set(validatorIndex, {epoch, feeRecipient});
|
|
16
16
|
}
|
|
17
17
|
|
|
18
|
+
/**
|
|
19
|
+
* Track a validator that uses this node for duties, keeping the fee recipient it may have
|
|
20
|
+
* registered. Returns true if the validator was not tracked before.
|
|
21
|
+
*/
|
|
22
|
+
track(epoch: Epoch, validatorIndex: number): boolean {
|
|
23
|
+
const entry = this.feeRecipientByValidatorIndex.get(validatorIndex);
|
|
24
|
+
if (entry !== undefined) {
|
|
25
|
+
entry.epoch = epoch;
|
|
26
|
+
return false;
|
|
27
|
+
}
|
|
28
|
+
this.feeRecipientByValidatorIndex.set(validatorIndex, {epoch});
|
|
29
|
+
return true;
|
|
30
|
+
}
|
|
31
|
+
|
|
32
|
+
has(validatorIndex: number): boolean {
|
|
33
|
+
return this.feeRecipientByValidatorIndex.has(validatorIndex);
|
|
34
|
+
}
|
|
35
|
+
|
|
18
36
|
prune(epoch: Epoch): void {
|
|
19
37
|
// This is not so optimized function, but could maintain a 2d array may be?
|
|
20
38
|
for (const [validatorIndex, feeRecipientEntry] of this.feeRecipientByValidatorIndex.entries()) {
|
|
@@ -210,7 +210,7 @@ export class BlockInputPreData extends AbstractBlockInput<ForkPreDeneb, null> {
|
|
|
210
210
|
this.blockPromise.resolve(state.block);
|
|
211
211
|
}
|
|
212
212
|
|
|
213
|
-
static createFromBlock(props: AddBlock & CreateBlockInputMeta): BlockInputPreData {
|
|
213
|
+
static createFromBlock(props: AddBlock<ForkPreDeneb> & CreateBlockInputMeta): BlockInputPreData {
|
|
214
214
|
const init: BlockInputInit = {
|
|
215
215
|
daOutOfRange: props.daOutOfRange,
|
|
216
216
|
timeCreated: props.seenTimestampSec,
|
|
@@ -22,6 +22,7 @@ import {
|
|
|
22
22
|
RootCache,
|
|
23
23
|
computeEpochAtSlot,
|
|
24
24
|
computeTimeAtSlot,
|
|
25
|
+
getBeaconCommittees,
|
|
25
26
|
isStatePostAltair,
|
|
26
27
|
isStatePostBellatrix,
|
|
27
28
|
} from "@lodestar/state-transition";
|
|
@@ -44,7 +45,7 @@ import {isQueueErrorAborted} from "../../util/queue/index.js";
|
|
|
44
45
|
import type {BeaconChain} from "../chain.js";
|
|
45
46
|
import {ChainEvent, ReorgEventData} from "../emitter.js";
|
|
46
47
|
import {ForkchoiceCaller} from "../forkChoice/index.js";
|
|
47
|
-
import {
|
|
48
|
+
import {REPROCESS_MIN_TIME_TO_NEXT_SLOT_BPS} from "../reprocess.js";
|
|
48
49
|
import {toCheckpointHex} from "../stateCache/persistentCheckpointsCache.js";
|
|
49
50
|
import {isBlockInputBlobs, isBlockInputColumns} from "./blockInput/blockInput.js";
|
|
50
51
|
import {AttestationImportOpt, FullyVerifiedBlock, ImportBlockOpts} from "./types.js";
|
|
@@ -129,11 +130,17 @@ export async function importBlock(
|
|
|
129
130
|
|
|
130
131
|
// Should compute checkpoint balances before forkchoice.onBlock
|
|
131
132
|
this.checkpointBalancesCache.processState(blockRootHex, postState);
|
|
132
|
-
if (
|
|
133
|
+
if (isGloasBeaconBlock(block.message)) {
|
|
134
|
+
// A gloas block has no payload of its own, it inherits the status of the payload it builds on,
|
|
135
|
+
// i.e. the parent variant matching the bid's parent block hash. The parent's default (PENDING)
|
|
136
|
+
// variant does not reflect a SYNCING parent payload, and onBlock would then mark that payload VALID.
|
|
133
137
|
const parentRootHex = toRootHex(block.message.parentRoot);
|
|
134
|
-
const
|
|
138
|
+
const parentBlockHashHex = toRootHex(block.message.body.signedExecutionPayloadBid.message.parentBlockHash);
|
|
139
|
+
const parentBlock = this.forkChoice.getBlockHexAndBlockHash(parentRootHex, parentBlockHashHex);
|
|
135
140
|
if (parentBlock === null) {
|
|
136
|
-
throw Error(
|
|
141
|
+
throw Error(
|
|
142
|
+
`Parent block not found in forkChoice, parentRoot=${parentRootHex} parentBlockHash=${parentBlockHashHex}`
|
|
143
|
+
);
|
|
137
144
|
}
|
|
138
145
|
if (parentBlock.executionStatus === ExecutionStatus.Invalid) {
|
|
139
146
|
throw Error(`Parent block has invalid execution status, parentRoot=${parentRootHex}`);
|
|
@@ -328,7 +335,8 @@ export async function importBlock(
|
|
|
328
335
|
this.metrics.headSlot.set(newHead.slot);
|
|
329
336
|
// Only track "recent" blocks. Otherwise sync can distort this metrics heavily.
|
|
330
337
|
// We want to track recent blocks coming from gossip, unknown block sync, and API.
|
|
331
|
-
|
|
338
|
+
const headFork = this.config.getForkName(newHead.slot);
|
|
339
|
+
if (delaySec < (SLOTS_PER_EPOCH * this.config.getSlotDurationMs(headFork)) / 1000) {
|
|
332
340
|
this.metrics.importBlock.elapsedTimeTillBecomeHead.observe(delaySec);
|
|
333
341
|
const cutOffSec = this.config.getAttestationDueMs(this.config.getForkName(blockSlot)) / 1000;
|
|
334
342
|
if (delaySec > cutOffSec) {
|
|
@@ -400,9 +408,8 @@ export async function importBlock(
|
|
|
400
408
|
const proposalSlot = blockSlot + 1;
|
|
401
409
|
try {
|
|
402
410
|
const proposerIndex = postState.getBeaconProposer(proposalSlot);
|
|
403
|
-
const feeRecipient = this.beaconProposerCache.get(proposerIndex);
|
|
404
411
|
|
|
405
|
-
if (
|
|
412
|
+
if (this.beaconProposerCache.has(proposerIndex)) {
|
|
406
413
|
// We would set this to true if
|
|
407
414
|
// 1) This is a gossip block
|
|
408
415
|
// 2) We are proposer of next slot
|
|
@@ -580,7 +587,7 @@ export async function importBlock(
|
|
|
580
587
|
this.validatorMonitor?.registerSyncAggregateInBlock(
|
|
581
588
|
blockEpoch,
|
|
582
589
|
(block as altair.SignedBeaconBlock).message.body.syncAggregate,
|
|
583
|
-
fullyVerifiedBlock.postState.
|
|
590
|
+
fullyVerifiedBlock.postState.currentSyncCommitteeValidatorIndices
|
|
584
591
|
);
|
|
585
592
|
}
|
|
586
593
|
|
|
@@ -594,7 +601,10 @@ export async function importBlock(
|
|
|
594
601
|
}
|
|
595
602
|
}
|
|
596
603
|
|
|
597
|
-
const
|
|
604
|
+
const reprocessGuardSec =
|
|
605
|
+
this.config.getSlotComponentDurationMs(this.config.getForkName(blockSlot), REPROCESS_MIN_TIME_TO_NEXT_SLOT_BPS) /
|
|
606
|
+
1000;
|
|
607
|
+
const advancedSlot = this.clock.slotWithFutureTolerance(reprocessGuardSec);
|
|
598
608
|
|
|
599
609
|
// Gossip blocks need to be imported as soon as possible, waiting attestations could be processed
|
|
600
610
|
// in the next event loop. See https://github.com/ChainSafe/lodestar/issues/4789
|
|
@@ -657,8 +667,12 @@ export function addAttestationPostElectra(
|
|
|
657
667
|
} else {
|
|
658
668
|
const attSlot = attestation.data.slot;
|
|
659
669
|
const attEpoch = computeEpochAtSlot(attSlot);
|
|
660
|
-
|
|
661
|
-
|
|
670
|
+
// calling getShufflingAtEpoch may take some time for NativeBeaconStateView
|
|
671
|
+
// we should have the shuffling inside ShufflingCache most of the time
|
|
672
|
+
const shuffling =
|
|
673
|
+
this.shufflingCache.getSync(attEpoch, state.getShufflingDecisionRoot(attEpoch)) ??
|
|
674
|
+
state.getShufflingAtEpoch(attEpoch);
|
|
675
|
+
const committees = getBeaconCommittees(shuffling, attSlot, committeeIndices);
|
|
662
676
|
const aggregationBools = attestation.aggregationBits.toBoolArray();
|
|
663
677
|
let offset = 0;
|
|
664
678
|
for (let i = 0; i < committees.length; i++) {
|
|
@@ -4,6 +4,7 @@ import {
|
|
|
4
4
|
DataAvailabilityStatus,
|
|
5
5
|
IBeaconStateView,
|
|
6
6
|
computeEpochAtSlot,
|
|
7
|
+
getIndexedAttestation,
|
|
7
8
|
signedBlockToSignedHeader,
|
|
8
9
|
} from "@lodestar/state-transition";
|
|
9
10
|
import {IndexedAttestation, Slot, deneb} from "@lodestar/types";
|
|
@@ -81,10 +82,6 @@ export async function verifyBlocksInEpoch(
|
|
|
81
82
|
throw new BlockError(block0, {code: BlockErrorCode.PRESTATE_MISSING, error: e as Error});
|
|
82
83
|
});
|
|
83
84
|
|
|
84
|
-
// in forky condition, make sure to populate ShufflingCache with regened state
|
|
85
|
-
// otherwise it may fail to get indexed attestations from shuffling cache later
|
|
86
|
-
this.shufflingCache.processState(preState0);
|
|
87
|
-
|
|
88
85
|
if (!preState0.isStateValidatorsNodesPopulated()) {
|
|
89
86
|
this.logger.verbose("verifyBlocksInEpoch preState0 SSZ cache stats", {
|
|
90
87
|
slot: preState0.slot,
|
|
@@ -117,8 +114,12 @@ export async function verifyBlocksInEpoch(
|
|
|
117
114
|
for (const [i, block] of blocks.entries()) {
|
|
118
115
|
indexedAttestationsByBlock[i] = block.message.body.attestations.map((attestation) => {
|
|
119
116
|
const attEpoch = computeEpochAtSlot(attestation.data.slot);
|
|
120
|
-
|
|
121
|
-
|
|
117
|
+
// calling getShufflingAtEpoch may take some time for NativeBeaconStateView
|
|
118
|
+
// we should have the shuffling inside ShufflingCache most of the time
|
|
119
|
+
const shuffling =
|
|
120
|
+
this.shufflingCache.getSync(attEpoch, preState0.getShufflingDecisionRoot(attEpoch)) ??
|
|
121
|
+
preState0.getShufflingAtEpoch(attEpoch);
|
|
122
|
+
return getIndexedAttestation(shuffling, fork, attestation);
|
|
122
123
|
});
|
|
123
124
|
}
|
|
124
125
|
|