@lodestar/beacon-node 1.50.0-rc.0 → 1.51.0-dev.02c5a19f35
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 +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 +133 -27
- package/lib/api/impl/validator/index.js.map +1 -1
- package/lib/chain/ColumnReconstructionTracker.d.ts +11 -13
- package/lib/chain/ColumnReconstructionTracker.d.ts.map +1 -1
- package/lib/chain/ColumnReconstructionTracker.js +49 -44
- package/lib/chain/ColumnReconstructionTracker.js.map +1 -1
- package/lib/chain/archiveStore/utils/archiveBlocks.d.ts.map +1 -1
- package/lib/chain/archiveStore/utils/archiveBlocks.js +4 -5
- package/lib/chain/archiveStore/utils/archiveBlocks.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/blockInput/utils.js +2 -2
- package/lib/chain/blocks/blockInput/utils.js.map +1 -1
- package/lib/chain/blocks/importBlock.js +10 -6
- 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 +50 -2
- package/lib/chain/blocks/importExecutionPayload.js.map +1 -1
- 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/chain.d.ts +2 -1
- package/lib/chain/chain.d.ts.map +1 -1
- package/lib/chain/chain.js +8 -3
- 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 +3 -2
- 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/prepareNextSlot.d.ts.map +1 -1
- package/lib/chain/prepareNextSlot.js +4 -3
- 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 +3 -1
- package/lib/chain/produceBlock/produceBlockBody.d.ts.map +1 -1
- package/lib/chain/produceBlock/produceBlockBody.js +37 -15
- package/lib/chain/produceBlock/produceBlockBody.js.map +1 -1
- package/lib/chain/regen/interface.d.ts +1 -0
- package/lib/chain/regen/interface.d.ts.map +1 -1
- package/lib/chain/regen/interface.js +1 -0
- package/lib/chain/regen/interface.js.map +1 -1
- package/lib/chain/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.map +1 -1
- package/lib/chain/seenCache/seenGossipBlockInput.js +1 -1
- package/lib/chain/seenCache/seenGossipBlockInput.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/validation/executionPayloadBid.d.ts.map +1 -1
- package/lib/chain/validation/executionPayloadBid.js +33 -1
- 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/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/repositories/blockArchive.js +2 -2
- package/lib/db/repositories/blockArchive.js.map +1 -1
- package/lib/db/repositories/blockArchiveIndex.d.ts +1 -1
- 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/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/index.d.ts.map +1 -1
- package/lib/execution/engine/index.js +1 -1
- package/lib/execution/engine/index.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/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 +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 +5 -2
- package/lib/execution/engine/restTransport.d.ts.map +1 -1
- package/lib/execution/engine/restTransport.js +36 -21
- 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/transportMetrics.d.ts +5 -1
- package/lib/execution/engine/transportMetrics.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 +29 -15
- package/lib/execution/engine/types.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 +20 -0
- package/lib/metrics/metrics/lodestar.d.ts.map +1 -1
- package/lib/metrics/metrics/lodestar.js +51 -1
- package/lib/metrics/metrics/lodestar.js.map +1 -1
- package/lib/network/gossip/gossipsub.d.ts.map +1 -1
- package/lib/network/gossip/gossipsub.js +3 -1
- package/lib/network/gossip/gossipsub.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 -19
- 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 +63 -17
- 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 +40 -29
- 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/dataColumnSidecarsByRange.d.ts.map +1 -1
- package/lib/network/reqresp/handlers/dataColumnSidecarsByRange.js +4 -4
- package/lib/network/reqresp/handlers/dataColumnSidecarsByRange.js.map +1 -1
- package/lib/network/reqresp/handlers/dataColumnSidecarsByRoot.js +3 -3
- package/lib/network/reqresp/handlers/dataColumnSidecarsByRoot.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 +6 -2
- 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/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/notifier.d.ts.map +1 -1
- package/lib/node/notifier.js +12 -13
- package/lib/node/notifier.js.map +1 -1
- package/lib/sync/unknownBlock.d.ts.map +1 -1
- package/lib/sync/unknownBlock.js +45 -20
- package/lib/sync/unknownBlock.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/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 +30 -30
- package/src/api/impl/beacon/blocks/index.ts +10 -3
- 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 +173 -29
- package/src/chain/ColumnReconstructionTracker.ts +63 -46
- package/src/chain/archiveStore/utils/archiveBlocks.ts +6 -7
- package/src/chain/blocks/blockInput/blockInput.ts +1 -1
- package/src/chain/blocks/blockInput/utils.ts +2 -2
- package/src/chain/blocks/importBlock.ts +11 -11
- package/src/chain/blocks/importExecutionPayload.ts +68 -2
- package/src/chain/blocks/types.ts +5 -0
- package/src/chain/chain.ts +8 -2
- 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 +4 -1
- package/src/chain/opPools/inclusionListStore.ts +208 -0
- package/src/chain/opPools/index.ts +1 -0
- package/src/chain/prepareNextSlot.ts +7 -3
- package/src/chain/produceBlock/computeNewStateRoot.ts +9 -2
- package/src/chain/produceBlock/produceBlockBody.ts +70 -24
- package/src/chain/regen/interface.ts +1 -0
- package/src/chain/reprocess.ts +2 -1
- package/src/chain/seenCache/seenGossipBlockInput.ts +2 -1
- package/src/chain/stateCache/persistentCheckpointsCache.ts +4 -1
- package/src/chain/validation/executionPayloadBid.ts +52 -2
- package/src/chain/validation/inclusionList.ts +192 -0
- package/src/chain/validation/index.ts +1 -0
- package/src/chain/validatorMonitor.ts +7 -4
- package/src/constants/constants.ts +1 -0
- package/src/db/repositories/blockArchive.ts +2 -2
- package/src/db/repositories/blockArchiveIndex.ts +2 -3
- 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/index.ts +2 -1
- package/src/execution/engine/interface.ts +27 -3
- package/src/execution/engine/jsonRpcHttpClient.ts +12 -5
- 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 +68 -23
- package/src/execution/engine/transport.ts +7 -2
- package/src/execution/engine/transportMetrics.ts +2 -1
- package/src/execution/engine/types.ts +53 -16
- package/src/metrics/metrics/beacon.ts +37 -0
- package/src/metrics/metrics/lodestar.ts +53 -1
- package/src/network/gossip/gossipsub.ts +3 -1
- 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 +80 -20
- package/src/network/processor/gossipQueues/index.ts +6 -0
- package/src/network/processor/gossipValidatorFn.ts +5 -0
- package/src/network/processor/index.ts +36 -27
- package/src/network/processor/types.ts +1 -1
- package/src/network/reqresp/ReqRespBeaconNode.ts +7 -0
- package/src/network/reqresp/handlers/dataColumnSidecarsByRange.ts +4 -10
- package/src/network/reqresp/handlers/dataColumnSidecarsByRoot.ts +3 -3
- 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 +6 -2
- package/src/network/reqresp/types.ts +6 -0
- package/src/network/subnets/attnetsService.ts +8 -3
- package/src/node/notifier.ts +14 -13
- package/src/sync/unknownBlock.ts +50 -30
- package/src/util/clock.ts +3 -4
- package/src/util/sszBytes.ts +25 -12
|
@@ -3,7 +3,7 @@ import {ChainConfig} from "@lodestar/config";
|
|
|
3
3
|
import {PayloadStatus} from "@lodestar/fork-choice";
|
|
4
4
|
import {ForkSeq, GENESIS_SLOT, SLOTS_PER_HISTORICAL_ROOT} from "@lodestar/params";
|
|
5
5
|
import {RespStatus, ResponseError, ResponseOutgoing} from "@lodestar/reqresp";
|
|
6
|
-
import {computeEpochAtSlot} from "@lodestar/state-transition";
|
|
6
|
+
import {computeEpochAtSlot, getBlobDataRetentionStartEpoch} from "@lodestar/state-transition";
|
|
7
7
|
import {ColumnIndex, Epoch, RootHex, fulu} from "@lodestar/types";
|
|
8
8
|
import {fromHex, toRootHex} from "@lodestar/utils";
|
|
9
9
|
import {IBeaconChain} from "../../../chain/index.js";
|
|
@@ -216,16 +216,10 @@ export function validateDataColumnSidecarsByRangeRequest(
|
|
|
216
216
|
throw new ResponseError(RespStatus.INVALID_REQUEST, "startSlot < genesis");
|
|
217
217
|
}
|
|
218
218
|
|
|
219
|
-
// Spec: [max(current_epoch
|
|
220
|
-
const minimumRequestEpoch = Math.max(
|
|
221
|
-
currentEpoch - config.MIN_EPOCHS_FOR_DATA_COLUMN_SIDECARS_REQUESTS,
|
|
222
|
-
config.FULU_FORK_EPOCH
|
|
223
|
-
);
|
|
219
|
+
// Spec: [max(compute_blob_data_retention_start_epoch(current_epoch), FULU_FORK_EPOCH), current_epoch]
|
|
220
|
+
const minimumRequestEpoch = Math.max(getBlobDataRetentionStartEpoch(config, currentEpoch), config.FULU_FORK_EPOCH);
|
|
224
221
|
if (computeEpochAtSlot(startSlot) < minimumRequestEpoch) {
|
|
225
|
-
throw new ResponseError(
|
|
226
|
-
RespStatus.RESOURCE_UNAVAILABLE,
|
|
227
|
-
"startSlot is before MIN_EPOCHS_FOR_DATA_COLUMN_SIDECARS_REQUESTS"
|
|
228
|
-
);
|
|
222
|
+
throw new ResponseError(RespStatus.RESOURCE_UNAVAILABLE, "startSlot is before the blob data retention window");
|
|
229
223
|
}
|
|
230
224
|
|
|
231
225
|
if (count > config.MAX_REQUEST_BLOCKS_DENEB) {
|
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
import {PeerId} from "@libp2p/interface";
|
|
2
2
|
import {ResponseOutgoing} from "@lodestar/reqresp";
|
|
3
|
-
import {computeEpochAtSlot} from "@lodestar/state-transition";
|
|
3
|
+
import {computeEpochAtSlot, getBlobDataRetentionStartEpoch} from "@lodestar/state-transition";
|
|
4
4
|
import {ColumnIndex} from "@lodestar/types";
|
|
5
5
|
import {toRootHex} from "@lodestar/utils";
|
|
6
6
|
import {IBeaconChain} from "../../../chain/index.js";
|
|
@@ -19,10 +19,10 @@ export async function* onDataColumnSidecarsByRoot(
|
|
|
19
19
|
peerId: PeerId,
|
|
20
20
|
peerClient: string
|
|
21
21
|
): AsyncIterable<ResponseOutgoing> {
|
|
22
|
-
// SPEC: minimum_request_epoch = max(current_epoch
|
|
22
|
+
// SPEC: minimum_request_epoch = max(compute_blob_data_retention_start_epoch(current_epoch), FULU_FORK_EPOCH)
|
|
23
23
|
const currentEpoch = chain.clock.currentEpoch;
|
|
24
24
|
const minimumRequestEpoch = Math.max(
|
|
25
|
-
|
|
25
|
+
getBlobDataRetentionStartEpoch(chain.config, currentEpoch),
|
|
26
26
|
chain.config.FULU_FORK_EPOCH
|
|
27
27
|
);
|
|
28
28
|
|
|
@@ -0,0 +1,44 @@
|
|
|
1
|
+
import {PeerId} from "@libp2p/interface";
|
|
2
|
+
import {ResponseOutgoing} from "@lodestar/reqresp";
|
|
3
|
+
import {computeEpochAtSlot, computeStartSlotAtEpoch} from "@lodestar/state-transition";
|
|
4
|
+
import {heze, ssz} from "@lodestar/types";
|
|
5
|
+
import {toRootHex} from "@lodestar/utils";
|
|
6
|
+
import {IBeaconChain} from "../../../chain/index.js";
|
|
7
|
+
import {prettyPrintPeerId} from "../../util.js";
|
|
8
|
+
|
|
9
|
+
/**
|
|
10
|
+
* Only lists that passed gossip validation are stored and the store skips equivocators, so the spec's
|
|
11
|
+
* "SHOULD NOT respond with lists that fail gossip validation or are from equivocators" holds by construction.
|
|
12
|
+
*/
|
|
13
|
+
export async function* onInclusionListsByIndices(
|
|
14
|
+
requestBody: heze.InclusionListsByIndicesRequest,
|
|
15
|
+
chain: IBeaconChain,
|
|
16
|
+
peerId: PeerId,
|
|
17
|
+
peerClient: string
|
|
18
|
+
): AsyncIterable<ResponseOutgoing> {
|
|
19
|
+
const {slot, dependentRoot, indices} = requestBody;
|
|
20
|
+
|
|
21
|
+
const minimumRequestSlot = Math.max(
|
|
22
|
+
chain.clock.currentSlot - chain.config.MIN_SLOTS_FOR_INCLUSION_LISTS_REQUESTS,
|
|
23
|
+
computeStartSlotAtEpoch(chain.config.HEZE_FORK_EPOCH)
|
|
24
|
+
);
|
|
25
|
+
if (slot < minimumRequestSlot) {
|
|
26
|
+
chain.logger.debug("Cannot serve InclusionListsByIndices: slot below minimum request slot", {
|
|
27
|
+
slot,
|
|
28
|
+
minimumRequestSlot,
|
|
29
|
+
peer: prettyPrintPeerId(peerId),
|
|
30
|
+
client: peerClient,
|
|
31
|
+
});
|
|
32
|
+
return;
|
|
33
|
+
}
|
|
34
|
+
|
|
35
|
+
const signedInclusionLists = chain.inclusionListStore.getByIndices(slot, toRootHex(dependentRoot), indices);
|
|
36
|
+
|
|
37
|
+
const boundary = chain.config.getForkBoundaryAtEpoch(computeEpochAtSlot(slot));
|
|
38
|
+
for (const signedInclusionList of signedInclusionLists.slice(0, chain.config.MAX_REQUEST_INCLUSION_LIST)) {
|
|
39
|
+
yield {
|
|
40
|
+
data: ssz.heze.SignedInclusionList.serialize(signedInclusionList),
|
|
41
|
+
boundary,
|
|
42
|
+
};
|
|
43
|
+
}
|
|
44
|
+
}
|
|
@@ -19,6 +19,7 @@ import {onDataColumnSidecarsByRange} from "./dataColumnSidecarsByRange.js";
|
|
|
19
19
|
import {onDataColumnSidecarsByRoot} from "./dataColumnSidecarsByRoot.js";
|
|
20
20
|
import {onExecutionPayloadEnvelopesByRange} from "./executionPayloadEnvelopesByRange.js";
|
|
21
21
|
import {onExecutionPayloadEnvelopesByRoot} from "./executionPayloadEnvelopesByRoot.js";
|
|
22
|
+
import {onInclusionListsByIndices} from "./inclusionListsByIndices.js";
|
|
22
23
|
import {onLightClientBootstrap} from "./lightClientBootstrap.js";
|
|
23
24
|
import {onLightClientFinalityUpdate} from "./lightClientFinalityUpdate.js";
|
|
24
25
|
import {onLightClientOptimisticUpdate} from "./lightClientOptimisticUpdate.js";
|
|
@@ -142,6 +143,10 @@ export function getReqRespHandlers({db, chain}: {db: IBeaconDb; chain: IBeaconCh
|
|
|
142
143
|
},
|
|
143
144
|
[ReqRespMethod.LightClientFinalityUpdate]: () => onLightClientFinalityUpdate(chain),
|
|
144
145
|
[ReqRespMethod.LightClientOptimisticUpdate]: () => onLightClientOptimisticUpdate(chain),
|
|
146
|
+
[ReqRespMethod.InclusionListsByIndices]: (req, peerId, peerClient) => {
|
|
147
|
+
const body = deserializeRequestBody(ssz.heze.InclusionListsByIndicesRequest, req.data);
|
|
148
|
+
return onInclusionListsByIndices(body, chain, peerId, peerClient);
|
|
149
|
+
},
|
|
145
150
|
};
|
|
146
151
|
|
|
147
152
|
return (method) => handlers[method];
|
|
@@ -113,6 +113,12 @@ export const ExecutionPayloadEnvelopesByRange = toProtocol({
|
|
|
113
113
|
contextBytesType: ContextBytesType.ForkDigest,
|
|
114
114
|
});
|
|
115
115
|
|
|
116
|
+
export const InclusionListsByIndices = toProtocol({
|
|
117
|
+
method: ReqRespMethod.InclusionListsByIndices,
|
|
118
|
+
version: Version.V1,
|
|
119
|
+
contextBytesType: ContextBytesType.ForkDigest,
|
|
120
|
+
});
|
|
121
|
+
|
|
116
122
|
export const LightClientBootstrap = toProtocol({
|
|
117
123
|
method: ReqRespMethod.LightClientBootstrap,
|
|
118
124
|
version: Version.V1,
|
|
@@ -107,12 +107,16 @@ export const rateLimitQuotas: (fork: ForkName, config: BeaconConfig) => Record<R
|
|
|
107
107
|
[ReqRespMethod.LightClientFinalityUpdate]: {
|
|
108
108
|
// Finality updates should not be requested more than once per epoch.
|
|
109
109
|
// Allow 2 per slot and a very safe bound until there's more testing of real usage.
|
|
110
|
-
byPeer: {quota: 2, quotaTimeMs:
|
|
110
|
+
byPeer: {quota: 2, quotaTimeMs: config.getSlotDurationMs(fork)},
|
|
111
|
+
},
|
|
112
|
+
[ReqRespMethod.InclusionListsByIndices]: {
|
|
113
|
+
// Peers only backfill what gossip missed, so a small per-slot allowance is enough
|
|
114
|
+
byPeer: {quota: 5, quotaTimeMs: config.getSlotDurationMs(fork)},
|
|
111
115
|
},
|
|
112
116
|
[ReqRespMethod.LightClientOptimisticUpdate]: {
|
|
113
117
|
// Optimistic updates should not be requested more than once per slot.
|
|
114
118
|
// Allow 2 per slot and a very safe bound until there's more testing of real usage.
|
|
115
|
-
byPeer: {quota: 2, quotaTimeMs:
|
|
119
|
+
byPeer: {quota: 2, quotaTimeMs: config.getSlotDurationMs(fork)},
|
|
116
120
|
},
|
|
117
121
|
});
|
|
118
122
|
|
|
@@ -16,6 +16,7 @@ import {
|
|
|
16
16
|
deneb,
|
|
17
17
|
fulu,
|
|
18
18
|
gloas,
|
|
19
|
+
heze,
|
|
19
20
|
phase0,
|
|
20
21
|
ssz,
|
|
21
22
|
sszTypesFor,
|
|
@@ -53,6 +54,7 @@ export enum ReqRespMethod {
|
|
|
53
54
|
LightClientUpdatesByRange = "light_client_updates_by_range",
|
|
54
55
|
LightClientFinalityUpdate = "light_client_finality_update",
|
|
55
56
|
LightClientOptimisticUpdate = "light_client_optimistic_update",
|
|
57
|
+
InclusionListsByIndices = "inclusion_lists_by_indices",
|
|
56
58
|
}
|
|
57
59
|
|
|
58
60
|
// To typesafe events to network
|
|
@@ -74,6 +76,7 @@ export type RequestBodyByMethod = {
|
|
|
74
76
|
[ReqRespMethod.LightClientUpdatesByRange]: altair.LightClientUpdatesByRange;
|
|
75
77
|
[ReqRespMethod.LightClientFinalityUpdate]: null;
|
|
76
78
|
[ReqRespMethod.LightClientOptimisticUpdate]: null;
|
|
79
|
+
[ReqRespMethod.InclusionListsByIndices]: heze.InclusionListsByIndicesRequest;
|
|
77
80
|
};
|
|
78
81
|
|
|
79
82
|
type ResponseBodyByMethod = {
|
|
@@ -96,6 +99,7 @@ type ResponseBodyByMethod = {
|
|
|
96
99
|
[ReqRespMethod.LightClientUpdatesByRange]: LightClientUpdate;
|
|
97
100
|
[ReqRespMethod.LightClientFinalityUpdate]: LightClientFinalityUpdate;
|
|
98
101
|
[ReqRespMethod.LightClientOptimisticUpdate]: LightClientOptimisticUpdate;
|
|
102
|
+
[ReqRespMethod.InclusionListsByIndices]: heze.SignedInclusionList;
|
|
99
103
|
};
|
|
100
104
|
|
|
101
105
|
/** Request SSZ type for each method and ForkName */
|
|
@@ -126,6 +130,7 @@ export const requestSszTypeByMethod: (
|
|
|
126
130
|
[ReqRespMethod.LightClientUpdatesByRange]: ssz.altair.LightClientUpdatesByRange,
|
|
127
131
|
[ReqRespMethod.LightClientFinalityUpdate]: null,
|
|
128
132
|
[ReqRespMethod.LightClientOptimisticUpdate]: null,
|
|
133
|
+
[ReqRespMethod.InclusionListsByIndices]: ssz.heze.InclusionListsByIndicesRequest,
|
|
129
134
|
});
|
|
130
135
|
|
|
131
136
|
export type ResponseTypeGetter<T> = (fork: ForkName, version: number) => Type<T>;
|
|
@@ -158,6 +163,7 @@ export const responseSszTypeByMethod: {[K in ReqRespMethod]: ResponseTypeGetter<
|
|
|
158
163
|
[ReqRespMethod.ExecutionPayloadEnvelopesByRange]: () => ssz.gloas.SignedExecutionPayloadEnvelope,
|
|
159
164
|
[ReqRespMethod.LightClientOptimisticUpdate]: (fork) =>
|
|
160
165
|
sszTypesFor(onlyPostAltairFork(fork)).LightClientOptimisticUpdate,
|
|
166
|
+
[ReqRespMethod.InclusionListsByIndices]: () => ssz.heze.SignedInclusionList,
|
|
161
167
|
};
|
|
162
168
|
|
|
163
169
|
function onlyPostAltairFork(fork: ForkName): ForkPostAltair {
|
|
@@ -3,6 +3,7 @@ import {ATTESTATION_SUBNET_COUNT, SLOTS_PER_EPOCH} from "@lodestar/params";
|
|
|
3
3
|
import {computeEpochAtSlot} from "@lodestar/state-transition";
|
|
4
4
|
import {Epoch, Slot, SubnetID, ssz} from "@lodestar/types";
|
|
5
5
|
import {Logger, MapDef} from "@lodestar/utils";
|
|
6
|
+
import {HALF_SLOT_BPS} from "../../constants/index.js";
|
|
6
7
|
import {ClockEvent, IClock} from "../../util/clock.js";
|
|
7
8
|
import {NetworkCoreMetrics} from "../core/metrics.js";
|
|
8
9
|
import {getActiveForkBoundaries} from "../forks.js";
|
|
@@ -163,9 +164,13 @@ export class AttnetsService implements IAttnetsService {
|
|
|
163
164
|
*/
|
|
164
165
|
private onSlot = (clockSlot: Slot): void => {
|
|
165
166
|
try {
|
|
166
|
-
|
|
167
|
-
|
|
168
|
-
|
|
167
|
+
const fork = this.config.getForkName(clockSlot);
|
|
168
|
+
setTimeout(
|
|
169
|
+
() => {
|
|
170
|
+
this.onHalfSlot(clockSlot);
|
|
171
|
+
},
|
|
172
|
+
this.config.getSlotComponentDurationMs(fork, HALF_SLOT_BPS)
|
|
173
|
+
);
|
|
169
174
|
|
|
170
175
|
for (const [dutiedSlot, dutiedInfo] of this.aggregatorSlotSubnet.entries()) {
|
|
171
176
|
if (dutiedSlot === clockSlot + this.opts.slotsToSubscribeBeforeAggregatorDuty) {
|
package/src/node/notifier.ts
CHANGED
|
@@ -5,6 +5,7 @@ import {
|
|
|
5
5
|
IBeaconStateView,
|
|
6
6
|
computeEpochAtSlot,
|
|
7
7
|
computeStartSlotAtEpoch,
|
|
8
|
+
computeTimeAtSlot,
|
|
8
9
|
isStatePostBellatrix,
|
|
9
10
|
} from "@lodestar/state-transition";
|
|
10
11
|
import {Epoch} from "@lodestar/types";
|
|
@@ -140,21 +141,21 @@ export async function runNodeNotifier(modules: NodeNotifierModules): Promise<voi
|
|
|
140
141
|
}
|
|
141
142
|
|
|
142
143
|
function timeToNextHalfSlot(config: BeaconConfig, chain: IBeaconChain, isFirstTime: boolean): number {
|
|
143
|
-
const
|
|
144
|
-
const
|
|
145
|
-
const
|
|
146
|
-
|
|
147
|
-
msFromGenesis < 0
|
|
148
|
-
? // For future genesis time, calculate time left in the slot
|
|
149
|
-
-msFromGenesis % msPerSlot
|
|
150
|
-
: // For past genesis time, calculate time until the next slot
|
|
151
|
-
msPerSlot - (msFromGenesis % msPerSlot);
|
|
144
|
+
const currentSlot = chain.clock.currentSlot;
|
|
145
|
+
const nextSlotTimeSec = computeTimeAtSlot(config, currentSlot + 1, chain.genesisTime);
|
|
146
|
+
const nowMs = Date.now();
|
|
147
|
+
|
|
152
148
|
if (isFirstTime) {
|
|
153
|
-
|
|
154
|
-
|
|
149
|
+
const currentSlotTimeSec = computeTimeAtSlot(config, currentSlot, chain.genesisTime);
|
|
150
|
+
const currentMidpointMs = ((currentSlotTimeSec + nextSlotTimeSec) / 2) * 1000;
|
|
151
|
+
if (currentMidpointMs > nowMs) {
|
|
152
|
+
return currentMidpointMs - nowMs;
|
|
153
|
+
}
|
|
155
154
|
}
|
|
156
|
-
|
|
157
|
-
|
|
155
|
+
|
|
156
|
+
const nextSlotEndTimeSec = computeTimeAtSlot(config, currentSlot + 2, chain.genesisTime);
|
|
157
|
+
const nextMidpointMs = ((nextSlotTimeSec + nextSlotEndTimeSec) / 2) * 1000;
|
|
158
|
+
return Math.max(0, nextMidpointMs - nowMs);
|
|
158
159
|
}
|
|
159
160
|
|
|
160
161
|
function getHeadExecutionInfo(
|
package/src/sync/unknownBlock.ts
CHANGED
|
@@ -300,10 +300,19 @@ export class BlockInputSync {
|
|
|
300
300
|
|
|
301
301
|
private onIncompletePayloadEnvelope = (data: ChainEventData[ChainEvent.incompletePayloadEnvelope]): void => {
|
|
302
302
|
try {
|
|
303
|
-
this.addByPayloadInput(data.payloadInput, data.peer);
|
|
304
|
-
this.
|
|
305
|
-
|
|
306
|
-
|
|
303
|
+
const isNewRoot = this.addByPayloadInput(data.payloadInput, data.peer);
|
|
304
|
+
const pendingPayload = this.pendingPayloads.get(data.payloadInput.blockRootHex);
|
|
305
|
+
if (
|
|
306
|
+
pendingPayload &&
|
|
307
|
+
pendingPayload.status !== PendingPayloadInputStatus.fetching &&
|
|
308
|
+
pendingPayload.status !== PendingPayloadInputStatus.processing
|
|
309
|
+
) {
|
|
310
|
+
this.triggerUnknownBlockSearch();
|
|
311
|
+
}
|
|
312
|
+
if (isNewRoot) {
|
|
313
|
+
this.metrics?.blockInputSync.requests.inc({type: PendingBlockType.INCOMPLETE_PAYLOAD_ENVELOPE});
|
|
314
|
+
this.metrics?.blockInputSync.payloadSource.inc({source: data.source});
|
|
315
|
+
}
|
|
307
316
|
} catch (e) {
|
|
308
317
|
this.logger.debug("Error handling incompletePayloadEnvelope event", {}, e as Error);
|
|
309
318
|
}
|
|
@@ -599,43 +608,44 @@ export class BlockInputSync {
|
|
|
599
608
|
return this.chain.seenPayloadEnvelopeInputCache.get(rootHex)?.slot;
|
|
600
609
|
}
|
|
601
610
|
|
|
602
|
-
private addByPayloadInput = (
|
|
603
|
-
payloadInput: PayloadEnvelopeInput,
|
|
604
|
-
peerIdStr?: PeerIdStr,
|
|
605
|
-
envelope?: gloas.SignedExecutionPayloadEnvelope
|
|
606
|
-
): void => {
|
|
611
|
+
private addByPayloadInput = (payloadInput: PayloadEnvelopeInput, peerIdStr?: PeerIdStr): boolean => {
|
|
607
612
|
if (this.knownBadBlocks.has(payloadInput.blockRootHex)) {
|
|
608
613
|
this.logger.debug("Ignoring payload input for known bad block root", {
|
|
609
614
|
slot: payloadInput.slot,
|
|
610
615
|
root: payloadInput.blockRootHex,
|
|
611
616
|
peerIdStr,
|
|
612
617
|
});
|
|
613
|
-
return;
|
|
618
|
+
return false;
|
|
614
619
|
}
|
|
615
620
|
|
|
616
|
-
|
|
617
|
-
|
|
618
|
-
|
|
619
|
-
|
|
620
|
-
|
|
621
|
+
let pendingPayload = this.pendingPayloads.get(payloadInput.blockRootHex);
|
|
622
|
+
const isNewRoot = pendingPayload === undefined;
|
|
623
|
+
// Envelope-only entries must go through reconciliation to validate their speculative envelope.
|
|
624
|
+
if (
|
|
625
|
+
!pendingPayload ||
|
|
626
|
+
pendingPayload.status === PendingPayloadInputStatus.pending ||
|
|
627
|
+
pendingPayload.status === PendingPayloadInputStatus.downloaded
|
|
628
|
+
) {
|
|
629
|
+
pendingPayload = this.toPendingPayloadInput(payloadInput, pendingPayload);
|
|
630
|
+
this.pendingPayloads.set(payloadInput.blockRootHex, pendingPayload);
|
|
631
|
+
|
|
632
|
+
this.logger.verbose("Added payloadInput to BlockInputSync.pendingPayloads", {
|
|
633
|
+
slot: payloadInput.slot,
|
|
634
|
+
root: payloadInput.blockRootHex,
|
|
635
|
+
delaySec: this.chain.clock.secFromSlot(payloadInput.slot),
|
|
636
|
+
});
|
|
637
|
+
}
|
|
621
638
|
|
|
622
639
|
if (peerIdStr && pendingPayload.peerIdStrings.size < MAX_PEERS_PER_ROOT) {
|
|
623
640
|
pendingPayload.peerIdStrings.add(peerIdStr);
|
|
624
641
|
}
|
|
625
642
|
|
|
626
|
-
this.pendingPayloads.set(payloadInput.blockRootHex, pendingPayload);
|
|
627
|
-
|
|
628
|
-
this.logger.verbose("Added payloadInput to BlockInputSync.pendingPayloads", {
|
|
629
|
-
slot: payloadInput.slot,
|
|
630
|
-
root: payloadInput.blockRootHex,
|
|
631
|
-
delaySec: this.chain.clock.secFromSlot(payloadInput.slot),
|
|
632
|
-
});
|
|
633
|
-
|
|
634
643
|
const prunedItemCount = pruneSetToMax(this.pendingPayloads, this.maxPendingBlocks);
|
|
635
644
|
if (prunedItemCount > 0) {
|
|
636
645
|
this.metrics?.blockInputSync.removedPayloads.inc({reason: DroppedItemReason.capacity}, prunedItemCount);
|
|
637
646
|
this.logger.verbose(`Pruned ${prunedItemCount} items from BlockInputSync.pendingPayloads`);
|
|
638
647
|
}
|
|
648
|
+
return isNewRoot;
|
|
639
649
|
};
|
|
640
650
|
|
|
641
651
|
private onPeerConnected = (data: NetworkEventData[NetworkEvent.peerConnected]): void => {
|
|
@@ -918,16 +928,17 @@ export class BlockInputSync {
|
|
|
918
928
|
* Poll unknown payloads of the current slot.
|
|
919
929
|
*/
|
|
920
930
|
private async pollPayloadsAtSlot(slot: Slot, signal: AbortSignal): Promise<void> {
|
|
931
|
+
const fork = this.config.getForkName(slot);
|
|
921
932
|
// fixed tick count so the loop cannot outlive its slot: for mainnet, it's 6 ticks
|
|
922
933
|
const tickCount = Math.floor(
|
|
923
|
-
(this.config.
|
|
934
|
+
(this.config.getSlotDurationMs(fork) - this.config.getPayloadDueMs(fork)) / PAYLOAD_POLL_INTERVAL_MS
|
|
924
935
|
);
|
|
925
936
|
// a root still missing on several ticks is searched on each of them, recorded once
|
|
926
937
|
const searchedRoots = new Set<RootHex>();
|
|
927
938
|
let polls = 0;
|
|
928
939
|
|
|
929
940
|
try {
|
|
930
|
-
await sleep(Math.max(0, this.config.getPayloadDueMs() - this.chain.clock.msFromSlot(slot)), signal);
|
|
941
|
+
await sleep(Math.max(0, this.config.getPayloadDueMs(fork) - this.chain.clock.msFromSlot(slot)), signal);
|
|
931
942
|
|
|
932
943
|
for (polls = 0; polls < tickCount; polls++) {
|
|
933
944
|
let importedCount = 0;
|
|
@@ -1266,6 +1277,9 @@ export class BlockInputSync {
|
|
|
1266
1277
|
}
|
|
1267
1278
|
|
|
1268
1279
|
const payloadInput = await this.chain.seenPayloadEnvelopeInputCache.getOrReload(rootHex);
|
|
1280
|
+
if (this.pendingPayloads.get(rootHex) !== pendingPayload) {
|
|
1281
|
+
return;
|
|
1282
|
+
}
|
|
1269
1283
|
if (!payloadInput) {
|
|
1270
1284
|
this.logger.debug("PayloadEnvelopeInput not yet reloadable for imported block, will retry", {
|
|
1271
1285
|
root: rootHex,
|
|
@@ -1277,6 +1291,9 @@ export class BlockInputSync {
|
|
|
1277
1291
|
const validationResult = await wrapError(
|
|
1278
1292
|
validateGossipExecutionPayloadEnvelope(this.chain, pendingPayload.envelope)
|
|
1279
1293
|
);
|
|
1294
|
+
if (this.pendingPayloads.get(rootHex) !== pendingPayload) {
|
|
1295
|
+
return;
|
|
1296
|
+
}
|
|
1280
1297
|
if (validationResult.err) {
|
|
1281
1298
|
this.logger.debug(
|
|
1282
1299
|
"Pending payload envelope failed validation after block import, refetching by root",
|
|
@@ -1344,14 +1361,13 @@ export class BlockInputSync {
|
|
|
1344
1361
|
payload.status = PendingPayloadInputStatus.fetching;
|
|
1345
1362
|
|
|
1346
1363
|
const res = await wrapError(this.fetchPayloadInput(payload));
|
|
1364
|
+
if (this.pendingPayloads.get(rootHex) !== payload) {
|
|
1365
|
+
this.logger.verbose("Dropping downloaded payload, entry changed during fetch", logCtx);
|
|
1366
|
+
return;
|
|
1367
|
+
}
|
|
1347
1368
|
if (!res.err) {
|
|
1348
1369
|
const pendingPayload = res.result;
|
|
1349
1370
|
const resultRootHex = getPayloadSyncCacheItemRootHex(pendingPayload);
|
|
1350
|
-
// finalization may have deleted this entry while we were awaiting the network, do not resurrect it via the set below
|
|
1351
|
-
if (!this.pendingPayloads.has(resultRootHex)) {
|
|
1352
|
-
this.logger.verbose("Dropping downloaded payload, entry pruned during fetch", logCtx);
|
|
1353
|
-
return;
|
|
1354
|
-
}
|
|
1355
1371
|
this.pendingPayloads.set(resultRootHex, pendingPayload);
|
|
1356
1372
|
const result = isPendingPayloadEnvelope(pendingPayload)
|
|
1357
1373
|
? DownloadResult.WaitingForBlock
|
|
@@ -1422,12 +1438,16 @@ export class BlockInputSync {
|
|
|
1422
1438
|
this.logger.debug("Processing downloaded payload", logCtx);
|
|
1423
1439
|
|
|
1424
1440
|
const res = await wrapError(this.chain.processExecutionPayload(pendingPayload.payloadInput));
|
|
1441
|
+
// The executionPayload event emitted during import usually removes the entry before this point
|
|
1425
1442
|
if (!res.err) {
|
|
1426
1443
|
this.logger.debug("Processed payload from unknown sync", logCtx);
|
|
1427
1444
|
this.pendingPayloads.delete(rootHex);
|
|
1428
1445
|
this.triggerUnknownBlockSearch();
|
|
1429
1446
|
return;
|
|
1430
1447
|
}
|
|
1448
|
+
if (this.pendingPayloads.get(rootHex) !== pendingPayload) {
|
|
1449
|
+
return;
|
|
1450
|
+
}
|
|
1431
1451
|
|
|
1432
1452
|
if (res.err instanceof PayloadError) {
|
|
1433
1453
|
switch (res.err.type.code) {
|
package/src/util/clock.ts
CHANGED
|
@@ -78,9 +78,9 @@ export class Clock extends EventEmitter implements IClock {
|
|
|
78
78
|
|
|
79
79
|
this.config = config;
|
|
80
80
|
this.genesisTime = genesisTime;
|
|
81
|
-
this.timeoutId = setTimeout(this.onNextSlot, this.msUntilNextSlot());
|
|
82
81
|
this.signal = signal;
|
|
83
82
|
this._currentSlot = getCurrentSlot(this.config, this.genesisTime);
|
|
83
|
+
this.timeoutId = setTimeout(this.onNextSlot, this.msUntilNextSlot());
|
|
84
84
|
this.signal.addEventListener("abort", () => clearTimeout(this.timeoutId), {once: true});
|
|
85
85
|
}
|
|
86
86
|
|
|
@@ -204,8 +204,7 @@ export class Clock extends EventEmitter implements IClock {
|
|
|
204
204
|
};
|
|
205
205
|
|
|
206
206
|
private msUntilNextSlot(): number {
|
|
207
|
-
const
|
|
208
|
-
|
|
209
|
-
return milliSecondsPerSlot - (diffInMilliSeconds % milliSecondsPerSlot);
|
|
207
|
+
const nextSlotTimeSec = computeTimeAtSlot(this.config, this._currentSlot + 1, this.genesisTime);
|
|
208
|
+
return Math.max(0, nextSlotTimeSec * 1000 - Date.now());
|
|
210
209
|
}
|
|
211
210
|
}
|
package/src/util/sszBytes.ts
CHANGED
|
@@ -6,10 +6,12 @@ import {
|
|
|
6
6
|
FIELD_ELEMENTS_PER_BLOB,
|
|
7
7
|
ForkName,
|
|
8
8
|
ForkPostDeneb,
|
|
9
|
+
ForkPostGloas,
|
|
9
10
|
ForkSeq,
|
|
10
11
|
MAX_COMMITTEES_PER_SLOT,
|
|
11
12
|
isForkPostElectra,
|
|
12
13
|
isForkPostGloas,
|
|
14
|
+
isForkPostHeze,
|
|
13
15
|
} from "@lodestar/params";
|
|
14
16
|
import {BLSSignature, CommitteeIndex, RootHex, Slot, ValidatorIndex, ssz} from "@lodestar/types";
|
|
15
17
|
|
|
@@ -57,6 +59,8 @@ const ATTESTATION_DATA_SIZE = 128;
|
|
|
57
59
|
// MAX_COMMITTEES_PER_SLOT is in bit, need to convert to byte
|
|
58
60
|
const COMMITTEE_BITS_SIZE = Math.max(Math.ceil(MAX_COMMITTEES_PER_SLOT / 8), 1);
|
|
59
61
|
const SIGNATURE_SIZE = 96;
|
|
62
|
+
// SyncAggregate is a fixed-size container, so minSize is its serialized size
|
|
63
|
+
const SYNC_AGGREGATE_SIZE = ssz.altair.SyncAggregate.minSize;
|
|
60
64
|
const SINGLE_ATTESTATION_ATTDATA_OFFSET = 8 + 8;
|
|
61
65
|
const SINGLE_ATTESTATION_SLOT_OFFSET = SINGLE_ATTESTATION_ATTDATA_OFFSET;
|
|
62
66
|
const SINGLE_ATTESTATION_COMMITTEE_INDEX_OFFSET = 0;
|
|
@@ -447,30 +451,39 @@ export function getParentRootFromSignedBeaconBlockSerialized(data: Uint8Array):
|
|
|
447
451
|
* BeaconBlockBody (GLOAS) fixed section before signedExecutionPayloadBid offset pointer:
|
|
448
452
|
* randaoReveal(96) + eth1Data(72) + graffiti(32)
|
|
449
453
|
* + proposerSlashings(4) + attesterSlashings(4) + attestations(4) + deposits(4) + voluntaryExits(4)
|
|
450
|
-
* + syncAggregate(
|
|
454
|
+
* + syncAggregate(SyncAggregate.minSize) + blsToExecutionChanges(4) = 384 bytes (mainnet preset)
|
|
451
455
|
*
|
|
452
|
-
*
|
|
456
|
+
* Heze body: randaoReveal(96) + graffiti(32) + proposerSlashings(4) + attesterSlashings(4) + attestations(4) + voluntaryExits(4) + syncAggregate(SyncAggregate.minSize) + blsToExecutionChanges(4) = 308 bytes (mainnet preset)
|
|
457
|
+
*
|
|
458
|
+
* The 4-byte pointer at byte 568 (= 184+384) for Gloas and 492 (= 184+308) for Heze (mainnet preset) gives the offset of SignedExecutionPayloadBid
|
|
453
459
|
* within BeaconBlockBody. parentBlockHash is at that bid's byte 100 (after offset+sig).
|
|
454
460
|
*/
|
|
455
461
|
// BeaconBlock body starts after: msg_offset(4) + sig(96) + slot(8) + proposer_index(8) + parent_root(32) + state_root(32) + body_offset_ptr(4)
|
|
456
462
|
const GLOAS_BODY_START_IN_SIGNED_BEACON_BLOCK =
|
|
457
463
|
VARIABLE_FIELD_OFFSET + SIGNATURE_SIZE + SLOT_SIZE + 8 + ROOT_SIZE + ROOT_SIZE + VARIABLE_FIELD_OFFSET; // = 184
|
|
458
|
-
const GLOAS_SIGNED_BID_OFFSET_POINTER_IN_BODY = 96 + 72 + 32 + 4 + 4 + 4 + 4 + 4 +
|
|
459
|
-
|
|
460
|
-
|
|
464
|
+
const GLOAS_SIGNED_BID_OFFSET_POINTER_IN_BODY = 96 + 72 + 32 + 4 + 4 + 4 + 4 + 4 + SYNC_AGGREGATE_SIZE + 4; // = 384 at mainnet preset
|
|
465
|
+
// Heze removes eth1Data (72 B) and the deposits offset (4 B) from the body fixed section
|
|
466
|
+
const HEZE_SIGNED_BID_OFFSET_POINTER_IN_BODY = GLOAS_SIGNED_BID_OFFSET_POINTER_IN_BODY - 72 - VARIABLE_FIELD_OFFSET; // = 308
|
|
461
467
|
// Within SignedExecutionPayloadBid, parentBlockHash is at byte 100 (msg_offset:4 + sig:96)
|
|
462
468
|
const PARENT_BLOCK_HASH_OFFSET_IN_SIGNED_BID = VARIABLE_FIELD_OFFSET + SIGNATURE_SIZE; // = 100
|
|
463
469
|
|
|
464
|
-
// CAUTION: update offsets if BeaconBlockBody fixed fields change after
|
|
465
|
-
export function getParentBlockHashFromGloasSignedBeaconBlockSerialized(
|
|
466
|
-
|
|
470
|
+
// CAUTION: update offsets if BeaconBlockBody fixed fields change after Heze
|
|
471
|
+
export function getParentBlockHashFromGloasSignedBeaconBlockSerialized(
|
|
472
|
+
data: Uint8Array,
|
|
473
|
+
fork: ForkPostGloas
|
|
474
|
+
): RootHex | null {
|
|
475
|
+
const bidOffsetPointer =
|
|
476
|
+
GLOAS_BODY_START_IN_SIGNED_BEACON_BLOCK +
|
|
477
|
+
(isForkPostHeze(fork) ? HEZE_SIGNED_BID_OFFSET_POINTER_IN_BODY : GLOAS_SIGNED_BID_OFFSET_POINTER_IN_BODY);
|
|
478
|
+
if (data.length < bidOffsetPointer + VARIABLE_FIELD_OFFSET) {
|
|
467
479
|
return null;
|
|
468
480
|
}
|
|
469
481
|
const bidOffset =
|
|
470
|
-
data[
|
|
471
|
-
|
|
472
|
-
|
|
473
|
-
|
|
482
|
+
(data[bidOffsetPointer] |
|
|
483
|
+
(data[bidOffsetPointer + 1] << 8) |
|
|
484
|
+
(data[bidOffsetPointer + 2] << 16) |
|
|
485
|
+
(data[bidOffsetPointer + 3] << 24)) >>>
|
|
486
|
+
0;
|
|
474
487
|
|
|
475
488
|
const parentBlockHashStart =
|
|
476
489
|
GLOAS_BODY_START_IN_SIGNED_BEACON_BLOCK + bidOffset + PARENT_BLOCK_HASH_OFFSET_IN_SIGNED_BID;
|