Skip to content

Commit

Permalink
Lint
Browse files Browse the repository at this point in the history
  • Loading branch information
ensi321 committed Sep 16, 2024
1 parent 5140630 commit 82fc1b0
Show file tree
Hide file tree
Showing 11 changed files with 102 additions and 37 deletions.
3 changes: 2 additions & 1 deletion packages/beacon-node/src/chain/chain.ts
Original file line number Diff line number Diff line change
Expand Up @@ -228,7 +228,8 @@ export class BeaconChain implements IBeaconChain {

if (!clock) clock = new Clock({config, genesisTime: this.genesisTime, signal});

const preAggregateCutOffTime = getSlotFractionFromInterval(SlotInterval.AGGREGATION_PROPAGATION) * this.config.SECONDS_PER_SLOT;
const preAggregateCutOffTime =
getSlotFractionFromInterval(SlotInterval.AGGREGATION_PROPAGATION) * this.config.SECONDS_PER_SLOT;
this.attestationPool = new AttestationPool(
config,
clock,
Expand Down
Original file line number Diff line number Diff line change
@@ -1,9 +1,13 @@
import {phase0, Epoch, RootHex} from "@lodestar/types";
import {CachedBeaconStateAllForks, ONE_INTERVAL_OF_SLOT, computeStartSlotAtEpoch, getBlockRootAtSlot, getCurrentEpoch} from "@lodestar/state-transition";
import {
CachedBeaconStateAllForks,
ONE_INTERVAL_OF_SLOT,
computeStartSlotAtEpoch,
getBlockRootAtSlot,
} from "@lodestar/state-transition";
import {Logger, MapDef, fromHex, sleep, toHex, toRootHex} from "@lodestar/utils";
import {routes} from "@lodestar/api";
import {loadCachedBeaconState} from "@lodestar/state-transition";
import {INTERVALS_PER_SLOT} from "@lodestar/params";
import {Metrics} from "../../metrics/index.js";
import {IClock} from "../../util/clock.js";
import {ShufflingCache} from "../shufflingCache.js";
Expand Down
Original file line number Diff line number Diff line change
@@ -1,12 +1,12 @@
import {ChainForkConfig} from "@lodestar/config";
import {computeTimeAtSlot} from "@lodestar/state-transition";
import {LightClientOptimisticUpdate} from "@lodestar/types";
import {ONE_INTERVAL_OF_SLOT} from "@lodestar/state-transition/src/index.js";
import {IBeaconChain} from "../interface.js";
import {LightClientError, LightClientErrorCode} from "../errors/lightClientError.js";
import {GossipAction} from "../errors/index.js";
import {MAXIMUM_GOSSIP_CLOCK_DISPARITY} from "../../constants/index.js";
import {assertLightClientServer} from "../../node/utils/lightclient.js";
import { ONE_INTERVAL_OF_SLOT } from "@lodestar/state-transition/src/index.js";

// https://github.com/ethereum/consensus-specs/blob/dev/specs/altair/light-client/p2p-interface.md#light_client_optimistic_update
export function validateLightClientOptimisticUpdate(
Expand Down Expand Up @@ -62,7 +62,8 @@ export function updateReceivedTooEarly(
genesisTime: number,
update: Pick<LightClientOptimisticUpdate, "signatureSlot">
): boolean {
const signatureSlot13TimestampMs = computeTimeAtSlot(config, update.signatureSlot + ONE_INTERVAL_OF_SLOT, genesisTime) * 1000;
const signatureSlot13TimestampMs =
computeTimeAtSlot(config, update.signatureSlot + ONE_INTERVAL_OF_SLOT, genesisTime) * 1000;
const earliestAllowedTimestampMs = signatureSlot13TimestampMs - MAXIMUM_GOSSIP_CLOCK_DISPARITY;
return Date.now() < earliestAllowedTimestampMs;
}
19 changes: 14 additions & 5 deletions packages/beacon-node/src/metrics/validatorMonitor.ts
Original file line number Diff line number Diff line change
Expand Up @@ -386,7 +386,8 @@ export function createValidatorMonitor(
registerBeaconBlock(src, seenTimestampSec, block) {
const validator = validators.get(block.proposerIndex);
// Returns the delay between the start of `block.slot` and `seenTimestamp`.
const delaySec = seenTimestampSec - computeTimeAtSlotInterval(config, block.slot, SlotInterval.BLOCK_PROPAGATION, genesisTime);
const delaySec =
seenTimestampSec - computeTimeAtSlotInterval(config, block.slot, SlotInterval.BLOCK_PROPAGATION, genesisTime);
metrics.gossipBlock.elapsedTimeTillReceived.observe(delaySec);
if (validator) {
metrics.validatorMonitor.beaconBlockTotal.inc({src});
Expand Down Expand Up @@ -430,7 +431,9 @@ export function createValidatorMonitor(
onPoolSubmitUnaggregatedAttestation(seenTimestampSec, indexedAttestation, subnet, sentPeers) {
const data = indexedAttestation.data;
// Returns the duration between when the attestation `data` could be produced (1/3rd through the slot) and `seenTimestamp`.
const delaySec = seenTimestampSec - computeTimeAtSlotInterval(config, data.slot, SlotInterval.ATTESTATION_PROPAGATION, genesisTime);
const delaySec =
seenTimestampSec -
computeTimeAtSlotInterval(config, data.slot, SlotInterval.ATTESTATION_PROPAGATION, genesisTime);
for (const index of indexedAttestation.attestingIndices) {
const validator = validators.get(index);
if (validator) {
Expand Down Expand Up @@ -463,7 +466,9 @@ export function createValidatorMonitor(
const data = indexedAttestation.data;
const epoch = computeEpochAtSlot(data.slot);
// Returns the duration between when the attestation `data` could be produced (one interval through the slot) and `seenTimestamp`.
const delaySec = seenTimestampSec - computeTimeAtSlotInterval(config, data.slot, SlotInterval.ATTESTATION_PROPAGATION, genesisTime);
const delaySec =
seenTimestampSec -
computeTimeAtSlotInterval(config, data.slot, SlotInterval.ATTESTATION_PROPAGATION, genesisTime);

for (const index of indexedAttestation.attestingIndices) {
const validator = validators.get(index);
Expand All @@ -480,7 +485,9 @@ export function createValidatorMonitor(
onPoolSubmitAggregatedAttestation(seenTimestampSec, indexedAttestation, sentPeers) {
const data = indexedAttestation.data;
// Returns the duration between when a `AggregateAndproof` with `data` could be produced (two intervals through the slot) and `seenTimestamp`.
const delaySec = seenTimestampSec - computeTimeAtSlotInterval(config, data.slot, SlotInterval.AGGREGATE_PROPAGATION, genesisTime);
const delaySec =
seenTimestampSec -
computeTimeAtSlotInterval(config, data.slot, SlotInterval.AGGREGATION_PROPAGATION, genesisTime);

for (const index of indexedAttestation.attestingIndices) {
const validator = validators.get(index);
Expand All @@ -507,7 +514,9 @@ export function createValidatorMonitor(
const data = indexedAttestation.data;
const epoch = computeEpochAtSlot(data.slot);
// Returns the duration between when a `AggregateAndProof` with `data` could be produced (two intervals through the slot) and `seenTimestamp`.
const delaySec = seenTimestampSec - computeTimeAtSlotInterval(config, data.slot, SlotInterval.AGGREGATE_PROPAGATION, genesisTime);
const delaySec =
seenTimestampSec -
computeTimeAtSlotInterval(config, data.slot, SlotInterval.AGGREGATION_PROPAGATION, genesisTime);

const aggregatorIndex = signedAggregateAndProof.message.aggregatorIndex;
const validatorAggregator = validators.get(aggregatorIndex);
Expand Down
9 changes: 7 additions & 2 deletions packages/state-transition/src/util/slot.ts
Original file line number Diff line number Diff line change
Expand Up @@ -2,7 +2,7 @@ import {ChainConfig} from "@lodestar/config";
import {GENESIS_SLOT, INTERVALS_PER_SLOT} from "@lodestar/params";
import {Slot, Epoch, TimeSeconds} from "@lodestar/types";
import {computeStartSlotAtEpoch, computeEpochAtSlot} from "./epoch.js";
import { SlotInterval, calculateSlotWithInterval } from "./slotInterval.js";
import {SlotInterval, calculateSlotWithInterval} from "./slotInterval.js";

export function getSlotsSinceGenesis(config: ChainConfig, genesisTime: TimeSeconds): Slot {
const diffInSeconds = Date.now() / 1000 - genesisTime;
Expand All @@ -23,7 +23,12 @@ export function computeTimeAtSlot(config: ChainConfig, slot: Slot, genesisTime:
}

/** Compute time in seconds of the beginnng of interval of slot */
export function computeTimeAtSlotInterval(config: ChainConfig, slot: Slot, interval: SlotInterval, genesisTime: TimeSeconds): TimeSeconds {
export function computeTimeAtSlotInterval(
config: ChainConfig,
slot: Slot,
interval: SlotInterval,
genesisTime: TimeSeconds
): TimeSeconds {
return genesisTime + calculateSlotWithInterval(slot, interval) * config.SECONDS_PER_SLOT;
}

Expand Down
9 changes: 5 additions & 4 deletions packages/state-transition/src/util/slotInterval.ts
Original file line number Diff line number Diff line change
@@ -1,17 +1,18 @@
import { INTERVALS_PER_SLOT } from "@lodestar/params";
import {INTERVALS_PER_SLOT} from "@lodestar/params";
import {Slot} from "@lodestar/types";
/**
* SlotInterval defines intervals within a slot.
* For example, attestation propagation happens at the beginning of interval 1 (second interval) of the slot
* whereas block propagation happens at the beginning of interval 0 (first interval) of the slot.
*
*
* This can also be interpret as seconds into the slot.
* For example, block propagation happens at (0 * SECONDS_PER_SLOT / INTERVALS_PER_SLOT) seconds into the slot
* and attestation propagation happens (1 * SECONDS_PER_SLOT / INTERVALS_PER_SLOT) seconds into the slot
*
*
* Some intervals might have several validator actions eg. aggregate and sync aggregate both happening at the beginning
* inteval 2.
*/
/* eslint-disable @typescript-eslint/no-duplicate-enum-values */
export enum SlotInterval {
BLOCK_PROPAGATION = 0,
SYNC_ATTESTATION_PROPAGATION = 0,
Expand All @@ -35,4 +36,4 @@ export function getSlotFractionFromInterval(interval: SlotInterval): Slot {
}
export function endOfInterval(interval: SlotInterval): Slot {
return interval + 1;
}
}
32 changes: 25 additions & 7 deletions packages/validator/src/services/attestation.ts
Original file line number Diff line number Diff line change
@@ -1,6 +1,11 @@
import {BLSSignature, phase0, Slot, ssz, Attestation, SignedAggregateAndProof} from "@lodestar/types";
import {ForkSeq} from "@lodestar/params";
import {SlotInterval, computeEpochAtSlot, endOfInterval, isAggregatorFromCommitteeLength} from "@lodestar/state-transition";
import {
SlotInterval,
computeEpochAtSlot,
endOfInterval,
isAggregatorFromCommitteeLength,
} from "@lodestar/state-transition";
import {prettyBytes, sleep, toRootHex} from "@lodestar/utils";
import {ApiClient, routes} from "@lodestar/api";
import {ChainForkConfig} from "@lodestar/config";
Expand Down Expand Up @@ -90,8 +95,13 @@ export class AttestationService {
// A validator should create and broadcast the attestation to the associated attestation subnet when either
// (a) the validator has received a valid block from the expected block proposer for the assigned slot or
// (b) one interval of the slot has transpired (SECONDS_PER_SLOT / INTERVALS_PER_SLOT seconds after the start of slot) -- whichever comes first.
await Promise.race([sleep(this.clock.msToSlotInterval(slot, SlotInterval.ATTESTATION_PROPAGATION), signal), this.emitter.waitForBlockSlot(slot)]);
this.metrics?.attesterStepCallProduceAttestation.observe(this.clock.secFromSlotInterval(slot, SlotInterval.ATTESTATION_PROPAGATION));
await Promise.race([
sleep(this.clock.msToSlotInterval(slot, SlotInterval.ATTESTATION_PROPAGATION), signal),
this.emitter.waitForBlockSlot(slot),
]);
this.metrics?.attesterStepCallProduceAttestation.observe(
this.clock.secFromSlotInterval(slot, SlotInterval.ATTESTATION_PROPAGATION)
);

if (this.opts?.disableAttestationGrouping) {
// Attestation service grouping optimization must be disabled in a distributed validator cluster as
Expand Down Expand Up @@ -135,7 +145,9 @@ export class AttestationService {
// Step 2. after all attestations are submitted, make an aggregate.
// First, wait until the beginning of SlotInterval.AGGREGATION_PROPAGATION
await sleep(this.clock.msToSlotInterval(slot, SlotInterval.AGGREGATION_PROPAGATION), signal);
this.metrics?.attesterStepCallProduceAggregate.observe(this.clock.secFromSlotInterval(slot, SlotInterval.AGGREGATION_PROPAGATION));
this.metrics?.attesterStepCallProduceAggregate.observe(
this.clock.secFromSlotInterval(slot, SlotInterval.AGGREGATION_PROPAGATION)
);

// Then download, sign and publish a `SignedAggregateAndProof` for each
// validator that is elected to aggregate for this `slot` and `committeeIndex`.
Expand All @@ -156,7 +168,9 @@ export class AttestationService {
// Step 2. after all attestations are submitted, make an aggregate.
// First, wait until the beginning of SlotInterval.AGGREGATION_PROPAGATION
await sleep(this.clock.msToSlotInterval(slot, SlotInterval.AGGREGATION_PROPAGATION), signal);
this.metrics?.attesterStepCallProduceAggregate.observe(this.clock.secFromSlotInterval(slot, SlotInterval.AGGREGATION_PROPAGATION));
this.metrics?.attesterStepCallProduceAggregate.observe(
this.clock.secFromSlotInterval(slot, SlotInterval.AGGREGATION_PROPAGATION)
);

const dutiesByCommitteeIndex = groupAttDutiesByCommitteeIndex(dutiesAll);
const isPostElectra = this.config.getForkSeq(slot) >= ForkSeq.electra;
Expand Down Expand Up @@ -227,7 +241,9 @@ export class AttestationService {
(this.opts?.afterBlockDelaySlotFraction ?? DEFAULT_AFTER_BLOCK_DELAY_SLOT_FRACTION);
await sleep(Math.min(msToAttestationInterval, afterBlockDelayMs));

this.metrics?.attesterStepCallPublishAttestation.observe(this.clock.secFromSlotInterval(slot, SlotInterval.ATTESTATION_PROPAGATION));
this.metrics?.attesterStepCallPublishAttestation.observe(
this.clock.secFromSlotInterval(slot, SlotInterval.ATTESTATION_PROPAGATION)
);

// Step 2. Publish all `Attestations` in one go
const logCtx = {
Expand Down Expand Up @@ -311,7 +327,9 @@ export class AttestationService {
})
);

this.metrics?.attesterStepCallPublishAggregate.observe(this.clock.secFromSlotInterval(attestation.slot, SlotInterval.AGGREGATION_PROPAGATION));
this.metrics?.attesterStepCallPublishAggregate.observe(
this.clock.secFromSlotInterval(attestation.slot, SlotInterval.AGGREGATION_PROPAGATION)
);

if (signedAggregateAndProofs.length > 0) {
try {
Expand Down
8 changes: 7 additions & 1 deletion packages/validator/src/services/attestationDuties.ts
Original file line number Diff line number Diff line change
@@ -1,6 +1,12 @@
import {SLOTS_PER_EPOCH} from "@lodestar/params";
import {sleep, toPubkeyHex} from "@lodestar/utils";
import {SlotInterval, computeEpochAtSlot, endOfInterval, isAggregatorFromCommitteeLength, isStartSlotOfEpoch} from "@lodestar/state-transition";
import {
SlotInterval,
computeEpochAtSlot,
endOfInterval,
isAggregatorFromCommitteeLength,
isStartSlotOfEpoch,
} from "@lodestar/state-transition";
import {BLSSignature, Epoch, Slot, ValidatorIndex, RootHex} from "@lodestar/types";
import {ApiClient, routes} from "@lodestar/api";
import {batchItems, IClock, LoggerVc} from "../util/index.js";
Expand Down
28 changes: 21 additions & 7 deletions packages/validator/src/services/syncCommittee.ts
Original file line number Diff line number Diff line change
@@ -1,7 +1,7 @@
import {ChainForkConfig} from "@lodestar/config";
import {Slot, CommitteeIndex, altair, Root, BLSSignature} from "@lodestar/types";
import {sleep} from "@lodestar/utils";
import {ONE_INTERVAL_OF_SLOT, SlotInterval, computeEpochAtSlot, endOfInterval, isSyncCommitteeAggregator} from "@lodestar/state-transition";
import {SlotInterval, computeEpochAtSlot, endOfInterval, isSyncCommitteeAggregator} from "@lodestar/state-transition";
import {ApiClient, routes} from "@lodestar/api";
import {IClock, LoggerVc} from "../util/index.js";
import {PubkeyHex} from "../types.js";
Expand Down Expand Up @@ -85,8 +85,13 @@ export class SyncCommitteeService {
// unlike Attestation, SyncCommitteeSignature could be published asap
// especially with lodestar, it's very busy at 1/3 of slot
// see https://github.com/ChainSafe/lodestar/issues/4608
await Promise.race([sleep(this.clock.msToSlotInterval(slot, endOfInterval(SlotInterval.SYNC_ATTESTATION_PROPAGATION)), signal), this.emitter.waitForBlockSlot(slot)]);
this.metrics?.syncCommitteeStepCallProduceMessage.observe(this.clock.secFromSlotInterval(slot, endOfInterval(SlotInterval.SYNC_ATTESTATION_PROPAGATION)));
await Promise.race([
sleep(this.clock.msToSlotInterval(slot, endOfInterval(SlotInterval.SYNC_ATTESTATION_PROPAGATION)), signal),
this.emitter.waitForBlockSlot(slot),
]);
this.metrics?.syncCommitteeStepCallProduceMessage.observe(
this.clock.secFromSlotInterval(slot, endOfInterval(SlotInterval.SYNC_ATTESTATION_PROPAGATION))
);

// Step 1. Download, sign and publish an `SyncCommitteeMessage` for each validator.
// Differs from AttestationService, `SyncCommitteeMessage` are equal for all
Expand All @@ -95,7 +100,9 @@ export class SyncCommitteeService {
// Step 2. If an attestation was produced, make an aggregate.
// First, wait until the beginning of SlotInterval.SYNC_AGGREGATE_PROPAGATION
await sleep(this.clock.msToSlotInterval(slot, SlotInterval.SYNC_AGGREGATE_PROPAGATION), signal);
this.metrics?.attesterStepCallProduceAggregate.observe(this.clock.secFromSlotInterval(slot, SlotInterval.SYNC_AGGREGATE_PROPAGATION));
this.metrics?.attesterStepCallProduceAggregate.observe(
this.clock.secFromSlotInterval(slot, SlotInterval.SYNC_AGGREGATE_PROPAGATION)
);

// await for all so if the Beacon node is overloaded it auto-throttles
// TODO: This approach is conservative to reduce the node's load, review
Expand Down Expand Up @@ -156,14 +163,19 @@ export class SyncCommitteeService {
// by default we want to submit SyncCommitteeSignature asap after we receive block
// provide a delay option just in case any client implementation validate the existence of block in
// SyncCommitteeSignature gossip validation.
const msToOneIntervalFromSlot = this.clock.msToSlotInterval(slot, endOfInterval(SlotInterval.SYNC_ATTESTATION_PROPAGATION));
const msToOneIntervalFromSlot = this.clock.msToSlotInterval(
slot,
endOfInterval(SlotInterval.SYNC_ATTESTATION_PROPAGATION)
);
const afterBlockDelayMs = 1000 * this.clock.secondsPerSlot * (this.opts?.scAfterBlockDelaySlotFraction ?? 0);
const toDelayMs = Math.min(msToOneIntervalFromSlot, afterBlockDelayMs);
if (toDelayMs > 0) {
await sleep(toDelayMs);
}

this.metrics?.syncCommitteeStepCallPublishMessage.observe(this.clock.secFromSlotInterval(slot, endOfInterval(SlotInterval.SYNC_ATTESTATION_PROPAGATION)));
this.metrics?.syncCommitteeStepCallPublishMessage.observe(
this.clock.secFromSlotInterval(slot, endOfInterval(SlotInterval.SYNC_ATTESTATION_PROPAGATION))
);

if (signatures.length > 0) {
try {
Expand Down Expand Up @@ -223,7 +235,9 @@ export class SyncCommitteeService {
})
);

this.metrics?.syncCommitteeStepCallPublishAggregate.observe(this.clock.secFromSlotInterval(slot, SlotInterval.SYNC_AGGREGATE_PROPAGATION));
this.metrics?.syncCommitteeStepCallPublishAggregate.observe(
this.clock.secFromSlotInterval(slot, SlotInterval.SYNC_AGGREGATE_PROPAGATION)
);

if (signedContributions.length > 0) {
try {
Expand Down
16 changes: 11 additions & 5 deletions packages/validator/src/util/clock.ts
Original file line number Diff line number Diff line change
Expand Up @@ -2,7 +2,13 @@ import {ErrorAborted, Logger, isErrorAborted, sleep} from "@lodestar/utils";
import {GENESIS_SLOT, SLOTS_PER_EPOCH} from "@lodestar/params";
import {ChainForkConfig} from "@lodestar/config";
import {Epoch, Slot, TimeSeconds} from "@lodestar/types";
import {SlotInterval, computeEpochAtSlot, computeTimeAtSlot, computeTimeAtSlotInterval, getCurrentSlot} from "@lodestar/state-transition";
import {
SlotInterval,
computeEpochAtSlot,
computeTimeAtSlot,
computeTimeAtSlotInterval,
getCurrentSlot,
} from "@lodestar/state-transition";

type RunEveryFn = (slot: Slot, signal: AbortSignal) => Promise<void>;

Expand Down Expand Up @@ -78,11 +84,11 @@ export class Clock implements IClock {
return timeAt * 1000 - Date.now();
}

/**
* Milliseconds from now to the beginning of specific interval in a specific slot
/**
* Milliseconds from now to the beginning of specific interval in a specific slot
* This function will return ms from now to the end of interval if it is called
* in `msToSlotInterval(slot, endOfInterval(interval))` manner
*/
*/
msToSlotInterval(slot: Slot, interval: SlotInterval): number {
const timeAt = computeTimeAtSlotInterval(this.config, slot, interval, this.genesisTime);
return timeAt * 1000 - Date.now();
Expand All @@ -93,7 +99,7 @@ export class Clock implements IClock {
return Date.now() / 1000 - computeTimeAtSlot(this.config, slot, this.genesisTime);
}

/**
/**
* Seconds elapsed from the beginning of specific slot interval to now
* This function will return seconds elapsed from end of slot interval to now
* if it is called in `secFromSlotInterval(slot, endOfInterval(interval))` manner
Expand Down
2 changes: 1 addition & 1 deletion packages/validator/test/utils/clock.ts
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
import {Epoch, Slot} from "@lodestar/types";
import {SlotInterval} from "@lodestar/state-transition";
import {IClock} from "../../src/util/index.js";
import { SlotInterval } from "@lodestar/state-transition";

type RunEveryFn = (slot: Slot, signal: AbortSignal) => Promise<void>;

Expand Down

0 comments on commit 82fc1b0

Please sign in to comment.