@lodestar/beacon-node 1.35.0-dev.21ba2777a9 → 1.35.0-dev.287e63792e
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 +8 -2
- package/lib/api/impl/beacon/blocks/index.js.map +1 -1
- package/lib/api/impl/lodestar/index.js +1 -1
- package/lib/api/impl/lodestar/index.js.map +1 -1
- package/lib/api/impl/validator/index.d.ts.map +1 -1
- package/lib/api/impl/validator/index.js +22 -26
- package/lib/api/impl/validator/index.js.map +1 -1
- package/lib/chain/blocks/blockInput/blockInput.d.ts.map +1 -1
- package/lib/chain/blocks/blockInput/blockInput.js +3 -2
- 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 +7 -6
- package/lib/chain/blocks/importBlock.js.map +1 -1
- package/lib/chain/blocks/verifyBlocksDataAvailability.d.ts.map +1 -1
- package/lib/chain/blocks/verifyBlocksDataAvailability.js +8 -1
- package/lib/chain/blocks/verifyBlocksDataAvailability.js.map +1 -1
- package/lib/chain/blocks/writeBlockInputToDb.d.ts.map +1 -1
- package/lib/chain/blocks/writeBlockInputToDb.js +1 -7
- package/lib/chain/blocks/writeBlockInputToDb.js.map +1 -1
- package/lib/chain/chain.d.ts.map +1 -1
- package/lib/chain/chain.js +3 -4
- package/lib/chain/chain.js.map +1 -1
- package/lib/chain/lightClient/index.d.ts +2 -2
- package/lib/chain/lightClient/index.d.ts.map +1 -1
- package/lib/chain/lightClient/index.js +2 -0
- package/lib/chain/lightClient/index.js.map +1 -1
- package/lib/chain/opPools/attestationPool.d.ts +2 -3
- package/lib/chain/opPools/attestationPool.d.ts.map +1 -1
- package/lib/chain/opPools/attestationPool.js +3 -5
- package/lib/chain/opPools/attestationPool.js.map +1 -1
- package/lib/chain/opPools/syncCommitteeMessagePool.d.ts +3 -2
- package/lib/chain/opPools/syncCommitteeMessagePool.d.ts.map +1 -1
- package/lib/chain/opPools/syncCommitteeMessagePool.js +6 -5
- package/lib/chain/opPools/syncCommitteeMessagePool.js.map +1 -1
- package/lib/chain/opPools/types.d.ts +1 -1
- package/lib/chain/opPools/types.d.ts.map +1 -1
- package/lib/chain/opPools/types.js +1 -1
- package/lib/chain/opPools/types.js.map +1 -1
- package/lib/chain/prepareNextSlot.d.ts +3 -3
- package/lib/chain/prepareNextSlot.d.ts.map +1 -1
- package/lib/chain/prepareNextSlot.js +8 -8
- package/lib/chain/prepareNextSlot.js.map +1 -1
- package/lib/chain/produceBlock/produceBlockBody.d.ts.map +1 -1
- package/lib/chain/produceBlock/produceBlockBody.js +10 -2
- 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/seenCache/seenGossipBlockInput.d.ts.map +1 -1
- package/lib/chain/seenCache/seenGossipBlockInput.js +8 -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 +9 -8
- package/lib/chain/stateCache/persistentCheckpointsCache.js.map +1 -1
- package/lib/chain/validation/dataColumnSidecar.js +1 -1
- package/lib/chain/validation/dataColumnSidecar.js.map +1 -1
- package/lib/chain/validation/lightClientFinalityUpdate.d.ts.map +1 -1
- package/lib/chain/validation/lightClientFinalityUpdate.js +4 -3
- package/lib/chain/validation/lightClientFinalityUpdate.js.map +1 -1
- package/lib/chain/validation/lightClientOptimisticUpdate.d.ts +6 -4
- package/lib/chain/validation/lightClientOptimisticUpdate.d.ts.map +1 -1
- package/lib/chain/validation/lightClientOptimisticUpdate.js +11 -11
- package/lib/chain/validation/lightClientOptimisticUpdate.js.map +1 -1
- package/lib/chain/validatorMonitor.d.ts.map +1 -1
- package/lib/chain/validatorMonitor.js +21 -15
- package/lib/chain/validatorMonitor.js.map +1 -1
- package/lib/metrics/metrics/lodestar.d.ts +1 -1
- package/lib/metrics/metrics/lodestar.js +3 -3
- package/lib/metrics/metrics/lodestar.js.map +1 -1
- package/lib/network/gossip/gossipsub.js +1 -1
- package/lib/network/gossip/gossipsub.js.map +1 -1
- package/lib/network/gossip/scoringParameters.js +4 -4
- package/lib/network/gossip/scoringParameters.js.map +1 -1
- package/lib/network/network.d.ts +1 -1
- package/lib/network/network.d.ts.map +1 -1
- package/lib/network/network.js +9 -9
- package/lib/network/network.js.map +1 -1
- package/lib/network/peers/peerManager.d.ts.map +1 -1
- package/lib/network/peers/peerManager.js +2 -1
- package/lib/network/peers/peerManager.js.map +1 -1
- package/lib/network/processor/gossipHandlers.js +1 -1
- package/lib/network/processor/gossipHandlers.js.map +1 -1
- package/lib/network/subnets/attnetsService.d.ts.map +1 -1
- package/lib/network/subnets/attnetsService.js +1 -1
- package/lib/network/subnets/attnetsService.js.map +1 -1
- package/lib/node/notifier.js +1 -1
- package/lib/node/notifier.js.map +1 -1
- package/lib/sync/unknownBlock.d.ts +0 -1
- package/lib/sync/unknownBlock.d.ts.map +1 -1
- package/lib/sync/unknownBlock.js +7 -6
- package/lib/sync/unknownBlock.js.map +1 -1
- package/lib/sync/utils/downloadByRange.d.ts +2 -1
- package/lib/sync/utils/downloadByRange.d.ts.map +1 -1
- package/lib/sync/utils/downloadByRange.js +8 -3
- package/lib/sync/utils/downloadByRange.js.map +1 -1
- package/lib/sync/utils/downloadByRoot.d.ts.map +1 -1
- package/lib/sync/utils/downloadByRoot.js +2 -1
- package/lib/sync/utils/downloadByRoot.js.map +1 -1
- package/lib/util/clock.d.ts +8 -3
- package/lib/util/clock.d.ts.map +1 -1
- package/lib/util/clock.js +8 -5
- package/lib/util/clock.js.map +1 -1
- package/lib/util/dataColumns.d.ts.map +1 -1
- package/lib/util/dataColumns.js +4 -2
- package/lib/util/dataColumns.js.map +1 -1
- package/package.json +14 -14
- package/src/api/impl/beacon/blocks/index.ts +11 -2
- package/src/api/impl/lodestar/index.ts +1 -1
- package/src/api/impl/validator/index.ts +25 -28
- package/src/chain/blocks/blockInput/blockInput.ts +7 -4
- package/src/chain/blocks/importBlock.ts +8 -12
- package/src/chain/blocks/verifyBlocksDataAvailability.ts +10 -2
- package/src/chain/blocks/writeBlockInputToDb.ts +1 -9
- package/src/chain/chain.ts +3 -14
- package/src/chain/lightClient/index.ts +11 -3
- package/src/chain/opPools/attestationPool.ts +2 -3
- package/src/chain/opPools/syncCommitteeMessagePool.ts +5 -3
- package/src/chain/opPools/types.ts +1 -1
- package/src/chain/prepareNextSlot.ts +8 -8
- package/src/chain/produceBlock/produceBlockBody.ts +13 -3
- package/src/chain/regen/interface.ts +1 -0
- package/src/chain/seenCache/seenGossipBlockInput.ts +10 -2
- package/src/chain/stateCache/persistentCheckpointsCache.ts +10 -8
- package/src/chain/validation/dataColumnSidecar.ts +1 -1
- package/src/chain/validation/lightClientFinalityUpdate.ts +4 -3
- package/src/chain/validation/lightClientOptimisticUpdate.ts +12 -11
- package/src/chain/validatorMonitor.ts +28 -17
- package/src/metrics/metrics/lodestar.ts +3 -3
- package/src/network/gossip/gossipsub.ts +1 -1
- package/src/network/gossip/scoringParameters.ts +4 -4
- package/src/network/network.ts +9 -9
- package/src/network/peers/peerManager.ts +2 -1
- package/src/network/processor/gossipHandlers.ts +1 -1
- package/src/network/subnets/attnetsService.ts +3 -6
- package/src/node/notifier.ts +1 -1
- package/src/sync/unknownBlock.ts +7 -6
- package/src/sync/utils/downloadByRange.ts +12 -6
- package/src/sync/utils/downloadByRoot.ts +12 -4
- package/src/util/clock.ts +14 -6
- package/src/util/dataColumns.ts +11 -2
|
@@ -4,9 +4,11 @@ import {
|
|
|
4
4
|
ForkPostBellatrix,
|
|
5
5
|
ForkPostDeneb,
|
|
6
6
|
ForkPostFulu,
|
|
7
|
+
ForkPreGloas,
|
|
7
8
|
ForkSeq,
|
|
8
9
|
isForkPostAltair,
|
|
9
10
|
isForkPostBellatrix,
|
|
11
|
+
isForkPostGloas,
|
|
10
12
|
} from "@lodestar/params";
|
|
11
13
|
import {
|
|
12
14
|
CachedBeaconStateAllForks,
|
|
@@ -182,7 +184,14 @@ export async function produceBlockBody<T extends BlockType>(
|
|
|
182
184
|
};
|
|
183
185
|
this.logger.verbose("Producing beacon block body", logMeta);
|
|
184
186
|
|
|
185
|
-
if (
|
|
187
|
+
if (isForkPostGloas(fork)) {
|
|
188
|
+
// TODO GLOAS: Set body.signedExecutionPayloadBid and body.payloadAttestation
|
|
189
|
+
const commonBlockBody = await commonBlockBodyPromise;
|
|
190
|
+
blockBody = Object.assign({}, commonBlockBody) as AssembledBodyType<T>;
|
|
191
|
+
executionPayloadValue = BigInt(0);
|
|
192
|
+
|
|
193
|
+
// We don't deal with blinded blocks, execution engine, blobs and execution requests post-gloas
|
|
194
|
+
} else if (isForkPostBellatrix(fork)) {
|
|
186
195
|
const safeBlockHash = this.forkChoice.getJustifiedBlock().executionPayloadBlockHash ?? ZERO_HASH_HEX;
|
|
187
196
|
const finalizedBlockHash = this.forkChoice.getFinalizedBlock().executionPayloadBlockHash ?? ZERO_HASH_HEX;
|
|
188
197
|
const feeRecipient = requestedFeeRecipient ?? this.beaconProposerCache.getOrDefault(proposerIndex);
|
|
@@ -307,6 +316,7 @@ export async function produceBlockBody<T extends BlockType>(
|
|
|
307
316
|
|
|
308
317
|
// blockType === BlockType.Full
|
|
309
318
|
else {
|
|
319
|
+
// enginePromise only supports pre-gloas
|
|
310
320
|
const enginePromise = (async () => {
|
|
311
321
|
const endExecutionPayload = this.metrics?.executionBlockProductionTimeSteps.startTimer();
|
|
312
322
|
|
|
@@ -384,13 +394,13 @@ export async function produceBlockBody<T extends BlockType>(
|
|
|
384
394
|
blockBody = Object.assign({}, commonBlockBody) as AssembledBodyType<BlockType.Blinded>;
|
|
385
395
|
|
|
386
396
|
if (engineRes.isPremerge) {
|
|
387
|
-
(blockBody as BeaconBlockBody<ForkPostBellatrix>).executionPayload = engineRes.executionPayload;
|
|
397
|
+
(blockBody as BeaconBlockBody<ForkPostBellatrix & ForkPreGloas>).executionPayload = engineRes.executionPayload;
|
|
388
398
|
executionPayloadValue = engineRes.executionPayloadValue;
|
|
389
399
|
} else {
|
|
390
400
|
const {prepType, payloadId, executionPayload, blobsBundle, executionRequests} = engineRes;
|
|
391
401
|
shouldOverrideBuilder = engineRes.shouldOverrideBuilder;
|
|
392
402
|
|
|
393
|
-
(blockBody as BeaconBlockBody<ForkPostBellatrix>).executionPayload = executionPayload;
|
|
403
|
+
(blockBody as BeaconBlockBody<ForkPostBellatrix & ForkPreGloas>).executionPayload = executionPayload;
|
|
394
404
|
(produceResult as ProduceFullBellatrix).executionPayload = executionPayload;
|
|
395
405
|
executionPayloadValue = engineRes.executionPayloadValue;
|
|
396
406
|
Object.assign(logMeta, {transactions: executionPayload.transactions.length, shouldOverrideBuilder});
|
|
@@ -10,6 +10,7 @@ export enum RegenCaller {
|
|
|
10
10
|
produceBlock = "produceBlock",
|
|
11
11
|
validateGossipBlock = "validateGossipBlock",
|
|
12
12
|
validateGossipBlob = "validateGossipBlob",
|
|
13
|
+
validateGossipDataColumn = "validateGossipDataColumn",
|
|
13
14
|
precomputeEpoch = "precomputeEpoch",
|
|
14
15
|
predictProposerHead = "predictProposerHead",
|
|
15
16
|
produceAttestationData = "produceAttestationData",
|
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
import {ChainForkConfig} from "@lodestar/config";
|
|
2
2
|
import {CheckpointWithHex} from "@lodestar/fork-choice";
|
|
3
|
-
import {ForkName, ForkPostFulu, isForkPostDeneb, isForkPostFulu} from "@lodestar/params";
|
|
3
|
+
import {ForkName, ForkPostFulu, ForkPreGloas, isForkPostDeneb, isForkPostFulu, isForkPostGloas} from "@lodestar/params";
|
|
4
4
|
import {computeStartSlotAtEpoch} from "@lodestar/state-transition";
|
|
5
5
|
import {RootHex, SignedBeaconBlock, Slot, deneb, fulu} from "@lodestar/types";
|
|
6
6
|
import {LodestarError, Logger} from "@lodestar/utils";
|
|
@@ -155,6 +155,12 @@ export class SeenBlockInput {
|
|
|
155
155
|
let blockInput = this.blockInputs.get(blockRootHex) as IBlockInput;
|
|
156
156
|
if (!blockInput) {
|
|
157
157
|
const {forkName, daOutOfRange} = this.buildCommonProps(block.message.slot);
|
|
158
|
+
|
|
159
|
+
// TODO GLOAS: Implement
|
|
160
|
+
if (isForkPostGloas(forkName)) {
|
|
161
|
+
throw Error("Not implemented");
|
|
162
|
+
}
|
|
163
|
+
// Pre-deneb
|
|
158
164
|
if (!isForkPostDeneb(forkName)) {
|
|
159
165
|
blockInput = BlockInputPreData.createFromBlock({
|
|
160
166
|
block,
|
|
@@ -165,9 +171,10 @@ export class SeenBlockInput {
|
|
|
165
171
|
seenTimestampSec,
|
|
166
172
|
peerIdStr,
|
|
167
173
|
});
|
|
174
|
+
// Fulu Only
|
|
168
175
|
} else if (isForkPostFulu(forkName)) {
|
|
169
176
|
blockInput = BlockInputColumns.createFromBlock({
|
|
170
|
-
block: block as SignedBeaconBlock<ForkPostFulu>,
|
|
177
|
+
block: block as SignedBeaconBlock<ForkPostFulu & ForkPreGloas>,
|
|
171
178
|
blockRootHex,
|
|
172
179
|
daOutOfRange,
|
|
173
180
|
forkName,
|
|
@@ -177,6 +184,7 @@ export class SeenBlockInput {
|
|
|
177
184
|
seenTimestampSec,
|
|
178
185
|
peerIdStr,
|
|
179
186
|
});
|
|
187
|
+
// Deneb and Electra
|
|
180
188
|
} else {
|
|
181
189
|
blockInput = BlockInputBlobs.createFromBlock({
|
|
182
190
|
block: block as SignedBeaconBlock<ForkBlobsDA>,
|
|
@@ -1,5 +1,4 @@
|
|
|
1
1
|
import {routes} from "@lodestar/api";
|
|
2
|
-
import {INTERVALS_PER_SLOT} from "@lodestar/params";
|
|
3
2
|
import {
|
|
4
3
|
CachedBeaconStateAllForks,
|
|
5
4
|
computeStartSlotAtEpoch,
|
|
@@ -59,6 +58,9 @@ type LoadedStateBytesData = {persistedKey: DatastoreKey; stateBytes: Uint8Array}
|
|
|
59
58
|
*/
|
|
60
59
|
export const DEFAULT_MAX_CP_STATE_EPOCHS_IN_MEMORY = 3;
|
|
61
60
|
|
|
61
|
+
// TODO GLOAS: re-evaluate this timing
|
|
62
|
+
const PROCESS_CHECKPOINT_STATES_BPS = 6667;
|
|
63
|
+
|
|
62
64
|
/**
|
|
63
65
|
* An implementation of CheckpointStateCache that keep up to n epoch checkpoint states in memory and persist the rest to disk
|
|
64
66
|
* - If it's more than `maxEpochsInMemory` epochs old, it will persist n last epochs to disk based on the view of the block
|
|
@@ -464,14 +466,14 @@ export class PersistentCheckpointStateCache implements CheckpointStateCache {
|
|
|
464
466
|
}
|
|
465
467
|
|
|
466
468
|
const blockSlot = state.slot;
|
|
467
|
-
const
|
|
469
|
+
const processCPStatesTimeMs = state.config.getSlotComponentDurationMs(PROCESS_CHECKPOINT_STATES_BPS);
|
|
468
470
|
// we always have clock in production, fallback value is only for test
|
|
469
|
-
const
|
|
470
|
-
const
|
|
471
|
-
if (
|
|
472
|
-
//
|
|
473
|
-
// normally it should only persist checkpoint states at
|
|
474
|
-
await sleep(
|
|
471
|
+
const msFromSlot = this.clock?.msFromSlot(blockSlot) ?? processCPStatesTimeMs;
|
|
472
|
+
const msToProcessCPStates = processCPStatesTimeMs - msFromSlot;
|
|
473
|
+
if (msToProcessCPStates > 0) {
|
|
474
|
+
// At ~67% of slot is the most free time of every slot, take that chance to persist checkpoint states
|
|
475
|
+
// normally it should only persist checkpoint states at ~67% of slot 0 of epoch
|
|
476
|
+
await sleep(msToProcessCPStates, this.signal);
|
|
475
477
|
}
|
|
476
478
|
// at syncing time, it's critical to persist checkpoint states as soon as possible to avoid OOM during unfinality time
|
|
477
479
|
// if node is synced this is not a hot time because block comes late, we'll likely miss attestation already, or the block is orphaned
|
|
@@ -99,7 +99,7 @@ export async function validateGossipDataColumnSidecar(
|
|
|
99
99
|
// this is something we should change this in the future to make the code airtight to the spec.
|
|
100
100
|
// 7) [REJECT] The sidecar's block's parent passes validation.
|
|
101
101
|
const blockState = await chain.regen
|
|
102
|
-
.getBlockSlotState(parentRoot, blockHeader.slot, {dontTransferCache: true}, RegenCaller.
|
|
102
|
+
.getBlockSlotState(parentRoot, blockHeader.slot, {dontTransferCache: true}, RegenCaller.validateGossipDataColumn)
|
|
103
103
|
.catch(() => {
|
|
104
104
|
throw new DataColumnSidecarGossipError(GossipAction.IGNORE, {
|
|
105
105
|
code: DataColumnSidecarErrorCode.PARENT_UNKNOWN,
|
|
@@ -25,9 +25,10 @@ export function validateLightClientFinalityUpdate(
|
|
|
25
25
|
}
|
|
26
26
|
|
|
27
27
|
// [IGNORE] The finality_update is received after the block at signature_slot was given enough time to propagate
|
|
28
|
-
// through the network -- i.e. validate that
|
|
29
|
-
// (
|
|
30
|
-
|
|
28
|
+
// through the network -- i.e. validate that `get_sync_message_due_ms(epoch)`
|
|
29
|
+
// milliseconds (with a `MAXIMUM_GOSSIP_CLOCK_DISPARITY` allowance) has
|
|
30
|
+
// transpired since the start of `signature_slot`.
|
|
31
|
+
if (updateReceivedTooEarly(config, chain.clock, gossipedFinalityUpdate)) {
|
|
31
32
|
throw new LightClientError(GossipAction.IGNORE, {
|
|
32
33
|
code: LightClientErrorCode.FINALITY_UPDATE_RECEIVED_TOO_EARLY,
|
|
33
34
|
});
|
|
@@ -1,8 +1,8 @@
|
|
|
1
1
|
import {ChainForkConfig} from "@lodestar/config";
|
|
2
|
-
import {computeTimeAtSlot} from "@lodestar/state-transition";
|
|
3
2
|
import {LightClientOptimisticUpdate} from "@lodestar/types";
|
|
4
3
|
import {MAXIMUM_GOSSIP_CLOCK_DISPARITY} from "../../constants/index.js";
|
|
5
4
|
import {assertLightClientServer} from "../../node/utils/lightclient.js";
|
|
5
|
+
import {IClock} from "../../util/clock.js";
|
|
6
6
|
import {GossipAction} from "../errors/index.js";
|
|
7
7
|
import {LightClientError, LightClientErrorCode} from "../errors/lightClientError.js";
|
|
8
8
|
import {IBeaconChain} from "../interface.js";
|
|
@@ -26,9 +26,10 @@ export function validateLightClientOptimisticUpdate(
|
|
|
26
26
|
}
|
|
27
27
|
|
|
28
28
|
// [IGNORE] The optimistic_update is received after the block at signature_slot was given enough time to propagate
|
|
29
|
-
// through the network -- i.e. validate that
|
|
30
|
-
// (
|
|
31
|
-
|
|
29
|
+
// through the network -- i.e. validate that `get_sync_message_due_ms(epoch)`
|
|
30
|
+
// milliseconds (with a `MAXIMUM_GOSSIP_CLOCK_DISPARITY` allowance) has
|
|
31
|
+
// transpired since the start of `signature_slot`.
|
|
32
|
+
if (updateReceivedTooEarly(config, chain.clock, gossipedOptimisticUpdate)) {
|
|
32
33
|
throw new LightClientError(GossipAction.IGNORE, {
|
|
33
34
|
code: LightClientErrorCode.OPTIMISTIC_UPDATE_RECEIVED_TOO_EARLY,
|
|
34
35
|
});
|
|
@@ -48,20 +49,20 @@ export function validateLightClientOptimisticUpdate(
|
|
|
48
49
|
/**
|
|
49
50
|
* Returns true, if the spec condition below triggers an IGNORE.
|
|
50
51
|
*
|
|
51
|
-
* Sig +
|
|
52
|
+
* Sig + SYNC_MESSAGE_DUE_BPS time
|
|
52
53
|
* -----|-----
|
|
53
54
|
* xxx|------- (x is not okay)
|
|
54
55
|
*
|
|
55
56
|
* [IGNORE] The *update is received after the block at signature_slot was given enough time to propagate
|
|
56
|
-
* through the network -- i.e. validate that
|
|
57
|
-
* (
|
|
57
|
+
* through the network -- i.e. validate that `get_sync_message_due_ms(epoch)`
|
|
58
|
+
* milliseconds (with a `MAXIMUM_GOSSIP_CLOCK_DISPARITY` allowance) has
|
|
59
|
+
* transpired since the start of `signature_slot`.
|
|
58
60
|
*/
|
|
59
61
|
export function updateReceivedTooEarly(
|
|
60
62
|
config: ChainForkConfig,
|
|
61
|
-
|
|
63
|
+
clock: IClock,
|
|
62
64
|
update: Pick<LightClientOptimisticUpdate, "signatureSlot">
|
|
63
65
|
): boolean {
|
|
64
|
-
const
|
|
65
|
-
|
|
66
|
-
return Date.now() < earliestAllowedTimestampMs;
|
|
66
|
+
const fork = config.getForkName(update.signatureSlot);
|
|
67
|
+
return clock.msFromSlot(update.signatureSlot) < config.getSyncMessageDueMs(fork) - MAXIMUM_GOSSIP_CLOCK_DISPARITY;
|
|
67
68
|
}
|
|
@@ -1,11 +1,12 @@
|
|
|
1
|
-
import {
|
|
2
|
-
import {ForkSeq,
|
|
1
|
+
import {ChainForkConfig} from "@lodestar/config";
|
|
2
|
+
import {ForkSeq, MIN_ATTESTATION_INCLUSION_DELAY, SLOTS_PER_EPOCH} from "@lodestar/params";
|
|
3
3
|
import {
|
|
4
4
|
CachedBeaconStateAllForks,
|
|
5
5
|
CachedBeaconStateAltair,
|
|
6
6
|
ParticipationFlags,
|
|
7
7
|
computeEpochAtSlot,
|
|
8
8
|
computeStartSlotAtEpoch,
|
|
9
|
+
computeTimeAtSlot,
|
|
9
10
|
getBlockRootAtSlot,
|
|
10
11
|
getCurrentSlot,
|
|
11
12
|
parseAttesterFlags,
|
|
@@ -34,8 +35,9 @@ const MAX_CACHED_EPOCHS = 4;
|
|
|
34
35
|
|
|
35
36
|
const MAX_CACHED_DISTINCT_TARGETS = 4;
|
|
36
37
|
|
|
37
|
-
|
|
38
|
-
const
|
|
38
|
+
// TODO GLOAS: re-evaluate these timings
|
|
39
|
+
const LATE_ATTESTATION_SUBMISSION_BPS = 5000;
|
|
40
|
+
const LATE_BLOCK_SUBMISSION_BPS = 2500;
|
|
39
41
|
|
|
40
42
|
const RETAIN_REGISTERED_VALIDATORS_MS = 1 * 3600 * 1000; // 1 hour
|
|
41
43
|
|
|
@@ -450,8 +452,11 @@ export function createValidatorMonitor(
|
|
|
450
452
|
|
|
451
453
|
onPoolSubmitUnaggregatedAttestation(seenTimestampSec, indexedAttestation, subnet, sentPeers) {
|
|
452
454
|
const data = indexedAttestation.data;
|
|
453
|
-
|
|
454
|
-
|
|
455
|
+
const fork = config.getForkName(data.slot);
|
|
456
|
+
// Returns the duration between when the attestation `data` could be produced (ATTESTATION_DUE_BPS through the slot) and `seenTimestamp`.
|
|
457
|
+
const delaySec =
|
|
458
|
+
seenTimestampSec -
|
|
459
|
+
(computeTimeAtSlot(config, data.slot, genesisTime) + config.getAttestationDueMs(fork) / 1000);
|
|
455
460
|
for (const index of indexedAttestation.attestingIndices) {
|
|
456
461
|
const validator = validators.get(index);
|
|
457
462
|
if (validator) {
|
|
@@ -483,8 +488,11 @@ export function createValidatorMonitor(
|
|
|
483
488
|
const src = OpSource.gossip;
|
|
484
489
|
const data = indexedAttestation.data;
|
|
485
490
|
const epoch = computeEpochAtSlot(data.slot);
|
|
486
|
-
|
|
487
|
-
|
|
491
|
+
const fork = config.getForkName(data.slot);
|
|
492
|
+
// Returns the duration between when the attestation `data` could be produced (ATTESTATION_DUE_BPS through the slot) and `seenTimestamp`.
|
|
493
|
+
const delaySec =
|
|
494
|
+
seenTimestampSec -
|
|
495
|
+
(computeTimeAtSlot(config, data.slot, genesisTime) + config.getAttestationDueMs(fork) / 1000);
|
|
488
496
|
|
|
489
497
|
for (const index of indexedAttestation.attestingIndices) {
|
|
490
498
|
const validator = validators.get(index);
|
|
@@ -500,8 +508,10 @@ export function createValidatorMonitor(
|
|
|
500
508
|
|
|
501
509
|
onPoolSubmitAggregatedAttestation(seenTimestampSec, indexedAttestation, sentPeers) {
|
|
502
510
|
const data = indexedAttestation.data;
|
|
503
|
-
|
|
504
|
-
|
|
511
|
+
const fork = config.getForkName(data.slot);
|
|
512
|
+
// Returns the duration between when a `AggregateAndproof` with `data` could be produced (AGGREGATE_DUE_BPS through the slot) and `seenTimestamp`.
|
|
513
|
+
const delaySec =
|
|
514
|
+
seenTimestampSec - (computeTimeAtSlot(config, data.slot, genesisTime) + config.getAggregateDueMs(fork) / 1000);
|
|
505
515
|
|
|
506
516
|
for (const index of indexedAttestation.attestingIndices) {
|
|
507
517
|
const validator = validators.get(index);
|
|
@@ -527,8 +537,10 @@ export function createValidatorMonitor(
|
|
|
527
537
|
const src = OpSource.gossip;
|
|
528
538
|
const data = indexedAttestation.data;
|
|
529
539
|
const epoch = computeEpochAtSlot(data.slot);
|
|
530
|
-
|
|
531
|
-
|
|
540
|
+
const fork = config.getForkName(data.slot);
|
|
541
|
+
// Returns the duration between when a `AggregateAndproof` with `data` could be produced (AGGREGATE_DUE_BPS through the slot) and `seenTimestamp`.
|
|
542
|
+
const delaySec =
|
|
543
|
+
seenTimestampSec - (computeTimeAtSlot(config, data.slot, genesisTime) + config.getAggregateDueMs(fork) / 1000);
|
|
532
544
|
|
|
533
545
|
const aggregatorIndex = signedAggregateAndProof.message.aggregatorIndex;
|
|
534
546
|
const validatorAggregator = validators.get(aggregatorIndex);
|
|
@@ -822,7 +834,7 @@ export function createValidatorMonitor(
|
|
|
822
834
|
* - Was the attestation seen in a block?
|
|
823
835
|
*/
|
|
824
836
|
function renderAttestationSummary(
|
|
825
|
-
config:
|
|
837
|
+
config: ChainForkConfig,
|
|
826
838
|
rootCache: RootHexCache,
|
|
827
839
|
summary: AttestationSummary | undefined,
|
|
828
840
|
flags: ParticipationFlags
|
|
@@ -925,8 +937,7 @@ function renderAttestationSummary(
|
|
|
925
937
|
}
|
|
926
938
|
|
|
927
939
|
const submittedLate =
|
|
928
|
-
summary.poolSubmitDelayMinSec >
|
|
929
|
-
(INTERVALS_LATE_ATTESTATION_SUBMISSION * config.SECONDS_PER_SLOT) / INTERVALS_PER_SLOT;
|
|
940
|
+
summary.poolSubmitDelayMinSec > config.getSlotComponentDurationMs(LATE_ATTESTATION_SUBMISSION_BPS) / 1000;
|
|
930
941
|
|
|
931
942
|
const aggregateInclusion = summary.aggregateInclusionDelaysSec.length > 0;
|
|
932
943
|
|
|
@@ -1030,7 +1041,7 @@ function isMissedSlot(rootCache: RootHexCache, slot: Slot): boolean {
|
|
|
1030
1041
|
}
|
|
1031
1042
|
|
|
1032
1043
|
function renderBlockProposalSummary(
|
|
1033
|
-
config:
|
|
1044
|
+
config: ChainForkConfig,
|
|
1034
1045
|
rootCache: RootHexCache,
|
|
1035
1046
|
summary: EpochSummary | undefined,
|
|
1036
1047
|
proposalSlot: Slot
|
|
@@ -1053,7 +1064,7 @@ function renderBlockProposalSummary(
|
|
|
1053
1064
|
|
|
1054
1065
|
if (
|
|
1055
1066
|
proposal.poolSubmitDelaySec !== null &&
|
|
1056
|
-
proposal.poolSubmitDelaySec >
|
|
1067
|
+
proposal.poolSubmitDelaySec > config.getSlotComponentDurationMs(LATE_BLOCK_SUBMISSION_BPS) / 1000
|
|
1057
1068
|
) {
|
|
1058
1069
|
out += "_late";
|
|
1059
1070
|
}
|
|
@@ -862,9 +862,9 @@ export function createLodestarMetrics(
|
|
|
862
862
|
help: "Time elapsed between block slot time and the time block becomes head",
|
|
863
863
|
buckets: [0.5, 1, 2, 4, 6, 12],
|
|
864
864
|
}),
|
|
865
|
-
|
|
866
|
-
name: "
|
|
867
|
-
help: "Total times an imported block is set as head after the
|
|
865
|
+
setHeadAfterCutoff: register.gauge({
|
|
866
|
+
name: "lodestar_import_block_set_head_after_cutoff_total",
|
|
867
|
+
help: "Total times an imported block is set as head after ATTESTATION_DUE_BPS of the slot",
|
|
868
868
|
}),
|
|
869
869
|
bySource: register.gauge<{source: BlockInputSource}>({
|
|
870
870
|
name: "lodestar_import_block_by_source_total",
|
|
@@ -105,7 +105,7 @@ export class Eth2Gossipsub extends GossipSub {
|
|
|
105
105
|
mcacheLength: 6,
|
|
106
106
|
mcacheGossip: 3,
|
|
107
107
|
// this should be in ms
|
|
108
|
-
seenTTL: config.
|
|
108
|
+
seenTTL: config.SLOT_DURATION_MS * SLOTS_PER_EPOCH * 2,
|
|
109
109
|
scoreParams,
|
|
110
110
|
scoreThresholds: gossipScoreThresholds,
|
|
111
111
|
// For a single stream, await processing each RPC before processing the next
|
|
@@ -84,10 +84,10 @@ export function computeGossipPeerScoreParams({
|
|
|
84
84
|
config: BeaconConfig;
|
|
85
85
|
eth2Context: Eth2Context;
|
|
86
86
|
}): Partial<PeerScoreParams> {
|
|
87
|
-
const decayIntervalMs = config.
|
|
87
|
+
const decayIntervalMs = config.SLOT_DURATION_MS;
|
|
88
88
|
const decayToZero = 0.01;
|
|
89
|
-
const epochDurationMs = config.
|
|
90
|
-
const slotDurationMs = config.
|
|
89
|
+
const epochDurationMs = config.SLOT_DURATION_MS * SLOTS_PER_EPOCH;
|
|
90
|
+
const slotDurationMs = config.SLOT_DURATION_MS;
|
|
91
91
|
const scoreParameterDecayFn = (decayTimeMs: number): number => {
|
|
92
92
|
return scoreParameterDecayWithBase(decayTimeMs, decayIntervalMs, decayToZero);
|
|
93
93
|
};
|
|
@@ -265,7 +265,7 @@ function getTopicScoreParams(
|
|
|
265
265
|
|
|
266
266
|
if (meshMessageInfo) {
|
|
267
267
|
const {decaySlots, capFactor, activationWindow, currentSlot} = meshMessageInfo;
|
|
268
|
-
const decayTimeMs = config.
|
|
268
|
+
const decayTimeMs = config.SLOT_DURATION_MS * decaySlots;
|
|
269
269
|
params.meshMessageDeliveriesDecay = scoreParameterDecayFn(decayTimeMs);
|
|
270
270
|
params.meshMessageDeliveriesThreshold = threshold(params.meshMessageDeliveriesDecay, expectedMessageRate / 50);
|
|
271
271
|
params.meshMessageDeliveriesCap = Math.max(capFactor * params.meshMessageDeliveriesThreshold, 2);
|
package/src/network/network.ts
CHANGED
|
@@ -7,7 +7,7 @@ import {BeaconConfig} from "@lodestar/config";
|
|
|
7
7
|
import {LoggerNode} from "@lodestar/logger/node";
|
|
8
8
|
import {ForkSeq} from "@lodestar/params";
|
|
9
9
|
import {ResponseIncoming} from "@lodestar/reqresp";
|
|
10
|
-
import {computeEpochAtSlot
|
|
10
|
+
import {computeEpochAtSlot} from "@lodestar/state-transition";
|
|
11
11
|
import {
|
|
12
12
|
AttesterSlashing,
|
|
13
13
|
LightClientBootstrap,
|
|
@@ -689,9 +689,9 @@ export class Network implements INetwork {
|
|
|
689
689
|
// TODO: Review is OK to remove if (this.hasAttachedSyncCommitteeMember())
|
|
690
690
|
|
|
691
691
|
try {
|
|
692
|
-
// messages SHOULD be broadcast after
|
|
692
|
+
// messages SHOULD be broadcast after SYNC_MESSAGE_DUE_BPS of slot has transpired
|
|
693
693
|
// https://github.com/ethereum/consensus-specs/blob/dev/specs/altair/light-client/p2p-interface.md#sync-committee
|
|
694
|
-
await this.
|
|
694
|
+
await this.waitForSyncMessageCutoff(finalityUpdate.signatureSlot);
|
|
695
695
|
await this.publishLightClientFinalityUpdate(finalityUpdate);
|
|
696
696
|
} catch (e) {
|
|
697
697
|
// Non-mandatory route on most of network as of Oct 2022. May not have found any peers on topic yet
|
|
@@ -706,9 +706,9 @@ export class Network implements INetwork {
|
|
|
706
706
|
// TODO: Review is OK to remove if (this.hasAttachedSyncCommitteeMember())
|
|
707
707
|
|
|
708
708
|
try {
|
|
709
|
-
// messages SHOULD be broadcast after
|
|
709
|
+
// messages SHOULD be broadcast after SYNC_MESSAGE_DUE_BPS of slot has transpired
|
|
710
710
|
// https://github.com/ethereum/consensus-specs/blob/dev/specs/altair/light-client/p2p-interface.md#sync-committee
|
|
711
|
-
await this.
|
|
711
|
+
await this.waitForSyncMessageCutoff(optimisticUpdate.signatureSlot);
|
|
712
712
|
await this.publishLightClientOptimisticUpdate(optimisticUpdate);
|
|
713
713
|
} catch (e) {
|
|
714
714
|
// Non-mandatory route on most of network as of Oct 2022. May not have found any peers on topic yet
|
|
@@ -719,10 +719,10 @@ export class Network implements INetwork {
|
|
|
719
719
|
}
|
|
720
720
|
};
|
|
721
721
|
|
|
722
|
-
private
|
|
723
|
-
const
|
|
724
|
-
const
|
|
725
|
-
await sleep(
|
|
722
|
+
private waitForSyncMessageCutoff = async (slot: number): Promise<void> => {
|
|
723
|
+
const fork = this.config.getForkName(slot);
|
|
724
|
+
const msToCutoffTime = this.config.getSyncMessageDueMs(fork) - this.chain.clock.msFromSlot(slot);
|
|
725
|
+
await sleep(msToCutoffTime, this.controller.signal);
|
|
726
726
|
};
|
|
727
727
|
|
|
728
728
|
private onHead = async (): Promise<void> => {
|
|
@@ -3,6 +3,7 @@ import {BitArray} from "@chainsafe/ssz";
|
|
|
3
3
|
import {BeaconConfig} from "@lodestar/config";
|
|
4
4
|
import {LoggerNode} from "@lodestar/logger/node";
|
|
5
5
|
import {ForkSeq, SLOTS_PER_EPOCH, SYNC_COMMITTEE_SUBNET_COUNT} from "@lodestar/params";
|
|
6
|
+
import {computeTimeAtSlot} from "@lodestar/state-transition";
|
|
6
7
|
import {Metadata, Status, altair, fulu, phase0} from "@lodestar/types";
|
|
7
8
|
import {prettyPrintIndices, toHex, withTimeout} from "@lodestar/utils";
|
|
8
9
|
import {GOODBYE_KNOWN_CODES, GoodByeReasonCode, Libp2pEvent} from "../../constants/index.js";
|
|
@@ -599,7 +600,7 @@ export class PeerManager {
|
|
|
599
600
|
subnet: query.subnet,
|
|
600
601
|
type,
|
|
601
602
|
maxPeersToDiscover: query.maxPeersToDiscover,
|
|
602
|
-
toUnixMs:
|
|
603
|
+
toUnixMs: computeTimeAtSlot(this.config, query.toSlot, this.clock.genesisTime) * 1000,
|
|
603
604
|
});
|
|
604
605
|
}
|
|
605
606
|
|
|
@@ -379,7 +379,7 @@ function getSequentialHandlers(modules: ValidatorFnsModules, options: GossipHand
|
|
|
379
379
|
|
|
380
380
|
// Handler - MUST NOT `await`, to allow validation result to be propagated
|
|
381
381
|
|
|
382
|
-
const delaySec = seenTimestampSec - (
|
|
382
|
+
const delaySec = seenTimestampSec - computeTimeAtSlot(config, slot, chain.genesisTime);
|
|
383
383
|
metrics?.gossipBlock.elapsedTimeTillReceived.observe({source: OpSource.gossip}, delaySec);
|
|
384
384
|
chain.validatorMonitor?.registerBeaconBlock(OpSource.gossip, delaySec, signedBlock.message);
|
|
385
385
|
if (!blockInput.hasBlockAndAllData()) {
|
|
@@ -163,12 +163,9 @@ export class AttnetsService implements IAttnetsService {
|
|
|
163
163
|
*/
|
|
164
164
|
private onSlot = (clockSlot: Slot): void => {
|
|
165
165
|
try {
|
|
166
|
-
setTimeout(
|
|
167
|
-
()
|
|
168
|
-
|
|
169
|
-
},
|
|
170
|
-
this.config.SECONDS_PER_SLOT * 0.5 * 1000
|
|
171
|
-
);
|
|
166
|
+
setTimeout(() => {
|
|
167
|
+
this.onHalfSlot(clockSlot);
|
|
168
|
+
}, this.config.SLOT_DURATION_MS * 0.5);
|
|
172
169
|
|
|
173
170
|
for (const [dutiedSlot, dutiedInfo] of this.aggregatorSlotSubnet.entries()) {
|
|
174
171
|
if (dutiedSlot === clockSlot + this.opts.slotsToSubscribeBeforeAggregatorDuty) {
|
package/src/node/notifier.ts
CHANGED
|
@@ -157,7 +157,7 @@ export async function runNodeNotifier(modules: NodeNotifierModules): Promise<voi
|
|
|
157
157
|
}
|
|
158
158
|
|
|
159
159
|
function timeToNextHalfSlot(config: BeaconConfig, chain: IBeaconChain, isFirstTime: boolean): number {
|
|
160
|
-
const msPerSlot = config.
|
|
160
|
+
const msPerSlot = config.SLOT_DURATION_MS;
|
|
161
161
|
const msPerHalfSlot = msPerSlot / 2;
|
|
162
162
|
const msFromGenesis = Date.now() - chain.genesisTime * 1000;
|
|
163
163
|
const msToNextSlot =
|
package/src/sync/unknownBlock.ts
CHANGED
|
@@ -1,6 +1,7 @@
|
|
|
1
1
|
import {ChainForkConfig} from "@lodestar/config";
|
|
2
|
-
import {ForkSeq
|
|
2
|
+
import {ForkSeq} from "@lodestar/params";
|
|
3
3
|
import {RequestError, RequestErrorCode} from "@lodestar/reqresp";
|
|
4
|
+
import {computeTimeAtSlot} from "@lodestar/state-transition";
|
|
4
5
|
import {RootHex} from "@lodestar/types";
|
|
5
6
|
import {Logger, prettyPrintIndices, pruneSetToMax, sleep} from "@lodestar/utils";
|
|
6
7
|
import {isBlockInputBlobs, isBlockInputColumns} from "../chain/blocks/blockInput/blockInput.js";
|
|
@@ -78,7 +79,6 @@ export class BlockInputSync {
|
|
|
78
79
|
*/
|
|
79
80
|
private readonly pendingBlocks = new Map<RootHex, BlockInputSyncCacheItem>();
|
|
80
81
|
private readonly knownBadBlocks = new Set<RootHex>();
|
|
81
|
-
private readonly proposerBoostSecWindow: number;
|
|
82
82
|
private readonly maxPendingBlocks;
|
|
83
83
|
private subscribedToNetworkEvents = false;
|
|
84
84
|
private peerBalancer: UnknownBlockPeerBalancer;
|
|
@@ -92,7 +92,6 @@ export class BlockInputSync {
|
|
|
92
92
|
private readonly opts?: SyncOptions
|
|
93
93
|
) {
|
|
94
94
|
this.maxPendingBlocks = opts?.maxPendingBlocks ?? MAX_PENDING_BLOCKS;
|
|
95
|
-
this.proposerBoostSecWindow = this.config.SECONDS_PER_SLOT / INTERVALS_PER_SLOT;
|
|
96
95
|
this.peerBalancer = new UnknownBlockPeerBalancer();
|
|
97
96
|
|
|
98
97
|
if (metrics) {
|
|
@@ -331,7 +330,7 @@ export class BlockInputSync {
|
|
|
331
330
|
this.pendingBlocks.set(pending.blockInput.blockRootHex, pending);
|
|
332
331
|
const blockSlot = pending.blockInput.slot;
|
|
333
332
|
const finalizedSlot = this.chain.forkChoice.getFinalizedBlock().slot;
|
|
334
|
-
const delaySec = Date.now() / 1000 - (this.
|
|
333
|
+
const delaySec = Date.now() / 1000 - computeTimeAtSlot(this.config, blockSlot, this.chain.genesisTime);
|
|
335
334
|
this.metrics?.blockInputSync.elapsedTimeTillReceived.observe(delaySec);
|
|
336
335
|
|
|
337
336
|
const parentInForkChoice = this.chain.forkChoice.hasBlockHex(pending.blockInput.parentRootHex);
|
|
@@ -396,8 +395,10 @@ export class BlockInputSync {
|
|
|
396
395
|
// this prevents unbundling attack
|
|
397
396
|
// see https://lighthouse-blog.sigmaprime.io/mev-unbundling-rpc.html
|
|
398
397
|
const {slot: blockSlot, proposerIndex} = pendingBlock.blockInput.getBlock().message;
|
|
398
|
+
const fork = this.config.getForkName(blockSlot);
|
|
399
|
+
const proposerBoostWindowMs = this.config.getAttestationDueMs(fork);
|
|
399
400
|
if (
|
|
400
|
-
this.chain.clock.
|
|
401
|
+
this.chain.clock.msFromSlot(blockSlot) < proposerBoostWindowMs &&
|
|
401
402
|
this.chain.seenBlockProposers.isKnown(blockSlot, proposerIndex)
|
|
402
403
|
) {
|
|
403
404
|
// proposer is known by a gossip block already, wait a bit to make sure this block is not
|
|
@@ -407,7 +408,7 @@ export class BlockInputSync {
|
|
|
407
408
|
root: pendingBlock.blockInput.blockRootHex,
|
|
408
409
|
proposerIndex,
|
|
409
410
|
});
|
|
410
|
-
await sleep(
|
|
411
|
+
await sleep(proposerBoostWindowMs);
|
|
411
412
|
}
|
|
412
413
|
// At gossip time, it's critical to keep a good number of mesh peers.
|
|
413
414
|
// To do that, the Gossip Job Wait Time should be consistently <3s to avoid the behavior penalties in gossip
|
|
@@ -1,5 +1,5 @@
|
|
|
1
1
|
import {ChainForkConfig} from "@lodestar/config";
|
|
2
|
-
import {ForkPostDeneb, ForkPostFulu} from "@lodestar/params";
|
|
2
|
+
import {ForkPostDeneb, ForkPostFulu, ForkPreFulu, ForkPreGloas} from "@lodestar/params";
|
|
3
3
|
import {SignedBeaconBlock, Slot, deneb, fulu, phase0} from "@lodestar/types";
|
|
4
4
|
import {LodestarError, Logger, fromHex, prettyBytes, prettyPrintIndices, toRootHex} from "@lodestar/utils";
|
|
5
5
|
import {
|
|
@@ -458,14 +458,16 @@ export function validateBlockByRangeResponse(
|
|
|
458
458
|
}
|
|
459
459
|
|
|
460
460
|
/**
|
|
461
|
-
* Should not be called directly. Only exported for unit testing purposes
|
|
461
|
+
* Should not be called directly. Only exported for unit testing purposes.
|
|
462
|
+
* This is used only in Deneb and Electra
|
|
462
463
|
*/
|
|
463
464
|
export async function validateBlobsByRangeResponse(
|
|
464
465
|
dataRequestBlocks: ValidatedBlock[],
|
|
465
466
|
blobSidecars: deneb.BlobSidecars
|
|
466
467
|
): Promise<ValidatedBlobSidecars[]> {
|
|
467
468
|
const expectedBlobCount = dataRequestBlocks.reduce(
|
|
468
|
-
(acc, {block}) =>
|
|
469
|
+
(acc, {block}) =>
|
|
470
|
+
(block as SignedBeaconBlock<ForkPostDeneb & ForkPreFulu>).message.body.blobKzgCommitments.length + acc,
|
|
469
471
|
0
|
|
470
472
|
);
|
|
471
473
|
if (blobSidecars.length > expectedBlobCount) {
|
|
@@ -492,7 +494,8 @@ export async function validateBlobsByRangeResponse(
|
|
|
492
494
|
const validateSidecarsPromises: Promise<ValidatedBlobSidecars>[] = [];
|
|
493
495
|
for (let blockIndex = 0, blobSidecarIndex = 0; blockIndex < dataRequestBlocks.length; blockIndex++) {
|
|
494
496
|
const {block, blockRoot} = dataRequestBlocks[blockIndex];
|
|
495
|
-
const blockKzgCommitments = (block as SignedBeaconBlock<ForkPostDeneb>).message.body
|
|
497
|
+
const blockKzgCommitments = (block as SignedBeaconBlock<ForkPostDeneb & ForkPreFulu>).message.body
|
|
498
|
+
.blobKzgCommitments;
|
|
496
499
|
if (blockKzgCommitments.length === 0) {
|
|
497
500
|
continue;
|
|
498
501
|
}
|
|
@@ -532,8 +535,9 @@ export async function validateColumnsByRangeResponse(
|
|
|
532
535
|
columnSidecars: fulu.DataColumnSidecars
|
|
533
536
|
): Promise<WarnResult<ValidatedColumnSidecars[], DownloadByRangeError>> {
|
|
534
537
|
// Expected column count considering currently-validated batch blocks
|
|
538
|
+
// TODO GLOAS: Post-gloas's blobKzgCommitments is not in beacon block body. Need to source it from somewhere else.
|
|
535
539
|
const expectedColumnCount = dataRequestBlocks.reduce((acc, {block}) => {
|
|
536
|
-
return (block as SignedBeaconBlock<ForkPostDeneb>).message.body.blobKzgCommitments.length > 0
|
|
540
|
+
return (block as SignedBeaconBlock<ForkPostDeneb & ForkPreGloas>).message.body.blobKzgCommitments.length > 0
|
|
537
541
|
? request.columns.length + acc
|
|
538
542
|
: acc;
|
|
539
543
|
}, 0);
|
|
@@ -566,7 +570,9 @@ export async function validateColumnsByRangeResponse(
|
|
|
566
570
|
const {block, blockRoot} = dataRequestBlocks[blockIndex];
|
|
567
571
|
const slot = block.message.slot;
|
|
568
572
|
const blockRootHex = toRootHex(blockRoot);
|
|
569
|
-
|
|
573
|
+
// TODO GLOAS: Post-gloas's blobKzgCommitments is not in beacon block body. Need to source it from somewhere else.
|
|
574
|
+
const blockKzgCommitments = (block as SignedBeaconBlock<ForkPostFulu & ForkPreGloas>).message.body
|
|
575
|
+
.blobKzgCommitments;
|
|
570
576
|
const expectedColumns = blockKzgCommitments.length ? request.columns.length : 0;
|
|
571
577
|
|
|
572
578
|
if (expectedColumns === 0) {
|
|
@@ -1,7 +1,14 @@
|
|
|
1
1
|
import {routes} from "@lodestar/api";
|
|
2
2
|
import {ChainForkConfig} from "@lodestar/config";
|
|
3
|
-
import {
|
|
4
|
-
|
|
3
|
+
import {
|
|
4
|
+
ForkPostDeneb,
|
|
5
|
+
ForkPostFulu,
|
|
6
|
+
ForkPreFulu,
|
|
7
|
+
ForkPreGloas,
|
|
8
|
+
isForkPostDeneb,
|
|
9
|
+
isForkPostFulu,
|
|
10
|
+
} from "@lodestar/params";
|
|
11
|
+
import {BeaconBlockBody, BlobIndex, ColumnIndex, SignedBeaconBlock, Slot, deneb, fulu} from "@lodestar/types";
|
|
5
12
|
import {LodestarError, fromHex, prettyBytes, prettyPrintIndices, toHex, toRootHex} from "@lodestar/utils";
|
|
6
13
|
import {isBlockInputBlobs, isBlockInputColumns} from "../../chain/blocks/blockInput/blockInput.js";
|
|
7
14
|
import {BlockInputSource, IBlockInput} from "../../chain/blocks/blockInput/types.js";
|
|
@@ -269,7 +276,7 @@ export async function fetchByRoot({
|
|
|
269
276
|
missing: network.custodyConfig.sampledColumns,
|
|
270
277
|
});
|
|
271
278
|
} else if (isForkPostDeneb(forkName)) {
|
|
272
|
-
const commitments = (block as SignedBeaconBlock<ForkPostDeneb>).message.body.blobKzgCommitments;
|
|
279
|
+
const commitments = (block as SignedBeaconBlock<ForkPostDeneb & ForkPreFulu>).message.body.blobKzgCommitments;
|
|
273
280
|
const blobCount = commitments.length;
|
|
274
281
|
blobSidecars = await fetchAndValidateBlobs({
|
|
275
282
|
config,
|
|
@@ -369,7 +376,8 @@ export async function fetchAndValidateColumns({
|
|
|
369
376
|
}: FetchByRootAndValidateColumnsProps): Promise<WarnResult<fulu.DataColumnSidecars, DownloadByRootError>> {
|
|
370
377
|
const {peerId: peerIdStr} = peerMeta;
|
|
371
378
|
const slot = block.message.slot;
|
|
372
|
-
|
|
379
|
+
// TODO GLOAS: Get blob count from somewhere else since blobKzgCommitments is absent from block body
|
|
380
|
+
const blobCount = (block.message.body as BeaconBlockBody<ForkPostFulu & ForkPreGloas>).blobKzgCommitments.length;
|
|
373
381
|
if (blobCount === 0) {
|
|
374
382
|
return {result: [], warnings: null};
|
|
375
383
|
}
|