Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
73 commits
Select commit Hold shift + click to select a range
5d65a34
Add presets
ensi321 Jul 29, 2025
afd5222
Update proposer boost
ensi321 Jul 29, 2025
17f4327
Attestation
ensi321 Jul 29, 2025
651e72c
Sync committee
ensi321 Jul 30, 2025
4a12dfa
Add todo
ensi321 Jul 30, 2025
bdde5fc
Block import
ensi321 Jul 30, 2025
f840b1e
lint
ensi321 Jul 30, 2025
dad1762
update test
ensi321 Jul 30, 2025
348b17d
fix check-types
ensi321 Jul 30, 2025
7b775e6
Use bps
ensi321 Aug 11, 2025
63e11ac
Merge branch 'unstable' into nc/timing-refactor
ensi321 Aug 11, 2025
80966aa
Fix merge
ensi321 Aug 11, 2025
d6cc273
Fix timing
ensi321 Aug 12, 2025
f71b200
Attempt to fix e2e and sim tests
ensi321 Aug 13, 2025
964776a
Fix more
ensi321 Aug 13, 2025
37fb092
Reduce diff
ensi321 Aug 13, 2025
9d48b8d
Merge branch 'unstable' into nc/timing-refactor
ensi321 Aug 14, 2025
99efd68
Address @nazarhussain's comments
ensi321 Aug 19, 2025
b702060
Merge branch 'unstable' into nc/timing-refactor
ensi321 Aug 19, 2025
e846ecf
Address @nazarhussain's comments
ensi321 Aug 19, 2025
2af4bcd
Fix calculation
ensi321 Aug 19, 2025
1b91496
Address @nflaig's comment
ensi321 Aug 21, 2025
149f2d8
Merge branch 'unstable' into nc/timing-refactor
ensi321 Aug 21, 2025
118ddc7
Remove Math.round
ensi321 Aug 25, 2025
4a3640b
Update deprecated style
ensi321 Aug 25, 2025
5848358
Address various @nflaig's comments
ensi321 Aug 25, 2025
8ac4473
lint
ensi321 Aug 25, 2025
a771107
Merge branch 'unstable' into nc/timing-refactor
ensi321 Aug 25, 2025
5617e22
Fix typo
ensi321 Aug 25, 2025
63e1b10
Line break in comment
ensi321 Aug 26, 2025
9a720df
Update getSlotComponentDurationMs's signature
ensi321 Aug 28, 2025
2d96459
Update deprecated style
ensi321 Aug 28, 2025
044fe5a
Merge branch 'unstable' into nc/timing-refactor
ensi321 Sep 5, 2025
31087e6
Update vc
ensi321 Sep 16, 2025
7d52fe7
Update bn
ensi321 Sep 16, 2025
3aa7007
Merge branch 'unstable' into nc/timing-refactor
ensi321 Sep 16, 2025
741a43b
Fix sync committee function calling
ensi321 Sep 19, 2025
85b50e9
Move timing functions to inside fork config
ensi321 Sep 23, 2025
ee6138a
Update comment
ensi321 Sep 23, 2025
cbc8ad4
Remove ISlotComponentClock
ensi321 Sep 23, 2025
ea53c5a
Merge branch 'unstable' into nc/timing-refactor
ensi321 Sep 23, 2025
e0d82cf
lint
ensi321 Sep 23, 2025
618b76e
Fix check-types
ensi321 Sep 23, 2025
bc91892
Address @nflaig's comment
ensi321 Sep 23, 2025
425a1df
Set `SLOT_DURATION_MS` if not provided
ensi321 Sep 23, 2025
2f7f330
Merge branch 'unstable' into nc/timing-refactor
ensi321 Sep 24, 2025
a44a9d0
Use getAggregateDueMs instead of 2/3
nflaig Sep 24, 2025
c447ee7
Remove skipped constants from config test
nflaig Sep 24, 2025
cfb8dad
Add todo
nflaig Sep 24, 2025
c05a28b
Fix collecting vc timings
nflaig Sep 24, 2025
0c7de6d
Properly deprecate
nflaig Sep 24, 2025
19574c8
More comment updates
nflaig Sep 24, 2025
bdf42ed
Update vc dashboard titles
nflaig Sep 24, 2025
0d41b40
Update comments to match CL spec
nflaig Sep 24, 2025
9d1460f
Pass actual fork
nflaig Sep 24, 2025
0625094
Add todo
nflaig Sep 24, 2025
8fb6816
Update more spec references
nflaig Sep 24, 2025
a22d049
Fix lint/type checks
nflaig Sep 24, 2025
b33f5f2
fix: make cutoffs initialized in constructors dynamic (#8459)
nflaig Sep 24, 2025
2e37d82
Misc changes
nflaig Sep 24, 2025
6c67529
Fix interface
nflaig Sep 24, 2025
7fa264b
Deduplicate stuff
nflaig Sep 24, 2025
a3fd1d7
Update todo
nflaig Sep 24, 2025
81cd580
Simplify waitForSyncMessageCutoff
nflaig Sep 24, 2025
83e05ee
Remove stray value
nflaig Sep 24, 2025
7940173
refactor: add msFromSlot to validator clock (#8463)
nflaig Sep 24, 2025
5386e6a
Simplify updateReceivedTooEarly
nflaig Sep 24, 2025
733dead
Fix light client unit tests
nflaig Sep 24, 2025
be6264c
Use Math.round
nflaig Sep 25, 2025
0ca9387
Merge branch 'unstable' into nc/timing-refactor
nflaig Sep 25, 2025
ec1f70c
Add todo to re-evaluate 1/3 sleep
nflaig Sep 25, 2025
ddd34fa
Merge branch 'unstable' into nc/timing-refactor
nflaig Sep 25, 2025
299c283
chore: remove remaining usage of intervals (#8471)
nflaig Sep 25, 2025
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
8 changes: 4 additions & 4 deletions dashboards/lodestar_validator_client.json
Original file line number Diff line number Diff line change
Expand Up @@ -1224,7 +1224,7 @@
"refId": "A"
}
],
"title": "Publish attestation diff from slot 1/3",
"title": "Publish attestation diff from slot ATTESTATION_DUE_BPS",
"tooltip": {
"show": true,
"showHistogram": false
Expand Down Expand Up @@ -1339,7 +1339,7 @@
"refId": "A"
}
],
"title": "Publish aggregate diff from slot 2/3",
"title": "Publish aggregate diff from slot AGGREGATE_DUE_BPS",
"tooltip": {
"show": true,
"showHistogram": false
Expand Down Expand Up @@ -1452,7 +1452,7 @@
"refId": "A"
}
],
"title": "Publish sync committee message diff from slot 1/3",
"title": "Publish sync committee message diff from slot SYNC_MESSAGE_DUE_BPS",
"tooltip": {
"show": true,
"showHistogram": false
Expand Down Expand Up @@ -1565,7 +1565,7 @@
"refId": "A"
}
],
"title": "Publish block diff from slot 0/3",
"title": "Publish block diff from start of slot",
"tooltip": {
"show": true,
"showHistogram": false
Expand Down
8 changes: 5 additions & 3 deletions packages/beacon-node/src/api/impl/validator/index.ts
Original file line number Diff line number Diff line change
Expand Up @@ -66,7 +66,7 @@ import {
SyncCommitteeErrorCode,
} from "../../../chain/errors/index.js";
import {ChainEvent, CheckpointHex, CommonBlockBody} from "../../../chain/index.js";
import {SCHEDULER_LOOKAHEAD_FACTOR} from "../../../chain/prepareNextSlot.js";
import {PREPARE_NEXT_SLOT_BPS} from "../../../chain/prepareNextSlot.js";
import {BlockType, ProduceFullDeneb} from "../../../chain/produceBlock/index.js";
import {RegenCaller} from "../../../chain/regen/index.js";
import {validateApiAggregateAndProof} from "../../../chain/validation/index.js";
Expand Down Expand Up @@ -108,6 +108,8 @@ export const SYNC_TOLERANCE_EPOCHS = 1;
* Empirically the builder block resolves in ~1 second, and execution block resolves in <500 ms.
* A cutoff of 2 seconds gives enough time and if there are unexpected delays it ensures we publish
* in time as proposals post 4 seconds into the slot will likely be orphaned due to proposer boost reorg.
*
* TODO GLOAS: re-evaluate cutoff timing
*/
const BLOCK_PRODUCTION_RACE_CUTOFF_MS = 2_000;
/** Overall timeout for execution and block production apis */
Expand Down Expand Up @@ -666,7 +668,7 @@ export function getValidatorApi(
: Promise.reject(new Error("Engine disabled"));

// Calculate cutoff time based on start of the slot
const cutoffMs = Math.max(0, BLOCK_PRODUCTION_RACE_CUTOFF_MS - Math.round(chain.clock.secFromSlot(slot) * 1000));
const cutoffMs = Math.max(0, BLOCK_PRODUCTION_RACE_CUTOFF_MS - chain.clock.msFromSlot(slot));

logger.verbose("Block production race (builder vs execution) starting", {
...loggerContext,
Expand Down Expand Up @@ -1017,7 +1019,7 @@ export function getValidatorApi(
let state: CachedBeaconStateAllForks | undefined = undefined;
const startSlot = computeStartSlotAtEpoch(epoch);
const slotMs = config.SECONDS_PER_SLOT * 1000;
const prepareNextSlotLookAheadMs = slotMs / SCHEDULER_LOOKAHEAD_FACTOR;
const prepareNextSlotLookAheadMs = slotMs - config.getSlotComponentDurationMs(PREPARE_NEXT_SLOT_BPS);
const toNextEpochMs = msToNextEpoch();
// validators may request next epoch's duties when it's close to next epoch
// this is to avoid missed block proposal due to 0 epoch look ahead
Expand Down
14 changes: 4 additions & 10 deletions packages/beacon-node/src/chain/blocks/importBlock.ts
Original file line number Diff line number Diff line change
Expand Up @@ -7,14 +7,7 @@ import {
ForkChoiceErrorCode,
NotReorgedReason,
} from "@lodestar/fork-choice";
import {
ForkPostAltair,
ForkPostElectra,
ForkSeq,
INTERVALS_PER_SLOT,
MAX_SEED_LOOKAHEAD,
SLOTS_PER_EPOCH,
} from "@lodestar/params";
import {ForkPostAltair, ForkPostElectra, ForkSeq, MAX_SEED_LOOKAHEAD, SLOTS_PER_EPOCH} from "@lodestar/params";
import {
CachedBeaconStateAltair,
EpochCache,
Expand Down Expand Up @@ -267,8 +260,9 @@ export async function importBlock(
// We want to track recent blocks coming from gossip, unknown block sync, and API.
if (delaySec < SLOTS_PER_EPOCH * this.config.SECONDS_PER_SLOT) {
this.metrics.importBlock.elapsedTimeTillBecomeHead.observe(delaySec);
if (delaySec > this.config.SECONDS_PER_SLOT / INTERVALS_PER_SLOT) {
this.metrics.importBlock.setHeadAfterFirstInterval.inc();
const cutOffSec = this.config.getAttestationDueMs(this.config.getForkName(blockSlot)) / 1000;
if (delaySec > cutOffSec) {
this.metrics.importBlock.setHeadAfterCutoff.inc();
}
}
}
Expand Down
15 changes: 2 additions & 13 deletions packages/beacon-node/src/chain/chain.ts
Original file line number Diff line number Diff line change
Expand Up @@ -254,20 +254,9 @@ export class BeaconChain implements IBeaconChain {
if (!clock) clock = new Clock({config, genesisTime: this.genesisTime, signal});

this.blacklistedBlocks = new Map((opts.blacklistedBlocks ?? []).map((hex) => [hex, null]));
const preAggregateCutOffTime = (2 / 3) * this.config.SECONDS_PER_SLOT;
this.attestationPool = new AttestationPool(
config,
clock,
preAggregateCutOffTime,
this.opts?.preaggregateSlotDistance,
metrics
);
this.attestationPool = new AttestationPool(config, clock, this.opts?.preaggregateSlotDistance, metrics);
this.aggregatedAttestationPool = new AggregatedAttestationPool(this.config, metrics);
this.syncCommitteeMessagePool = new SyncCommitteeMessagePool(
clock,
preAggregateCutOffTime,
this.opts?.preaggregateSlotDistance
);
this.syncCommitteeMessagePool = new SyncCommitteeMessagePool(config, clock, this.opts?.preaggregateSlotDistance);
this.syncContributionAndProofPool = new SyncContributionAndProofPool(clock, metrics, logger);

this.seenAggregatedAttestations = new SeenAggregatedAttestations(metrics);
Expand Down
5 changes: 2 additions & 3 deletions packages/beacon-node/src/chain/opPools/attestationPool.ts
Original file line number Diff line number Diff line change
Expand Up @@ -74,7 +74,6 @@ export class AttestationPool {
constructor(
private readonly config: ChainForkConfig,
private readonly clock: IClock,
private readonly cutOffSecFromSlot: number,
private readonly preaggregateSlotDistance = 0,
private readonly metrics: Metrics | null = null
) {}
Expand All @@ -98,7 +97,7 @@ export class AttestationPool {
* `SignedAggregateAndProof`.
*
* If the attestation is too old (low slot) to be included in the pool it is simply dropped
* and no error is returned. Also if it's at clock slot but come to the pool later than 2/3
* and no error is returned. Also if it's at clock slot but come to the pool later than AGGREGATE_DUE_BPS
* of slot time, it's dropped too since it's not helpful for the validator anymore
*
* Expects the attestation to be fully validated:
Expand Down Expand Up @@ -126,7 +125,7 @@ export class AttestationPool {

// Reject gossip attestations in the current slot but come to this pool very late
// for api attestations, we allow them to be added to the pool
if (!priority && this.clock.secFromSlot(slot) > this.cutOffSecFromSlot) {
if (!priority && this.clock.msFromSlot(slot) > this.config.getAggregateDueMs(fork)) {
return InsertOutcome.Late;
}

Expand Down
Original file line number Diff line number Diff line change
@@ -1,5 +1,6 @@
import {Signature, aggregateSignatures} from "@chainsafe/blst";
import {BitArray} from "@chainsafe/ssz";
import {ChainForkConfig} from "@lodestar/config";
import {SYNC_COMMITTEE_SIZE, SYNC_COMMITTEE_SUBNET_COUNT} from "@lodestar/params";
import {Root, Slot, SubcommitteeIndex, SubnetID, altair} from "@lodestar/types";
import {MapDef, toRootHex} from "@lodestar/utils";
Expand Down Expand Up @@ -44,8 +45,8 @@ export class SyncCommitteeMessagePool {
private lowestPermissibleSlot = 0;

constructor(
private readonly config: ChainForkConfig,
private readonly clock: IClock,
private readonly cutOffSecFromSlot: number,
private readonly preaggregateSlotDistance = 0
) {}

Expand All @@ -68,6 +69,7 @@ export class SyncCommitteeMessagePool {
priority?: boolean
): InsertOutcome {
const {slot, beaconBlockRoot} = signature;
const fork = this.config.getForkName(slot);
const rootHex = toRootHex(beaconBlockRoot);
const lowestPermissibleSlot = this.lowestPermissibleSlot;

Expand All @@ -76,8 +78,8 @@ export class SyncCommitteeMessagePool {
return InsertOutcome.Old;
}

// validator gets SyncCommitteeContribution at 2/3 of slot, it's no use to preaggregate later than that time
if (!priority && this.clock.secFromSlot(slot) > this.cutOffSecFromSlot) {
// validator gets SyncCommitteeContribution at CONTRIBUTION_DUE_BPS of slot, it's no use to preaggregate later than that time
if (!priority && this.clock.msFromSlot(slot) > this.config.getSyncContributionDueMs(fork)) {
return InsertOutcome.Late;
}

Expand Down
2 changes: 1 addition & 1 deletion packages/beacon-node/src/chain/opPools/types.ts
Original file line number Diff line number Diff line change
Expand Up @@ -13,7 +13,7 @@ export enum InsertOutcome {
Old = "Old",
/** The pool has reached its limit. No changes were made. */
ReachLimit = "ReachLimit",
/** Messages don't bring any value, for example attestations come to the pool at > 2/3 of slot. No changes were made */
/** Messages don't bring any value, for example attestations come to the pool at > AGGREGATE_DUE_BPS of slot. No changes were made */
Late = "Late",
/** The data is know, and the new participants have been added to the aggregated signature */
Aggregated = "Aggregated",
Expand Down
16 changes: 8 additions & 8 deletions packages/beacon-node/src/chain/prepareNextSlot.ts
Original file line number Diff line number Diff line change
Expand Up @@ -22,17 +22,18 @@ import {IBeaconChain} from "./interface.js";
import {getPayloadAttributesForSSE, prepareExecutionPayload} from "./produceBlock/produceBlockBody.js";
import {RegenCaller} from "./regen/index.js";

/* With 12s slot times, this scheduler will run 4s before the start of each slot (`12 / 3 = 4`). */
export const SCHEDULER_LOOKAHEAD_FACTOR = 3;
// TODO GLOAS: re-evaluate this timing
/* With 12s slot times, this scheduler will run 4s before the start of each slot (`12 - 0.6667 * 12 = 4`). */
export const PREPARE_NEXT_SLOT_BPS = 6667;

/* We don't want to do more epoch transition than this */
const PREPARE_EPOCH_LIMIT = 1;

/**
* At Bellatrix, if we are responsible for proposing in next slot, we want to prepare payload
* 4s (1/3 slot) before the start of next slot
* 4s before the start of next slot at PREPARE_NEXT_SLOT_BPS of the current slot.
*
* For all forks, when clock is 1/3 slot before an epoch, we want to prepare for the next epoch
* For all forks, when clock reaches PREPARE_NEXT_SLOT_BPS of slot before an epoch, we want to prepare for the next epoch
* transition from our head so that:
* + validators vote for block head on time through attestation
* + validators propose blocks on time
Expand Down Expand Up @@ -74,10 +75,9 @@ export class PrepareNextSlotScheduler {
}

try {
// At 1/3 slot time before the next slot, we either prepare payload or precompute
// epoch transition
const slotMs = this.config.SECONDS_PER_SLOT * 1000;
await sleep(slotMs - slotMs / SCHEDULER_LOOKAHEAD_FACTOR, this.signal);
// At PREPARE_NEXT_SLOT_BPS (~67%) of the current slot we prepare payload for the next slot
// or precompute epoch transition
await sleep(this.config.getSlotComponentDurationMs(PREPARE_NEXT_SLOT_BPS), this.signal);

// calling updateHead() here before we produce a block to reduce reorg possibility
const {slot: headSlot, blockRoot: headRoot} = this.chain.recomputeForkChoiceHead(
Expand Down
Original file line number Diff line number Diff line change
@@ -1,5 +1,4 @@
import {routes} from "@lodestar/api";
import {INTERVALS_PER_SLOT} from "@lodestar/params";
import {
CachedBeaconStateAllForks,
computeStartSlotAtEpoch,
Expand Down Expand Up @@ -59,6 +58,9 @@ type LoadedStateBytesData = {persistedKey: DatastoreKey; stateBytes: Uint8Array}
*/
export const DEFAULT_MAX_CP_STATE_EPOCHS_IN_MEMORY = 3;

// TODO GLOAS: re-evaluate this timing
const PROCESS_CHECKPOINT_STATES_BPS = 6667;

/**
* An implementation of CheckpointStateCache that keep up to n epoch checkpoint states in memory and persist the rest to disk
* - If it's more than `maxEpochsInMemory` epochs old, it will persist n last epochs to disk based on the view of the block
Expand Down Expand Up @@ -464,14 +466,14 @@ export class PersistentCheckpointStateCache implements CheckpointStateCache {
}

const blockSlot = state.slot;
const twoThirdsSlot = (2 * state.config.SECONDS_PER_SLOT) / INTERVALS_PER_SLOT;
const processCPStatesTimeMs = state.config.getSlotComponentDurationMs(PROCESS_CHECKPOINT_STATES_BPS);
// we always have clock in production, fallback value is only for test
const secFromSlot = this.clock?.secFromSlot(blockSlot) ?? twoThirdsSlot;
const secToTwoThirdsSlot = twoThirdsSlot - secFromSlot;
if (secToTwoThirdsSlot > 0) {
// 2/3 of slot is the most free time of every slot, take that chance to persist checkpoint states
// normally it should only persist checkpoint states at 2/3 of slot 0 of epoch
await sleep(secToTwoThirdsSlot * 1000, this.signal);
const msFromSlot = this.clock?.msFromSlot(blockSlot) ?? processCPStatesTimeMs;
const msToProcessCPStates = processCPStatesTimeMs - msFromSlot;
if (msToProcessCPStates > 0) {
// At ~67% of slot is the most free time of every slot, take that chance to persist checkpoint states
// normally it should only persist checkpoint states at ~67% of slot 0 of epoch
await sleep(msToProcessCPStates, this.signal);
}
// at syncing time, it's critical to persist checkpoint states as soon as possible to avoid OOM during unfinality time
// 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
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -25,9 +25,10 @@ export function validateLightClientFinalityUpdate(
}

// [IGNORE] The finality_update is received after the block at signature_slot was given enough time to propagate
// through the network -- i.e. validate that one-third of finality_update.signature_slot has transpired
// (SECONDS_PER_SLOT / INTERVALS_PER_SLOT seconds after the start of the slot, with a MAXIMUM_GOSSIP_CLOCK_DISPARITY allowance)
if (updateReceivedTooEarly(config, chain.genesisTime, gossipedFinalityUpdate)) {
// through the network -- i.e. validate that `get_sync_message_due_ms(epoch)`
// milliseconds (with a `MAXIMUM_GOSSIP_CLOCK_DISPARITY` allowance) has
// transpired since the start of `signature_slot`.
if (updateReceivedTooEarly(config, chain.clock, gossipedFinalityUpdate)) {
throw new LightClientError(GossipAction.IGNORE, {
code: LightClientErrorCode.FINALITY_UPDATE_RECEIVED_TOO_EARLY,
});
Expand Down
Original file line number Diff line number Diff line change
@@ -1,8 +1,8 @@
import {ChainForkConfig} from "@lodestar/config";
import {computeTimeAtSlot} from "@lodestar/state-transition";
import {LightClientOptimisticUpdate} from "@lodestar/types";
import {MAXIMUM_GOSSIP_CLOCK_DISPARITY} from "../../constants/index.js";
import {assertLightClientServer} from "../../node/utils/lightclient.js";
import {IClock} from "../../util/clock.js";
import {GossipAction} from "../errors/index.js";
import {LightClientError, LightClientErrorCode} from "../errors/lightClientError.js";
import {IBeaconChain} from "../interface.js";
Expand All @@ -26,9 +26,10 @@ export function validateLightClientOptimisticUpdate(
}

// [IGNORE] The optimistic_update is received after the block at signature_slot was given enough time to propagate
// through the network -- i.e. validate that one-third of optimistic_update.signature_slot has transpired
// (SECONDS_PER_SLOT / INTERVALS_PER_SLOT seconds after the start of the slot, with a MAXIMUM_GOSSIP_CLOCK_DISPARITY allowance)
if (updateReceivedTooEarly(config, chain.genesisTime, gossipedOptimisticUpdate)) {
// through the network -- i.e. validate that `get_sync_message_due_ms(epoch)`
// milliseconds (with a `MAXIMUM_GOSSIP_CLOCK_DISPARITY` allowance) has
// transpired since the start of `signature_slot`.
if (updateReceivedTooEarly(config, chain.clock, gossipedOptimisticUpdate)) {
throw new LightClientError(GossipAction.IGNORE, {
code: LightClientErrorCode.OPTIMISTIC_UPDATE_RECEIVED_TOO_EARLY,
});
Expand All @@ -48,20 +49,20 @@ export function validateLightClientOptimisticUpdate(
/**
* Returns true, if the spec condition below triggers an IGNORE.
*
* Sig +1/3 time
* Sig + SYNC_MESSAGE_DUE_BPS time
* -----|-----
* xxx|------- (x is not okay)
*
* [IGNORE] The *update is received after the block at signature_slot was given enough time to propagate
* through the network -- i.e. validate that one-third of *update.signature_slot has transpired
* (SECONDS_PER_SLOT / INTERVALS_PER_SLOT seconds after the start of the slot, with a MAXIMUM_GOSSIP_CLOCK_DISPARITY allowance)
* through the network -- i.e. validate that `get_sync_message_due_ms(epoch)`
* milliseconds (with a `MAXIMUM_GOSSIP_CLOCK_DISPARITY` allowance) has
* transpired since the start of `signature_slot`.
*/
export function updateReceivedTooEarly(
config: ChainForkConfig,
genesisTime: number,
clock: IClock,
update: Pick<LightClientOptimisticUpdate, "signatureSlot">
): boolean {
const signatureSlot13TimestampMs = computeTimeAtSlot(config, update.signatureSlot + 1 / 3, genesisTime) * 1000;
const earliestAllowedTimestampMs = signatureSlot13TimestampMs - MAXIMUM_GOSSIP_CLOCK_DISPARITY;
return Date.now() < earliestAllowedTimestampMs;
const fork = config.getForkName(update.signatureSlot);
return clock.msFromSlot(update.signatureSlot) < config.getSyncMessageDueMs(fork) - MAXIMUM_GOSSIP_CLOCK_DISPARITY;
}
Loading
Loading