From 9f4bf50408fe51cf783a475ab6f0d2db40850753 Mon Sep 17 00:00:00 2001 From: twoeths Date: Thu, 12 Sep 2024 08:34:15 +0700 Subject: [PATCH 01/52] fix: avoid toHexString() (#7075) * fix: avoid toHexString() * fix: use toRootHex and toPubkeyHex where applicable --- packages/api/src/beacon/routes/proof.ts | 7 ++++--- packages/api/src/beacon/routes/validator.ts | 15 ++++++++------- packages/api/src/builder/routes.ts | 6 +++--- packages/api/src/utils/serdes.ts | 5 +++-- .../beacon-node/src/chain/blocks/importBlock.ts | 7 +++---- packages/beacon-node/src/chain/opPools/opPool.ts | 6 +++--- .../src/chain/stateCache/datastore/file.ts | 9 +++++---- .../stateCache/persistentCheckpointsCache.ts | 12 ++++++------ .../beacon-node/src/eth1/provider/eth1Provider.ts | 5 ++--- packages/beacon-node/src/eth1/provider/utils.ts | 8 ++++---- packages/beacon-node/src/eth1/utils/eth1Vote.ts | 1 - .../network/peers/utils/assertPeerRelevance.ts | 5 ++--- .../cli/src/cmds/validator/keymanager/server.ts | 4 ++-- packages/config/package.json | 1 + packages/config/src/chainConfig/json.ts | 5 +++-- packages/config/src/genesisConfig/index.ts | 4 ++-- packages/fork-choice/src/forkChoice/forkChoice.ts | 5 ++--- packages/fork-choice/src/protoArray/protoArray.ts | 4 ++-- packages/light-client/src/index.ts | 6 +++--- packages/logger/src/utils/json.ts | 6 +++--- .../src/block/processBlsToExecutionChange.ts | 7 +++---- .../src/block/processExecutionPayload.ts | 9 ++++----- .../src/block/processWithdrawalRequest.ts | 6 +++--- packages/utils/src/format.ts | 8 ++++---- packages/validator/src/services/attestation.ts | 5 ++--- packages/validator/src/services/validatorStore.ts | 14 +++++++------- .../interchange/formats/completeV4.ts | 6 +++--- .../slashingProtection/interchange/formats/v5.ts | 6 +++--- .../validator/src/slashingProtection/utils.ts | 7 ++++--- packages/validator/src/util/difference.ts | 6 +++--- .../validator/src/util/externalSignerClient.ts | 11 ++++++----- packages/validator/src/validator.ts | 9 ++++----- 32 files changed, 107 insertions(+), 108 deletions(-) diff --git a/packages/api/src/beacon/routes/proof.ts b/packages/api/src/beacon/routes/proof.ts index 5c20a0194fc5..a48caf02c9e7 100644 --- a/packages/api/src/beacon/routes/proof.ts +++ b/packages/api/src/beacon/routes/proof.ts @@ -1,6 +1,7 @@ /* eslint-disable @typescript-eslint/naming-convention */ import {CompactMultiProof, ProofType} from "@chainsafe/persistent-merkle-tree"; -import {ByteListType, ContainerType, fromHexString, toHexString} from "@chainsafe/ssz"; +import {ByteListType, ContainerType, fromHexString} from "@chainsafe/ssz"; +import {toHex} from "@lodestar/utils"; import {ChainForkConfig} from "@lodestar/config"; import {ssz} from "@lodestar/types"; import {Endpoint, RouteDefinitions, Schema} from "../../utils/index.js"; @@ -45,7 +46,7 @@ export function getDefinitions(_config: ChainForkConfig): RouteDefinitions ({params: {state_id: stateId}, query: {format: toHexString(descriptor)}}), + writeReq: ({stateId, descriptor}) => ({params: {state_id: stateId}, query: {format: toHex(descriptor)}}), parseReq: ({params, query}) => ({stateId: params.state_id, descriptor: fromHexString(query.format)}), schema: {params: {state_id: Schema.StringRequired}, query: {format: Schema.StringRequired}}, }, @@ -63,7 +64,7 @@ export function getDefinitions(_config: ChainForkConfig): RouteDefinitions ({params: {block_id: blockId}, query: {format: toHexString(descriptor)}}), + writeReq: ({blockId, descriptor}) => ({params: {block_id: blockId}, query: {format: toHex(descriptor)}}), parseReq: ({params, query}) => ({blockId: params.block_id, descriptor: fromHexString(query.format)}), schema: {params: {block_id: Schema.StringRequired}, query: {format: Schema.StringRequired}}, }, diff --git a/packages/api/src/beacon/routes/validator.ts b/packages/api/src/beacon/routes/validator.ts index 664caf44a2c4..3acbfec3e800 100644 --- a/packages/api/src/beacon/routes/validator.ts +++ b/packages/api/src/beacon/routes/validator.ts @@ -1,5 +1,5 @@ /* eslint-disable @typescript-eslint/naming-convention */ -import {ContainerType, fromHexString, toHexString, Type, ValueOf} from "@chainsafe/ssz"; +import {ContainerType, fromHexString, Type, ValueOf} from "@chainsafe/ssz"; import {ChainForkConfig} from "@lodestar/config"; import {isForkBlobs, isForkPostElectra} from "@lodestar/params"; import { @@ -20,6 +20,7 @@ import { Attestation, sszTypesFor, } from "@lodestar/types"; +import {toHex, toRootHex} from "@lodestar/utils"; import {Endpoint, RouteDefinitions, Schema} from "../../utils/index.js"; import {fromGraffitiHex, toBoolean, toGraffitiHex} from "../../utils/serdes.js"; import {getExecutionForkTypes, toForkName} from "../../utils/fork.js"; @@ -623,7 +624,7 @@ export function getDefinitions(config: ChainForkConfig): RouteDefinitions ({ params: {slot}, query: { - randao_reveal: toHexString(randaoReveal), + randao_reveal: toHex(randaoReveal), graffiti: toGraffitiHex(graffiti), fee_recipient: feeRecipient, builder_selection: builderSelection, @@ -674,7 +675,7 @@ export function getDefinitions(config: ChainForkConfig): RouteDefinitions ({ params: {slot}, query: { - randao_reveal: toHexString(randaoReveal), + randao_reveal: toHex(randaoReveal), graffiti: toGraffitiHex(graffiti), skip_randao_verification: writeSkipRandaoVerification(skipRandaoVerification), fee_recipient: feeRecipient, @@ -765,7 +766,7 @@ export function getDefinitions(config: ChainForkConfig): RouteDefinitions ({ params: {slot}, - query: {randao_reveal: toHexString(randaoReveal), graffiti: toGraffitiHex(graffiti)}, + query: {randao_reveal: toHex(randaoReveal), graffiti: toGraffitiHex(graffiti)}, }), parseReq: ({params, query}) => ({ slot: params.slot, @@ -805,7 +806,7 @@ export function getDefinitions(config: ChainForkConfig): RouteDefinitions ({ - query: {slot, subcommittee_index: subcommitteeIndex, beacon_block_root: toHexString(beaconBlockRoot)}, + query: {slot, subcommittee_index: subcommitteeIndex, beacon_block_root: toRootHex(beaconBlockRoot)}, }), parseReq: ({query}) => ({ slot: query.slot, @@ -830,7 +831,7 @@ export function getDefinitions(config: ChainForkConfig): RouteDefinitions ({ - query: {attestation_data_root: toHexString(attestationDataRoot), slot}, + query: {attestation_data_root: toRootHex(attestationDataRoot), slot}, }), parseReq: ({query}) => ({ attestationDataRoot: fromHexString(query.attestation_data_root), @@ -853,7 +854,7 @@ export function getDefinitions(config: ChainForkConfig): RouteDefinitions ({ - query: {attestation_data_root: toHexString(attestationDataRoot), slot, committee_index: committeeIndex}, + query: {attestation_data_root: toHex(attestationDataRoot), slot, committee_index: committeeIndex}, }), parseReq: ({query}) => ({ attestationDataRoot: fromHexString(query.attestation_data_root), diff --git a/packages/api/src/builder/routes.ts b/packages/api/src/builder/routes.ts index 3d74101bb046..ffed5a91824c 100644 --- a/packages/api/src/builder/routes.ts +++ b/packages/api/src/builder/routes.ts @@ -1,5 +1,5 @@ /* eslint-disable @typescript-eslint/naming-convention */ -import {fromHexString, toHexString} from "@chainsafe/ssz"; +import {fromHexString} from "@chainsafe/ssz"; import { ssz, bellatrix, @@ -13,7 +13,7 @@ import { } from "@lodestar/types"; import {ForkName, isForkBlobs} from "@lodestar/params"; import {ChainForkConfig} from "@lodestar/config"; -import {toPubkeyHex} from "@lodestar/utils"; +import {toPubkeyHex, toRootHex} from "@lodestar/utils"; import {Endpoint, RouteDefinitions, Schema} from "../utils/index.js"; import {MetaHeader, VersionCodec, VersionMeta} from "../utils/metadata.js"; @@ -106,7 +106,7 @@ export function getDefinitions(config: ChainForkConfig): RouteDefinitions ({ - params: {slot, parent_hash: toHexString(parentHash), pubkey: toPubkeyHex(proposerPubKey)}, + params: {slot, parent_hash: toRootHex(parentHash), pubkey: toPubkeyHex(proposerPubKey)}, }), parseReq: ({params}) => ({ slot: params.slot, diff --git a/packages/api/src/utils/serdes.ts b/packages/api/src/utils/serdes.ts index 233d7db9e7f8..8fc746ac8264 100644 --- a/packages/api/src/utils/serdes.ts +++ b/packages/api/src/utils/serdes.ts @@ -1,4 +1,5 @@ -import {fromHexString, JsonPath, toHexString} from "@chainsafe/ssz"; +import {fromHexString, JsonPath} from "@chainsafe/ssz"; +import {toHex} from "@lodestar/utils"; /** * Serialize proof path to JSON. @@ -82,7 +83,7 @@ export function toGraffitiHex(utf8?: string): string | undefined { return undefined; } - const hex = toHexString(new TextEncoder().encode(utf8)); + const hex = toHex(new TextEncoder().encode(utf8)); if (hex.length > GRAFFITI_HEX_LENGTH) { // remove characters from the end if hex string is too long diff --git a/packages/beacon-node/src/chain/blocks/importBlock.ts b/packages/beacon-node/src/chain/blocks/importBlock.ts index de5ecf607d95..4c46bdae53ee 100644 --- a/packages/beacon-node/src/chain/blocks/importBlock.ts +++ b/packages/beacon-node/src/chain/blocks/importBlock.ts @@ -1,4 +1,3 @@ -import {toHexString} from "@chainsafe/ssz"; import {capella, ssz, altair, BeaconBlock} from "@lodestar/types"; import {ForkLightClient, ForkSeq, INTERVALS_PER_SLOT, MAX_SEED_LOOKAHEAD, SLOTS_PER_EPOCH} from "@lodestar/params"; import { @@ -10,7 +9,7 @@ import { } from "@lodestar/state-transition"; import {routes} from "@lodestar/api"; import {ForkChoiceError, ForkChoiceErrorCode, EpochDifference, AncestorStatus} from "@lodestar/fork-choice"; -import {isErrorAborted, toRootHex} from "@lodestar/utils"; +import {isErrorAborted, toHex, toRootHex} from "@lodestar/utils"; import {ZERO_HASH_HEX} from "../../constants/index.js"; import {toCheckpointHex} from "../stateCache/index.js"; import {isOptimisticBlock} from "../../util/forkChoice.js"; @@ -433,8 +432,8 @@ export async function importBlock( blockRoot: blockRootHex, slot: blockSlot, index, - kzgCommitment: toHexString(kzgCommitment), - versionedHash: toHexString(kzgCommitmentToVersionedHash(kzgCommitment)), + kzgCommitment: toHex(kzgCommitment), + versionedHash: toHex(kzgCommitmentToVersionedHash(kzgCommitment)), }); } } diff --git a/packages/beacon-node/src/chain/opPools/opPool.ts b/packages/beacon-node/src/chain/opPools/opPool.ts index a2180a718fee..dc3fee0ac8a8 100644 --- a/packages/beacon-node/src/chain/opPools/opPool.ts +++ b/packages/beacon-node/src/chain/opPools/opPool.ts @@ -1,4 +1,4 @@ -import {fromHexString, toHexString} from "@chainsafe/ssz"; +import {fromHexString} from "@chainsafe/ssz"; import { CachedBeaconStateAllForks, computeEpochAtSlot, @@ -16,7 +16,7 @@ import { ForkSeq, MAX_ATTESTER_SLASHINGS_ELECTRA, } from "@lodestar/params"; -import {toRootHex} from "@lodestar/utils"; +import {toHex, toRootHex} from "@lodestar/utils"; import {Epoch, phase0, capella, ssz, ValidatorIndex, SignedBeaconBlock, AttesterSlashing} from "@lodestar/types"; import {IBeaconDb} from "../../db/index.js"; import {SignedBLSToExecutionChangeVersioned} from "../../util/types.js"; @@ -88,7 +88,7 @@ export class OpPool { key: fromHexString(key), value: value.attesterSlashing, })), - toHexString + toHex ), persistDiff( db.proposerSlashing, diff --git a/packages/beacon-node/src/chain/stateCache/datastore/file.ts b/packages/beacon-node/src/chain/stateCache/datastore/file.ts index 6529d12f84db..8a07df90d168 100644 --- a/packages/beacon-node/src/chain/stateCache/datastore/file.ts +++ b/packages/beacon-node/src/chain/stateCache/datastore/file.ts @@ -1,6 +1,7 @@ import path from "node:path"; -import {toHexString, fromHexString} from "@chainsafe/ssz"; +import {fromHexString} from "@chainsafe/ssz"; import {phase0, ssz} from "@lodestar/types"; +import {toHex} from "@lodestar/utils"; import {ensureDir, readFile, readFileNames, removeFile, writeIfNotExist} from "../../../util/file.js"; import {CPStateDatastore, DatastoreKey} from "./types.js"; @@ -28,18 +29,18 @@ export class FileCPStateDatastore implements CPStateDatastore { async write(cpKey: phase0.Checkpoint, stateBytes: Uint8Array): Promise { const serializedCheckpoint = ssz.phase0.Checkpoint.serialize(cpKey); - const filePath = path.join(this.folderPath, toHexString(serializedCheckpoint)); + const filePath = path.join(this.folderPath, toHex(serializedCheckpoint)); await writeIfNotExist(filePath, stateBytes); return serializedCheckpoint; } async remove(serializedCheckpoint: DatastoreKey): Promise { - const filePath = path.join(this.folderPath, toHexString(serializedCheckpoint)); + const filePath = path.join(this.folderPath, toHex(serializedCheckpoint)); await removeFile(filePath); } async read(serializedCheckpoint: DatastoreKey): Promise { - const filePath = path.join(this.folderPath, toHexString(serializedCheckpoint)); + const filePath = path.join(this.folderPath, toHex(serializedCheckpoint)); return readFile(filePath); } diff --git a/packages/beacon-node/src/chain/stateCache/persistentCheckpointsCache.ts b/packages/beacon-node/src/chain/stateCache/persistentCheckpointsCache.ts index 190b79e58cd6..c919c3c86233 100644 --- a/packages/beacon-node/src/chain/stateCache/persistentCheckpointsCache.ts +++ b/packages/beacon-node/src/chain/stateCache/persistentCheckpointsCache.ts @@ -1,7 +1,7 @@ -import {fromHexString, toHexString} from "@chainsafe/ssz"; +import {fromHexString} from "@chainsafe/ssz"; import {phase0, Epoch, RootHex} from "@lodestar/types"; import {CachedBeaconStateAllForks, computeStartSlotAtEpoch, getBlockRootAtSlot} from "@lodestar/state-transition"; -import {Logger, MapDef, sleep, toRootHex} from "@lodestar/utils"; +import {Logger, MapDef, sleep, toHex, toRootHex} from "@lodestar/utils"; import {routes} from "@lodestar/api"; import {loadCachedBeaconState} from "@lodestar/state-transition"; import {INTERVALS_PER_SLOT} from "@lodestar/params"; @@ -193,7 +193,7 @@ export class PersistentCheckpointStateCache implements CheckpointStateCache { return stateOrStateBytesData?.clone(opts?.dontTransferCache) ?? null; } const {persistedKey, stateBytes} = stateOrStateBytesData; - const logMeta = {persistedKey: toHexString(persistedKey)}; + const logMeta = {persistedKey: toHex(persistedKey)}; this.logger.debug("Reload: read state successful", logMeta); this.metrics?.stateReloadSecFromSlot.observe(this.clock?.secFromSlot(this.clock?.currentSlot ?? 0) ?? 0); const seedState = this.findSeedStateToReload(cp); @@ -341,7 +341,7 @@ export class PersistentCheckpointStateCache implements CheckpointStateCache { this.logger.verbose("Added checkpoint state to memory but a persisted key existed", { epoch: cp.epoch, rootHex: cpHex.rootHex, - persistedKey: toHexString(persistedKey), + persistedKey: toHex(persistedKey), }); } else { this.cache.set(key, {type: CacheItemType.inMemory, state}); @@ -688,7 +688,7 @@ export class PersistentCheckpointStateCache implements CheckpointStateCache { stateSlot: state.slot, rootHex, epochBoundaryHex, - persistedKey: persistedKey ? toHexString(persistedKey) : "", + persistedKey: persistedKey ? toHex(persistedKey) : "", }; if (persistedRootHexes.has(rootHex)) { @@ -716,7 +716,7 @@ export class PersistentCheckpointStateCache implements CheckpointStateCache { persistCount++; this.logger.verbose("Pruned checkpoint state from memory and persisted to disk", { ...logMeta, - persistedKey: toHexString(persistedKey), + persistedKey: toHex(persistedKey), }); } // overwrite cpKey, this means the state is deleted from memory diff --git a/packages/beacon-node/src/eth1/provider/eth1Provider.ts b/packages/beacon-node/src/eth1/provider/eth1Provider.ts index 3af909cd132e..c86991eb7d15 100644 --- a/packages/beacon-node/src/eth1/provider/eth1Provider.ts +++ b/packages/beacon-node/src/eth1/provider/eth1Provider.ts @@ -1,7 +1,6 @@ -import {toHexString} from "@chainsafe/ssz"; import {phase0} from "@lodestar/types"; import {ChainConfig} from "@lodestar/config"; -import {fromHex, isErrorAborted, createElapsedTimeTracker, toPrintableUrl} from "@lodestar/utils"; +import {fromHex, isErrorAborted, createElapsedTimeTracker, toPrintableUrl, toHex} from "@lodestar/utils"; import {Logger} from "@lodestar/logger"; import {FetchError, isFetchError} from "@lodestar/api"; @@ -72,7 +71,7 @@ export class Eth1Provider implements IEth1Provider { ) { this.logger = opts.logger; this.deployBlock = opts.depositContractDeployBlock ?? 0; - this.depositContractAddress = toHexString(config.DEPOSIT_CONTRACT_ADDRESS); + this.depositContractAddress = toHex(config.DEPOSIT_CONTRACT_ADDRESS); const providerUrls = opts.providerUrls ?? DEFAULT_PROVIDER_URLS; this.rpc = new JsonRpcHttpClient(providerUrls, { diff --git a/packages/beacon-node/src/eth1/provider/utils.ts b/packages/beacon-node/src/eth1/provider/utils.ts index 506e4e48711a..cddf48c40d5a 100644 --- a/packages/beacon-node/src/eth1/provider/utils.ts +++ b/packages/beacon-node/src/eth1/provider/utils.ts @@ -1,6 +1,6 @@ -import {fromHexString, toHexString} from "@chainsafe/ssz"; +import {fromHexString} from "@chainsafe/ssz"; import {RootHex} from "@lodestar/types"; -import {bytesToBigInt, bigIntToBytes} from "@lodestar/utils"; +import {bytesToBigInt, bigIntToBytes, toHex} from "@lodestar/utils"; import {ErrorParseJson} from "./jsonRpcHttpClient.js"; /** QUANTITY as defined in ethereum execution layer JSON RPC https://eth.wiki/json-rpc/API */ @@ -32,7 +32,7 @@ export function bytesToHex(bytes: Uint8Array): string { return "0x" + bytes[0].toString(16); } - return toHexString(bytes); + return toHex(bytes); } /** @@ -100,7 +100,7 @@ export function bytesToQuantity(bytes: Uint8Array): QUANTITY { * - WRONG: 004200 (must be prefixed 0x) */ export function bytesToData(bytes: Uint8Array): DATA { - return toHexString(bytes); + return toHex(bytes); } /** diff --git a/packages/beacon-node/src/eth1/utils/eth1Vote.ts b/packages/beacon-node/src/eth1/utils/eth1Vote.ts index cdc8fa04163e..7a4e3ddca9b6 100644 --- a/packages/beacon-node/src/eth1/utils/eth1Vote.ts +++ b/packages/beacon-node/src/eth1/utils/eth1Vote.ts @@ -120,7 +120,6 @@ function getKeysWithMaxValue(map: Map): T[] { * ✓ pickEth1Vote - max votes 37.89912 ops/s 26.38583 ms/op - 29 runs 1.27 s */ function getEth1DataKey(eth1Data: phase0.Eth1Data): string { - // return toHexString(ssz.phase0.Eth1Data.hashTreeRoot(eth1Data)); return fastSerializeEth1Data(eth1Data); } diff --git a/packages/beacon-node/src/network/peers/utils/assertPeerRelevance.ts b/packages/beacon-node/src/network/peers/utils/assertPeerRelevance.ts index 96e35e9d317d..e588b1ae0308 100644 --- a/packages/beacon-node/src/network/peers/utils/assertPeerRelevance.ts +++ b/packages/beacon-node/src/network/peers/utils/assertPeerRelevance.ts @@ -1,6 +1,5 @@ -import {toHexString} from "@chainsafe/ssz"; import {ForkDigest, Root, Slot, phase0, ssz} from "@lodestar/types"; -import {toRootHex} from "@lodestar/utils"; +import {toHex, toRootHex} from "@lodestar/utils"; // TODO: Why this value? (From Lighthouse) const FUTURE_SLOT_TOLERANCE = 1; @@ -79,7 +78,7 @@ export function isZeroRoot(root: Root): boolean { export function renderIrrelevantPeerType(type: IrrelevantPeerType): string { switch (type.code) { case IrrelevantPeerCode.INCOMPATIBLE_FORKS: - return `INCOMPATIBLE_FORKS ours: ${toHexString(type.ours)} theirs: ${toHexString(type.theirs)}`; + return `INCOMPATIBLE_FORKS ours: ${toHex(type.ours)} theirs: ${toHex(type.theirs)}`; case IrrelevantPeerCode.DIFFERENT_CLOCKS: return `DIFFERENT_CLOCKS slotDiff: ${type.slotDiff}`; case IrrelevantPeerCode.DIFFERENT_FINALIZED: diff --git a/packages/cli/src/cmds/validator/keymanager/server.ts b/packages/cli/src/cmds/validator/keymanager/server.ts index 03880c8b8842..cca1a1f3b76b 100644 --- a/packages/cli/src/cmds/validator/keymanager/server.ts +++ b/packages/cli/src/cmds/validator/keymanager/server.ts @@ -1,10 +1,10 @@ import crypto from "node:crypto"; import fs from "node:fs"; import path from "node:path"; -import {toHexString} from "@chainsafe/ssz"; import {RestApiServer, RestApiServerOpts, RestApiServerModules} from "@lodestar/beacon-node"; import {KeymanagerApiMethods, registerRoutes} from "@lodestar/api/keymanager/server"; import {ChainForkConfig} from "@lodestar/config"; +import {toHex} from "@lodestar/utils"; import {writeFile600Perm} from "../../../util/index.js"; export type KeymanagerRestApiServerOpts = RestApiServerOpts & { @@ -50,7 +50,7 @@ export class KeymanagerRestApiServer extends RestApiServer { if (opts.isAuthEnabled) { // Generate a new token if token file does not exist or file do exist, but is empty - bearerToken = readFileIfExists(apiTokenPath) ?? `api-token-${toHexString(crypto.randomBytes(32))}`; + bearerToken = readFileIfExists(apiTokenPath) ?? `api-token-${toHex(crypto.randomBytes(32))}`; writeFile600Perm(apiTokenPath, bearerToken, {encoding: "utf8"}); } diff --git a/packages/config/package.json b/packages/config/package.json index 45c462e19081..d13713d376c6 100644 --- a/packages/config/package.json +++ b/packages/config/package.json @@ -66,6 +66,7 @@ "dependencies": { "@chainsafe/ssz": "^0.17.1", "@lodestar/params": "^1.21.0", + "@lodestar/utils": "^1.21.0", "@lodestar/types": "^1.21.0" } } diff --git a/packages/config/src/chainConfig/json.ts b/packages/config/src/chainConfig/json.ts index 4e61333cbdee..887409cd4c5b 100644 --- a/packages/config/src/chainConfig/json.ts +++ b/packages/config/src/chainConfig/json.ts @@ -1,4 +1,5 @@ -import {fromHexString, toHexString} from "@chainsafe/ssz"; +import {fromHexString} from "@chainsafe/ssz"; +import {toHex} from "@lodestar/utils"; import {ChainConfig, chainConfigTypes, SpecValue, SpecValueTypeName} from "./types.js"; const MAX_UINT64_JSON = "18446744073709551615"; @@ -69,7 +70,7 @@ export function serializeSpecValue(value: SpecValue, typeName: SpecValueTypeName if (!(value instanceof Uint8Array)) { throw Error(`Invalid value ${value.toString()} expected Uint8Array`); } - return toHexString(value); + return toHex(value); case "string": if (typeof value !== "string") { diff --git a/packages/config/src/genesisConfig/index.ts b/packages/config/src/genesisConfig/index.ts index 52fdd03880a6..d2dfae2a8e08 100644 --- a/packages/config/src/genesisConfig/index.ts +++ b/packages/config/src/genesisConfig/index.ts @@ -1,6 +1,6 @@ -import {toHexString} from "@chainsafe/ssz"; import {ForkName, SLOTS_PER_EPOCH, DOMAIN_VOLUNTARY_EXIT} from "@lodestar/params"; import {DomainType, ForkDigest, phase0, Root, Slot, ssz, Version} from "@lodestar/types"; +import {toHex} from "@lodestar/utils"; import {ChainForkConfig} from "../beaconConfig.js"; import {ForkDigestHex, CachedGenesis} from "./types.js"; export type {ForkDigestContext} from "./types.js"; @@ -139,7 +139,7 @@ function computeForkDataRoot(currentVersion: Version, genesisValidatorsRoot: Roo } function toHexStringNoPrefix(hex: string | Uint8Array): string { - return strip0xPrefix(typeof hex === "string" ? hex : toHexString(hex)); + return strip0xPrefix(typeof hex === "string" ? hex : toHex(hex)); } function strip0xPrefix(hex: string): string { diff --git a/packages/fork-choice/src/forkChoice/forkChoice.ts b/packages/fork-choice/src/forkChoice/forkChoice.ts index 2405a442c8cd..6ae3f52e7d3a 100644 --- a/packages/fork-choice/src/forkChoice/forkChoice.ts +++ b/packages/fork-choice/src/forkChoice/forkChoice.ts @@ -1,4 +1,3 @@ -import {toHexString} from "@chainsafe/ssz"; import {Logger, fromHex, toRootHex} from "@lodestar/utils"; import {SLOTS_PER_HISTORICAL_ROOT, SLOTS_PER_EPOCH, INTERVALS_PER_SLOT} from "@lodestar/params"; import {bellatrix, Slot, ValidatorIndex, phase0, ssz, RootHex, Epoch, Root, BeaconBlock} from "@lodestar/types"; @@ -643,7 +642,7 @@ export class ForkChoice implements IForkChoice { ...(isExecutionBlockBodyType(block.body) && isExecutionStateType(state) && isExecutionEnabled(state, block) ? { - executionPayloadBlockHash: toHexString(block.body.executionPayload.blockHash), + executionPayloadBlockHash: toRootHex(block.body.executionPayload.blockHash), executionPayloadNumber: block.body.executionPayload.blockNumber, executionStatus: this.getPostMergeExecStatus(executionStatus), dataAvailabilityStatus, @@ -1484,7 +1483,7 @@ export function assertValidTerminalPowBlock( // powBock.blockHash is hex, so we just pick the corresponding root if (!ssz.Root.equals(block.body.executionPayload.parentHash, config.TERMINAL_BLOCK_HASH)) throw new Error( - `Invalid terminal block hash, expected: ${toHexString(config.TERMINAL_BLOCK_HASH)}, actual: ${toHexString( + `Invalid terminal block hash, expected: ${toRootHex(config.TERMINAL_BLOCK_HASH)}, actual: ${toRootHex( block.body.executionPayload.parentHash )}` ); diff --git a/packages/fork-choice/src/protoArray/protoArray.ts b/packages/fork-choice/src/protoArray/protoArray.ts index eaa86b2f0ee1..0b793d2be099 100644 --- a/packages/fork-choice/src/protoArray/protoArray.ts +++ b/packages/fork-choice/src/protoArray/protoArray.ts @@ -1,8 +1,8 @@ -import {toHexString} from "@chainsafe/ssz"; import {Epoch, RootHex, Slot} from "@lodestar/types"; import {computeEpochAtSlot, computeStartSlotAtEpoch} from "@lodestar/state-transition"; import {GENESIS_EPOCH} from "@lodestar/params"; +import {toRootHex} from "@lodestar/utils"; import {ForkChoiceError, ForkChoiceErrorCode} from "../forkChoice/errors.js"; import {ProtoBlock, ProtoNode, HEX_ZERO_HASH, ExecutionStatus, LVHExecResponse} from "./interface.js"; import {ProtoArrayError, ProtoArrayErrorCode, LVHExecError, LVHExecErrorCode} from "./errors.js"; @@ -10,7 +10,7 @@ import {ProtoArrayError, ProtoArrayErrorCode, LVHExecError, LVHExecErrorCode} fr export const DEFAULT_PRUNE_THRESHOLD = 0; type ProposerBoost = {root: RootHex; score: number}; -const ZERO_HASH_HEX = toHexString(Buffer.alloc(32, 0)); +const ZERO_HASH_HEX = toRootHex(Buffer.alloc(32, 0)); export class ProtoArray { // Do not attempt to prune the tree unless it has at least this many nodes. diff --git a/packages/light-client/src/index.ts b/packages/light-client/src/index.ts index 16ecf1adf939..03be60eca05d 100644 --- a/packages/light-client/src/index.ts +++ b/packages/light-client/src/index.ts @@ -1,5 +1,5 @@ import mitt from "mitt"; -import {fromHexString, toHexString} from "@chainsafe/ssz"; +import {fromHexString} from "@chainsafe/ssz"; import {EPOCHS_PER_SYNC_COMMITTEE_PERIOD} from "@lodestar/params"; import { LightClientBootstrap, @@ -13,7 +13,7 @@ import { SyncPeriod, } from "@lodestar/types"; import {createBeaconConfig, BeaconConfig, ChainForkConfig} from "@lodestar/config"; -import {isErrorAborted, sleep} from "@lodestar/utils"; +import {isErrorAborted, sleep, toRootHex} from "@lodestar/utils"; import {getCurrentSlot, slotWithFutureTolerance, timeUntilNextEpoch} from "./utils/clock.js"; import {chunkifyInclusiveRange} from "./utils/chunkify.js"; import {LightclientEmitter, LightclientEvent} from "./events.js"; @@ -162,7 +162,7 @@ export class Lightclient { const {transport, checkpointRoot} = args; // Fetch bootstrap state with proof at the trusted block root - const {data: bootstrap} = await transport.getBootstrap(toHexString(checkpointRoot)); + const {data: bootstrap} = await transport.getBootstrap(toRootHex(checkpointRoot)); validateLightClientBootstrap(args.config, checkpointRoot, bootstrap); diff --git a/packages/logger/src/utils/json.ts b/packages/logger/src/utils/json.ts index f6f2d85487c7..7408de582dd1 100644 --- a/packages/logger/src/utils/json.ts +++ b/packages/logger/src/utils/json.ts @@ -1,4 +1,4 @@ -import {LodestarError, mapValues, toHexString} from "@lodestar/utils"; +import {LodestarError, mapValues, toHex} from "@lodestar/utils"; const MAX_DEPTH = 0; @@ -29,7 +29,7 @@ export function logCtxToJson(arg: unknown, depth = 0, fromError = false): LogDat if (arg === null) return "null"; if (arg instanceof Uint8Array) { - return toHexString(arg); + return toHex(arg); } // For any type that may include recursiveness break early at the first level @@ -90,7 +90,7 @@ export function logCtxToString(arg: unknown, depth = 0, fromError = false): stri if (arg === null) return "null"; if (arg instanceof Uint8Array) { - return toHexString(arg); + return toHex(arg); } // For any type that may include recursiveness break early at the first level diff --git a/packages/state-transition/src/block/processBlsToExecutionChange.ts b/packages/state-transition/src/block/processBlsToExecutionChange.ts index 1cc3706a756f..be79f06f3f21 100644 --- a/packages/state-transition/src/block/processBlsToExecutionChange.ts +++ b/packages/state-transition/src/block/processBlsToExecutionChange.ts @@ -1,7 +1,8 @@ -import {toHexString, byteArrayEquals} from "@chainsafe/ssz"; +import {byteArrayEquals} from "@chainsafe/ssz"; import {digest} from "@chainsafe/as-sha256"; import {capella} from "@lodestar/types"; import {BLS_WITHDRAWAL_PREFIX, ETH1_ADDRESS_WITHDRAWAL_PREFIX} from "@lodestar/params"; +import {toHex} from "@lodestar/utils"; import {verifyBlsToExecutionChangeSignature} from "../signatureSets/index.js"; import {CachedBeaconStateCapella} from "../types.js"; @@ -60,9 +61,7 @@ export function isValidBlsToExecutionChange( return { valid: false, error: Error( - `Invalid withdrawalCredentials expected=${toHexString(withdrawalCredentials)} actual=${toHexString( - digestCredentials - )}` + `Invalid withdrawalCredentials expected=${toHex(withdrawalCredentials)} actual=${toHex(digestCredentials)}` ), }; } diff --git a/packages/state-transition/src/block/processExecutionPayload.ts b/packages/state-transition/src/block/processExecutionPayload.ts index 3c28a400d3bf..3d70e46d40fd 100644 --- a/packages/state-transition/src/block/processExecutionPayload.ts +++ b/packages/state-transition/src/block/processExecutionPayload.ts @@ -1,6 +1,7 @@ -import {toHexString, byteArrayEquals} from "@chainsafe/ssz"; +import {byteArrayEquals} from "@chainsafe/ssz"; import {BeaconBlockBody, BlindedBeaconBlockBody, deneb, isExecutionPayload} from "@lodestar/types"; import {ForkSeq, MAX_BLOBS_PER_BLOCK} from "@lodestar/params"; +import {toHex, toRootHex} from "@lodestar/utils"; import {CachedBeaconStateBellatrix, CachedBeaconStateCapella} from "../types.js"; import {getRandaoMix} from "../util/index.js"; import { @@ -23,7 +24,7 @@ export function processExecutionPayload( const {latestExecutionPayloadHeader} = state; if (!byteArrayEquals(payload.parentHash, latestExecutionPayloadHeader.blockHash)) { throw Error( - `Invalid execution payload parentHash ${toHexString(payload.parentHash)} latest blockHash ${toHexString( + `Invalid execution payload parentHash ${toRootHex(payload.parentHash)} latest blockHash ${toRootHex( latestExecutionPayloadHeader.blockHash )}` ); @@ -33,9 +34,7 @@ export function processExecutionPayload( // Verify random const expectedRandom = getRandaoMix(state, state.epochCtx.epoch); if (!byteArrayEquals(payload.prevRandao, expectedRandom)) { - throw Error( - `Invalid execution payload random ${toHexString(payload.prevRandao)} expected=${toHexString(expectedRandom)}` - ); + throw Error(`Invalid execution payload random ${toHex(payload.prevRandao)} expected=${toHex(expectedRandom)}`); } // Verify timestamp diff --git a/packages/state-transition/src/block/processWithdrawalRequest.ts b/packages/state-transition/src/block/processWithdrawalRequest.ts index cff1ea03bd80..0587a06ee179 100644 --- a/packages/state-transition/src/block/processWithdrawalRequest.ts +++ b/packages/state-transition/src/block/processWithdrawalRequest.ts @@ -1,4 +1,3 @@ -import {toHexString} from "@chainsafe/ssz"; import {electra, phase0, ssz} from "@lodestar/types"; import { FAR_FUTURE_EPOCH, @@ -8,6 +7,7 @@ import { ForkSeq, } from "@lodestar/params"; +import {toHex} from "@lodestar/utils"; import {CachedBeaconStateElectra} from "../types.js"; import {hasCompoundingWithdrawalCredential, hasExecutionWithdrawalCredential} from "../util/electra.js"; import {getPendingBalanceToWithdraw, isActiveValidator} from "../util/validator.js"; @@ -85,8 +85,8 @@ function isValidatorEligibleForWithdrawOrExit( state: CachedBeaconStateElectra ): boolean { const {withdrawalCredentials} = validator; - const addressStr = toHexString(withdrawalCredentials.subarray(12)); - const sourceAddressStr = toHexString(sourceAddress); + const addressStr = toHex(withdrawalCredentials.subarray(12)); + const sourceAddressStr = toHex(sourceAddress); const {epoch: currentEpoch, config} = state.epochCtx; return ( diff --git a/packages/utils/src/format.ts b/packages/utils/src/format.ts index 8bd8a40273f1..5567eb89cc68 100644 --- a/packages/utils/src/format.ts +++ b/packages/utils/src/format.ts @@ -1,4 +1,4 @@ -import {toHexString} from "./bytes.js"; +import {toRootHex} from "./bytes/index.js"; import {ETH_TO_WEI} from "./ethConversion.js"; /** @@ -6,7 +6,7 @@ import {ETH_TO_WEI} from "./ethConversion.js"; * 4 bytes can represent 4294967296 values, so the chance of collision is low */ export function prettyBytes(root: Uint8Array | string): string { - const str = typeof root === "string" ? root : toHexString(root); + const str = typeof root === "string" ? root : toRootHex(root); return `${str.slice(0, 6)}…${str.slice(-4)}`; } @@ -15,7 +15,7 @@ export function prettyBytes(root: Uint8Array | string): string { * Paired with block numbers or slots, it can still act as a decent identify-able format */ export function prettyBytesShort(root: Uint8Array | string): string { - const str = typeof root === "string" ? root : toHexString(root); + const str = typeof root === "string" ? root : toRootHex(root); return `${str.slice(0, 6)}…`; } @@ -25,7 +25,7 @@ export function prettyBytesShort(root: Uint8Array | string): string { * values on explorers like beaconcha.in while improving readability of logs */ export function truncBytes(root: Uint8Array | string): string { - const str = typeof root === "string" ? root : toHexString(root); + const str = typeof root === "string" ? root : toRootHex(root); return str.slice(0, 14); } diff --git a/packages/validator/src/services/attestation.ts b/packages/validator/src/services/attestation.ts index 927bd3d92bb4..7f0dffa3e970 100644 --- a/packages/validator/src/services/attestation.ts +++ b/packages/validator/src/services/attestation.ts @@ -1,8 +1,7 @@ -import {toHexString} from "@chainsafe/ssz"; import {BLSSignature, phase0, Slot, ssz, Attestation, SignedAggregateAndProof} from "@lodestar/types"; import {ForkSeq} from "@lodestar/params"; import {computeEpochAtSlot, isAggregatorFromCommitteeLength} from "@lodestar/state-transition"; -import {prettyBytes, sleep} from "@lodestar/utils"; +import {prettyBytes, sleep, toRootHex} from "@lodestar/utils"; import {ApiClient, routes} from "@lodestar/api"; import {ChainForkConfig} from "@lodestar/config"; import {IClock, LoggerVc} from "../util/index.js"; @@ -195,7 +194,7 @@ export class AttestationService { duties: AttDutyAndProof[] ): Promise { const signedAttestations: Attestation[] = []; - const headRootHex = toHexString(attestationNoCommittee.beaconBlockRoot); + const headRootHex = toRootHex(attestationNoCommittee.beaconBlockRoot); const currentEpoch = computeEpochAtSlot(slot); const isPostElectra = currentEpoch >= this.config.ELECTRA_FORK_EPOCH; diff --git a/packages/validator/src/services/validatorStore.ts b/packages/validator/src/services/validatorStore.ts index c6130f1fab95..b64917ec03ae 100644 --- a/packages/validator/src/services/validatorStore.ts +++ b/packages/validator/src/services/validatorStore.ts @@ -1,4 +1,4 @@ -import {BitArray, fromHexString, toHexString} from "@chainsafe/ssz"; +import {BitArray, fromHexString} from "@chainsafe/ssz"; import {SecretKey} from "@chainsafe/blst"; import { computeEpochAtSlot, @@ -42,7 +42,7 @@ import { SignedAggregateAndProof, } from "@lodestar/types"; import {routes} from "@lodestar/api"; -import {toPubkeyHex} from "@lodestar/utils"; +import {toPubkeyHex, toRootHex} from "@lodestar/utils"; import {ISlashingProtection} from "../slashingProtection/index.js"; import {PubkeyHex} from "../types.js"; import {externalSignerPostSignature, SignableMessageType, SignableMessage} from "../util/externalSignerClient.js"; @@ -459,8 +459,8 @@ export class ValidatorStore { logger?.debug("Signing the block proposal", { slot: signingSlot, - blockRoot: toHexString(blockRoot), - signingRoot: toHexString(signingRoot), + blockRoot: toRootHex(blockRoot), + signingRoot: toRootHex(signingRoot), }); try { @@ -748,7 +748,7 @@ export class ValidatorStore { signingSlot: Slot, signableMessage: SignableMessage ): Promise { - // TODO: Refactor indexing to not have to run toHexString() on the pubkey every time + // TODO: Refactor indexing to not have to run toHex() on the pubkey every time const pubkeyHex = typeof pubkey === "string" ? pubkey : toPubkeyHex(pubkey); const signer = this.validators.get(pubkeyHex)?.signer; @@ -787,7 +787,7 @@ export class ValidatorStore { } private getSignerAndPubkeyHex(pubkey: BLSPubkeyMaybeHex): [Signer, string] { - // TODO: Refactor indexing to not have to run toHexString() on the pubkey every time + // TODO: Refactor indexing to not have to run toHex() on the pubkey every time const pubkeyHex = typeof pubkey === "string" ? pubkey : toPubkeyHex(pubkey); const signer = this.validators.get(pubkeyHex)?.signer; if (!signer) { @@ -824,7 +824,7 @@ export class ValidatorStore { function getSignerPubkeyHex(signer: Signer): PubkeyHex { switch (signer.type) { case SignerType.Local: - return toHexString(signer.secretKey.toPublicKey().toBytes()); + return toPubkeyHex(signer.secretKey.toPublicKey().toBytes()); case SignerType.Remote: if (!isValidatePubkeyHex(signer.pubkey)) { diff --git a/packages/validator/src/slashingProtection/interchange/formats/completeV4.ts b/packages/validator/src/slashingProtection/interchange/formats/completeV4.ts index 66aa31c52194..d1e9475daa0e 100644 --- a/packages/validator/src/slashingProtection/interchange/formats/completeV4.ts +++ b/packages/validator/src/slashingProtection/interchange/formats/completeV4.ts @@ -1,6 +1,6 @@ /* eslint-disable @typescript-eslint/naming-convention */ -import {fromHexString, toHexString} from "@chainsafe/ssz"; -import {toPubkeyHex} from "@lodestar/utils"; +import {fromHexString} from "@chainsafe/ssz"; +import {toPubkeyHex, toRootHex} from "@lodestar/utils"; import {InterchangeLodestar} from "../types.js"; import {fromOptionalHexString, numToString, toOptionalHexString} from "../../utils.js"; @@ -91,7 +91,7 @@ export function serializeInterchangeCompleteV4({ metadata: { interchange_format: "complete", interchange_format_version: "4", - genesis_validators_root: toHexString(genesisValidatorsRoot), + genesis_validators_root: toRootHex(genesisValidatorsRoot), }, data: data.map((validator) => ({ pubkey: toPubkeyHex(validator.pubkey), diff --git a/packages/validator/src/slashingProtection/interchange/formats/v5.ts b/packages/validator/src/slashingProtection/interchange/formats/v5.ts index 1c7f67b706a5..20d11aefe91a 100644 --- a/packages/validator/src/slashingProtection/interchange/formats/v5.ts +++ b/packages/validator/src/slashingProtection/interchange/formats/v5.ts @@ -1,6 +1,6 @@ /* eslint-disable @typescript-eslint/naming-convention */ -import {fromHexString, toHexString} from "@chainsafe/ssz"; -import {toPubkeyHex} from "@lodestar/utils"; +import {fromHexString} from "@chainsafe/ssz"; +import {toPubkeyHex, toRootHex} from "@lodestar/utils"; import {InterchangeLodestar} from "../types.js"; import {fromOptionalHexString, numToString, toOptionalHexString} from "../../utils.js"; @@ -86,7 +86,7 @@ export function serializeInterchangeV5({data, genesisValidatorsRoot}: Interchang return { metadata: { interchange_format_version: "5", - genesis_validators_root: toHexString(genesisValidatorsRoot), + genesis_validators_root: toRootHex(genesisValidatorsRoot), }, data: data.map((validator) => ({ pubkey: toPubkeyHex(validator.pubkey), diff --git a/packages/validator/src/slashingProtection/utils.ts b/packages/validator/src/slashingProtection/utils.ts index f1fc0f24b9ae..294036981b14 100644 --- a/packages/validator/src/slashingProtection/utils.ts +++ b/packages/validator/src/slashingProtection/utils.ts @@ -1,5 +1,6 @@ -import {fromHexString, toHexString} from "@chainsafe/ssz"; +import {fromHexString} from "@chainsafe/ssz"; import {Epoch, Root, ssz} from "@lodestar/types"; +import {toHex, toRootHex} from "@lodestar/utils"; export const blsPubkeyLen = 48; export const ZERO_ROOT = ssz.Root.defaultValue(); @@ -17,7 +18,7 @@ export function fromOptionalHexString(hex: string | undefined): Root { } export function toOptionalHexString(root: Root): string | undefined { - return isEqualRoot(root, ZERO_ROOT) ? undefined : toHexString(root); + return isEqualRoot(root, ZERO_ROOT) ? undefined : toRootHex(root); } /** @@ -34,7 +35,7 @@ export function minEpoch(epochs: Epoch[]): Epoch | null { export function uniqueVectorArr(buffers: Uint8Array[]): Uint8Array[] { const bufferStr = new Set(); return buffers.filter((buffer) => { - const str = toHexString(buffer); + const str = toHex(buffer); const seen = bufferStr.has(str); bufferStr.add(str); return !seen; diff --git a/packages/validator/src/util/difference.ts b/packages/validator/src/util/difference.ts index bafc6ff8f42f..b8c3c5e7b089 100644 --- a/packages/validator/src/util/difference.ts +++ b/packages/validator/src/util/difference.ts @@ -1,10 +1,10 @@ -import {toHexString} from "@chainsafe/ssz"; import {Root} from "@lodestar/types"; +import {toHex} from "@lodestar/utils"; /** * Return items included in `next` but not in `prev` */ export function differenceHex(prev: T[], next: T[]): T[] { - const existing = new Set(prev.map((item) => toHexString(item))); - return next.filter((item) => !existing.has(toHexString(item))); + const existing = new Set(prev.map((item) => toHex(item))); + return next.filter((item) => !existing.has(toHex(item))); } diff --git a/packages/validator/src/util/externalSignerClient.ts b/packages/validator/src/util/externalSignerClient.ts index dc1d0d0f1dd5..4fd615ce5280 100644 --- a/packages/validator/src/util/externalSignerClient.ts +++ b/packages/validator/src/util/externalSignerClient.ts @@ -1,4 +1,4 @@ -import {ContainerType, toHexString, ValueOf} from "@chainsafe/ssz"; +import {ContainerType, ValueOf} from "@chainsafe/ssz"; import {fetch} from "@lodestar/api"; import {phase0, altair, capella, BeaconBlock, BlindedBeaconBlock} from "@lodestar/types"; import {ForkSeq} from "@lodestar/params"; @@ -6,6 +6,7 @@ import {ValidatorRegistrationV1} from "@lodestar/types/bellatrix"; import {BeaconConfig} from "@lodestar/config"; import {computeEpochAtSlot, blindedOrFullBlockToHeader} from "@lodestar/state-transition"; import {Epoch, Root, RootHex, Slot, ssz} from "@lodestar/types"; +import {toHex, toRootHex} from "@lodestar/utils"; import {PubkeyHex} from "../types.js"; /* eslint-disable @typescript-eslint/naming-convention */ @@ -131,17 +132,17 @@ export async function externalSignerPostSignature( const requestObj = serializerSignableMessagePayload(config, signableMessage) as Web3SignerSerializedRequest; requestObj.type = signableMessage.type; - requestObj.signingRoot = toHexString(signingRoot); + requestObj.signingRoot = toRootHex(signingRoot); if (requiresForkInfo[signableMessage.type]) { const forkInfo = config.getForkInfo(signingSlot); requestObj.fork_info = { fork: { - previous_version: toHexString(forkInfo.prevVersion), - current_version: toHexString(forkInfo.version), + previous_version: toHex(forkInfo.prevVersion), + current_version: toHex(forkInfo.version), epoch: String(computeEpochAtSlot(signingSlot)), }, - genesis_validators_root: toHexString(config.genesisValidatorsRoot), + genesis_validators_root: toRootHex(config.genesisValidatorsRoot), }; } diff --git a/packages/validator/src/validator.ts b/packages/validator/src/validator.ts index 8ec8f3330af2..980e64f7eac2 100644 --- a/packages/validator/src/validator.ts +++ b/packages/validator/src/validator.ts @@ -1,8 +1,7 @@ -import {toHexString} from "@chainsafe/ssz"; import {BLSPubkey, phase0, ssz} from "@lodestar/types"; import {createBeaconConfig, BeaconConfig, ChainForkConfig} from "@lodestar/config"; import {Genesis} from "@lodestar/types/phase0"; -import {Logger, toPrintableUrl} from "@lodestar/utils"; +import {Logger, toPrintableUrl, toRootHex} from "@lodestar/utils"; import {getClient, ApiClient, routes, ApiRequestInit, defaultInit} from "@lodestar/api"; import {computeEpochAtSlot, getCurrentSlot} from "@lodestar/state-transition"; import {Clock, IClock} from "./util/clock.js"; @@ -397,14 +396,14 @@ async function assertEqualGenesis(opts: ValidatorOptions, genesis: Genesis): Pro if (!ssz.Root.equals(genesisValidatorsRoot, nodeGenesisValidatorRoot)) { // this happens when the existing validator db served another network before opts.logger.error("Not the same genesisValidatorRoot", { - expected: toHexString(nodeGenesisValidatorRoot), - actual: toHexString(genesisValidatorsRoot), + expected: toRootHex(nodeGenesisValidatorRoot), + actual: toRootHex(genesisValidatorsRoot), }); throw new NotEqualParamsError("Not the same genesisValidatorRoot"); } } else { await metaDataRepository.setGenesisValidatorsRoot(nodeGenesisValidatorRoot); - opts.logger.info("Persisted genesisValidatorRoot", toHexString(nodeGenesisValidatorRoot)); + opts.logger.info("Persisted genesisValidatorRoot", toRootHex(nodeGenesisValidatorRoot)); } const nodeGenesisTime = genesis.genesisTime; From d6e8c057d23fcb2e6f8ed1c13d27dbdc6a52e1d0 Mon Sep 17 00:00:00 2001 From: twoeths Date: Fri, 13 Sep 2024 20:07:32 +0700 Subject: [PATCH 02/52] chore: avoid fromHexString (#7080) * fix: fromHexString() to fromHex() * fix: throw error for NodeJS fromHex() if malformed string * fix: correct hex value in sim test --- packages/api/src/beacon/routes/proof.ts | 8 ++++---- packages/api/src/beacon/routes/validator.ts | 16 ++++++++-------- packages/api/src/builder/routes.ts | 7 +++---- packages/api/src/utils/serdes.ts | 6 +++--- .../src/chain/archiver/archiveBlocks.ts | 9 ++++----- packages/beacon-node/src/chain/chain.ts | 16 ++++++++-------- packages/beacon-node/src/chain/opPools/opPool.ts | 5 ++--- packages/beacon-node/src/chain/regen/regen.ts | 5 ++--- .../src/chain/stateCache/datastore/file.ts | 5 ++--- .../stateCache/persistentCheckpointsCache.ts | 7 +++---- packages/beacon-node/src/eth1/index.ts | 4 ++-- packages/beacon-node/src/eth1/provider/utils.ts | 5 ++--- .../src/eth1/utils/depositContract.ts | 10 +++++----- .../beacon-node/src/network/core/networkCore.ts | 5 ++--- .../reqresp/beaconBlocksMaybeBlobsByRoot.ts | 4 ++-- packages/beacon-node/src/sync/unknownBlock.ts | 7 +++---- packages/cli/src/cmds/lightclient/handler.ts | 4 ++-- .../src/cmds/validator/blsToExecutionChange.ts | 7 +++---- .../cli/src/cmds/validator/keymanager/impl.ts | 5 ++--- packages/cli/src/util/format.ts | 4 ++-- .../utils/crucible/assertions/blobsAssertion.ts | 2 +- .../config/src/chainConfig/configs/mainnet.ts | 2 +- .../config/src/chainConfig/configs/minimal.ts | 2 +- packages/config/src/chainConfig/json.ts | 5 ++--- .../config/src/chainConfig/networks/chiado.ts | 2 +- .../config/src/chainConfig/networks/ephemery.ts | 2 +- .../config/src/chainConfig/networks/gnosis.ts | 2 +- .../config/src/chainConfig/networks/holesky.ts | 2 +- .../config/src/chainConfig/networks/mainnet.ts | 2 +- .../config/src/chainConfig/networks/sepolia.ts | 2 +- packages/light-client/src/index.ts | 5 ++--- .../state-transition/src/cache/epochCache.ts | 5 ++--- packages/utils/src/bytes/nodejs.ts | 14 +++++++++++++- .../validator/src/services/chainHeaderTracker.ts | 5 ++--- .../src/services/doppelgangerService.ts | 5 ++--- .../validator/src/services/externalSignerSync.ts | 5 ++--- .../validator/src/services/validatorStore.ts | 10 +++++----- .../interchange/formats/completeV4.ts | 7 +++---- .../slashingProtection/interchange/formats/v5.ts | 7 +++---- .../validator/src/slashingProtection/utils.ts | 5 ++--- 40 files changed, 111 insertions(+), 119 deletions(-) diff --git a/packages/api/src/beacon/routes/proof.ts b/packages/api/src/beacon/routes/proof.ts index a48caf02c9e7..2ef4dad15e81 100644 --- a/packages/api/src/beacon/routes/proof.ts +++ b/packages/api/src/beacon/routes/proof.ts @@ -1,7 +1,7 @@ /* eslint-disable @typescript-eslint/naming-convention */ import {CompactMultiProof, ProofType} from "@chainsafe/persistent-merkle-tree"; -import {ByteListType, ContainerType, fromHexString} from "@chainsafe/ssz"; -import {toHex} from "@lodestar/utils"; +import {ByteListType, ContainerType} from "@chainsafe/ssz"; +import {fromHex, toHex} from "@lodestar/utils"; import {ChainForkConfig} from "@lodestar/config"; import {ssz} from "@lodestar/types"; import {Endpoint, RouteDefinitions, Schema} from "../../utils/index.js"; @@ -47,7 +47,7 @@ export function getDefinitions(_config: ChainForkConfig): RouteDefinitions ({params: {state_id: stateId}, query: {format: toHex(descriptor)}}), - parseReq: ({params, query}) => ({stateId: params.state_id, descriptor: fromHexString(query.format)}), + parseReq: ({params, query}) => ({stateId: params.state_id, descriptor: fromHex(query.format)}), schema: {params: {state_id: Schema.StringRequired}, query: {format: Schema.StringRequired}}, }, resp: { @@ -65,7 +65,7 @@ export function getDefinitions(_config: ChainForkConfig): RouteDefinitions ({params: {block_id: blockId}, query: {format: toHex(descriptor)}}), - parseReq: ({params, query}) => ({blockId: params.block_id, descriptor: fromHexString(query.format)}), + parseReq: ({params, query}) => ({blockId: params.block_id, descriptor: fromHex(query.format)}), schema: {params: {block_id: Schema.StringRequired}, query: {format: Schema.StringRequired}}, }, resp: { diff --git a/packages/api/src/beacon/routes/validator.ts b/packages/api/src/beacon/routes/validator.ts index 3acbfec3e800..a9a1423e4da2 100644 --- a/packages/api/src/beacon/routes/validator.ts +++ b/packages/api/src/beacon/routes/validator.ts @@ -1,5 +1,5 @@ /* eslint-disable @typescript-eslint/naming-convention */ -import {ContainerType, fromHexString, Type, ValueOf} from "@chainsafe/ssz"; +import {ContainerType, Type, ValueOf} from "@chainsafe/ssz"; import {ChainForkConfig} from "@lodestar/config"; import {isForkBlobs, isForkPostElectra} from "@lodestar/params"; import { @@ -20,7 +20,7 @@ import { Attestation, sszTypesFor, } from "@lodestar/types"; -import {toHex, toRootHex} from "@lodestar/utils"; +import {fromHex, toHex, toRootHex} from "@lodestar/utils"; import {Endpoint, RouteDefinitions, Schema} from "../../utils/index.js"; import {fromGraffitiHex, toBoolean, toGraffitiHex} from "../../utils/serdes.js"; import {getExecutionForkTypes, toForkName} from "../../utils/fork.js"; @@ -633,7 +633,7 @@ export function getDefinitions(config: ChainForkConfig): RouteDefinitions ({ slot: params.slot, - randaoReveal: fromHexString(query.randao_reveal), + randaoReveal: fromHex(query.randao_reveal), graffiti: fromGraffitiHex(query.graffiti), feeRecipient: query.fee_recipient, builderSelection: query.builder_selection as BuilderSelection, @@ -687,7 +687,7 @@ export function getDefinitions(config: ChainForkConfig): RouteDefinitions ({ slot: params.slot, - randaoReveal: fromHexString(query.randao_reveal), + randaoReveal: fromHex(query.randao_reveal), graffiti: fromGraffitiHex(query.graffiti), skipRandaoVerification: parseSkipRandaoVerification(query.skip_randao_verification), feeRecipient: query.fee_recipient, @@ -770,7 +770,7 @@ export function getDefinitions(config: ChainForkConfig): RouteDefinitions ({ slot: params.slot, - randaoReveal: fromHexString(query.randao_reveal), + randaoReveal: fromHex(query.randao_reveal), graffiti: fromGraffitiHex(query.graffiti), }), schema: { @@ -811,7 +811,7 @@ export function getDefinitions(config: ChainForkConfig): RouteDefinitions ({ slot: query.slot, subcommitteeIndex: query.subcommittee_index, - beaconBlockRoot: fromHexString(query.beacon_block_root), + beaconBlockRoot: fromHex(query.beacon_block_root), }), schema: { query: { @@ -834,7 +834,7 @@ export function getDefinitions(config: ChainForkConfig): RouteDefinitions ({ - attestationDataRoot: fromHexString(query.attestation_data_root), + attestationDataRoot: fromHex(query.attestation_data_root), slot: query.slot, }), schema: { @@ -857,7 +857,7 @@ export function getDefinitions(config: ChainForkConfig): RouteDefinitions ({ - attestationDataRoot: fromHexString(query.attestation_data_root), + attestationDataRoot: fromHex(query.attestation_data_root), slot: query.slot, committeeIndex: query.committee_index, }), diff --git a/packages/api/src/builder/routes.ts b/packages/api/src/builder/routes.ts index ffed5a91824c..7459e46abd0b 100644 --- a/packages/api/src/builder/routes.ts +++ b/packages/api/src/builder/routes.ts @@ -1,5 +1,4 @@ /* eslint-disable @typescript-eslint/naming-convention */ -import {fromHexString} from "@chainsafe/ssz"; import { ssz, bellatrix, @@ -13,7 +12,7 @@ import { } from "@lodestar/types"; import {ForkName, isForkBlobs} from "@lodestar/params"; import {ChainForkConfig} from "@lodestar/config"; -import {toPubkeyHex, toRootHex} from "@lodestar/utils"; +import {fromHex, toPubkeyHex, toRootHex} from "@lodestar/utils"; import {Endpoint, RouteDefinitions, Schema} from "../utils/index.js"; import {MetaHeader, VersionCodec, VersionMeta} from "../utils/metadata.js"; @@ -110,8 +109,8 @@ export function getDefinitions(config: ChainForkConfig): RouteDefinitions ({ slot: params.slot, - parentHash: fromHexString(params.parent_hash), - proposerPubkey: fromHexString(params.pubkey), + parentHash: fromHex(params.parent_hash), + proposerPubkey: fromHex(params.pubkey), }), schema: { params: {slot: Schema.UintRequired, parent_hash: Schema.StringRequired, pubkey: Schema.StringRequired}, diff --git a/packages/api/src/utils/serdes.ts b/packages/api/src/utils/serdes.ts index 8fc746ac8264..282c2514e00d 100644 --- a/packages/api/src/utils/serdes.ts +++ b/packages/api/src/utils/serdes.ts @@ -1,5 +1,5 @@ -import {fromHexString, JsonPath} from "@chainsafe/ssz"; -import {toHex} from "@lodestar/utils"; +import {JsonPath} from "@chainsafe/ssz"; +import {fromHex, toHex} from "@lodestar/utils"; /** * Serialize proof path to JSON. @@ -103,7 +103,7 @@ export function fromGraffitiHex(hex?: string): string | undefined { return undefined; } try { - return new TextDecoder("utf8").decode(fromHexString(hex)); + return new TextDecoder("utf8").decode(fromHex(hex)); } catch { // allow malformed graffiti hex string return hex; diff --git a/packages/beacon-node/src/chain/archiver/archiveBlocks.ts b/packages/beacon-node/src/chain/archiver/archiveBlocks.ts index ed6dd5bfc091..8e1ac456579a 100644 --- a/packages/beacon-node/src/chain/archiver/archiveBlocks.ts +++ b/packages/beacon-node/src/chain/archiver/archiveBlocks.ts @@ -1,7 +1,6 @@ -import {fromHexString} from "@chainsafe/ssz"; import {Epoch, Slot, RootHex} from "@lodestar/types"; import {IForkChoice} from "@lodestar/fork-choice"; -import {Logger, toRootHex} from "@lodestar/utils"; +import {Logger, fromHex, toRootHex} from "@lodestar/utils"; import {ForkSeq, SLOTS_PER_EPOCH} from "@lodestar/params"; import {computeEpochAtSlot, computeStartSlotAtEpoch} from "@lodestar/state-transition"; import {KeyValue} from "@lodestar/db"; @@ -48,7 +47,7 @@ export async function archiveBlocks( const finalizedCanonicalBlockRoots: BlockRootSlot[] = finalizedCanonicalBlocks.map((block) => ({ slot: block.slot, - root: fromHexString(block.blockRoot), + root: fromHex(block.blockRoot), })); if (finalizedCanonicalBlockRoots.length > 0) { @@ -68,7 +67,7 @@ export async function archiveBlocks( // deleteNonCanonicalBlocks // loop through forkchoice single time - const nonCanonicalBlockRoots = finalizedNonCanonicalBlocks.map((summary) => fromHexString(summary.blockRoot)); + const nonCanonicalBlockRoots = finalizedNonCanonicalBlocks.map((summary) => fromHex(summary.blockRoot)); if (nonCanonicalBlockRoots.length > 0) { await db.block.batchDelete(nonCanonicalBlockRoots); logger.verbose("Deleted non canonical blocks from hot DB", { @@ -144,7 +143,7 @@ async function migrateBlocksFromHotToColdDb(db: IBeaconDb, blocks: BlockRootSlot value: blockBuffer, slot: block.slot, blockRoot: block.root, - // TODO: Benchmark if faster to slice Buffer or fromHexString() + // TODO: Benchmark if faster to slice Buffer or fromHex() parentRoot: getParentRootFromSignedBlock(blockBuffer), }; }) diff --git a/packages/beacon-node/src/chain/chain.ts b/packages/beacon-node/src/chain/chain.ts index 8dbb49798538..ee70231c7d40 100644 --- a/packages/beacon-node/src/chain/chain.ts +++ b/packages/beacon-node/src/chain/chain.ts @@ -1,5 +1,5 @@ import path from "node:path"; -import {CompositeTypeAny, fromHexString, TreeView, Type} from "@chainsafe/ssz"; +import {CompositeTypeAny, TreeView, Type} from "@chainsafe/ssz"; import { BeaconStateAllForks, CachedBeaconStateAllForks, @@ -35,7 +35,7 @@ import { } from "@lodestar/types"; import {CheckpointWithHex, ExecutionStatus, IForkChoice, ProtoBlock, UpdateHeadOpt} from "@lodestar/fork-choice"; import {ProcessShutdownCallback} from "@lodestar/validator"; -import {Logger, gweiToWei, isErrorAborted, pruneSetToMax, sleep, toRootHex} from "@lodestar/utils"; +import {Logger, fromHex, gweiToWei, isErrorAborted, pruneSetToMax, sleep, toRootHex} from "@lodestar/utils"; import {ForkSeq, GENESIS_SLOT, SLOTS_PER_EPOCH} from "@lodestar/params"; import {GENESIS_EPOCH, ZERO_HASH} from "../constants/index.js"; @@ -521,7 +521,7 @@ export class BeaconChain implements IBeaconChain { }; } - const data = await this.db.stateArchive.getByRoot(fromHexString(stateRoot)); + const data = await this.db.stateArchive.getByRoot(fromHex(stateRoot)); return data && {state: data, executionOptimistic: false, finalized: true}; } @@ -568,7 +568,7 @@ export class BeaconChain implements IBeaconChain { // Unfinalized slot, attempt to find in fork-choice const block = this.forkChoice.getCanonicalBlockAtSlot(slot); if (block) { - const data = await this.db.block.get(fromHexString(block.blockRoot)); + const data = await this.db.block.get(fromHex(block.blockRoot)); if (data) { return {block: data, executionOptimistic: isOptimisticBlock(block), finalized: false}; } @@ -587,7 +587,7 @@ export class BeaconChain implements IBeaconChain { ): Promise<{block: SignedBeaconBlock; executionOptimistic: boolean; finalized: boolean} | null> { const block = this.forkChoice.getBlockHex(root); if (block) { - const data = await this.db.block.get(fromHexString(root)); + const data = await this.db.block.get(fromHex(root)); if (data) { return {block: data, executionOptimistic: isOptimisticBlock(block), finalized: false}; } @@ -595,7 +595,7 @@ export class BeaconChain implements IBeaconChain { // TODO: Add a lock to the archiver to have deterministic behavior on where are blocks } - const data = await this.db.blockArchive.getByRoot(fromHexString(root)); + const data = await this.db.blockArchive.getByRoot(fromHex(root)); return data && {block: data, executionOptimistic: false, finalized: true}; } @@ -768,7 +768,7 @@ export class BeaconChain implements IBeaconChain { finalizedRoot: finalizedCheckpoint.epoch === GENESIS_EPOCH ? ZERO_HASH : finalizedCheckpoint.root, finalizedEpoch: finalizedCheckpoint.epoch, // TODO: PERFORMANCE: Memoize to prevent re-computing every time - headRoot: fromHexString(head.blockRoot), + headRoot: fromHex(head.blockRoot), headSlot: head.slot, }; } @@ -1120,7 +1120,7 @@ export class BeaconChain implements IBeaconChain { // TODO: Improve using regen here const {blockRoot, stateRoot, slot} = this.forkChoice.getHead(); const headState = this.regen.getStateSync(stateRoot); - const headBlock = await this.db.block.get(fromHexString(blockRoot)); + const headBlock = await this.db.block.get(fromHex(blockRoot)); if (headBlock == null) { throw Error(`Head block ${slot} ${headBlock} is not available in database`); } diff --git a/packages/beacon-node/src/chain/opPools/opPool.ts b/packages/beacon-node/src/chain/opPools/opPool.ts index dc3fee0ac8a8..ee66591e9aef 100644 --- a/packages/beacon-node/src/chain/opPools/opPool.ts +++ b/packages/beacon-node/src/chain/opPools/opPool.ts @@ -1,4 +1,3 @@ -import {fromHexString} from "@chainsafe/ssz"; import { CachedBeaconStateAllForks, computeEpochAtSlot, @@ -16,7 +15,7 @@ import { ForkSeq, MAX_ATTESTER_SLASHINGS_ELECTRA, } from "@lodestar/params"; -import {toHex, toRootHex} from "@lodestar/utils"; +import {fromHex, toHex, toRootHex} from "@lodestar/utils"; import {Epoch, phase0, capella, ssz, ValidatorIndex, SignedBeaconBlock, AttesterSlashing} from "@lodestar/types"; import {IBeaconDb} from "../../db/index.js"; import {SignedBLSToExecutionChangeVersioned} from "../../util/types.js"; @@ -85,7 +84,7 @@ export class OpPool { persistDiff( db.attesterSlashing, Array.from(this.attesterSlashings.entries()).map(([key, value]) => ({ - key: fromHexString(key), + key: fromHex(key), value: value.attesterSlashing, })), toHex diff --git a/packages/beacon-node/src/chain/regen/regen.ts b/packages/beacon-node/src/chain/regen/regen.ts index 04cf5b40b494..08fda70d9184 100644 --- a/packages/beacon-node/src/chain/regen/regen.ts +++ b/packages/beacon-node/src/chain/regen/regen.ts @@ -1,4 +1,3 @@ -import {fromHexString} from "@chainsafe/ssz"; import {phase0, Slot, RootHex, BeaconBlock, SignedBeaconBlock} from "@lodestar/types"; import { CachedBeaconStateAllForks, @@ -11,7 +10,7 @@ import { StateHashTreeRootSource, } from "@lodestar/state-transition"; import {IForkChoice, ProtoBlock} from "@lodestar/fork-choice"; -import {Logger, toRootHex} from "@lodestar/utils"; +import {Logger, fromHex, toRootHex} from "@lodestar/utils"; import {SLOTS_PER_EPOCH} from "@lodestar/params"; import {ChainForkConfig} from "@lodestar/config"; import {Metrics} from "../../metrics/index.js"; @@ -216,7 +215,7 @@ export class StateRegenerator implements IStateRegeneratorInternal { const protoBlocksAsc = blocksToReplay.reverse(); for (const [i, protoBlock] of protoBlocksAsc.entries()) { replaySlots[i] = protoBlock.slot; - blockPromises[i] = this.modules.db.block.get(fromHexString(protoBlock.blockRoot)); + blockPromises[i] = this.modules.db.block.get(fromHex(protoBlock.blockRoot)); } const logCtx = {stateRoot, replaySlots: replaySlots.join(",")}; diff --git a/packages/beacon-node/src/chain/stateCache/datastore/file.ts b/packages/beacon-node/src/chain/stateCache/datastore/file.ts index 8a07df90d168..f487079ae443 100644 --- a/packages/beacon-node/src/chain/stateCache/datastore/file.ts +++ b/packages/beacon-node/src/chain/stateCache/datastore/file.ts @@ -1,7 +1,6 @@ import path from "node:path"; -import {fromHexString} from "@chainsafe/ssz"; import {phase0, ssz} from "@lodestar/types"; -import {toHex} from "@lodestar/utils"; +import {fromHex, toHex} from "@lodestar/utils"; import {ensureDir, readFile, readFileNames, removeFile, writeIfNotExist} from "../../../util/file.js"; import {CPStateDatastore, DatastoreKey} from "./types.js"; @@ -48,6 +47,6 @@ export class FileCPStateDatastore implements CPStateDatastore { const fileNames = await readFileNames(this.folderPath); return fileNames .filter((fileName) => fileName.startsWith("0x") && fileName.length === CHECKPOINT_FILE_NAME_LENGTH) - .map((fileName) => fromHexString(fileName)); + .map((fileName) => fromHex(fileName)); } } diff --git a/packages/beacon-node/src/chain/stateCache/persistentCheckpointsCache.ts b/packages/beacon-node/src/chain/stateCache/persistentCheckpointsCache.ts index c919c3c86233..d8769374a29c 100644 --- a/packages/beacon-node/src/chain/stateCache/persistentCheckpointsCache.ts +++ b/packages/beacon-node/src/chain/stateCache/persistentCheckpointsCache.ts @@ -1,7 +1,6 @@ -import {fromHexString} from "@chainsafe/ssz"; import {phase0, Epoch, RootHex} from "@lodestar/types"; import {CachedBeaconStateAllForks, computeStartSlotAtEpoch, getBlockRootAtSlot} from "@lodestar/state-transition"; -import {Logger, MapDef, sleep, toHex, toRootHex} from "@lodestar/utils"; +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"; @@ -657,7 +656,7 @@ export class PersistentCheckpointStateCache implements CheckpointStateCache { let persistCount = 0; const epochBoundarySlot = computeStartSlotAtEpoch(epoch); const epochBoundaryRoot = - epochBoundarySlot === state.slot ? fromHexString(blockRootHex) : getBlockRootAtSlot(state, epochBoundarySlot); + epochBoundarySlot === state.slot ? fromHex(blockRootHex) : getBlockRootAtSlot(state, epochBoundarySlot); const epochBoundaryHex = toRootHex(epochBoundaryRoot); const prevEpochRoot = toRootHex(getBlockRootAtSlot(state, epochBoundarySlot - 1)); @@ -698,7 +697,7 @@ export class PersistentCheckpointStateCache implements CheckpointStateCache { } else { // persist and do not update epochIndex this.metrics?.statePersistSecFromSlot.observe(this.clock?.secFromSlot(this.clock?.currentSlot ?? 0) ?? 0); - const cpPersist = {epoch: epoch, root: fromHexString(rootHex)}; + const cpPersist = {epoch: epoch, root: fromHex(rootHex)}; // It's not sustainable to allocate ~240MB for each state every epoch, so we use buffer pool to reuse the memory. // As monitored on holesky as of Jan 2024: // - This does not increase heap allocation while gc time is the same diff --git a/packages/beacon-node/src/eth1/index.ts b/packages/beacon-node/src/eth1/index.ts index a8ba55c54141..7b2ec17496d3 100644 --- a/packages/beacon-node/src/eth1/index.ts +++ b/packages/beacon-node/src/eth1/index.ts @@ -1,6 +1,6 @@ -import {fromHexString} from "@chainsafe/ssz"; import {CachedBeaconStateAllForks} from "@lodestar/state-transition"; import {Root} from "@lodestar/types"; +import {fromHex} from "@lodestar/utils"; import {IEth1ForBlockProduction, Eth1DataAndDeposits, IEth1Provider, PowMergeBlock, TDProgress} from "./interface.js"; import {Eth1DepositDataTracker, Eth1DepositDataTrackerModules} from "./eth1DepositDataTracker.js"; import {Eth1MergeBlockTracker, Eth1MergeBlockTrackerModules} from "./eth1MergeBlockTracker.js"; @@ -92,7 +92,7 @@ export class Eth1ForBlockProduction implements IEth1ForBlockProduction { async getTerminalPowBlock(): Promise { const block = await this.eth1MergeBlockTracker.getTerminalPowBlock(); - return block && fromHexString(block.blockHash); + return block && fromHex(block.blockHash); } getPowBlock(powBlockHash: string): Promise { diff --git a/packages/beacon-node/src/eth1/provider/utils.ts b/packages/beacon-node/src/eth1/provider/utils.ts index cddf48c40d5a..096f1d7233c8 100644 --- a/packages/beacon-node/src/eth1/provider/utils.ts +++ b/packages/beacon-node/src/eth1/provider/utils.ts @@ -1,6 +1,5 @@ -import {fromHexString} from "@chainsafe/ssz"; import {RootHex} from "@lodestar/types"; -import {bytesToBigInt, bigIntToBytes, toHex} from "@lodestar/utils"; +import {bytesToBigInt, bigIntToBytes, toHex, fromHex} from "@lodestar/utils"; import {ErrorParseJson} from "./jsonRpcHttpClient.js"; /** QUANTITY as defined in ethereum execution layer JSON RPC https://eth.wiki/json-rpc/API */ @@ -108,7 +107,7 @@ export function bytesToData(bytes: Uint8Array): DATA { */ export function dataToBytes(hex: DATA, fixedLength: number | null): Uint8Array { try { - const bytes = fromHexString(hex); + const bytes = fromHex(hex); if (fixedLength != null && bytes.length !== fixedLength) { throw Error(`Wrong data length ${bytes.length} expected ${fixedLength}`); } diff --git a/packages/beacon-node/src/eth1/utils/depositContract.ts b/packages/beacon-node/src/eth1/utils/depositContract.ts index 7247fe8cebaf..b576a3d5f61c 100644 --- a/packages/beacon-node/src/eth1/utils/depositContract.ts +++ b/packages/beacon-node/src/eth1/utils/depositContract.ts @@ -1,6 +1,6 @@ import {Interface} from "@ethersproject/abi"; -import {fromHexString} from "@chainsafe/ssz"; import {phase0, ssz} from "@lodestar/types"; +import {fromHex} from "@lodestar/utils"; const depositEventFragment = "event DepositEvent(bytes pubkey, bytes withdrawal_credentials, bytes amount, bytes signature, bytes index)"; @@ -23,15 +23,15 @@ export function parseDepositLog(log: {blockNumber: number; data: string; topics: blockNumber: log.blockNumber, index: parseHexNumLittleEndian(values.index), depositData: { - pubkey: fromHexString(values.pubkey), - withdrawalCredentials: fromHexString(values.withdrawal_credentials), + pubkey: fromHex(values.pubkey), + withdrawalCredentials: fromHex(values.withdrawal_credentials), amount: parseHexNumLittleEndian(values.amount), - signature: fromHexString(values.signature), + signature: fromHex(values.signature), }, }; } function parseHexNumLittleEndian(hex: string): number { // Can't use parseInt() because amount is a hex string in little endian - return ssz.UintNum64.deserialize(fromHexString(hex)); + return ssz.UintNum64.deserialize(fromHex(hex)); } diff --git a/packages/beacon-node/src/network/core/networkCore.ts b/packages/beacon-node/src/network/core/networkCore.ts index 07b346bc29e4..83ef4c4fb063 100644 --- a/packages/beacon-node/src/network/core/networkCore.ts +++ b/packages/beacon-node/src/network/core/networkCore.ts @@ -2,13 +2,12 @@ import {Connection, PeerId} from "@libp2p/interface"; import {multiaddr} from "@multiformats/multiaddr"; import {PublishOpts} from "@chainsafe/libp2p-gossipsub/types"; import {PeerScoreStatsDump} from "@chainsafe/libp2p-gossipsub/dist/src/score/peer-score.js"; -import {fromHexString} from "@chainsafe/ssz"; import {ENR} from "@chainsafe/enr"; import {routes} from "@lodestar/api"; import {BeaconConfig} from "@lodestar/config"; import type {LoggerNode} from "@lodestar/logger/node"; import {Epoch, phase0} from "@lodestar/types"; -import {withTimeout} from "@lodestar/utils"; +import {fromHex, withTimeout} from "@lodestar/utils"; import {ForkName} from "@lodestar/params"; import {ResponseIncoming} from "@lodestar/reqresp"; import {Libp2p} from "../interface.js"; @@ -195,7 +194,7 @@ export class NetworkCore implements INetworkCore { await gossip.start(); const enr = opts.discv5?.enr; - const nodeId = enr ? fromHexString(ENR.decodeTxt(enr).nodeId) : null; + const nodeId = enr ? fromHex(ENR.decodeTxt(enr).nodeId) : null; const attnetsService = new AttnetsService(config, clock, gossip, metadata, logger, metrics, nodeId, opts); const syncnetsService = new SyncnetsService(config, clock, gossip, metadata, logger, metrics, opts); diff --git a/packages/beacon-node/src/network/reqresp/beaconBlocksMaybeBlobsByRoot.ts b/packages/beacon-node/src/network/reqresp/beaconBlocksMaybeBlobsByRoot.ts index 2b802ab1edd9..b53addab9b43 100644 --- a/packages/beacon-node/src/network/reqresp/beaconBlocksMaybeBlobsByRoot.ts +++ b/packages/beacon-node/src/network/reqresp/beaconBlocksMaybeBlobsByRoot.ts @@ -1,7 +1,7 @@ -import {fromHexString} from "@chainsafe/ssz"; import {ChainForkConfig} from "@lodestar/config"; import {phase0, deneb} from "@lodestar/types"; import {ForkSeq} from "@lodestar/params"; +import {fromHex} from "@lodestar/utils"; import { BlockInput, BlockInputType, @@ -66,7 +66,7 @@ export async function unavailableBeaconBlobsByRoot( // resolve the block if thats unavailable let block, blobsCache, blockBytes, resolveAvailability, cachedData; if (unavailableBlockInput.block === null) { - const allBlocks = await network.sendBeaconBlocksByRoot(peerId, [fromHexString(unavailableBlockInput.blockRootHex)]); + const allBlocks = await network.sendBeaconBlocksByRoot(peerId, [fromHex(unavailableBlockInput.blockRootHex)]); block = allBlocks[0].data; blockBytes = allBlocks[0].bytes; cachedData = unavailableBlockInput.cachedData; diff --git a/packages/beacon-node/src/sync/unknownBlock.ts b/packages/beacon-node/src/sync/unknownBlock.ts index d985847d450f..a172b5d723db 100644 --- a/packages/beacon-node/src/sync/unknownBlock.ts +++ b/packages/beacon-node/src/sync/unknownBlock.ts @@ -1,6 +1,5 @@ -import {fromHexString} from "@chainsafe/ssz"; import {ChainForkConfig} from "@lodestar/config"; -import {Logger, pruneSetToMax, toRootHex} from "@lodestar/utils"; +import {Logger, fromHex, pruneSetToMax, toRootHex} from "@lodestar/utils"; import {Root, RootHex, deneb} from "@lodestar/types"; import {INTERVALS_PER_SLOT} from "@lodestar/params"; import {sleep} from "@lodestar/utils"; @@ -288,7 +287,7 @@ export class UnknownBlockSync { let res; if (block.blockInput === null) { - res = await wrapError(this.fetchUnknownBlockRoot(fromHexString(block.blockRootHex), connectedPeers)); + res = await wrapError(this.fetchUnknownBlockRoot(fromHex(block.blockRootHex), connectedPeers)); } else { res = await wrapError(this.fetchUnavailableBlockInput(block.blockInput, connectedPeers)); } @@ -519,7 +518,7 @@ export class UnknownBlockSync { if (unavailableBlockInput.block === null) { blockRootHex = unavailableBlockInput.blockRootHex; - blockRoot = fromHexString(blockRootHex); + blockRoot = fromHex(blockRootHex); } else { const unavailableBlock = unavailableBlockInput.block; blockRoot = this.config diff --git a/packages/cli/src/cmds/lightclient/handler.ts b/packages/cli/src/cmds/lightclient/handler.ts index a8e3d7333f98..5af8f84d8959 100644 --- a/packages/cli/src/cmds/lightclient/handler.ts +++ b/packages/cli/src/cmds/lightclient/handler.ts @@ -1,9 +1,9 @@ import path from "node:path"; -import {fromHexString} from "@chainsafe/ssz"; import {getClient} from "@lodestar/api"; import {Lightclient} from "@lodestar/light-client"; import {LightClientRestTransport} from "@lodestar/light-client/transport"; import {getNodeLogger} from "@lodestar/logger/node"; +import {fromHex} from "@lodestar/utils"; import {getBeaconConfigFromArgs} from "../../config/beaconParams.js"; import {getGlobalPaths} from "../../paths/global.js"; import {parseLoggerArgs} from "../../util/logger.js"; @@ -28,7 +28,7 @@ export async function lightclientHandler(args: ILightClientArgs & GlobalArgs): P genesisTime, genesisValidatorsRoot, }, - checkpointRoot: fromHexString(args.checkpointRoot), + checkpointRoot: fromHex(args.checkpointRoot), transport: new LightClientRestTransport(api), }); diff --git a/packages/cli/src/cmds/validator/blsToExecutionChange.ts b/packages/cli/src/cmds/validator/blsToExecutionChange.ts index 3a2fabcc37eb..dc55647fda80 100644 --- a/packages/cli/src/cmds/validator/blsToExecutionChange.ts +++ b/packages/cli/src/cmds/validator/blsToExecutionChange.ts @@ -1,11 +1,10 @@ -import {fromHexString} from "@chainsafe/ssz"; import {SecretKey} from "@chainsafe/blst"; import {computeSigningRoot} from "@lodestar/state-transition"; import {DOMAIN_BLS_TO_EXECUTION_CHANGE, ForkName} from "@lodestar/params"; import {createBeaconConfig} from "@lodestar/config"; import {ssz, capella} from "@lodestar/types"; import {getClient} from "@lodestar/api"; -import {CliCommand} from "@lodestar/utils"; +import {CliCommand, fromHex} from "@lodestar/utils"; import {GlobalArgs} from "../../options/index.js"; import {getBeaconConfigFromArgs} from "../../config/index.js"; @@ -67,13 +66,13 @@ like to choose for BLS To Execution Change.", throw new Error(`Validator pubkey ${publicKey} not found in state`); } - const blsPrivkey = SecretKey.fromBytes(fromHexString(args.fromBlsPrivkey)); + const blsPrivkey = SecretKey.fromBytes(fromHex(args.fromBlsPrivkey)); const fromBlsPubkey = blsPrivkey.toPublicKey().toBytes(); const blsToExecutionChange: capella.BLSToExecutionChange = { validatorIndex: validator.index, fromBlsPubkey, - toExecutionAddress: fromHexString(args.toExecutionAddress), + toExecutionAddress: fromHex(args.toExecutionAddress), }; const signatureFork = ForkName.phase0; diff --git a/packages/cli/src/cmds/validator/keymanager/impl.ts b/packages/cli/src/cmds/validator/keymanager/impl.ts index 2915c125eac2..d965b2af5075 100644 --- a/packages/cli/src/cmds/validator/keymanager/impl.ts +++ b/packages/cli/src/cmds/validator/keymanager/impl.ts @@ -1,5 +1,4 @@ import {Keystore} from "@chainsafe/bls-keystore"; -import {fromHexString} from "@chainsafe/ssz"; import {SecretKey} from "@chainsafe/blst"; import { DeleteRemoteKeyStatus, @@ -21,7 +20,7 @@ import {KeymanagerApiMethods as Api} from "@lodestar/api/keymanager/server"; import {Interchange, SignerType, Validator} from "@lodestar/validator"; import {ApiError} from "@lodestar/api/server"; import {Epoch} from "@lodestar/types"; -import {isValidHttpUrl} from "@lodestar/utils"; +import {fromHex, isValidHttpUrl} from "@lodestar/utils"; import {getPubkeyHexFromKeystore, isValidatePubkeyHex} from "../../../util/format.js"; import {parseFeeRecipient} from "../../../util/index.js"; import {DecryptKeystoresThreadPool} from "./decryptKeystores/index.js"; @@ -224,7 +223,7 @@ export class KeymanagerApi implements Api { } } - const pubkeysBytes = pubkeys.map((pubkeyHex) => fromHexString(pubkeyHex)); + const pubkeysBytes = pubkeys.map((pubkeyHex) => fromHex(pubkeyHex)); const interchangeV5 = await this.validator.exportInterchange(pubkeysBytes, { version: "5", diff --git a/packages/cli/src/util/format.ts b/packages/cli/src/util/format.ts index 01c2753193a4..a86ca0662a9f 100644 --- a/packages/cli/src/util/format.ts +++ b/packages/cli/src/util/format.ts @@ -1,5 +1,5 @@ import {PublicKey} from "@chainsafe/blst"; -import {fromHexString} from "@chainsafe/ssz"; +import {fromHex} from "@lodestar/utils"; /** * 0x prefix a string if not prefixed already @@ -50,7 +50,7 @@ export function parseRange(range: string): number[] { export function assertValidPubkeysHex(pubkeysHex: string[]): void { for (const pubkeyHex of pubkeysHex) { - const pubkeyBytes = fromHexString(pubkeyHex); + const pubkeyBytes = fromHex(pubkeyHex); PublicKey.fromBytes(pubkeyBytes, true); } } diff --git a/packages/cli/test/utils/crucible/assertions/blobsAssertion.ts b/packages/cli/test/utils/crucible/assertions/blobsAssertion.ts index dece5bc58ce8..50c9ed13f972 100644 --- a/packages/cli/test/utils/crucible/assertions/blobsAssertion.ts +++ b/packages/cli/test/utils/crucible/assertions/blobsAssertion.ts @@ -35,7 +35,7 @@ export function createBlobsAssertion( gasLimit: "0xc350", maxPriorityFeePerGas: "0x3b9aca00", maxFeePerGas: "0x3ba26b20", - maxFeePerBlobGas: "0x3e8", + maxFeePerBlobGas: "0x3e", value: "0x10000", nonce: `0x${(nonce ?? 0).toString(16)}`, blobVersionedHashes, diff --git a/packages/config/src/chainConfig/configs/mainnet.ts b/packages/config/src/chainConfig/configs/mainnet.ts index 741ddc99f8cd..e5792a87ac70 100644 --- a/packages/config/src/chainConfig/configs/mainnet.ts +++ b/packages/config/src/chainConfig/configs/mainnet.ts @@ -1,5 +1,5 @@ /* eslint-disable @typescript-eslint/naming-convention */ -import {fromHexString as b} from "@chainsafe/ssz"; +import {fromHex as b} from "@lodestar/utils"; import {PresetName} from "@lodestar/params"; import {ChainConfig} from "../types.js"; diff --git a/packages/config/src/chainConfig/configs/minimal.ts b/packages/config/src/chainConfig/configs/minimal.ts index 26f49cc3e47d..53229d283511 100644 --- a/packages/config/src/chainConfig/configs/minimal.ts +++ b/packages/config/src/chainConfig/configs/minimal.ts @@ -1,5 +1,5 @@ /* eslint-disable @typescript-eslint/naming-convention */ -import {fromHexString as b} from "@chainsafe/ssz"; +import {fromHex as b} from "@lodestar/utils"; import {PresetName} from "@lodestar/params"; import {ChainConfig} from "../types.js"; diff --git a/packages/config/src/chainConfig/json.ts b/packages/config/src/chainConfig/json.ts index 887409cd4c5b..78db9230c836 100644 --- a/packages/config/src/chainConfig/json.ts +++ b/packages/config/src/chainConfig/json.ts @@ -1,5 +1,4 @@ -import {fromHexString} from "@chainsafe/ssz"; -import {toHex} from "@lodestar/utils"; +import {fromHex, toHex} from "@lodestar/utils"; import {ChainConfig, chainConfigTypes, SpecValue, SpecValueTypeName} from "./types.js"; const MAX_UINT64_JSON = "18446744073709551615"; @@ -96,7 +95,7 @@ export function deserializeSpecValue(valueStr: unknown, typeName: SpecValueTypeN return BigInt(valueStr); case "bytes": - return fromHexString(valueStr); + return fromHex(valueStr); case "string": return valueStr; diff --git a/packages/config/src/chainConfig/networks/chiado.ts b/packages/config/src/chainConfig/networks/chiado.ts index 43b13a210dac..d96bd7510c65 100644 --- a/packages/config/src/chainConfig/networks/chiado.ts +++ b/packages/config/src/chainConfig/networks/chiado.ts @@ -1,5 +1,5 @@ /* eslint-disable @typescript-eslint/naming-convention */ -import {fromHexString as b} from "@chainsafe/ssz"; +import {fromHex as b} from "@lodestar/utils"; import {ChainConfig} from "../types.js"; import {gnosisChainConfig as gnosis} from "./gnosis.js"; diff --git a/packages/config/src/chainConfig/networks/ephemery.ts b/packages/config/src/chainConfig/networks/ephemery.ts index 29e3f7b92d01..6fefc1800bfc 100644 --- a/packages/config/src/chainConfig/networks/ephemery.ts +++ b/packages/config/src/chainConfig/networks/ephemery.ts @@ -1,5 +1,5 @@ /* eslint-disable @typescript-eslint/naming-convention */ -import {fromHexString as b} from "@chainsafe/ssz"; +import {fromHex as b} from "@lodestar/utils"; import {ChainConfig} from "../types.js"; import {chainConfig as mainnet} from "../configs/mainnet.js"; diff --git a/packages/config/src/chainConfig/networks/gnosis.ts b/packages/config/src/chainConfig/networks/gnosis.ts index 8034e478fd28..2f58ffd4d045 100644 --- a/packages/config/src/chainConfig/networks/gnosis.ts +++ b/packages/config/src/chainConfig/networks/gnosis.ts @@ -1,5 +1,5 @@ /* eslint-disable @typescript-eslint/naming-convention */ -import {fromHexString as b} from "@chainsafe/ssz"; +import {fromHex as b} from "@lodestar/utils"; import {PresetName} from "@lodestar/params"; import {ChainConfig} from "../types.js"; import {chainConfig as mainnet} from "../configs/mainnet.js"; diff --git a/packages/config/src/chainConfig/networks/holesky.ts b/packages/config/src/chainConfig/networks/holesky.ts index 187543b871f2..16c462a9468e 100644 --- a/packages/config/src/chainConfig/networks/holesky.ts +++ b/packages/config/src/chainConfig/networks/holesky.ts @@ -1,5 +1,5 @@ /* eslint-disable @typescript-eslint/naming-convention */ -import {fromHexString as b} from "@chainsafe/ssz"; +import {fromHex as b} from "@lodestar/utils"; import {ChainConfig} from "../types.js"; import {chainConfig as mainnet} from "../configs/mainnet.js"; diff --git a/packages/config/src/chainConfig/networks/mainnet.ts b/packages/config/src/chainConfig/networks/mainnet.ts index 24584ad8442b..c137c578fc0e 100644 --- a/packages/config/src/chainConfig/networks/mainnet.ts +++ b/packages/config/src/chainConfig/networks/mainnet.ts @@ -1,5 +1,5 @@ /* eslint-disable @typescript-eslint/naming-convention */ -import {fromHexString as b} from "@chainsafe/ssz"; +import {fromHex as b} from "@lodestar/utils"; import {ChainConfig} from "../types.js"; import {chainConfig as mainnet} from "../configs/mainnet.js"; diff --git a/packages/config/src/chainConfig/networks/sepolia.ts b/packages/config/src/chainConfig/networks/sepolia.ts index 51102cfafa7d..39e72a24f3f6 100644 --- a/packages/config/src/chainConfig/networks/sepolia.ts +++ b/packages/config/src/chainConfig/networks/sepolia.ts @@ -1,5 +1,5 @@ /* eslint-disable @typescript-eslint/naming-convention */ -import {fromHexString as b} from "@chainsafe/ssz"; +import {fromHex as b} from "@lodestar/utils"; import {ChainConfig} from "../types.js"; import {chainConfig as mainnet} from "../configs/mainnet.js"; diff --git a/packages/light-client/src/index.ts b/packages/light-client/src/index.ts index 03be60eca05d..5ec0dd73b469 100644 --- a/packages/light-client/src/index.ts +++ b/packages/light-client/src/index.ts @@ -1,5 +1,4 @@ import mitt from "mitt"; -import {fromHexString} from "@chainsafe/ssz"; import {EPOCHS_PER_SYNC_COMMITTEE_PERIOD} from "@lodestar/params"; import { LightClientBootstrap, @@ -13,7 +12,7 @@ import { SyncPeriod, } from "@lodestar/types"; import {createBeaconConfig, BeaconConfig, ChainForkConfig} from "@lodestar/config"; -import {isErrorAborted, sleep, toRootHex} from "@lodestar/utils"; +import {fromHex, isErrorAborted, sleep, toRootHex} from "@lodestar/utils"; import {getCurrentSlot, slotWithFutureTolerance, timeUntilNextEpoch} from "./utils/clock.js"; import {chunkifyInclusiveRange} from "./utils/chunkify.js"; import {LightclientEmitter, LightclientEvent} from "./events.js"; @@ -120,7 +119,7 @@ export class Lightclient { this.genesisTime = genesisData.genesisTime; this.genesisValidatorsRoot = typeof genesisData.genesisValidatorsRoot === "string" - ? fromHexString(genesisData.genesisValidatorsRoot) + ? fromHex(genesisData.genesisValidatorsRoot) : genesisData.genesisValidatorsRoot; this.config = createBeaconConfig(config, this.genesisValidatorsRoot); diff --git a/packages/state-transition/src/cache/epochCache.ts b/packages/state-transition/src/cache/epochCache.ts index af6e976e9089..ba8ec9b05ab5 100644 --- a/packages/state-transition/src/cache/epochCache.ts +++ b/packages/state-transition/src/cache/epochCache.ts @@ -1,6 +1,5 @@ import {PublicKey} from "@chainsafe/blst"; import * as immutable from "immutable"; -import {fromHexString} from "@chainsafe/ssz"; import { BLSSignature, CommitteeIndex, @@ -25,7 +24,7 @@ import { SLOTS_PER_EPOCH, WEIGHT_DENOMINATOR, } from "@lodestar/params"; -import {LodestarError} from "@lodestar/utils"; +import {LodestarError, fromHex} from "@lodestar/utils"; import { computeActivationExitEpoch, computeEpochAtSlot, @@ -964,7 +963,7 @@ export class EpochCache { } this.pubkey2index.set(pubkey, index); - const pubkeyBytes = pubkey instanceof Uint8Array ? pubkey : fromHexString(pubkey); + const pubkeyBytes = pubkey instanceof Uint8Array ? pubkey : fromHex(pubkey); this.index2pubkey[index] = PublicKey.fromBytes(pubkeyBytes); // Optimize for aggregation } diff --git a/packages/utils/src/bytes/nodejs.ts b/packages/utils/src/bytes/nodejs.ts index 636f49bd8e76..4cf8e78c67c6 100644 --- a/packages/utils/src/bytes/nodejs.ts +++ b/packages/utils/src/bytes/nodejs.ts @@ -44,6 +44,18 @@ export function toPubkeyHex(pubkey: Uint8Array): string { } export function fromHex(hex: string): Uint8Array { - const b = Buffer.from(hex.replace("0x", ""), "hex"); + if (typeof hex !== "string") { + throw new Error(`hex argument type ${typeof hex} must be of type string`); + } + + if (hex.startsWith("0x")) { + hex = hex.slice(2); + } + + if (hex.length % 2 !== 0) { + throw new Error(`hex string length ${hex.length} must be multiple of 2`); + } + + const b = Buffer.from(hex, "hex"); return new Uint8Array(b.buffer, b.byteOffset, b.length); } diff --git a/packages/validator/src/services/chainHeaderTracker.ts b/packages/validator/src/services/chainHeaderTracker.ts index 845743264d0b..1c0b0d9a56d8 100644 --- a/packages/validator/src/services/chainHeaderTracker.ts +++ b/packages/validator/src/services/chainHeaderTracker.ts @@ -1,6 +1,5 @@ -import {fromHexString} from "@chainsafe/ssz"; import {ApiClient, routes} from "@lodestar/api"; -import {Logger} from "@lodestar/utils"; +import {Logger, fromHex} from "@lodestar/utils"; import {Slot, Root, RootHex} from "@lodestar/types"; import {GENESIS_SLOT} from "@lodestar/params"; import {ValidatorEvent, ValidatorEventEmitter} from "./emitter.js"; @@ -64,7 +63,7 @@ export class ChainHeaderTracker { const {message} = event; const {slot, block, previousDutyDependentRoot, currentDutyDependentRoot} = message; this.headBlockSlot = slot; - this.headBlockRoot = fromHexString(block); + this.headBlockRoot = fromHex(block); const headEventData = { slot: this.headBlockSlot, diff --git a/packages/validator/src/services/doppelgangerService.ts b/packages/validator/src/services/doppelgangerService.ts index 5435c5aed37f..e167ee1d5028 100644 --- a/packages/validator/src/services/doppelgangerService.ts +++ b/packages/validator/src/services/doppelgangerService.ts @@ -1,7 +1,6 @@ -import {fromHexString} from "@chainsafe/ssz"; import {Epoch, ValidatorIndex} from "@lodestar/types"; import {ApiClient, routes} from "@lodestar/api"; -import {Logger, sleep, truncBytes} from "@lodestar/utils"; +import {Logger, fromHex, sleep, truncBytes} from "@lodestar/utils"; import {computeStartSlotAtEpoch} from "@lodestar/state-transition"; import {ISlashingProtection} from "../slashingProtection/index.js"; import {ProcessShutdownCallback, PubkeyHex} from "../types.js"; @@ -69,7 +68,7 @@ export class DoppelgangerService { if (remainingEpochs > 0) { const previousEpoch = currentEpoch - 1; const attestedInPreviousEpoch = await this.slashingProtection.hasAttestedInEpoch( - fromHexString(pubkeyHex), + fromHex(pubkeyHex), previousEpoch ); diff --git a/packages/validator/src/services/externalSignerSync.ts b/packages/validator/src/services/externalSignerSync.ts index 2f1880dda1bb..2f6828d9e09b 100644 --- a/packages/validator/src/services/externalSignerSync.ts +++ b/packages/validator/src/services/externalSignerSync.ts @@ -1,8 +1,7 @@ -import {fromHexString} from "@chainsafe/ssz"; import {PublicKey} from "@chainsafe/blst"; import {ChainForkConfig} from "@lodestar/config"; import {SLOTS_PER_EPOCH} from "@lodestar/params"; -import {toPrintableUrl} from "@lodestar/utils"; +import {fromHex, toPrintableUrl} from "@lodestar/utils"; import {LoggerVc} from "../util/index.js"; import {externalSignerGetKeys} from "../util/externalSignerClient.js"; @@ -77,7 +76,7 @@ export function pollExternalSignerPubkeys( function assertValidPubkeysHex(pubkeysHex: string[]): void { for (const pubkeyHex of pubkeysHex) { - const pubkeyBytes = fromHexString(pubkeyHex); + const pubkeyBytes = fromHex(pubkeyHex); PublicKey.fromBytes(pubkeyBytes, true); } } diff --git a/packages/validator/src/services/validatorStore.ts b/packages/validator/src/services/validatorStore.ts index b64917ec03ae..6da4f597d87c 100644 --- a/packages/validator/src/services/validatorStore.ts +++ b/packages/validator/src/services/validatorStore.ts @@ -1,4 +1,4 @@ -import {BitArray, fromHexString} from "@chainsafe/ssz"; +import {BitArray} from "@chainsafe/ssz"; import {SecretKey} from "@chainsafe/blst"; import { computeEpochAtSlot, @@ -42,7 +42,7 @@ import { SignedAggregateAndProof, } from "@lodestar/types"; import {routes} from "@lodestar/api"; -import {toPubkeyHex, toRootHex} from "@lodestar/utils"; +import {fromHex, toPubkeyHex, toRootHex} from "@lodestar/utils"; import {ISlashingProtection} from "../slashingProtection/index.js"; import {PubkeyHex} from "../types.js"; import {externalSignerPostSignature, SignableMessageType, SignableMessage} from "../util/externalSignerClient.js"; @@ -693,8 +693,8 @@ export class ValidatorStore { regAttributes: {feeRecipient: Eth1Address; gasLimit: number}, _slot: Slot ): Promise { - const pubkey = typeof pubkeyMaybeHex === "string" ? fromHexString(pubkeyMaybeHex) : pubkeyMaybeHex; - const feeRecipient = fromHexString(regAttributes.feeRecipient); + const pubkey = typeof pubkeyMaybeHex === "string" ? fromHex(pubkeyMaybeHex) : pubkeyMaybeHex; + const feeRecipient = fromHex(regAttributes.feeRecipient); const {gasLimit} = regAttributes; const validatorRegistration: bellatrix.ValidatorRegistrationV1 = { @@ -775,7 +775,7 @@ export class ValidatorStore { signingSlot, signableMessage ); - return fromHexString(signatureHex); + return fromHex(signatureHex); } catch (e) { this.metrics?.remoteSignErrors.inc(); throw e; diff --git a/packages/validator/src/slashingProtection/interchange/formats/completeV4.ts b/packages/validator/src/slashingProtection/interchange/formats/completeV4.ts index d1e9475daa0e..b43ced6c80d3 100644 --- a/packages/validator/src/slashingProtection/interchange/formats/completeV4.ts +++ b/packages/validator/src/slashingProtection/interchange/formats/completeV4.ts @@ -1,6 +1,5 @@ /* eslint-disable @typescript-eslint/naming-convention */ -import {fromHexString} from "@chainsafe/ssz"; -import {toPubkeyHex, toRootHex} from "@lodestar/utils"; +import {fromHex, toPubkeyHex, toRootHex} from "@lodestar/utils"; import {InterchangeLodestar} from "../types.js"; import {fromOptionalHexString, numToString, toOptionalHexString} from "../../utils.js"; @@ -110,9 +109,9 @@ export function serializeInterchangeCompleteV4({ export function parseInterchangeCompleteV4(interchange: InterchangeCompleteV4): InterchangeLodestar { return { - genesisValidatorsRoot: fromHexString(interchange.metadata.genesis_validators_root), + genesisValidatorsRoot: fromHex(interchange.metadata.genesis_validators_root), data: interchange.data.map((validator) => ({ - pubkey: fromHexString(validator.pubkey), + pubkey: fromHex(validator.pubkey), signedBlocks: validator.signed_blocks.map((block) => ({ slot: parseInt(block.slot, 10), signingRoot: fromOptionalHexString(block.signing_root), diff --git a/packages/validator/src/slashingProtection/interchange/formats/v5.ts b/packages/validator/src/slashingProtection/interchange/formats/v5.ts index 20d11aefe91a..838ba76c1a57 100644 --- a/packages/validator/src/slashingProtection/interchange/formats/v5.ts +++ b/packages/validator/src/slashingProtection/interchange/formats/v5.ts @@ -1,6 +1,5 @@ /* eslint-disable @typescript-eslint/naming-convention */ -import {fromHexString} from "@chainsafe/ssz"; -import {toPubkeyHex, toRootHex} from "@lodestar/utils"; +import {fromHex, toPubkeyHex, toRootHex} from "@lodestar/utils"; import {InterchangeLodestar} from "../types.js"; import {fromOptionalHexString, numToString, toOptionalHexString} from "../../utils.js"; @@ -105,9 +104,9 @@ export function serializeInterchangeV5({data, genesisValidatorsRoot}: Interchang export function parseInterchangeV5(interchange: InterchangeV5): InterchangeLodestar { return { - genesisValidatorsRoot: fromHexString(interchange.metadata.genesis_validators_root), + genesisValidatorsRoot: fromHex(interchange.metadata.genesis_validators_root), data: interchange.data.map((validator) => ({ - pubkey: fromHexString(validator.pubkey), + pubkey: fromHex(validator.pubkey), signedBlocks: validator.signed_blocks.map((block) => ({ slot: parseInt(block.slot, 10), signingRoot: fromOptionalHexString(block.signing_root), diff --git a/packages/validator/src/slashingProtection/utils.ts b/packages/validator/src/slashingProtection/utils.ts index 294036981b14..adc93bdafee5 100644 --- a/packages/validator/src/slashingProtection/utils.ts +++ b/packages/validator/src/slashingProtection/utils.ts @@ -1,6 +1,5 @@ -import {fromHexString} from "@chainsafe/ssz"; import {Epoch, Root, ssz} from "@lodestar/types"; -import {toHex, toRootHex} from "@lodestar/utils"; +import {fromHex, toHex, toRootHex} from "@lodestar/utils"; export const blsPubkeyLen = 48; export const ZERO_ROOT = ssz.Root.defaultValue(); @@ -14,7 +13,7 @@ export function isEqualNonZeroRoot(root1: Root, root2: Root): boolean { } export function fromOptionalHexString(hex: string | undefined): Root { - return hex ? fromHexString(hex) : ZERO_ROOT; + return hex ? fromHex(hex) : ZERO_ROOT; } export function toOptionalHexString(root: Root): string | undefined { From 295690b89611da4e9bdc551afcd47dda49642462 Mon Sep 17 00:00:00 2001 From: g11tech Date: Sat, 14 Sep 2024 14:44:11 +0530 Subject: [PATCH 03/52] fix: use bigint gwei type for amount in requests instead of num 64 (#7085) * fix: use bigint gwei type for amount in requests instead of num 64 * revert deposit amount to uintnum64 as unlikely to get a high amount * fix --- packages/beacon-node/src/execution/engine/types.ts | 2 +- packages/types/src/electra/sszTypes.ts | 4 +++- 2 files changed, 4 insertions(+), 2 deletions(-) diff --git a/packages/beacon-node/src/execution/engine/types.ts b/packages/beacon-node/src/execution/engine/types.ts index 63cb4da88b6c..139fc6822780 100644 --- a/packages/beacon-node/src/execution/engine/types.ts +++ b/packages/beacon-node/src/execution/engine/types.ts @@ -461,7 +461,7 @@ export function deserializeWithdrawalRequest(withdrawalRequest: WithdrawalReques return { sourceAddress: dataToBytes(withdrawalRequest.sourceAddress, 20), validatorPubkey: dataToBytes(withdrawalRequest.validatorPubkey, 48), - amount: quantityToNum(withdrawalRequest.amount), + amount: quantityToBigint(withdrawalRequest.amount), }; } diff --git a/packages/types/src/electra/sszTypes.ts b/packages/types/src/electra/sszTypes.ts index 31844aac86cc..c0485597686a 100644 --- a/packages/types/src/electra/sszTypes.ts +++ b/packages/types/src/electra/sszTypes.ts @@ -116,6 +116,8 @@ export const DepositRequest = new ContainerType( { pubkey: BLSPubkey, withdrawalCredentials: Bytes32, + // this is actually gwei uintbn64 type, but super unlikely to get a high amount here + // to warrant a bn type amount: UintNum64, signature: BLSSignature, index: DepositIndex, @@ -129,7 +131,7 @@ export const WithdrawalRequest = new ContainerType( { sourceAddress: ExecutionAddress, validatorPubkey: BLSPubkey, - amount: UintNum64, + amount: Gwei, }, {typeName: "WithdrawalRequest", jsonCase: "eth2"} ); From 43b41afd341b14777fa4ed352ae1460bea843553 Mon Sep 17 00:00:00 2001 From: twoeths Date: Mon, 16 Sep 2024 17:58:55 +0700 Subject: [PATCH 04/52] chore: metrics for regen getState() (#7086) --- dashboards/lodestar_state_cache_regen.json | 491 ++++++++++++++++++++- 1 file changed, 480 insertions(+), 11 deletions(-) diff --git a/dashboards/lodestar_state_cache_regen.json b/dashboards/lodestar_state_cache_regen.json index e7f6336eaeb9..426cde226022 100644 --- a/dashboards/lodestar_state_cache_regen.json +++ b/dashboards/lodestar_state_cache_regen.json @@ -1333,7 +1333,7 @@ "options": { "mode": "exclude", "names": [ - "count_per_epoch" + "sec_from_slot" ], "prefix": "All except:", "readOnly": true @@ -1610,7 +1610,32 @@ }, "mappings": [] }, - "overrides": [] + "overrides": [ + { + "__systemRef": "hideSeriesFrom", + "matcher": { + "id": "byNames", + "options": { + "mode": "exclude", + "names": [ + "from_persistent" + ], + "prefix": "All except:", + "readOnly": true + } + }, + "properties": [ + { + "id": "custom.hideFrom", + "value": { + "legend": false, + "tooltip": false, + "viz": true + } + } + ] + } + ] }, "gridPos": { "h": 8, @@ -1705,7 +1730,32 @@ }, "mappings": [] }, - "overrides": [] + "overrides": [ + { + "__systemRef": "hideSeriesFrom", + "matcher": { + "id": "byNames", + "options": { + "mode": "exclude", + "names": [ + "state_reload_validator_serialization" + ], + "prefix": "All except:", + "readOnly": true + } + }, + "properties": [ + { + "id": "custom.hideFrom", + "value": { + "legend": false, + "tooltip": false, + "viz": true + } + } + ] + } + ] }, "gridPos": { "h": 8, @@ -1827,7 +1877,32 @@ }, "mappings": [] }, - "overrides": [] + "overrides": [ + { + "__systemRef": "hideSeriesFrom", + "matcher": { + "id": "byNames", + "options": { + "mode": "exclude", + "names": [ + "getState" + ], + "prefix": "All except:", + "readOnly": true + } + }, + "properties": [ + { + "id": "custom.hideFrom", + "value": { + "legend": false, + "tooltip": false, + "viz": true + } + } + ] + } + ] }, "gridPos": { "h": 8, @@ -2445,6 +2520,400 @@ "title": "Error rate (grouped by caller)", "type": "timeseries" }, + { + "collapsed": false, + "gridPos": { + "h": 1, + "w": 24, + "x": 0, + "y": 82 + }, + "id": 60, + "panels": [], + "title": "Regen - getState", + "type": "row" + }, + { + "datasource": { + "type": "prometheus", + "uid": "${DS_PROMETHEUS}" + }, + "fieldConfig": { + "defaults": { + "color": { + "mode": "palette-classic" + }, + "custom": { + "axisBorderShow": false, + "axisCenteredZero": false, + "axisColorMode": "text", + "axisLabel": "", + "axisPlacement": "auto", + "barAlignment": 0, + "drawStyle": "line", + "fillOpacity": 0, + "gradientMode": "none", + "hideFrom": { + "legend": false, + "tooltip": false, + "viz": false + }, + "insertNulls": false, + "lineInterpolation": "linear", + "lineWidth": 1, + "pointSize": 5, + "scaleDistribution": { + "type": "linear" + }, + "showPoints": "auto", + "spanNulls": false, + "stacking": { + "group": "A", + "mode": "none" + }, + "thresholdsStyle": { + "mode": "off" + } + }, + "mappings": [], + "unit": "s" + }, + "overrides": [] + }, + "gridPos": { + "h": 8, + "w": 12, + "x": 0, + "y": 83 + }, + "id": 61, + "options": { + "legend": { + "calcs": [], + "displayMode": "list", + "placement": "bottom", + "showLegend": true + }, + "tooltip": { + "mode": "single", + "sort": "none" + } + }, + "targets": [ + { + "datasource": { + "type": "prometheus", + "uid": "${DS_PROMETHEUS}" + }, + "editorMode": "code", + "expr": "rate(lodestar_regen_get_state_get_seed_state_seconds_sum[$rate_interval])\n/\nrate(lodestar_regen_get_state_get_seed_state_seconds_count[$rate_interval])", + "instant": false, + "legendFormat": "{{caller}}", + "range": true, + "refId": "A" + } + ], + "title": "Get seed state duration", + "type": "timeseries" + }, + { + "datasource": { + "type": "prometheus", + "uid": "${DS_PROMETHEUS}" + }, + "fieldConfig": { + "defaults": { + "color": { + "mode": "palette-classic" + }, + "custom": { + "axisBorderShow": false, + "axisCenteredZero": false, + "axisColorMode": "text", + "axisLabel": "", + "axisPlacement": "auto", + "barAlignment": 0, + "drawStyle": "line", + "fillOpacity": 0, + "gradientMode": "none", + "hideFrom": { + "legend": false, + "tooltip": false, + "viz": false + }, + "insertNulls": false, + "lineInterpolation": "linear", + "lineWidth": 1, + "pointSize": 5, + "scaleDistribution": { + "type": "linear" + }, + "showPoints": "auto", + "spanNulls": false, + "stacking": { + "group": "A", + "mode": "none" + }, + "thresholdsStyle": { + "mode": "off" + } + }, + "mappings": [], + "unit": "s" + }, + "overrides": [] + }, + "gridPos": { + "h": 8, + "w": 12, + "x": 12, + "y": 83 + }, + "id": 62, + "options": { + "legend": { + "calcs": [], + "displayMode": "list", + "placement": "bottom", + "showLegend": true + }, + "tooltip": { + "mode": "single", + "sort": "none" + } + }, + "targets": [ + { + "datasource": { + "type": "prometheus", + "uid": "${DS_PROMETHEUS}" + }, + "editorMode": "code", + "expr": "rate(lodestar_regen_get_state_load_blocks_seconds_sum[$rate_interval])\n/\nrate(lodestar_regen_get_state_load_blocks_seconds_count[$rate_interval])", + "instant": false, + "legendFormat": "{{caller}}", + "range": true, + "refId": "A" + } + ], + "title": "Load blocks duration", + "type": "timeseries" + }, + { + "datasource": { + "type": "prometheus", + "uid": "${DS_PROMETHEUS}" + }, + "fieldConfig": { + "defaults": { + "color": { + "mode": "palette-classic" + }, + "custom": { + "axisBorderShow": false, + "axisCenteredZero": false, + "axisColorMode": "text", + "axisLabel": "", + "axisPlacement": "auto", + "barAlignment": 0, + "drawStyle": "line", + "fillOpacity": 0, + "gradientMode": "none", + "hideFrom": { + "legend": false, + "tooltip": false, + "viz": false + }, + "insertNulls": false, + "lineInterpolation": "linear", + "lineWidth": 1, + "pointSize": 5, + "scaleDistribution": { + "type": "linear" + }, + "showPoints": "auto", + "spanNulls": false, + "stacking": { + "group": "A", + "mode": "none" + }, + "thresholdsStyle": { + "mode": "off" + } + }, + "mappings": [], + "unit": "s" + }, + "overrides": [ + { + "__systemRef": "hideSeriesFrom", + "matcher": { + "id": "byNames", + "options": { + "mode": "exclude", + "names": [ + "validateGossipBlock" + ], + "prefix": "All except:", + "readOnly": true + } + }, + "properties": [ + { + "id": "custom.hideFrom", + "value": { + "legend": false, + "tooltip": false, + "viz": true + } + } + ] + } + ] + }, + "gridPos": { + "h": 8, + "w": 12, + "x": 0, + "y": 91 + }, + "id": 63, + "options": { + "legend": { + "calcs": [], + "displayMode": "list", + "placement": "bottom", + "showLegend": true + }, + "tooltip": { + "mode": "single", + "sort": "none" + } + }, + "targets": [ + { + "datasource": { + "type": "prometheus", + "uid": "${DS_PROMETHEUS}" + }, + "editorMode": "code", + "expr": "rate(lodestar_regen_get_state_state_transition_seconds_sum[$rate_interval])\n/\nrate(lodestar_regen_get_state_state_transition_seconds_count[$rate_interval])", + "instant": false, + "legendFormat": "{{caller}}", + "range": true, + "refId": "A" + } + ], + "title": "State transition duration", + "type": "timeseries" + }, + { + "datasource": { + "type": "prometheus", + "uid": "${DS_PROMETHEUS}" + }, + "fieldConfig": { + "defaults": { + "color": { + "mode": "palette-classic" + }, + "custom": { + "axisBorderShow": false, + "axisCenteredZero": false, + "axisColorMode": "text", + "axisLabel": "", + "axisPlacement": "auto", + "barAlignment": 0, + "drawStyle": "line", + "fillOpacity": 0, + "gradientMode": "none", + "hideFrom": { + "legend": false, + "tooltip": false, + "viz": false + }, + "insertNulls": false, + "lineInterpolation": "linear", + "lineWidth": 1, + "pointSize": 5, + "scaleDistribution": { + "type": "linear" + }, + "showPoints": "auto", + "spanNulls": false, + "stacking": { + "group": "A", + "mode": "none" + }, + "thresholdsStyle": { + "mode": "off" + } + }, + "mappings": [] + }, + "overrides": [ + { + "__systemRef": "hideSeriesFrom", + "matcher": { + "id": "byNames", + "options": { + "mode": "exclude", + "names": [ + "validateGossipBlock" + ], + "prefix": "All except:", + "readOnly": true + } + }, + "properties": [ + { + "id": "custom.hideFrom", + "value": { + "legend": false, + "tooltip": false, + "viz": true + } + } + ] + } + ] + }, + "gridPos": { + "h": 8, + "w": 12, + "x": 12, + "y": 91 + }, + "id": 64, + "options": { + "legend": { + "calcs": [], + "displayMode": "list", + "placement": "bottom", + "showLegend": true + }, + "tooltip": { + "mode": "single", + "sort": "none" + } + }, + "targets": [ + { + "datasource": { + "type": "prometheus", + "uid": "${DS_PROMETHEUS}" + }, + "editorMode": "code", + "expr": "rate(lodestar_regen_get_state_block_count_sum[$rate_interval])\n/\nrate(lodestar_regen_get_state_block_count_count[$rate_interval])", + "instant": false, + "legendFormat": "{{caller}}", + "range": true, + "refId": "A" + } + ], + "title": "Reprocessed block count", + "type": "timeseries" + }, { "collapsed": false, "datasource": { @@ -2455,7 +2924,7 @@ "h": 1, "w": 24, "x": 0, - "y": 82 + "y": 99 }, "id": 54, "panels": [], @@ -2523,7 +2992,7 @@ "h": 7, "w": 12, "x": 0, - "y": 83 + "y": 100 }, "id": 42, "options": { @@ -2608,7 +3077,7 @@ "h": 7, "w": 6, "x": 12, - "y": 83 + "y": 100 }, "id": 44, "options": { @@ -2692,7 +3161,7 @@ "h": 7, "w": 6, "x": 18, - "y": 83 + "y": 100 }, "id": 48, "options": { @@ -2776,7 +3245,7 @@ "h": 7, "w": 12, "x": 0, - "y": 90 + "y": 107 }, "id": 46, "options": { @@ -2860,7 +3329,7 @@ "h": 7, "w": 6, "x": 12, - "y": 90 + "y": 107 }, "id": 50, "options": { @@ -2944,7 +3413,7 @@ "h": 7, "w": 6, "x": 18, - "y": 90 + "y": 107 }, "id": 52, "options": { From d3d61af6bd33b92ce7d767953ea80cdeecd686cf Mon Sep 17 00:00:00 2001 From: "dependabot[bot]" <49699333+dependabot[bot]@users.noreply.github.com> Date: Mon, 16 Sep 2024 12:47:05 +0100 Subject: [PATCH 05/52] chore(deps): bump path-to-regexp from 6.2.2 to 6.3.0 (#7082) Bumps [path-to-regexp](https://github.com/pillarjs/path-to-regexp) from 6.2.2 to 6.3.0. - [Release notes](https://github.com/pillarjs/path-to-regexp/releases) - [Changelog](https://github.com/pillarjs/path-to-regexp/blob/master/History.md) - [Commits](https://github.com/pillarjs/path-to-regexp/compare/v6.2.2...v6.3.0) --- updated-dependencies: - dependency-name: path-to-regexp dependency-type: indirect ... Signed-off-by: dependabot[bot] Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com> --- yarn.lock | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/yarn.lock b/yarn.lock index 60e41c276e53..7eb7a89c33dd 100644 --- a/yarn.lock +++ b/yarn.lock @@ -10647,9 +10647,9 @@ path-scurry@^1.11.1: minipass "^5.0.0 || ^6.0.2 || ^7.0.0" path-to-regexp@^6.2.0: - version "6.2.2" - resolved "https://registry.yarnpkg.com/path-to-regexp/-/path-to-regexp-6.2.2.tgz#324377a83e5049cbecadc5554d6a63a9a4866b36" - integrity sha512-GQX3SSMokngb36+whdpRXE+3f9V8UzyAorlYvOGx87ufGHehNTn5lCxrKtLyZ4Yl/wEKnNnr98ZzOwwDZV5ogw== + version "6.3.0" + resolved "https://registry.yarnpkg.com/path-to-regexp/-/path-to-regexp-6.3.0.tgz#2b6a26a337737a8e1416f9272ed0766b1c0389f4" + integrity sha512-Yhpw4T9C6hPpgPeA28us07OJeqZ5EzQTkbfwuhsUg0c237RomFoETJgmp2sa3F/41gfLE6G5cqcYwznmeEeOlQ== path-type@^3.0.0: version "3.0.0" From 67a35f8e76642661287aeec86115e5b19b51fdbb Mon Sep 17 00:00:00 2001 From: "dependabot[bot]" <49699333+dependabot[bot]@users.noreply.github.com> Date: Mon, 16 Sep 2024 12:47:51 +0100 Subject: [PATCH 06/52] chore(deps): bump express from 4.19.2 to 4.21.0 in /docs (#7078) Bumps [express](https://github.com/expressjs/express) from 4.19.2 to 4.21.0. - [Release notes](https://github.com/expressjs/express/releases) - [Changelog](https://github.com/expressjs/express/blob/4.21.0/History.md) - [Commits](https://github.com/expressjs/express/compare/4.19.2...4.21.0) --- updated-dependencies: - dependency-name: express dependency-type: indirect ... Signed-off-by: dependabot[bot] Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com> --- docs/yarn.lock | 95 ++++++++++++++++++++++++++------------------------ 1 file changed, 50 insertions(+), 45 deletions(-) diff --git a/docs/yarn.lock b/docs/yarn.lock index 41966c013183..c39bab969363 100644 --- a/docs/yarn.lock +++ b/docs/yarn.lock @@ -3136,10 +3136,10 @@ binary-extensions@^2.0.0: resolved "https://registry.yarnpkg.com/binary-extensions/-/binary-extensions-2.2.0.tgz#75f502eeaf9ffde42fc98829645be4ea76bd9e2d" integrity sha512-jDctJ/IVQbZoJykoeHbhXpOlNBqGNcwXJKJog42E5HDPUwQTSdjCHdihjj0DlnheQ7blbT6dHOafNAiS8ooQKA== -body-parser@1.20.2: - version "1.20.2" - resolved "https://registry.yarnpkg.com/body-parser/-/body-parser-1.20.2.tgz#6feb0e21c4724d06de7ff38da36dad4f57a747fd" - integrity sha512-ml9pReCu3M61kGlqoTm2umSXTlRTuGTx0bfYj+uIUKKYycG5NtSbeetV3faSU6R7ajOPw0g/J1PvK4qNy7s5bA== +body-parser@1.20.3: + version "1.20.3" + resolved "https://registry.yarnpkg.com/body-parser/-/body-parser-1.20.3.tgz#1953431221c6fb5cd63c4b36d53fab0928e548c6" + integrity sha512-7rAxByjUMqQ3/bHJy7D6OGXvx/MMc4IqBn/X0fcM1QUcAItpZrBEYhWGem+tzXH90c+G01ypMcYJBO9Y30203g== dependencies: bytes "3.1.2" content-type "~1.0.5" @@ -3149,7 +3149,7 @@ body-parser@1.20.2: http-errors "2.0.0" iconv-lite "0.4.24" on-finished "2.4.1" - qs "6.11.0" + qs "6.13.0" raw-body "2.5.2" type-is "~1.6.18" unpipe "1.0.0" @@ -4454,6 +4454,11 @@ encodeurl@~1.0.2: resolved "https://registry.yarnpkg.com/encodeurl/-/encodeurl-1.0.2.tgz#ad3ff4c86ec2d029322f5a02c3a9a606c95b3f59" integrity sha512-TPJXq8JqFaVYm2CWmPvnP2Iyo4ZSM7/QKcSmuMLDObfpH5fi7RUGmd/rTDf+rut/saiDiQEeVTNgAmJEdAOx0w== +encodeurl@~2.0.0: + version "2.0.0" + resolved "https://registry.yarnpkg.com/encodeurl/-/encodeurl-2.0.0.tgz#7b8ea898077d7e409d3ac45474ea38eaf0857a58" + integrity sha512-Q0n9HRi4m6JuGIV1eFlmvJB7ZEVxu93IrMyiMsGC0lrMJMWzRgx6WGquyfQgZVb31vhGgXnfmPNNXmxnOkRBrg== + enhanced-resolve@^5.15.0: version "5.15.1" resolved "https://registry.yarnpkg.com/enhanced-resolve/-/enhanced-resolve-5.15.1.tgz#384391e025f099e67b4b00bfd7f0906a408214e1" @@ -4659,36 +4664,36 @@ execa@^5.0.0: strip-final-newline "^2.0.0" express@^4.17.3: - version "4.19.2" - resolved "https://registry.yarnpkg.com/express/-/express-4.19.2.tgz#e25437827a3aa7f2a827bc8171bbbb664a356465" - integrity sha512-5T6nhjsT+EOMzuck8JjBHARTHfMht0POzlA60WV2pMD3gyXw2LZnZ+ueGdNxG+0calOJcWKbpFcuzLZ91YWq9Q== + version "4.21.0" + resolved "https://registry.yarnpkg.com/express/-/express-4.21.0.tgz#d57cb706d49623d4ac27833f1cbc466b668eb915" + integrity sha512-VqcNGcj/Id5ZT1LZ/cfihi3ttTn+NJmkli2eZADigjq29qTlWi/hAQ43t/VLPq8+UX06FCEx3ByOYet6ZFblng== dependencies: accepts "~1.3.8" array-flatten "1.1.1" - body-parser "1.20.2" + body-parser "1.20.3" content-disposition "0.5.4" content-type "~1.0.4" cookie "0.6.0" cookie-signature "1.0.6" debug "2.6.9" depd "2.0.0" - encodeurl "~1.0.2" + encodeurl "~2.0.0" escape-html "~1.0.3" etag "~1.8.1" - finalhandler "1.2.0" + finalhandler "1.3.1" fresh "0.5.2" http-errors "2.0.0" - merge-descriptors "1.0.1" + merge-descriptors "1.0.3" methods "~1.1.2" on-finished "2.4.1" parseurl "~1.3.3" - path-to-regexp "0.1.7" + path-to-regexp "0.1.10" proxy-addr "~2.0.7" - qs "6.11.0" + qs "6.13.0" range-parser "~1.2.1" safe-buffer "5.2.1" - send "0.18.0" - serve-static "1.15.0" + send "0.19.0" + serve-static "1.16.2" setprototypeof "1.2.0" statuses "2.0.1" type-is "~1.6.18" @@ -4783,13 +4788,13 @@ fill-range@^7.0.1: dependencies: to-regex-range "^5.0.1" -finalhandler@1.2.0: - version "1.2.0" - resolved "https://registry.yarnpkg.com/finalhandler/-/finalhandler-1.2.0.tgz#7d23fe5731b207b4640e4fcd00aec1f9207a7b32" - integrity sha512-5uXcUVftlQMFnWC9qu/svkWv3GTd2PfUhK/3PLkYNAe7FbqJMt3515HaxE6eRL74GdsriiwujiawdaB1BpEISg== +finalhandler@1.3.1: + version "1.3.1" + resolved "https://registry.yarnpkg.com/finalhandler/-/finalhandler-1.3.1.tgz#0c575f1d1d324ddd1da35ad7ece3df7d19088019" + integrity sha512-6BN9trH7bp3qvnrRyzsBz+g3lZxTNZTbVO2EV1CS0WIcDbawYVdYvGflME/9QP0h0pYlCDBCTjYa9nZzMDpyxQ== dependencies: debug "2.6.9" - encodeurl "~1.0.2" + encodeurl "~2.0.0" escape-html "~1.0.3" on-finished "2.4.1" parseurl "~1.3.3" @@ -6345,10 +6350,10 @@ memfs@^3.1.2, memfs@^3.4.3: dependencies: fs-monkey "^1.0.4" -merge-descriptors@1.0.1: - version "1.0.1" - resolved "https://registry.yarnpkg.com/merge-descriptors/-/merge-descriptors-1.0.1.tgz#b00aaa556dd8b44568150ec9d1b953f3f90cbb61" - integrity sha512-cCi6g3/Zr1iqQi6ySbseM1Xvooa98N0w31jzUYrXPX2xqObmFGHJ0tQ5u74H3mVh7wLouTseZyYIq39g8cNp1w== +merge-descriptors@1.0.3: + version "1.0.3" + resolved "https://registry.yarnpkg.com/merge-descriptors/-/merge-descriptors-1.0.3.tgz#d80319a65f3c7935351e5cfdac8f9318504dbed5" + integrity sha512-gaNvAS7TZ897/rVaZ0nMtAyxNyi/pdbjbAwUpFQpN70GqnVfOiXpeUUMKRBmzXaSQ8DdTX4/0ms62r2K+hE6mQ== merge-stream@^2.0.0: version "2.0.0" @@ -7426,10 +7431,10 @@ path-parse@^1.0.7: resolved "https://registry.yarnpkg.com/path-parse/-/path-parse-1.0.7.tgz#fbc114b60ca42b30d9daf5858e4bd68bbedb6735" integrity sha512-LDJzPVEEEPR+y48z93A0Ed0yXb8pAByGWo/k5YYdYgpY2/2EsOsksJrq7lOHxryrVOn1ejG6oAp8ahvOIQD8sw== -path-to-regexp@0.1.7: - version "0.1.7" - resolved "https://registry.yarnpkg.com/path-to-regexp/-/path-to-regexp-0.1.7.tgz#df604178005f522f15eb4490e7247a1bfaa67f8c" - integrity sha512-5DFkuoqlv1uYQKxy8omFBeJPQcdoE07Kv2sferDCrAq1ohOU+MSDswDIbnx3YAM60qIOnYa53wBhXW0EbMonrQ== +path-to-regexp@0.1.10: + version "0.1.10" + resolved "https://registry.yarnpkg.com/path-to-regexp/-/path-to-regexp-0.1.10.tgz#67e9108c5c0551b9e5326064387de4763c4d5f8b" + integrity sha512-7lf7qcQidTku0Gu3YDPc8DJ1q7OOucfa/BSsIwjuh56VU7katFvuM8hULfkwB3Fns/rsVF7PwPKVw1sl5KQS9w== path-to-regexp@2.2.1: version "2.2.1" @@ -7854,12 +7859,12 @@ pupa@^3.1.0: dependencies: escape-goat "^4.0.0" -qs@6.11.0: - version "6.11.0" - resolved "https://registry.yarnpkg.com/qs/-/qs-6.11.0.tgz#fd0d963446f7a65e1367e01abd85429453f0c37a" - integrity sha512-MvjoMCJwEarSbUYk5O+nmoSzSutSsTwF85zcHPQ9OrlFoZOYIjaqBAJIqIXjptyD5vThxGq52Xu/MaJzRkIk4Q== +qs@6.13.0: + version "6.13.0" + resolved "https://registry.yarnpkg.com/qs/-/qs-6.13.0.tgz#6ca3bd58439f7e245655798997787b0d88a51906" + integrity sha512-+38qI9SOr8tfZ4QmJNplMUxqjbe7LKvvZgWdExBOmd+egZTtjLB67Gu0HRX3u/XOq7UU2Nx6nsjvS16Z9uwfpg== dependencies: - side-channel "^1.0.4" + side-channel "^1.0.6" queue-microtask@^1.2.2: version "1.2.3" @@ -8458,10 +8463,10 @@ semver@^7.3.2, semver@^7.3.5, semver@^7.3.7, semver@^7.5.4: dependencies: lru-cache "^6.0.0" -send@0.18.0: - version "0.18.0" - resolved "https://registry.yarnpkg.com/send/-/send-0.18.0.tgz#670167cc654b05f5aa4a767f9113bb371bc706be" - integrity sha512-qqWzuOjSFOuqPjFe4NOsMLafToQQwBSOEpS+FwEt3A2V3vKubTquT3vmLTQpFgMXp8AlFWFuP1qKaJZOtPpVXg== +send@0.19.0: + version "0.19.0" + resolved "https://registry.yarnpkg.com/send/-/send-0.19.0.tgz#bbc5a388c8ea6c048967049dbeac0e4a3f09d7f8" + integrity sha512-dW41u5VfLXu8SJh5bwRmyYUbAoSB3c9uQh6L8h/KtsFREPWpbX1lrljJo186Jc4nmci/sGUZ9a0a0J2zgfq2hw== dependencies: debug "2.6.9" depd "2.0.0" @@ -8511,15 +8516,15 @@ serve-index@^1.9.1: mime-types "~2.1.17" parseurl "~1.3.2" -serve-static@1.15.0: - version "1.15.0" - resolved "https://registry.yarnpkg.com/serve-static/-/serve-static-1.15.0.tgz#faaef08cffe0a1a62f60cad0c4e513cff0ac9540" - integrity sha512-XGuRDNjXUijsUL0vl6nSD7cwURuzEgglbOaFuZM9g3kwDXOWVTck0jLzjPzGD+TazWbboZYu52/9/XPdUgne9g== +serve-static@1.16.2: + version "1.16.2" + resolved "https://registry.yarnpkg.com/serve-static/-/serve-static-1.16.2.tgz#b6a5343da47f6bdd2673848bf45754941e803296" + integrity sha512-VqpjJZKadQB/PEbEwvFdO43Ax5dFBZ2UECszz8bQ7pi7wt//PWe1P6MN7eCnjsatYtBT6EuiClbjSWP2WrIoTw== dependencies: - encodeurl "~1.0.2" + encodeurl "~2.0.0" escape-html "~1.0.3" parseurl "~1.3.3" - send "0.18.0" + send "0.19.0" set-function-length@^1.2.1: version "1.2.1" @@ -8581,7 +8586,7 @@ shelljs@^0.8.5: interpret "^1.0.0" rechoir "^0.6.2" -side-channel@^1.0.4: +side-channel@^1.0.6: version "1.0.6" resolved "https://registry.yarnpkg.com/side-channel/-/side-channel-1.0.6.tgz#abd25fb7cd24baf45466406b1096b7831c9215f2" integrity sha512-fDW/EZ6Q9RiO8eFG8Hj+7u/oW+XrPTIChwCOM2+th2A6OblDtYYIpve9m+KvI9Z4C9qSEXlaGR6bTEYHReuglA== From 9fe72391bea93f7f88b7b739006844352d929cad Mon Sep 17 00:00:00 2001 From: "dependabot[bot]" <49699333+dependabot[bot]@users.noreply.github.com> Date: Mon, 16 Sep 2024 12:51:12 +0100 Subject: [PATCH 07/52] chore(deps): bump micromatch from 4.0.5 to 4.0.8 (#7058) Bumps [micromatch](https://github.com/micromatch/micromatch) from 4.0.5 to 4.0.8. - [Release notes](https://github.com/micromatch/micromatch/releases) - [Changelog](https://github.com/micromatch/micromatch/blob/master/CHANGELOG.md) - [Commits](https://github.com/micromatch/micromatch/compare/4.0.5...4.0.8) --- updated-dependencies: - dependency-name: micromatch dependency-type: indirect ... Signed-off-by: dependabot[bot] Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com> --- yarn.lock | 24 +++++++++++++++++++----- 1 file changed, 19 insertions(+), 5 deletions(-) diff --git a/yarn.lock b/yarn.lock index 7eb7a89c33dd..f9fa36847af9 100644 --- a/yarn.lock +++ b/yarn.lock @@ -4506,7 +4506,14 @@ brace-expansion@^2.0.1: dependencies: balanced-match "^1.0.0" -braces@^3.0.2, braces@~3.0.2: +braces@^3.0.3: + version "3.0.3" + resolved "https://registry.yarnpkg.com/braces/-/braces-3.0.3.tgz#490332f40919452272d55a8480adc0c441358789" + integrity sha512-yQbXgO/OSZVD2IsiLlro+7Hf6Q18EJrKSEsdoMzKePKXct3gvD8oLcOQdIzGupr5Fj+EDe8gO/lxc1BzfMpxvA== + dependencies: + fill-range "^7.1.1" + +braces@~3.0.2: version "3.0.2" resolved "https://registry.yarnpkg.com/braces/-/braces-3.0.2.tgz#3454e1a462ee8d599e236df336cd9ea4f8afe107" integrity sha512-b8um+L1RzM3WDSzvhm6gIz1yfTbBt6YTlcEKAvsmqCZZFw46z626lVj9j1yEPW33H5H+lBQpZMP1k8l+78Ha0A== @@ -6768,6 +6775,13 @@ fill-range@^7.0.1: dependencies: to-regex-range "^5.0.1" +fill-range@^7.1.1: + version "7.1.1" + resolved "https://registry.yarnpkg.com/fill-range/-/fill-range-7.1.1.tgz#44265d3cac07e3ea7dc247516380643754a05292" + integrity sha512-YsGpe3WHLK8ZYi4tWDg2Jy3ebRz2rXowDxnld4bkQB00cc/1Zw9AWnC0i9ztDJitivtQvaI9KaLyKrc+hBW0yg== + dependencies: + to-regex-range "^5.0.1" + find-my-way@^8.0.0: version "8.1.0" resolved "https://registry.yarnpkg.com/find-my-way/-/find-my-way-8.1.0.tgz#cc05e8e4b145322299d0de0a839b5be528c2083e" @@ -9274,11 +9288,11 @@ micro-ftch@^0.3.1: integrity sha512-/0LLxhzP0tfiR5hcQebtudP56gUurs2CLkGarnCiB/OqEyUFQ6U3paQi/tgLv0hBJYt2rnr9MNpxz4fiiugstg== micromatch@^4.0.4: - version "4.0.5" - resolved "https://registry.yarnpkg.com/micromatch/-/micromatch-4.0.5.tgz#bc8999a7cbbf77cdc89f132f6e467051b49090c6" - integrity sha512-DMy+ERcEW2q8Z2Po+WNXuw3c5YaUSFjAO5GsJqfEl7UjvtIuFKO6ZrKvcItdy98dwFI2N1tg3zNIdKaQT+aNdA== + version "4.0.8" + resolved "https://registry.yarnpkg.com/micromatch/-/micromatch-4.0.8.tgz#d66fa18f3a47076789320b9b1af32bd86d9fa202" + integrity sha512-PXwfBhYu0hBCPw8Dn0E+WDYb7af3dSLVWKi3HGv84IdF4TyFoC0ysxFd0Goxw7nSv4T/PzEJQxsYsEiFCKo2BA== dependencies: - braces "^3.0.2" + braces "^3.0.3" picomatch "^2.3.1" miller-rabin@^4.0.0: From 1bb98ed6db16e2d1ec2fb9f1f9a0ea8fafba7aac Mon Sep 17 00:00:00 2001 From: "dependabot[bot]" <49699333+dependabot[bot]@users.noreply.github.com> Date: Mon, 16 Sep 2024 12:38:42 +0000 Subject: [PATCH 08/52] chore(deps): bump webpack from 5.90.3 to 5.94.0 in /docs (#7059) Bumps [webpack](https://github.com/webpack/webpack) from 5.90.3 to 5.94.0. - [Release notes](https://github.com/webpack/webpack/releases) - [Commits](https://github.com/webpack/webpack/compare/v5.90.3...v5.94.0) --- updated-dependencies: - dependency-name: webpack dependency-type: indirect ... Signed-off-by: dependabot[bot] Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com> --- docs/yarn.lock | 167 ++++++++++++++++++++++--------------------------- 1 file changed, 75 insertions(+), 92 deletions(-) diff --git a/docs/yarn.lock b/docs/yarn.lock index c39bab969363..06e7cf388568 100644 --- a/docs/yarn.lock +++ b/docs/yarn.lock @@ -2430,22 +2430,6 @@ dependencies: "@types/ms" "*" -"@types/eslint-scope@^3.7.3": - version "3.7.7" - resolved "https://registry.yarnpkg.com/@types/eslint-scope/-/eslint-scope-3.7.7.tgz#3108bd5f18b0cdb277c867b3dd449c9ed7079ac5" - integrity sha512-MzMFlSLBqNF2gcHWO0G1vP/YQyfvrxZ0bF+u7mzUdZ1/xK4A4sru+nraZz5i3iEIk1l1uyicaDVTB4QbbEkAYg== - dependencies: - "@types/eslint" "*" - "@types/estree" "*" - -"@types/eslint@*": - version "8.56.5" - resolved "https://registry.yarnpkg.com/@types/eslint/-/eslint-8.56.5.tgz#94b88cab77588fcecdd0771a6d576fa1c0af9d02" - integrity sha512-u5/YPJHo1tvkSF2CE0USEkxon82Z5DBy2xR+qfyYNszpX9qcs4sT6uq2kBbj4BXY1+DBGDPnrhMZV3pKWGNukw== - dependencies: - "@types/estree" "*" - "@types/json-schema" "*" - "@types/estree-jsx@^1.0.0": version "1.0.5" resolved "https://registry.yarnpkg.com/@types/estree-jsx/-/estree-jsx-1.0.5.tgz#858a88ea20f34fe65111f005a689fa1ebf70dc18" @@ -2536,7 +2520,7 @@ dependencies: "@types/istanbul-lib-report" "*" -"@types/json-schema@*", "@types/json-schema@^7.0.4", "@types/json-schema@^7.0.5", "@types/json-schema@^7.0.8", "@types/json-schema@^7.0.9": +"@types/json-schema@^7.0.4", "@types/json-schema@^7.0.5", "@types/json-schema@^7.0.8", "@types/json-schema@^7.0.9": version "7.0.15" resolved "https://registry.yarnpkg.com/@types/json-schema/-/json-schema-7.0.15.tgz#596a1747233694d50f6ad8a7869fcb6f56cf5841" integrity sha512-5+fP8P8MFNC+AyZCDxrB2pkZFPGzqQWUzpSeuuVLvm8VMcorNYavBqoFcxK8bQz4Qsbn4oUEEem4wDLfcysGHA== @@ -2736,10 +2720,10 @@ resolved "https://registry.yarnpkg.com/@ungap/structured-clone/-/structured-clone-1.2.0.tgz#756641adb587851b5ccb3e095daf27ae581c8406" integrity sha512-zuVdFrMJiuCDQUMCzQaD6KL28MjnqqN8XnAqiEq9PNm/hCPTSGfrXCOfwj1ow4LFb/tNymJPwsNbVePc1xFqrQ== -"@webassemblyjs/ast@1.11.6", "@webassemblyjs/ast@^1.11.5": - version "1.11.6" - resolved "https://registry.yarnpkg.com/@webassemblyjs/ast/-/ast-1.11.6.tgz#db046555d3c413f8966ca50a95176a0e2c642e24" - integrity sha512-IN1xI7PwOvLPgjcf180gC1bqn3q/QaOCwYUahIOhbYUu8KA/3tw2RT/T0Gidi1l7Hhj5D/INhJxiICObqpMu4Q== +"@webassemblyjs/ast@1.12.1", "@webassemblyjs/ast@^1.12.1": + version "1.12.1" + resolved "https://registry.yarnpkg.com/@webassemblyjs/ast/-/ast-1.12.1.tgz#bb16a0e8b1914f979f45864c23819cc3e3f0d4bb" + integrity sha512-EKfMUOPRRUTy5UII4qJDGPpqfwjOmZ5jeGFwid9mnoqIFK+e0vqoi1qH56JpmZSzEL53jKnNzScdmftJyG5xWg== dependencies: "@webassemblyjs/helper-numbers" "1.11.6" "@webassemblyjs/helper-wasm-bytecode" "1.11.6" @@ -2754,10 +2738,10 @@ resolved "https://registry.yarnpkg.com/@webassemblyjs/helper-api-error/-/helper-api-error-1.11.6.tgz#6132f68c4acd59dcd141c44b18cbebbd9f2fa768" integrity sha512-o0YkoP4pVu4rN8aTJgAyj9hC2Sv5UlkzCHhxqWj8butaLvnpdc2jOwh4ewE6CX0txSfLn/UYaV/pheS2Txg//Q== -"@webassemblyjs/helper-buffer@1.11.6": - version "1.11.6" - resolved "https://registry.yarnpkg.com/@webassemblyjs/helper-buffer/-/helper-buffer-1.11.6.tgz#b66d73c43e296fd5e88006f18524feb0f2c7c093" - integrity sha512-z3nFzdcp1mb8nEOFFk8DrYLpHvhKC3grJD2ardfKOzmbmJvEf/tPIqCY+sNcwZIY8ZD7IkB2l7/pqhUhqm7hLA== +"@webassemblyjs/helper-buffer@1.12.1": + version "1.12.1" + resolved "https://registry.yarnpkg.com/@webassemblyjs/helper-buffer/-/helper-buffer-1.12.1.tgz#6df20d272ea5439bf20ab3492b7fb70e9bfcb3f6" + integrity sha512-nzJwQw99DNDKr9BVCOZcLuJJUlqkJh+kVzVl6Fmq/tI5ZtEyWT1KZMyOXltXLZJmDtvLCDgwsyrkohEtopTXCw== "@webassemblyjs/helper-numbers@1.11.6": version "1.11.6" @@ -2773,15 +2757,15 @@ resolved "https://registry.yarnpkg.com/@webassemblyjs/helper-wasm-bytecode/-/helper-wasm-bytecode-1.11.6.tgz#bb2ebdb3b83aa26d9baad4c46d4315283acd51e9" integrity sha512-sFFHKwcmBprO9e7Icf0+gddyWYDViL8bpPjJJl0WHxCdETktXdmtWLGVzoHbqUcY4Be1LkNfwTmXOJUFZYSJdA== -"@webassemblyjs/helper-wasm-section@1.11.6": - version "1.11.6" - resolved "https://registry.yarnpkg.com/@webassemblyjs/helper-wasm-section/-/helper-wasm-section-1.11.6.tgz#ff97f3863c55ee7f580fd5c41a381e9def4aa577" - integrity sha512-LPpZbSOwTpEC2cgn4hTydySy1Ke+XEu+ETXuoyvuyezHO3Kjdu90KK95Sh9xTbmjrCsUwvWwCOQQNta37VrS9g== +"@webassemblyjs/helper-wasm-section@1.12.1": + version "1.12.1" + resolved "https://registry.yarnpkg.com/@webassemblyjs/helper-wasm-section/-/helper-wasm-section-1.12.1.tgz#3da623233ae1a60409b509a52ade9bc22a37f7bf" + integrity sha512-Jif4vfB6FJlUlSbgEMHUyk1j234GTNG9dBJ4XJdOySoj518Xj0oGsNi59cUQF4RRMS9ouBUxDDdyBVfPTypa5g== dependencies: - "@webassemblyjs/ast" "1.11.6" - "@webassemblyjs/helper-buffer" "1.11.6" + "@webassemblyjs/ast" "1.12.1" + "@webassemblyjs/helper-buffer" "1.12.1" "@webassemblyjs/helper-wasm-bytecode" "1.11.6" - "@webassemblyjs/wasm-gen" "1.11.6" + "@webassemblyjs/wasm-gen" "1.12.1" "@webassemblyjs/ieee754@1.11.6": version "1.11.6" @@ -2802,59 +2786,59 @@ resolved "https://registry.yarnpkg.com/@webassemblyjs/utf8/-/utf8-1.11.6.tgz#90f8bc34c561595fe156603be7253cdbcd0fab5a" integrity sha512-vtXf2wTQ3+up9Zsg8sa2yWiQpzSsMyXj0qViVP6xKGCUT8p8YJ6HqI7l5eCnWx1T/FYdsv07HQs2wTFbbof/RA== -"@webassemblyjs/wasm-edit@^1.11.5": - version "1.11.6" - resolved "https://registry.yarnpkg.com/@webassemblyjs/wasm-edit/-/wasm-edit-1.11.6.tgz#c72fa8220524c9b416249f3d94c2958dfe70ceab" - integrity sha512-Ybn2I6fnfIGuCR+Faaz7YcvtBKxvoLV3Lebn1tM4o/IAJzmi9AWYIPWpyBfU8cC+JxAO57bk4+zdsTjJR+VTOw== +"@webassemblyjs/wasm-edit@^1.12.1": + version "1.12.1" + resolved "https://registry.yarnpkg.com/@webassemblyjs/wasm-edit/-/wasm-edit-1.12.1.tgz#9f9f3ff52a14c980939be0ef9d5df9ebc678ae3b" + integrity sha512-1DuwbVvADvS5mGnXbE+c9NfA8QRcZ6iKquqjjmR10k6o+zzsRVesil54DKexiowcFCPdr/Q0qaMgB01+SQ1u6g== dependencies: - "@webassemblyjs/ast" "1.11.6" - "@webassemblyjs/helper-buffer" "1.11.6" + "@webassemblyjs/ast" "1.12.1" + "@webassemblyjs/helper-buffer" "1.12.1" "@webassemblyjs/helper-wasm-bytecode" "1.11.6" - "@webassemblyjs/helper-wasm-section" "1.11.6" - "@webassemblyjs/wasm-gen" "1.11.6" - "@webassemblyjs/wasm-opt" "1.11.6" - "@webassemblyjs/wasm-parser" "1.11.6" - "@webassemblyjs/wast-printer" "1.11.6" - -"@webassemblyjs/wasm-gen@1.11.6": - version "1.11.6" - resolved "https://registry.yarnpkg.com/@webassemblyjs/wasm-gen/-/wasm-gen-1.11.6.tgz#fb5283e0e8b4551cc4e9c3c0d7184a65faf7c268" - integrity sha512-3XOqkZP/y6B4F0PBAXvI1/bky7GryoogUtfwExeP/v7Nzwo1QLcq5oQmpKlftZLbT+ERUOAZVQjuNVak6UXjPA== - dependencies: - "@webassemblyjs/ast" "1.11.6" + "@webassemblyjs/helper-wasm-section" "1.12.1" + "@webassemblyjs/wasm-gen" "1.12.1" + "@webassemblyjs/wasm-opt" "1.12.1" + "@webassemblyjs/wasm-parser" "1.12.1" + "@webassemblyjs/wast-printer" "1.12.1" + +"@webassemblyjs/wasm-gen@1.12.1": + version "1.12.1" + resolved "https://registry.yarnpkg.com/@webassemblyjs/wasm-gen/-/wasm-gen-1.12.1.tgz#a6520601da1b5700448273666a71ad0a45d78547" + integrity sha512-TDq4Ojh9fcohAw6OIMXqiIcTq5KUXTGRkVxbSo1hQnSy6lAM5GSdfwWeSxpAo0YzgsgF182E/U0mDNhuA0tW7w== + dependencies: + "@webassemblyjs/ast" "1.12.1" "@webassemblyjs/helper-wasm-bytecode" "1.11.6" "@webassemblyjs/ieee754" "1.11.6" "@webassemblyjs/leb128" "1.11.6" "@webassemblyjs/utf8" "1.11.6" -"@webassemblyjs/wasm-opt@1.11.6": - version "1.11.6" - resolved "https://registry.yarnpkg.com/@webassemblyjs/wasm-opt/-/wasm-opt-1.11.6.tgz#d9a22d651248422ca498b09aa3232a81041487c2" - integrity sha512-cOrKuLRE7PCe6AsOVl7WasYf3wbSo4CeOk6PkrjS7g57MFfVUF9u6ysQBBODX0LdgSvQqRiGz3CXvIDKcPNy4g== +"@webassemblyjs/wasm-opt@1.12.1": + version "1.12.1" + resolved "https://registry.yarnpkg.com/@webassemblyjs/wasm-opt/-/wasm-opt-1.12.1.tgz#9e6e81475dfcfb62dab574ac2dda38226c232bc5" + integrity sha512-Jg99j/2gG2iaz3hijw857AVYekZe2SAskcqlWIZXjji5WStnOpVoat3gQfT/Q5tb2djnCjBtMocY/Su1GfxPBg== dependencies: - "@webassemblyjs/ast" "1.11.6" - "@webassemblyjs/helper-buffer" "1.11.6" - "@webassemblyjs/wasm-gen" "1.11.6" - "@webassemblyjs/wasm-parser" "1.11.6" + "@webassemblyjs/ast" "1.12.1" + "@webassemblyjs/helper-buffer" "1.12.1" + "@webassemblyjs/wasm-gen" "1.12.1" + "@webassemblyjs/wasm-parser" "1.12.1" -"@webassemblyjs/wasm-parser@1.11.6", "@webassemblyjs/wasm-parser@^1.11.5": - version "1.11.6" - resolved "https://registry.yarnpkg.com/@webassemblyjs/wasm-parser/-/wasm-parser-1.11.6.tgz#bb85378c527df824004812bbdb784eea539174a1" - integrity sha512-6ZwPeGzMJM3Dqp3hCsLgESxBGtT/OeCvCZ4TA1JUPYgmhAx38tTPR9JaKy0S5H3evQpO/h2uWs2j6Yc/fjkpTQ== +"@webassemblyjs/wasm-parser@1.12.1", "@webassemblyjs/wasm-parser@^1.12.1": + version "1.12.1" + resolved "https://registry.yarnpkg.com/@webassemblyjs/wasm-parser/-/wasm-parser-1.12.1.tgz#c47acb90e6f083391e3fa61d113650eea1e95937" + integrity sha512-xikIi7c2FHXysxXe3COrVUPSheuBtpcfhbpFj4gmu7KRLYOzANztwUU0IbsqvMqzuNK2+glRGWCEqZo1WCLyAQ== dependencies: - "@webassemblyjs/ast" "1.11.6" + "@webassemblyjs/ast" "1.12.1" "@webassemblyjs/helper-api-error" "1.11.6" "@webassemblyjs/helper-wasm-bytecode" "1.11.6" "@webassemblyjs/ieee754" "1.11.6" "@webassemblyjs/leb128" "1.11.6" "@webassemblyjs/utf8" "1.11.6" -"@webassemblyjs/wast-printer@1.11.6": - version "1.11.6" - resolved "https://registry.yarnpkg.com/@webassemblyjs/wast-printer/-/wast-printer-1.11.6.tgz#a7bf8dd7e362aeb1668ff43f35cb849f188eff20" - integrity sha512-JM7AhRcE+yW2GWYaKeHL5vt4xqee5N2WcezptmgyhNS+ScggqcT1OtXykhAb13Sn5Yas0j2uv9tHgrjwvzAP4A== +"@webassemblyjs/wast-printer@1.12.1": + version "1.12.1" + resolved "https://registry.yarnpkg.com/@webassemblyjs/wast-printer/-/wast-printer-1.12.1.tgz#bcecf661d7d1abdaf989d8341a4833e33e2b31ac" + integrity sha512-+X4WAlOisVWQMikjbcvY2e0rwPsKQ9F688lksZhBcPycBBuii3O7m8FACbDMWDojpAqvjIncrG8J0XHKyQfVeA== dependencies: - "@webassemblyjs/ast" "1.11.6" + "@webassemblyjs/ast" "1.12.1" "@xtuc/long" "4.2.2" "@xtuc/ieee754@^1.2.0": @@ -2875,10 +2859,10 @@ accepts@~1.3.4, accepts@~1.3.5, accepts@~1.3.8: mime-types "~2.1.34" negotiator "0.6.3" -acorn-import-assertions@^1.9.0: - version "1.9.0" - resolved "https://registry.yarnpkg.com/acorn-import-assertions/-/acorn-import-assertions-1.9.0.tgz#507276249d684797c84e0734ef84860334cfb1ac" - integrity sha512-cmMwop9x+8KFhxvKrKfPYmN6/pKTYYHBqLa0DfvVZcKMJWNyWLnaqND7dx/qn66R7ewM1UX5XMaDVP5wlVTaVA== +acorn-import-attributes@^1.9.5: + version "1.9.5" + resolved "https://registry.yarnpkg.com/acorn-import-attributes/-/acorn-import-attributes-1.9.5.tgz#7eb1557b1ba05ef18b5ed0ec67591bfab04688ef" + integrity sha512-n02Vykv5uA3eHGM/Z2dQrcD56kL8TyDb2p1+0P83PClMnC/nc+anbQRhIOWnSq4Ke/KvDPrY3C9hDtC/A3eHnQ== acorn-jsx@^5.0.0: version "5.3.2" @@ -4459,10 +4443,10 @@ encodeurl@~2.0.0: resolved "https://registry.yarnpkg.com/encodeurl/-/encodeurl-2.0.0.tgz#7b8ea898077d7e409d3ac45474ea38eaf0857a58" integrity sha512-Q0n9HRi4m6JuGIV1eFlmvJB7ZEVxu93IrMyiMsGC0lrMJMWzRgx6WGquyfQgZVb31vhGgXnfmPNNXmxnOkRBrg== -enhanced-resolve@^5.15.0: - version "5.15.1" - resolved "https://registry.yarnpkg.com/enhanced-resolve/-/enhanced-resolve-5.15.1.tgz#384391e025f099e67b4b00bfd7f0906a408214e1" - integrity sha512-3d3JRbwsCLJsYgvb6NuWEG44jjPSOMuS73L/6+7BZuoKm3W+qXnSoIYVHi8dG7Qcg4inAY4jbzkZ7MnskePeDg== +enhanced-resolve@^5.17.1: + version "5.17.1" + resolved "https://registry.yarnpkg.com/enhanced-resolve/-/enhanced-resolve-5.17.1.tgz#67bfbbcc2f81d511be77d686a90267ef7f898a15" + integrity sha512-LMHl3dXhTcfv8gM4kEzIUeTQ+7fpdA0l2tUf34BddXPkz2A5xJ5L/Pchd5BL6rdccM9QGvu0sWZzK1Z1t4wwyg== dependencies: graceful-fs "^4.2.4" tapable "^2.2.0" @@ -5076,7 +5060,7 @@ graceful-fs@4.2.10: resolved "https://registry.yarnpkg.com/graceful-fs/-/graceful-fs-4.2.10.tgz#147d3a006da4ca3ce14728c7aefc287c367d7a6c" integrity sha512-9ByhssR2fPVsNZj478qUUbKfmL0+t5BDVyjShtyZZLiK7ZDAArFFfopyOTj0M05wE2tJPisA4iTnnXl2YoPvOA== -graceful-fs@^4.1.11, graceful-fs@^4.1.2, graceful-fs@^4.1.6, graceful-fs@^4.2.0, graceful-fs@^4.2.4, graceful-fs@^4.2.6, graceful-fs@^4.2.9: +graceful-fs@^4.1.11, graceful-fs@^4.1.2, graceful-fs@^4.1.6, graceful-fs@^4.2.0, graceful-fs@^4.2.11, graceful-fs@^4.2.4, graceful-fs@^4.2.6, graceful-fs@^4.2.9: version "4.2.11" resolved "https://registry.yarnpkg.com/graceful-fs/-/graceful-fs-4.2.11.tgz#4183e4e8bf08bb6e05bbb2f7d2e0c8f712ca40e3" integrity sha512-RbJ5/jmFcNNCcDV5o9eTnBLJ/HszWV0P73bc+Ff4nS/rJj+YaS6IGyiOL0VoBYX+l1Wrl3k63h/KrH+nhJ0XvQ== @@ -9251,10 +9235,10 @@ vfile@^6.0.0, vfile@^6.0.1: unist-util-stringify-position "^4.0.0" vfile-message "^4.0.0" -watchpack@^2.4.0: - version "2.4.0" - resolved "https://registry.yarnpkg.com/watchpack/-/watchpack-2.4.0.tgz#fa33032374962c78113f93c7f2fb4c54c9862a5d" - integrity sha512-Lcvm7MGST/4fup+ifyKi2hjyIAwcdI4HRgtvTpIUxBRhB+RFtUh8XtDOxUfctVCnhVi+QQj49i91OyvzkJl6cg== +watchpack@^2.4.1: + version "2.4.2" + resolved "https://registry.yarnpkg.com/watchpack/-/watchpack-2.4.2.tgz#2feeaed67412e7c33184e5a79ca738fbd38564da" + integrity sha512-TnbFSbcOCcDgjZ4piURLCbJ3nJhznVh9kw6F6iokjiFPl8ONxe9A6nMDVXDiNbrSfLILs6vB07F7wLBrwPYzJw== dependencies: glob-to-regexp "^0.4.1" graceful-fs "^4.1.2" @@ -9357,25 +9341,24 @@ webpack-sources@^3.2.2, webpack-sources@^3.2.3: integrity sha512-/DyMEOrDgLKKIG0fmvtz+4dUX/3Ghozwgm6iPp8KRhvn+eQf9+Q7GWxVNMk3+uCPWfdXYC4ExGBckIXdFEfH1w== webpack@^5.88.1: - version "5.90.3" - resolved "https://registry.yarnpkg.com/webpack/-/webpack-5.90.3.tgz#37b8f74d3ded061ba789bb22b31e82eed75bd9ac" - integrity sha512-h6uDYlWCctQRuXBs1oYpVe6sFcWedl0dpcVaTf/YF67J9bKvwJajFulMVSYKHrksMB3I/pIagRzDxwxkebuzKA== + version "5.94.0" + resolved "https://registry.yarnpkg.com/webpack/-/webpack-5.94.0.tgz#77a6089c716e7ab90c1c67574a28da518a20970f" + integrity sha512-KcsGn50VT+06JH/iunZJedYGUJS5FGjow8wb9c0v5n1Om8O1g4L6LjtfxwlXIATopoQu+vOXXa7gYisWxCoPyg== dependencies: - "@types/eslint-scope" "^3.7.3" "@types/estree" "^1.0.5" - "@webassemblyjs/ast" "^1.11.5" - "@webassemblyjs/wasm-edit" "^1.11.5" - "@webassemblyjs/wasm-parser" "^1.11.5" + "@webassemblyjs/ast" "^1.12.1" + "@webassemblyjs/wasm-edit" "^1.12.1" + "@webassemblyjs/wasm-parser" "^1.12.1" acorn "^8.7.1" - acorn-import-assertions "^1.9.0" + acorn-import-attributes "^1.9.5" browserslist "^4.21.10" chrome-trace-event "^1.0.2" - enhanced-resolve "^5.15.0" + enhanced-resolve "^5.17.1" es-module-lexer "^1.2.1" eslint-scope "5.1.1" events "^3.2.0" glob-to-regexp "^0.4.1" - graceful-fs "^4.2.9" + graceful-fs "^4.2.11" json-parse-even-better-errors "^2.3.1" loader-runner "^4.2.0" mime-types "^2.1.27" @@ -9383,7 +9366,7 @@ webpack@^5.88.1: schema-utils "^3.2.0" tapable "^2.1.1" terser-webpack-plugin "^5.3.10" - watchpack "^2.4.0" + watchpack "^2.4.1" webpack-sources "^3.2.3" webpackbar@^5.0.2: From 2fcecd61f51d076769d4146611e898ec83690948 Mon Sep 17 00:00:00 2001 From: "dependabot[bot]" <49699333+dependabot[bot]@users.noreply.github.com> Date: Mon, 16 Sep 2024 22:28:24 +0100 Subject: [PATCH 09/52] chore(deps): bump dompurify from 3.0.9 to 3.1.6 in /docs (#7088) Bumps [dompurify](https://github.com/cure53/DOMPurify) from 3.0.9 to 3.1.6. - [Release notes](https://github.com/cure53/DOMPurify/releases) - [Commits](https://github.com/cure53/DOMPurify/compare/3.0.9...3.1.6) --- updated-dependencies: - dependency-name: dompurify dependency-type: indirect ... Signed-off-by: dependabot[bot] Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com> --- docs/yarn.lock | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/docs/yarn.lock b/docs/yarn.lock index 06e7cf388568..27123932fe26 100644 --- a/docs/yarn.lock +++ b/docs/yarn.lock @@ -4346,9 +4346,9 @@ domhandler@^5.0.2, domhandler@^5.0.3: domelementtype "^2.3.0" dompurify@^3.0.5: - version "3.0.9" - resolved "https://registry.yarnpkg.com/dompurify/-/dompurify-3.0.9.tgz#b3f362f24b99f53498c75d43ecbd784b0b3ad65e" - integrity sha512-uyb4NDIvQ3hRn6NiC+SIFaP4mJ/MdXlvtunaqK9Bn6dD3RuB/1S/gasEjDHD8eiaqdSael2vBv+hOs7Y+jhYOQ== + version "3.1.6" + resolved "https://registry.yarnpkg.com/dompurify/-/dompurify-3.1.6.tgz#43c714a94c6a7b8801850f82e756685300a027e2" + integrity sha512-cTOAhc36AalkjtBpfG6O8JimdTMWNXjiePT2xQH/ppBGi/4uIpmj8eKyIkMJErXWARyINV/sB38yf8JCLF5pbQ== domutils@^2.5.2, domutils@^2.8.0: version "2.8.0" From 25837f61fed8089ebb8e06e505fea8e7a48b614e Mon Sep 17 00:00:00 2001 From: Phil Ngo Date: Tue, 17 Sep 2024 14:45:18 -0400 Subject: [PATCH 10/52] Merge branch 'stable' into unstable --- lerna.json | 2 +- packages/api/package.json | 10 +++++----- packages/beacon-node/package.json | 26 +++++++++++++------------- packages/cli/package.json | 26 +++++++++++++------------- packages/config/package.json | 8 ++++---- packages/db/package.json | 8 ++++---- packages/flare/package.json | 14 +++++++------- packages/fork-choice/package.json | 12 ++++++------ packages/light-client/package.json | 12 ++++++------ packages/logger/package.json | 6 +++--- packages/params/package.json | 2 +- packages/prover/package.json | 18 +++++++++--------- packages/reqresp/package.json | 12 ++++++------ packages/spec-test-util/package.json | 4 ++-- packages/state-transition/package.json | 10 +++++----- packages/test-utils/package.json | 6 +++--- packages/types/package.json | 4 ++-- packages/utils/package.json | 2 +- packages/validator/package.json | 18 +++++++++--------- 19 files changed, 100 insertions(+), 100 deletions(-) diff --git a/lerna.json b/lerna.json index 043a5c48569a..0ffc65fe5402 100644 --- a/lerna.json +++ b/lerna.json @@ -4,7 +4,7 @@ ], "npmClient": "yarn", "useNx": true, - "version": "1.21.0", + "version": "1.22.0", "stream": true, "command": { "version": { diff --git a/packages/api/package.json b/packages/api/package.json index 138964ed946a..d2f8a621f02e 100644 --- a/packages/api/package.json +++ b/packages/api/package.json @@ -11,7 +11,7 @@ "bugs": { "url": "https://github.com/ChainSafe/lodestar/issues" }, - "version": "1.21.0", + "version": "1.22.0", "type": "module", "exports": { ".": { @@ -72,10 +72,10 @@ "dependencies": { "@chainsafe/persistent-merkle-tree": "^0.8.0", "@chainsafe/ssz": "^0.17.1", - "@lodestar/config": "^1.21.0", - "@lodestar/params": "^1.21.0", - "@lodestar/types": "^1.21.0", - "@lodestar/utils": "^1.21.0", + "@lodestar/config": "^1.22.0", + "@lodestar/params": "^1.22.0", + "@lodestar/types": "^1.22.0", + "@lodestar/utils": "^1.22.0", "eventsource": "^2.0.2", "qs": "^6.11.1" }, diff --git a/packages/beacon-node/package.json b/packages/beacon-node/package.json index b41450f12d34..ade89ebc6cc1 100644 --- a/packages/beacon-node/package.json +++ b/packages/beacon-node/package.json @@ -11,7 +11,7 @@ "bugs": { "url": "https://github.com/ChainSafe/lodestar/issues" }, - "version": "1.21.0", + "version": "1.22.0", "type": "module", "exports": { ".": { @@ -119,18 +119,18 @@ "@libp2p/peer-id-factory": "^4.1.0", "@libp2p/prometheus-metrics": "^3.0.21", "@libp2p/tcp": "9.0.23", - "@lodestar/api": "^1.21.0", - "@lodestar/config": "^1.21.0", - "@lodestar/db": "^1.21.0", - "@lodestar/fork-choice": "^1.21.0", - "@lodestar/light-client": "^1.21.0", - "@lodestar/logger": "^1.21.0", - "@lodestar/params": "^1.21.0", - "@lodestar/reqresp": "^1.21.0", - "@lodestar/state-transition": "^1.21.0", - "@lodestar/types": "^1.21.0", - "@lodestar/utils": "^1.21.0", - "@lodestar/validator": "^1.21.0", + "@lodestar/api": "^1.22.0", + "@lodestar/config": "^1.22.0", + "@lodestar/db": "^1.22.0", + "@lodestar/fork-choice": "^1.22.0", + "@lodestar/light-client": "^1.22.0", + "@lodestar/logger": "^1.22.0", + "@lodestar/params": "^1.22.0", + "@lodestar/reqresp": "^1.22.0", + "@lodestar/state-transition": "^1.22.0", + "@lodestar/types": "^1.22.0", + "@lodestar/utils": "^1.22.0", + "@lodestar/validator": "^1.22.0", "@multiformats/multiaddr": "^12.1.3", "c-kzg": "^2.1.2", "datastore-core": "^9.1.1", diff --git a/packages/cli/package.json b/packages/cli/package.json index bf8621344dc5..579725eba04e 100644 --- a/packages/cli/package.json +++ b/packages/cli/package.json @@ -1,6 +1,6 @@ { "name": "@chainsafe/lodestar", - "version": "1.21.0", + "version": "1.22.0", "description": "Command line interface for lodestar", "author": "ChainSafe Systems", "license": "LGPL-3.0", @@ -62,17 +62,17 @@ "@libp2p/crypto": "^4.1.0", "@libp2p/peer-id": "^4.1.0", "@libp2p/peer-id-factory": "^4.1.0", - "@lodestar/api": "^1.21.0", - "@lodestar/beacon-node": "^1.21.0", - "@lodestar/config": "^1.21.0", - "@lodestar/db": "^1.21.0", - "@lodestar/light-client": "^1.21.0", - "@lodestar/logger": "^1.21.0", - "@lodestar/params": "^1.21.0", - "@lodestar/state-transition": "^1.21.0", - "@lodestar/types": "^1.21.0", - "@lodestar/utils": "^1.21.0", - "@lodestar/validator": "^1.21.0", + "@lodestar/api": "^1.22.0", + "@lodestar/beacon-node": "^1.22.0", + "@lodestar/config": "^1.22.0", + "@lodestar/db": "^1.22.0", + "@lodestar/light-client": "^1.22.0", + "@lodestar/logger": "^1.22.0", + "@lodestar/params": "^1.22.0", + "@lodestar/state-transition": "^1.22.0", + "@lodestar/types": "^1.22.0", + "@lodestar/utils": "^1.22.0", + "@lodestar/validator": "^1.22.0", "@multiformats/multiaddr": "^12.1.3", "deepmerge": "^4.3.1", "ethers": "^6.7.0", @@ -88,7 +88,7 @@ "yargs": "^17.7.1" }, "devDependencies": { - "@lodestar/test-utils": "^1.21.0", + "@lodestar/test-utils": "^1.22.0", "@types/debug": "^4.1.7", "@types/got": "^9.6.12", "@types/inquirer": "^9.0.3", diff --git a/packages/config/package.json b/packages/config/package.json index d13713d376c6..f257db65cf6e 100644 --- a/packages/config/package.json +++ b/packages/config/package.json @@ -1,6 +1,6 @@ { "name": "@lodestar/config", - "version": "1.21.0", + "version": "1.22.0", "description": "Chain configuration required for lodestar", "author": "ChainSafe Systems", "license": "Apache-2.0", @@ -65,8 +65,8 @@ ], "dependencies": { "@chainsafe/ssz": "^0.17.1", - "@lodestar/params": "^1.21.0", - "@lodestar/utils": "^1.21.0", - "@lodestar/types": "^1.21.0" + "@lodestar/params": "^1.22.0", + "@lodestar/utils": "^1.22.0", + "@lodestar/types": "^1.22.0" } } diff --git a/packages/db/package.json b/packages/db/package.json index 1a31603b6791..0e3a2c847d4b 100644 --- a/packages/db/package.json +++ b/packages/db/package.json @@ -1,6 +1,6 @@ { "name": "@lodestar/db", - "version": "1.21.0", + "version": "1.22.0", "description": "DB modules of Lodestar", "author": "ChainSafe Systems", "homepage": "https://github.com/ChainSafe/lodestar#readme", @@ -36,12 +36,12 @@ }, "dependencies": { "@chainsafe/ssz": "^0.17.1", - "@lodestar/config": "^1.21.0", - "@lodestar/utils": "^1.21.0", + "@lodestar/config": "^1.22.0", + "@lodestar/utils": "^1.22.0", "classic-level": "^1.4.1", "it-all": "^3.0.4" }, "devDependencies": { - "@lodestar/logger": "^1.21.0" + "@lodestar/logger": "^1.22.0" } } diff --git a/packages/flare/package.json b/packages/flare/package.json index 461147274591..3a11e9b49ebf 100644 --- a/packages/flare/package.json +++ b/packages/flare/package.json @@ -1,6 +1,6 @@ { "name": "@lodestar/flare", - "version": "1.21.0", + "version": "1.22.0", "description": "Beacon chain debugging tool", "author": "ChainSafe Systems", "license": "Apache-2.0", @@ -60,12 +60,12 @@ "dependencies": { "@chainsafe/bls-keygen": "^0.4.0", "@chainsafe/blst": "^2.0.3", - "@lodestar/api": "^1.21.0", - "@lodestar/config": "^1.21.0", - "@lodestar/params": "^1.21.0", - "@lodestar/state-transition": "^1.21.0", - "@lodestar/types": "^1.21.0", - "@lodestar/utils": "^1.21.0", + "@lodestar/api": "^1.22.0", + "@lodestar/config": "^1.22.0", + "@lodestar/params": "^1.22.0", + "@lodestar/state-transition": "^1.22.0", + "@lodestar/types": "^1.22.0", + "@lodestar/utils": "^1.22.0", "source-map-support": "^0.5.21", "yargs": "^17.7.1" }, diff --git a/packages/fork-choice/package.json b/packages/fork-choice/package.json index dfe4c942832d..728036b365d3 100644 --- a/packages/fork-choice/package.json +++ b/packages/fork-choice/package.json @@ -11,7 +11,7 @@ "bugs": { "url": "https://github.com/ChainSafe/lodestar/issues" }, - "version": "1.21.0", + "version": "1.22.0", "type": "module", "exports": "./lib/index.js", "types": "./lib/index.d.ts", @@ -37,11 +37,11 @@ }, "dependencies": { "@chainsafe/ssz": "^0.17.1", - "@lodestar/config": "^1.21.0", - "@lodestar/params": "^1.21.0", - "@lodestar/state-transition": "^1.21.0", - "@lodestar/types": "^1.21.0", - "@lodestar/utils": "^1.21.0" + "@lodestar/config": "^1.22.0", + "@lodestar/params": "^1.22.0", + "@lodestar/state-transition": "^1.22.0", + "@lodestar/types": "^1.22.0", + "@lodestar/utils": "^1.22.0" }, "keywords": [ "ethereum", diff --git a/packages/light-client/package.json b/packages/light-client/package.json index 1188732c8870..940a78ae66d5 100644 --- a/packages/light-client/package.json +++ b/packages/light-client/package.json @@ -11,7 +11,7 @@ "bugs": { "url": "https://github.com/ChainSafe/lodestar/issues" }, - "version": "1.21.0", + "version": "1.22.0", "type": "module", "exports": { ".": { @@ -77,11 +77,11 @@ "@chainsafe/blst": "^0.2.0", "@chainsafe/persistent-merkle-tree": "^0.8.0", "@chainsafe/ssz": "^0.17.1", - "@lodestar/api": "^1.21.0", - "@lodestar/config": "^1.21.0", - "@lodestar/params": "^1.21.0", - "@lodestar/types": "^1.21.0", - "@lodestar/utils": "^1.21.0", + "@lodestar/api": "^1.22.0", + "@lodestar/config": "^1.22.0", + "@lodestar/params": "^1.22.0", + "@lodestar/types": "^1.22.0", + "@lodestar/utils": "^1.22.0", "mitt": "^3.0.0" }, "devDependencies": { diff --git a/packages/logger/package.json b/packages/logger/package.json index 1ab176dbfd93..196fb306a8b0 100644 --- a/packages/logger/package.json +++ b/packages/logger/package.json @@ -11,7 +11,7 @@ "bugs": { "url": "https://github.com/ChainSafe/lodestar/issues" }, - "version": "1.21.0", + "version": "1.22.0", "type": "module", "exports": { ".": { @@ -66,14 +66,14 @@ }, "types": "lib/index.d.ts", "dependencies": { - "@lodestar/utils": "^1.21.0", + "@lodestar/utils": "^1.22.0", "winston": "^3.8.2", "winston-daily-rotate-file": "^4.7.1", "winston-transport": "^4.5.0" }, "devDependencies": { "@chainsafe/threads": "^1.11.1", - "@lodestar/test-utils": "^1.21.0", + "@lodestar/test-utils": "^1.22.0", "@types/triple-beam": "^1.3.2", "triple-beam": "^1.3.0" }, diff --git a/packages/params/package.json b/packages/params/package.json index c246918959e4..c281f97a41ec 100644 --- a/packages/params/package.json +++ b/packages/params/package.json @@ -1,6 +1,6 @@ { "name": "@lodestar/params", - "version": "1.21.0", + "version": "1.22.0", "description": "Chain parameters required for lodestar", "author": "ChainSafe Systems", "license": "Apache-2.0", diff --git a/packages/prover/package.json b/packages/prover/package.json index 974125e2a17f..6a31b5b1baa0 100644 --- a/packages/prover/package.json +++ b/packages/prover/package.json @@ -11,7 +11,7 @@ "bugs": { "url": "https://github.com/ChainSafe/lodestar/issues" }, - "version": "1.21.0", + "version": "1.22.0", "type": "module", "exports": { ".": { @@ -69,13 +69,13 @@ "@ethereumjs/tx": "^4.1.2", "@ethereumjs/util": "^8.0.6", "@ethereumjs/vm": "^6.4.2", - "@lodestar/api": "^1.21.0", - "@lodestar/config": "^1.21.0", - "@lodestar/light-client": "^1.21.0", - "@lodestar/logger": "^1.21.0", - "@lodestar/params": "^1.21.0", - "@lodestar/types": "^1.21.0", - "@lodestar/utils": "^1.21.0", + "@lodestar/api": "^1.22.0", + "@lodestar/config": "^1.22.0", + "@lodestar/light-client": "^1.22.0", + "@lodestar/logger": "^1.22.0", + "@lodestar/params": "^1.22.0", + "@lodestar/types": "^1.22.0", + "@lodestar/utils": "^1.22.0", "ethereum-cryptography": "^2.0.0", "find-up": "^6.3.0", "http-proxy": "^1.18.1", @@ -84,7 +84,7 @@ "yargs": "^17.7.1" }, "devDependencies": { - "@lodestar/test-utils": "^1.21.0", + "@lodestar/test-utils": "^1.22.0", "@types/http-proxy": "^1.17.10", "@types/yargs": "^17.0.24", "axios": "^1.3.4", diff --git a/packages/reqresp/package.json b/packages/reqresp/package.json index 1b9d99b000a8..44dcb8048f99 100644 --- a/packages/reqresp/package.json +++ b/packages/reqresp/package.json @@ -11,7 +11,7 @@ "bugs": { "url": "https://github.com/ChainSafe/lodestar/issues" }, - "version": "1.21.0", + "version": "1.22.0", "type": "module", "exports": { ".": { @@ -54,9 +54,9 @@ "dependencies": { "@chainsafe/fast-crc32c": "^4.1.1", "@libp2p/interface": "^1.3.0", - "@lodestar/config": "^1.21.0", - "@lodestar/params": "^1.21.0", - "@lodestar/utils": "^1.21.0", + "@lodestar/config": "^1.22.0", + "@lodestar/params": "^1.22.0", + "@lodestar/utils": "^1.22.0", "it-all": "^3.0.4", "it-pipe": "^3.0.1", "snappy": "^7.2.2", @@ -65,8 +65,8 @@ "uint8arraylist": "^2.4.7" }, "devDependencies": { - "@lodestar/logger": "^1.21.0", - "@lodestar/types": "^1.21.0", + "@lodestar/logger": "^1.22.0", + "@lodestar/types": "^1.22.0", "libp2p": "1.4.3" }, "peerDependencies": { diff --git a/packages/spec-test-util/package.json b/packages/spec-test-util/package.json index 166df67a7409..b4aabf0140e8 100644 --- a/packages/spec-test-util/package.json +++ b/packages/spec-test-util/package.json @@ -1,6 +1,6 @@ { "name": "@lodestar/spec-test-util", - "version": "1.21.0", + "version": "1.22.0", "description": "Spec test suite generator from yaml test files", "author": "ChainSafe Systems", "license": "Apache-2.0", @@ -62,7 +62,7 @@ "blockchain" ], "dependencies": { - "@lodestar/utils": "^1.21.0", + "@lodestar/utils": "^1.22.0", "axios": "^1.3.4", "rimraf": "^4.4.1", "snappyjs": "^0.7.0", diff --git a/packages/state-transition/package.json b/packages/state-transition/package.json index 1dd43ef98f88..2df87a522a63 100644 --- a/packages/state-transition/package.json +++ b/packages/state-transition/package.json @@ -11,7 +11,7 @@ "bugs": { "url": "https://github.com/ChainSafe/lodestar/issues" }, - "version": "1.21.0", + "version": "1.22.0", "type": "module", "exports": { ".": { @@ -63,10 +63,10 @@ "@chainsafe/persistent-merkle-tree": "^0.8.0", "@chainsafe/persistent-ts": "^0.19.1", "@chainsafe/ssz": "^0.17.1", - "@lodestar/config": "^1.21.0", - "@lodestar/params": "^1.21.0", - "@lodestar/types": "^1.21.0", - "@lodestar/utils": "^1.21.0", + "@lodestar/config": "^1.22.0", + "@lodestar/params": "^1.22.0", + "@lodestar/types": "^1.22.0", + "@lodestar/utils": "^1.22.0", "bigint-buffer": "^1.1.5", "immutable": "^4.3.2" }, diff --git a/packages/test-utils/package.json b/packages/test-utils/package.json index 6c8c9e62894f..5bf61891a9d5 100644 --- a/packages/test-utils/package.json +++ b/packages/test-utils/package.json @@ -1,7 +1,7 @@ { "name": "@lodestar/test-utils", "private": true, - "version": "1.21.0", + "version": "1.22.0", "description": "Test utilities reused across other packages", "author": "ChainSafe Systems", "license": "Apache-2.0", @@ -59,8 +59,8 @@ "dependencies": { "@chainsafe/bls-keystore": "^3.1.0", "@chainsafe/blst": "^2.0.3", - "@lodestar/params": "^1.21.0", - "@lodestar/utils": "^1.21.0", + "@lodestar/params": "^1.22.0", + "@lodestar/utils": "^1.22.0", "axios": "^1.3.4", "testcontainers": "^10.2.1", "tmp": "^0.2.1", diff --git a/packages/types/package.json b/packages/types/package.json index 861dbdbee0ef..f3e034ec1b35 100644 --- a/packages/types/package.json +++ b/packages/types/package.json @@ -11,7 +11,7 @@ "bugs": { "url": "https://github.com/ChainSafe/lodestar/issues" }, - "version": "1.21.0", + "version": "1.22.0", "type": "module", "exports": { ".": { @@ -74,7 +74,7 @@ "types": "lib/index.d.ts", "dependencies": { "@chainsafe/ssz": "^0.17.1", - "@lodestar/params": "^1.21.0", + "@lodestar/params": "^1.22.0", "ethereum-cryptography": "^2.0.0" }, "keywords": [ diff --git a/packages/utils/package.json b/packages/utils/package.json index 492c65606dfb..0723f5f1815c 100644 --- a/packages/utils/package.json +++ b/packages/utils/package.json @@ -11,7 +11,7 @@ "bugs": { "url": "https://github.com/ChainSafe/lodestar/issues" }, - "version": "1.21.0", + "version": "1.22.0", "type": "module", "exports": "./lib/index.js", "files": [ diff --git a/packages/validator/package.json b/packages/validator/package.json index 373e59817d2a..65ed656f010d 100644 --- a/packages/validator/package.json +++ b/packages/validator/package.json @@ -1,6 +1,6 @@ { "name": "@lodestar/validator", - "version": "1.21.0", + "version": "1.22.0", "description": "A Typescript implementation of the validator client", "author": "ChainSafe Systems", "license": "LGPL-3.0", @@ -47,17 +47,17 @@ "dependencies": { "@chainsafe/blst": "^2.0.3", "@chainsafe/ssz": "^0.17.1", - "@lodestar/api": "^1.21.0", - "@lodestar/config": "^1.21.0", - "@lodestar/db": "^1.21.0", - "@lodestar/params": "^1.21.0", - "@lodestar/state-transition": "^1.21.0", - "@lodestar/types": "^1.21.0", - "@lodestar/utils": "^1.21.0", + "@lodestar/api": "^1.22.0", + "@lodestar/config": "^1.22.0", + "@lodestar/db": "^1.22.0", + "@lodestar/params": "^1.22.0", + "@lodestar/state-transition": "^1.22.0", + "@lodestar/types": "^1.22.0", + "@lodestar/utils": "^1.22.0", "strict-event-emitter-types": "^2.0.0" }, "devDependencies": { - "@lodestar/test-utils": "^1.21.0", + "@lodestar/test-utils": "^1.22.0", "bigint-buffer": "^1.1.5", "rimraf": "^4.4.1" } From 8da003e0f18523a1e6093177a147815365bd37e2 Mon Sep 17 00:00:00 2001 From: "dependabot[bot]" <49699333+dependabot[bot]@users.noreply.github.com> Date: Tue, 17 Sep 2024 22:02:41 +0100 Subject: [PATCH 11/52] chore(deps-dev): bump vite from 5.3.4 to 5.3.6 (#7090) Bumps [vite](https://github.com/vitejs/vite/tree/HEAD/packages/vite) from 5.3.4 to 5.3.6. - [Release notes](https://github.com/vitejs/vite/releases) - [Changelog](https://github.com/vitejs/vite/blob/v5.3.6/packages/vite/CHANGELOG.md) - [Commits](https://github.com/vitejs/vite/commits/v5.3.6/packages/vite) --- updated-dependencies: - dependency-name: vite dependency-type: direct:development ... Signed-off-by: dependabot[bot] Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com> --- yarn.lock | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/yarn.lock b/yarn.lock index f9fa36847af9..5ed1b898f00c 100644 --- a/yarn.lock +++ b/yarn.lock @@ -13136,9 +13136,9 @@ vite-plugin-top-level-await@^1.4.2: uuid "^10.0.0" vite@^5.0.0, vite@^5.3.4: - version "5.3.4" - resolved "https://registry.yarnpkg.com/vite/-/vite-5.3.4.tgz#b36ebd47c8a5e3a8727046375d5f10bf9fdf8715" - integrity sha512-Cw+7zL3ZG9/NZBB8C+8QbQZmR54GwqIz+WMI4b3JgdYJvX+ny9AjJXqkGQlDXSXRP9rP0B4tbciRMOVEKulVOA== + version "5.3.6" + resolved "https://registry.yarnpkg.com/vite/-/vite-5.3.6.tgz#e097c0a7b79adb2e60bec9ef7907354f09d027bd" + integrity sha512-es78AlrylO8mTVBygC0gTC0FENv0C6T496vvd33ydbjF/mIi9q3XQ9A3NWo5qLGFKywvz10J26813OkLvcQleA== dependencies: esbuild "^0.21.3" postcss "^8.4.39" From fd6e23edab7cf3ca70aa596aaeb440908fb28bc6 Mon Sep 17 00:00:00 2001 From: "dependabot[bot]" <49699333+dependabot[bot]@users.noreply.github.com> Date: Wed, 18 Sep 2024 18:18:54 +0100 Subject: [PATCH 12/52] chore(deps): bump find-my-way from 8.1.0 to 8.2.2 (#7093) Bumps [find-my-way](https://github.com/delvedor/find-my-way) from 8.1.0 to 8.2.2. - [Release notes](https://github.com/delvedor/find-my-way/releases) - [Commits](https://github.com/delvedor/find-my-way/compare/v8.1.0...v8.2.2) --- updated-dependencies: - dependency-name: find-my-way dependency-type: indirect ... Signed-off-by: dependabot[bot] Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com> --- yarn.lock | 26 +++++++++++++------------- 1 file changed, 13 insertions(+), 13 deletions(-) diff --git a/yarn.lock b/yarn.lock index 5ed1b898f00c..38e6bae97d60 100644 --- a/yarn.lock +++ b/yarn.lock @@ -6783,13 +6783,13 @@ fill-range@^7.1.1: to-regex-range "^5.0.1" find-my-way@^8.0.0: - version "8.1.0" - resolved "https://registry.yarnpkg.com/find-my-way/-/find-my-way-8.1.0.tgz#cc05e8e4b145322299d0de0a839b5be528c2083e" - integrity sha512-41QwjCGcVTODUmLLqTMeoHeiozbMXYMAE1CKFiDyi9zVZ2Vjh0yz3MF0WQZoIb+cmzP/XlbFjlF2NtJmvZHznA== + version "8.2.2" + resolved "https://registry.yarnpkg.com/find-my-way/-/find-my-way-8.2.2.tgz#f3e78bc6ead2da4fdaa201335da3228600ed0285" + integrity sha512-Dobi7gcTEq8yszimcfp/R7+owiT4WncAJ7VTTgFH1jYJ5GaG1FbhjwDG820hptN0QDFvzVY3RfCzdInvGPGzjA== dependencies: fast-deep-equal "^3.1.3" fast-querystring "^1.0.0" - safe-regex2 "^2.0.0" + safe-regex2 "^3.1.0" find-up@5.0.0, find-up@^5.0.0: version "5.0.0" @@ -11358,10 +11358,10 @@ restore-cursor@^4.0.0: onetime "^5.1.0" signal-exit "^3.0.2" -ret@~0.2.0: - version "0.2.2" - resolved "https://registry.npmjs.org/ret/-/ret-0.2.2.tgz" - integrity sha512-M0b3YWQs7R3Z917WRQy1HHA7Ba7D8hvZg6UE5mLykJxQVE2ju0IXbGlaHPPlkY+WN7wFP+wUMXmBFA0aV6vYGQ== +ret@~0.4.0: + version "0.4.3" + resolved "https://registry.yarnpkg.com/ret/-/ret-0.4.3.tgz#5243fa30e704a2e78a9b9b1e86079e15891aa85c" + integrity sha512-0f4Memo5QP7WQyUEAYUO3esD/XjOc3Zjjg5CPsAq1p8sIu0XPeMbHJemKA0BO7tV0X7+A0FoEpbmHXWxPyD3wQ== retry@^0.12.0: version "0.12.0" @@ -11550,12 +11550,12 @@ safe-regex-test@^1.0.0: get-intrinsic "^1.1.3" is-regex "^1.1.4" -safe-regex2@^2.0.0: - version "2.0.0" - resolved "https://registry.npmjs.org/safe-regex2/-/safe-regex2-2.0.0.tgz" - integrity sha512-PaUSFsUaNNuKwkBijoAPHAK6/eM6VirvyPWlZ7BAQy4D+hCvh4B6lIG+nPdhbFfIbP+gTGBcrdsOaUs0F+ZBOQ== +safe-regex2@^3.1.0: + version "3.1.0" + resolved "https://registry.yarnpkg.com/safe-regex2/-/safe-regex2-3.1.0.tgz#fd7ec23908e2c730e1ce7359a5b72883a87d2763" + integrity sha512-RAAZAGbap2kBfbVhvmnTFv73NWLMvDGOITFYTZBAaY8eR+Ir4ef7Up/e7amo+y1+AH+3PtLkrt9mvcTsG9LXug== dependencies: - ret "~0.2.0" + ret "~0.4.0" safe-stable-stringify@^2.3.1: version "2.4.2" From bb40ef7eb77f9441ec66ab8f1fdf6664240bb1a3 Mon Sep 17 00:00:00 2001 From: Matthew Keil Date: Wed, 18 Sep 2024 15:09:07 -0400 Subject: [PATCH 13/52] feat: add electra support for light-client (#7063) * Add constant * Use constants * Remove ZERO_NEXT_SYNC_COMMITTEE_BRANCH * Add normalizeMerkleBranch * add getId to CheckpointHeaderRepository * fix: light-client unit tests * chore: lint * Fix normalizeMerkleBranch * Enable LC spec test * fix spec test --------- Co-authored-by: NC <17676176+ensi321@users.noreply.github.com> --- .../src/chain/lightClient/proofs.ts | 14 +++++--- .../lightclientCheckpointHeader.ts | 4 +++ .../beacon-node/src/network/reqresp/types.ts | 23 ++++++++++--- .../test/spec/utils/specTestIterator.ts | 5 ++- packages/light-client/src/spec/index.ts | 6 ++-- packages/light-client/src/spec/utils.ts | 32 +++++++++++++++++-- .../src/spec/validateLightClientBootstrap.ts | 8 +++-- .../src/spec/validateLightClientUpdate.ts | 16 ++++++---- .../src/utils/normalizeMerkleBranch.ts | 15 +++++++++ packages/light-client/src/validation.ts | 23 ++++++++++--- packages/light-client/test/unit/utils.test.ts | 16 ++++++++++ packages/params/src/index.ts | 6 ++-- packages/types/src/electra/sszTypes.ts | 20 ++++++------ packages/types/src/utils/typeguards.ts | 9 ++++++ 14 files changed, 155 insertions(+), 42 deletions(-) create mode 100644 packages/light-client/src/utils/normalizeMerkleBranch.ts diff --git a/packages/beacon-node/src/chain/lightClient/proofs.ts b/packages/beacon-node/src/chain/lightClient/proofs.ts index 87ad4544ec69..8d273e30ae5c 100644 --- a/packages/beacon-node/src/chain/lightClient/proofs.ts +++ b/packages/beacon-node/src/chain/lightClient/proofs.ts @@ -1,6 +1,11 @@ import {Tree} from "@chainsafe/persistent-merkle-tree"; -import {BeaconStateAllForks} from "@lodestar/state-transition"; -import {FINALIZED_ROOT_GINDEX, BLOCK_BODY_EXECUTION_PAYLOAD_GINDEX, ForkExecution} from "@lodestar/params"; +import {BeaconStateAllForks, CachedBeaconStateAllForks} from "@lodestar/state-transition"; +import { + FINALIZED_ROOT_GINDEX, + BLOCK_BODY_EXECUTION_PAYLOAD_GINDEX, + ForkExecution, + FINALIZED_ROOT_GINDEX_ELECTRA, +} from "@lodestar/params"; import {BeaconBlockBody, SSZTypesFor, ssz} from "@lodestar/types"; import {SyncCommitteeWitness} from "./types.js"; @@ -40,9 +45,10 @@ export function getCurrentSyncCommitteeBranch(syncCommitteesWitness: SyncCommitt return [syncCommitteesWitness.nextSyncCommitteeRoot, ...syncCommitteesWitness.witness]; } -export function getFinalizedRootProof(state: BeaconStateAllForks): Uint8Array[] { +export function getFinalizedRootProof(state: CachedBeaconStateAllForks): Uint8Array[] { state.commit(); - return new Tree(state.node).getSingleProof(BigInt(FINALIZED_ROOT_GINDEX)); + const finalizedRootGindex = state.epochCtx.isPostElectra() ? FINALIZED_ROOT_GINDEX_ELECTRA : FINALIZED_ROOT_GINDEX; + return new Tree(state.node).getSingleProof(BigInt(finalizedRootGindex)); } export function getBlockBodyExecutionHeaderProof( diff --git a/packages/beacon-node/src/db/repositories/lightclientCheckpointHeader.ts b/packages/beacon-node/src/db/repositories/lightclientCheckpointHeader.ts index 78f165bb975c..22d6559792eb 100644 --- a/packages/beacon-node/src/db/repositories/lightclientCheckpointHeader.ts +++ b/packages/beacon-node/src/db/repositories/lightclientCheckpointHeader.ts @@ -25,4 +25,8 @@ export class CheckpointHeaderRepository extends Repository; @@ -48,10 +61,10 @@ type ResponseBodyByMethod = { [ReqRespMethod.BeaconBlocksByRoot]: SignedBeaconBlock; [ReqRespMethod.BlobSidecarsByRange]: deneb.BlobSidecar; [ReqRespMethod.BlobSidecarsByRoot]: deneb.BlobSidecar; - [ReqRespMethod.LightClientBootstrap]: altair.LightClientBootstrap; - [ReqRespMethod.LightClientUpdatesByRange]: altair.LightClientUpdate; - [ReqRespMethod.LightClientFinalityUpdate]: altair.LightClientFinalityUpdate; - [ReqRespMethod.LightClientOptimisticUpdate]: altair.LightClientOptimisticUpdate; + [ReqRespMethod.LightClientBootstrap]: LightClientBootstrap; + [ReqRespMethod.LightClientUpdatesByRange]: LightClientUpdate; + [ReqRespMethod.LightClientFinalityUpdate]: LightClientFinalityUpdate; + [ReqRespMethod.LightClientOptimisticUpdate]: LightClientOptimisticUpdate; }; /** Request SSZ type for each method and ForkName */ diff --git a/packages/beacon-node/test/spec/utils/specTestIterator.ts b/packages/beacon-node/test/spec/utils/specTestIterator.ts index 48a002580043..d8b4f9c0574c 100644 --- a/packages/beacon-node/test/spec/utils/specTestIterator.ts +++ b/packages/beacon-node/test/spec/utils/specTestIterator.ts @@ -65,10 +65,9 @@ export const defaultSkipOpts: SkipOpts = { skippedTestSuites: [ /^capella\/light_client\/single_merkle_proof\/BeaconBlockBody.*/, /^deneb\/light_client\/single_merkle_proof\/BeaconBlockBody.*/, - /^electra\/light_client\/.*/, + /^electra\/light_client\/single_merkle_proof\/BeaconBlockBody.*/, ], - // TODO Electra: Review this test in the next spec test release - skippedTests: [/^deneb\/light_client\/sync\/.*electra_fork.*/], + skippedTests: [], skippedRunners: ["merkle_proof", "networking"], }; diff --git a/packages/light-client/src/spec/index.ts b/packages/light-client/src/spec/index.ts index fc1a431129e8..0934e15b1c17 100644 --- a/packages/light-client/src/spec/index.ts +++ b/packages/light-client/src/spec/index.ts @@ -10,7 +10,7 @@ import { import {computeSyncPeriodAtSlot} from "../utils/index.js"; import {getSyncCommitteeAtPeriod, processLightClientUpdate, ProcessUpdateOpts} from "./processLightClientUpdate.js"; import {ILightClientStore, LightClientStore, LightClientStoreEvents} from "./store.js"; -import {ZERO_FINALITY_BRANCH, ZERO_HEADER, ZERO_NEXT_SYNC_COMMITTEE_BRANCH, ZERO_SYNC_COMMITTEE} from "./utils.js"; +import {ZERO_FINALITY_BRANCH, ZERO_HEADER, ZERO_SYNC_COMMITTEE, getZeroSyncCommitteeBranch} from "./utils.js"; export {isBetterUpdate, toLightClientUpdateSummary} from "./isBetterUpdate.js"; export type {LightClientUpdateSummary} from "./isBetterUpdate.js"; @@ -37,7 +37,7 @@ export class LightclientSpec { this.onUpdate(currentSlot, { attestedHeader: finalityUpdate.attestedHeader, nextSyncCommittee: ZERO_SYNC_COMMITTEE, - nextSyncCommitteeBranch: ZERO_NEXT_SYNC_COMMITTEE_BRANCH, + nextSyncCommitteeBranch: getZeroSyncCommitteeBranch(this.config.getForkName(finalityUpdate.signatureSlot)), finalizedHeader: finalityUpdate.finalizedHeader, finalityBranch: finalityUpdate.finalityBranch, syncAggregate: finalityUpdate.syncAggregate, @@ -49,7 +49,7 @@ export class LightclientSpec { this.onUpdate(currentSlot, { attestedHeader: optimisticUpdate.attestedHeader, nextSyncCommittee: ZERO_SYNC_COMMITTEE, - nextSyncCommitteeBranch: ZERO_NEXT_SYNC_COMMITTEE_BRANCH, + nextSyncCommitteeBranch: getZeroSyncCommitteeBranch(this.config.getForkName(optimisticUpdate.signatureSlot)), finalizedHeader: {beacon: ZERO_HEADER}, finalityBranch: ZERO_FINALITY_BRANCH, syncAggregate: optimisticUpdate.syncAggregate, diff --git a/packages/light-client/src/spec/utils.ts b/packages/light-client/src/spec/utils.ts index 3e59cb14cfa0..872aa5d9f910 100644 --- a/packages/light-client/src/spec/utils.ts +++ b/packages/light-client/src/spec/utils.ts @@ -7,6 +7,9 @@ import { ForkName, BLOCK_BODY_EXECUTION_PAYLOAD_DEPTH as EXECUTION_PAYLOAD_DEPTH, BLOCK_BODY_EXECUTION_PAYLOAD_INDEX as EXECUTION_PAYLOAD_INDEX, + NEXT_SYNC_COMMITTEE_DEPTH_ELECTRA, + isForkPostElectra, + FINALIZED_ROOT_DEPTH_ELECTRA, } from "@lodestar/params"; import { ssz, @@ -17,17 +20,18 @@ import { LightClientUpdate, BeaconBlockHeader, SyncCommittee, + isElectraLightClientUpdate, } from "@lodestar/types"; import {ChainForkConfig} from "@lodestar/config"; import {isValidMerkleBranch, computeEpochAtSlot, computeSyncPeriodAtSlot} from "../utils/index.js"; +import {normalizeMerkleBranch} from "../utils/normalizeMerkleBranch.js"; import {LightClientStore} from "./store.js"; export const GENESIS_SLOT = 0; export const ZERO_HASH = new Uint8Array(32); export const ZERO_PUBKEY = new Uint8Array(48); export const ZERO_SYNC_COMMITTEE = ssz.altair.SyncCommittee.defaultValue(); -export const ZERO_NEXT_SYNC_COMMITTEE_BRANCH = Array.from({length: NEXT_SYNC_COMMITTEE_DEPTH}, () => ZERO_HASH); export const ZERO_HEADER = ssz.phase0.BeaconBlockHeader.defaultValue(); export const ZERO_FINALITY_BRANCH = Array.from({length: FINALIZED_ROOT_DEPTH}, () => ZERO_HASH); /** From https://notes.ethereum.org/@vbuterin/extended_light_client_protocol#Optimistic-head-determining-function */ @@ -41,10 +45,19 @@ export function getSafetyThreshold(maxActiveParticipants: number): number { return Math.floor(maxActiveParticipants / SAFETY_THRESHOLD_FACTOR); } +export function getZeroSyncCommitteeBranch(fork: ForkName): Uint8Array[] { + const nextSyncCommitteeDepth = isForkPostElectra(fork) + ? NEXT_SYNC_COMMITTEE_DEPTH_ELECTRA + : NEXT_SYNC_COMMITTEE_DEPTH; + + return Array.from({length: nextSyncCommitteeDepth}, () => ZERO_HASH); +} + export function isSyncCommitteeUpdate(update: LightClientUpdate): boolean { return ( // Fast return for when constructing full LightClientUpdate from partial updates - update.nextSyncCommitteeBranch !== ZERO_NEXT_SYNC_COMMITTEE_BRANCH && + update.nextSyncCommitteeBranch !== + getZeroSyncCommitteeBranch(isElectraLightClientUpdate(update) ? ForkName.electra : ForkName.altair) && update.nextSyncCommitteeBranch.some((branch) => !byteArrayEquals(branch, ZERO_HASH)) ); } @@ -160,7 +173,8 @@ export function isValidLightClientHeader(config: ChainForkConfig, header: LightC if (epoch < config.ELECTRA_FORK_EPOCH) { if ( (header as LightClientHeader).execution.depositRequestsRoot !== undefined || - (header as LightClientHeader).execution.withdrawalRequestsRoot !== undefined + (header as LightClientHeader).execution.withdrawalRequestsRoot !== undefined || + (header as LightClientHeader).execution.consolidationRequestsRoot !== undefined ) { return false; } @@ -184,6 +198,14 @@ export function upgradeLightClientUpdate( ): LightClientUpdate { update.attestedHeader = upgradeLightClientHeader(config, targetFork, update.attestedHeader); update.finalizedHeader = upgradeLightClientHeader(config, targetFork, update.finalizedHeader); + update.nextSyncCommitteeBranch = normalizeMerkleBranch( + update.nextSyncCommitteeBranch, + isForkPostElectra(targetFork) ? NEXT_SYNC_COMMITTEE_DEPTH_ELECTRA : NEXT_SYNC_COMMITTEE_DEPTH + ); + update.finalityBranch = normalizeMerkleBranch( + update.finalityBranch, + isForkPostElectra(targetFork) ? FINALIZED_ROOT_DEPTH_ELECTRA : FINALIZED_ROOT_DEPTH + ); return update; } @@ -195,6 +217,10 @@ export function upgradeLightClientFinalityUpdate( ): LightClientFinalityUpdate { finalityUpdate.attestedHeader = upgradeLightClientHeader(config, targetFork, finalityUpdate.attestedHeader); finalityUpdate.finalizedHeader = upgradeLightClientHeader(config, targetFork, finalityUpdate.finalizedHeader); + finalityUpdate.finalityBranch = normalizeMerkleBranch( + finalityUpdate.finalityBranch, + isForkPostElectra(targetFork) ? FINALIZED_ROOT_DEPTH_ELECTRA : FINALIZED_ROOT_DEPTH + ); return finalityUpdate; } diff --git a/packages/light-client/src/spec/validateLightClientBootstrap.ts b/packages/light-client/src/spec/validateLightClientBootstrap.ts index 30540da24bd1..2eafea0791f0 100644 --- a/packages/light-client/src/spec/validateLightClientBootstrap.ts +++ b/packages/light-client/src/spec/validateLightClientBootstrap.ts @@ -2,11 +2,14 @@ import {byteArrayEquals} from "@chainsafe/ssz"; import {LightClientBootstrap, Root, ssz} from "@lodestar/types"; import {ChainForkConfig} from "@lodestar/config"; import {toHex} from "@lodestar/utils"; +import {isForkPostElectra} from "@lodestar/params"; import {isValidMerkleBranch} from "../utils/verifyMerkleBranch.js"; import {isValidLightClientHeader} from "./utils.js"; const CURRENT_SYNC_COMMITTEE_INDEX = 22; const CURRENT_SYNC_COMMITTEE_DEPTH = 5; +const CURRENT_SYNC_COMMITTEE_INDEX_ELECTRA = 22; +const CURRENT_SYNC_COMMITTEE_DEPTH_ELECTRA = 6; export function validateLightClientBootstrap( config: ChainForkConfig, @@ -14,6 +17,7 @@ export function validateLightClientBootstrap( bootstrap: LightClientBootstrap ): void { const headerRoot = ssz.phase0.BeaconBlockHeader.hashTreeRoot(bootstrap.header.beacon); + const fork = config.getForkName(bootstrap.header.beacon.slot); if (!isValidLightClientHeader(config, bootstrap.header)) { throw Error("Bootstrap Header is not Valid Light Client Header"); @@ -27,8 +31,8 @@ export function validateLightClientBootstrap( !isValidMerkleBranch( ssz.altair.SyncCommittee.hashTreeRoot(bootstrap.currentSyncCommittee), bootstrap.currentSyncCommitteeBranch, - CURRENT_SYNC_COMMITTEE_DEPTH, - CURRENT_SYNC_COMMITTEE_INDEX, + isForkPostElectra(fork) ? CURRENT_SYNC_COMMITTEE_DEPTH_ELECTRA : CURRENT_SYNC_COMMITTEE_DEPTH, + isForkPostElectra(fork) ? CURRENT_SYNC_COMMITTEE_INDEX_ELECTRA : CURRENT_SYNC_COMMITTEE_INDEX, bootstrap.header.beacon.stateRoot ) ) { diff --git a/packages/light-client/src/spec/validateLightClientUpdate.ts b/packages/light-client/src/spec/validateLightClientUpdate.ts index fde760da3b05..9a5ea1985f16 100644 --- a/packages/light-client/src/spec/validateLightClientUpdate.ts +++ b/packages/light-client/src/spec/validateLightClientUpdate.ts @@ -1,15 +1,19 @@ import bls from "@chainsafe/bls"; import type {PublicKey, Signature} from "@chainsafe/bls/types"; -import {LightClientUpdate, Root, ssz} from "@lodestar/types"; +import {LightClientUpdate, Root, isElectraLightClientUpdate, ssz} from "@lodestar/types"; import {ChainForkConfig} from "@lodestar/config"; import { FINALIZED_ROOT_INDEX, FINALIZED_ROOT_DEPTH, - NEXT_SYNC_COMMITTEE_INDEX, NEXT_SYNC_COMMITTEE_DEPTH, MIN_SYNC_COMMITTEE_PARTICIPANTS, DOMAIN_SYNC_COMMITTEE, GENESIS_SLOT, + NEXT_SYNC_COMMITTEE_DEPTH_ELECTRA, + NEXT_SYNC_COMMITTEE_INDEX_ELECTRA, + NEXT_SYNC_COMMITTEE_INDEX, + FINALIZED_ROOT_DEPTH_ELECTRA, + FINALIZED_ROOT_INDEX_ELECTRA, } from "@lodestar/params"; import {getParticipantPubkeys, sumBits} from "../utils/utils.js"; import {isValidMerkleBranch} from "../utils/index.js"; @@ -78,8 +82,8 @@ export function validateLightClientUpdate( !isValidMerkleBranch( finalizedRoot, update.finalityBranch, - FINALIZED_ROOT_DEPTH, - FINALIZED_ROOT_INDEX, + isElectraLightClientUpdate(update) ? FINALIZED_ROOT_DEPTH_ELECTRA : FINALIZED_ROOT_DEPTH, + isElectraLightClientUpdate(update) ? FINALIZED_ROOT_INDEX_ELECTRA : FINALIZED_ROOT_INDEX, update.attestedHeader.beacon.stateRoot ) ) { @@ -98,8 +102,8 @@ export function validateLightClientUpdate( !isValidMerkleBranch( ssz.altair.SyncCommittee.hashTreeRoot(update.nextSyncCommittee), update.nextSyncCommitteeBranch, - NEXT_SYNC_COMMITTEE_DEPTH, - NEXT_SYNC_COMMITTEE_INDEX, + isElectraLightClientUpdate(update) ? NEXT_SYNC_COMMITTEE_DEPTH_ELECTRA : NEXT_SYNC_COMMITTEE_DEPTH, + isElectraLightClientUpdate(update) ? NEXT_SYNC_COMMITTEE_INDEX_ELECTRA : NEXT_SYNC_COMMITTEE_INDEX, update.attestedHeader.beacon.stateRoot ) ) { diff --git a/packages/light-client/src/utils/normalizeMerkleBranch.ts b/packages/light-client/src/utils/normalizeMerkleBranch.ts new file mode 100644 index 000000000000..ae3309f8ff2e --- /dev/null +++ b/packages/light-client/src/utils/normalizeMerkleBranch.ts @@ -0,0 +1,15 @@ +import {ZERO_HASH} from "../spec/utils.js"; + +export const SYNC_COMMITTEES_DEPTH = 4; +export const SYNC_COMMITTEES_INDEX = 11; + +/** + * Given merkle branch ``branch``, extend its depth according to ``depth`` + * If given ``depth`` is less than the depth of ``branch``, it will return + * unmodified ``branch`` + */ +export function normalizeMerkleBranch(branch: Uint8Array[], depth: number): Uint8Array[] { + const numExtraDepth = depth - branch.length; + + return [...Array.from({length: numExtraDepth}, () => ZERO_HASH), ...branch]; +} diff --git a/packages/light-client/src/validation.ts b/packages/light-client/src/validation.ts index e7839f115153..c756d612f3e7 100644 --- a/packages/light-client/src/validation.ts +++ b/packages/light-client/src/validation.ts @@ -1,6 +1,14 @@ import bls from "@chainsafe/bls"; import type {PublicKey, Signature} from "@chainsafe/bls/types"; -import {altair, LightClientFinalityUpdate, LightClientUpdate, Root, Slot, ssz} from "@lodestar/types"; +import { + altair, + isElectraLightClientUpdate, + LightClientFinalityUpdate, + LightClientUpdate, + Root, + Slot, + ssz, +} from "@lodestar/types"; import { FINALIZED_ROOT_INDEX, FINALIZED_ROOT_DEPTH, @@ -8,6 +16,9 @@ import { NEXT_SYNC_COMMITTEE_DEPTH, MIN_SYNC_COMMITTEE_PARTICIPANTS, DOMAIN_SYNC_COMMITTEE, + NEXT_SYNC_COMMITTEE_DEPTH_ELECTRA, + FINALIZED_ROOT_DEPTH_ELECTRA, + NEXT_SYNC_COMMITTEE_INDEX_ELECTRA, } from "@lodestar/params"; import {BeaconConfig} from "@lodestar/config"; import {isValidMerkleBranch} from "./utils/verifyMerkleBranch.js"; @@ -39,7 +50,11 @@ export function assertValidLightClientUpdate( if (isFinalized) { assertValidFinalityProof(update); } else { - assertZeroHashes(update.finalityBranch, FINALIZED_ROOT_DEPTH, "finalityBranches"); + assertZeroHashes( + update.finalityBranch, + isElectraLightClientUpdate(update) ? FINALIZED_ROOT_DEPTH_ELECTRA : FINALIZED_ROOT_DEPTH, + "finalityBranches" + ); } // DIFF FROM SPEC: @@ -99,8 +114,8 @@ export function assertValidSyncCommitteeProof(update: LightClientUpdate): void { !isValidMerkleBranch( ssz.altair.SyncCommittee.hashTreeRoot(update.nextSyncCommittee), update.nextSyncCommitteeBranch, - NEXT_SYNC_COMMITTEE_DEPTH, - NEXT_SYNC_COMMITTEE_INDEX, + isElectraLightClientUpdate(update) ? NEXT_SYNC_COMMITTEE_DEPTH_ELECTRA : NEXT_SYNC_COMMITTEE_DEPTH, + isElectraLightClientUpdate(update) ? NEXT_SYNC_COMMITTEE_INDEX_ELECTRA : NEXT_SYNC_COMMITTEE_INDEX, update.attestedHeader.beacon.stateRoot ) ) { diff --git a/packages/light-client/test/unit/utils.test.ts b/packages/light-client/test/unit/utils.test.ts index 91bfab113431..9913c6c462a4 100644 --- a/packages/light-client/test/unit/utils.test.ts +++ b/packages/light-client/test/unit/utils.test.ts @@ -1,6 +1,8 @@ import {describe, it, expect} from "vitest"; import {isValidMerkleBranch} from "../../src/utils/verifyMerkleBranch.js"; import {computeMerkleBranch} from "../utils/utils.js"; +import {normalizeMerkleBranch} from "../../src/utils/normalizeMerkleBranch.js"; +import {ZERO_HASH} from "../../src/spec/utils.js"; describe("utils", () => { it("constructMerkleBranch", () => { @@ -11,4 +13,18 @@ describe("utils", () => { expect(isValidMerkleBranch(leaf, proof, depth, index, root)).toBe(true); }); + it("normalizeMerkleBranch", () => { + const branch: Uint8Array[] = []; + const branchDepth = 5; + const newDepth = 7; + + for (let i = 0; i < branchDepth; i++) { + branch.push(new Uint8Array(Array.from({length: 32}, () => i))); + } + + const normalizedBranch = normalizeMerkleBranch(branch, newDepth); + const expectedNormalizedBranch = [ZERO_HASH, ZERO_HASH, ...branch]; + + expect(normalizedBranch).toEqual(expectedNormalizedBranch); + }); }); diff --git a/packages/params/src/index.ts b/packages/params/src/index.ts index e7fd5b976336..a44fd5d0e0cd 100644 --- a/packages/params/src/index.ts +++ b/packages/params/src/index.ts @@ -264,7 +264,9 @@ export const BLOBSIDECAR_FIXED_SIZE = ACTIVE_PRESET === PresetName.minimal ? 131 // Electra Misc export const UNSET_DEPOSIT_REQUESTS_START_INDEX = 2n ** 64n - 1n; export const FULL_EXIT_REQUEST_AMOUNT = 0; +export const FINALIZED_ROOT_GINDEX_ELECTRA = 169; +export const FINALIZED_ROOT_DEPTH_ELECTRA = 7; +export const FINALIZED_ROOT_INDEX_ELECTRA = 41; export const NEXT_SYNC_COMMITTEE_GINDEX_ELECTRA = 87; export const NEXT_SYNC_COMMITTEE_DEPTH_ELECTRA = 6; -export const FINALIZED_ROOT_DEPTH_ELECTRA = 7; -export const FINALIZED_ROOT_INDEX_ELECTRA = 169; +export const NEXT_SYNC_COMMITTEE_INDEX_ELECTRA = 23; diff --git a/packages/types/src/electra/sszTypes.ts b/packages/types/src/electra/sszTypes.ts index c0485597686a..522f7245cc1b 100644 --- a/packages/types/src/electra/sszTypes.ts +++ b/packages/types/src/electra/sszTypes.ts @@ -358,20 +358,20 @@ export const LightClientHeader = new ContainerType( export const LightClientBootstrap = new ContainerType( { - header: LightClientHeader, + header: LightClientHeader, // Modified in ELECTRA currentSyncCommittee: altairSsz.SyncCommittee, - currentSyncCommitteeBranch: new VectorCompositeType(Bytes32, NEXT_SYNC_COMMITTEE_DEPTH_ELECTRA), + currentSyncCommitteeBranch: new VectorCompositeType(Bytes32, NEXT_SYNC_COMMITTEE_DEPTH_ELECTRA), // Modified in ELECTRA }, {typeName: "LightClientBootstrap", jsonCase: "eth2"} ); export const LightClientUpdate = new ContainerType( { - attestedHeader: LightClientHeader, + attestedHeader: LightClientHeader, // Modified in ELECTRA nextSyncCommittee: altairSsz.SyncCommittee, - nextSyncCommitteeBranch: new VectorCompositeType(Bytes32, NEXT_SYNC_COMMITTEE_DEPTH_ELECTRA), - finalizedHeader: LightClientHeader, - finalityBranch: new VectorCompositeType(Bytes32, FINALIZED_ROOT_DEPTH_ELECTRA), + nextSyncCommitteeBranch: new VectorCompositeType(Bytes32, NEXT_SYNC_COMMITTEE_DEPTH_ELECTRA), // Modified in ELECTRA + finalizedHeader: LightClientHeader, // Modified in ELECTRA + finalityBranch: new VectorCompositeType(Bytes32, FINALIZED_ROOT_DEPTH_ELECTRA), // Modified in ELECTRA syncAggregate: altairSsz.SyncAggregate, signatureSlot: Slot, }, @@ -382,7 +382,7 @@ export const LightClientFinalityUpdate = new ContainerType( { attestedHeader: LightClientHeader, finalizedHeader: LightClientHeader, - finalityBranch: new VectorCompositeType(Bytes32, FINALIZED_ROOT_DEPTH_ELECTRA), + finalityBranch: new VectorCompositeType(Bytes32, FINALIZED_ROOT_DEPTH_ELECTRA), // Modified in ELECTRA syncAggregate: altairSsz.SyncAggregate, signatureSlot: Slot, }, @@ -391,7 +391,7 @@ export const LightClientFinalityUpdate = new ContainerType( export const LightClientOptimisticUpdate = new ContainerType( { - attestedHeader: LightClientHeader, + attestedHeader: LightClientHeader, // Modified in ELECTRA syncAggregate: altairSsz.SyncAggregate, signatureSlot: Slot, }, @@ -400,8 +400,8 @@ export const LightClientOptimisticUpdate = new ContainerType( export const LightClientStore = new ContainerType( { - snapshot: LightClientBootstrap, - validUpdates: new ListCompositeType(LightClientUpdate, EPOCHS_PER_SYNC_COMMITTEE_PERIOD * SLOTS_PER_EPOCH), + snapshot: LightClientBootstrap, // Modified in ELECTRA + validUpdates: new ListCompositeType(LightClientUpdate, EPOCHS_PER_SYNC_COMMITTEE_PERIOD * SLOTS_PER_EPOCH), // Modified in ELECTRA }, {typeName: "LightClientStore", jsonCase: "eth2"} ); diff --git a/packages/types/src/utils/typeguards.ts b/packages/types/src/utils/typeguards.ts index 72910645f6e1..a5f5b7808ae5 100644 --- a/packages/types/src/utils/typeguards.ts +++ b/packages/types/src/utils/typeguards.ts @@ -14,6 +14,7 @@ import { SignedBlockContents, BeaconBlock, Attestation, + LightClientUpdate, } from "../types.js"; export function isExecutionPayload( @@ -71,3 +72,11 @@ export function isSignedBlockContents( export function isElectraAttestation(attestation: Attestation): attestation is Attestation { return (attestation as Attestation).committeeBits !== undefined; } + +export function isElectraLightClientUpdate(update: LightClientUpdate): update is LightClientUpdate { + const updatePostElectra = update as LightClientUpdate; + return ( + updatePostElectra.attestedHeader.execution !== undefined && + updatePostElectra.attestedHeader.execution.depositRequestsRoot !== undefined + ); +} From 404f13abfd56a859a35c69f198178d5669d3867a Mon Sep 17 00:00:00 2001 From: Nico Flaig Date: Sat, 21 Sep 2024 18:53:39 +0100 Subject: [PATCH 14/52] chore: update Teku holesky bootnode (#7099) --- packages/cli/src/networks/holesky.ts | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/packages/cli/src/networks/holesky.ts b/packages/cli/src/networks/holesky.ts index b86f6b543582..63bc6e07f8f2 100644 --- a/packages/cli/src/networks/holesky.ts +++ b/packages/cli/src/networks/holesky.ts @@ -10,7 +10,7 @@ export const bootEnrs = [ "enr:-Ku4QPG7F72mbKx3gEQEx07wpYYusGDh-ni6SNkLvOS-hhN-BxIggN7tKlmalb0L5JPoAfqD-akTZ-gX06hFeBEz4WoBh2F0dG5ldHOIAAAAAAAAAACEZXRoMpAhnTT-AQFwAP__________gmlkgnY0gmlwhJK-DYCJc2VjcDI1NmsxoQKLVXFOhp2uX6jeT0DvvDpPcU8FWMjQdR4wMuORMhpX24N1ZHCCIyk", "enr:-LK4QPxe-mDiSOtEB_Y82ozvxn9aQM07Ui8A-vQHNgYGMMthfsfOabaaTHhhJHFCBQQVRjBww_A5bM1rf8MlkJU_l68Eh2F0dG5ldHOIAADAAAAAAACEZXRoMpBpt9l0BAFwAAABAAAAAAAAgmlkgnY0gmlwhLKAiOmJc2VjcDI1NmsxoQJu6T9pclPObAzEVQ53DpVQqjadmVxdTLL-J3h9NFoCeIN0Y3CCIyiDdWRwgiMo", "enr:-Ly4QGbOw4xNel5EhmDsJJ-QhC9XycWtsetnWoZ0uRy381GHdHsNHJiCwDTOkb3S1Ade0SFQkWJX_pgb3g8Jfh93rvMBh2F0dG5ldHOIAAAAAAAAAACEZXRoMpBpt9l0BAFwAAABAAAAAAAAgmlkgnY0gmlwhJK-DYCJc2VjcDI1NmsxoQOxKv9sv3zKF8GDewgFGGHKP5HCZZpPpTrwl9eXKAWGxIhzeW5jbmV0cwCDdGNwgiMog3VkcIIjKA", - "enr:-LS4QG0uV4qvcpJ-HFDJRGBmnlD3TJo7yc4jwK8iP7iKaTlfQ5kZvIDspLMJhk7j9KapuL9yyHaZmwTEZqr10k9XumyCEcmHYXR0bmV0c4gAAAAABgAAAIRldGgykGm32XQEAXAAAAEAAAAAAACCaWSCdjSCaXCErK4j-YlzZWNwMjU2azGhAgfWRBEJlb7gAhXIB5ePmjj2b8io0UpEenq1Kl9cxStJg3RjcIIjKIN1ZHCCIyg", + "enr:-KO4QCi3ZY4TM5KL7bAG6laSYiYelDWu0crvUjCXlyc_cwEfUpMIuARuMJYGxWe-UYYpHEw_aBbZ1u-4tHQ8imyI5uaCAsGEZXRoMpBprg6ZBQFwAP__________gmlkgnY0gmlwhKyuI_mJc2VjcDI1NmsxoQLoFG5-vuNX6N49vnkTBaA3ZsBDF8B30DGqWOGtRGz5w4N0Y3CCIyiDdWRwgiMo", "enr:-Le4QLoE1wFHSlGcm48a9ZESb_MRLqPPu6G0vHqu4MaUcQNDHS69tsy-zkN0K6pglyzX8m24mkb-LtBcbjAYdP1uxm4BhGV0aDKQabfZdAQBcAAAAQAAAAAAAIJpZIJ2NIJpcIQ5gR6Wg2lwNpAgAUHQBwEQAAAAAAAAADR-iXNlY3AyNTZrMaEDPMSNdcL92uNIyCsS177Z6KTXlbZakQqxv3aQcWawNXeDdWRwgiMohHVkcDaCI4I", "enr:-KG4QC9Wm32mtzB5Fbj2ri2TEKglHmIWgvwTQCvNHBopuwpNAi1X6qOsBg_Z1-Bee-kfSrhzUQZSgDUyfH5outUprtoBgmlkgnY0gmlwhHEel3eDaXA2kP6AAAAAAAAAAlBW__4Srr-Jc2VjcDI1NmsxoQO7KE63Z4eSI55S1Yn7q9_xFkJ1Wt-a3LgiXuKGs19s0YN1ZHCCIyiEdWRwNoIjKA", ]; From cd98c237683456be7959d752bbd7d10f8b02b8ec Mon Sep 17 00:00:00 2001 From: Matthew Keil Date: Sun, 22 Sep 2024 21:41:47 -0400 Subject: [PATCH 15/52] feat: async shuffling refactor (#6938) * feat: add ShufflingCache to EpochCache * fix: implementation in state-transition for EpochCache with ShufflingCache * feat: remove shufflingCache.processState * feat: implement ShufflingCache changes in beacon-node * feat: pass shufflingCache when loading cached state from db * test: fix state-transition tests for EpochCache changes * feat: Pass shufflingCache to EpochCache at startup * test: fix slot off by one for decision root in perf test * chore: use ?. syntax * chore: refactoring * feat: add comments and clean up afterProcessEpoch * fix: perf test slot incrementing * fix: remove MockShufflingCache * Revert "chore: refactoring" This reverts commit 104aa56d84ce3ca33d045705591767ef578dec3a. * refactor: shufflingCache getters * refactor: shufflingCache setters * refactor: build and getOrBuild * docs: add comments to ShufflingCache methods * chore: lint issues * test: update tests in beacon-node * chore: lint * feat: get shufflings from cache for API * feat: minTimeDelayToBuildShuffling cli flag * test: fix shufflingCache promise insertion test * fix: rebase conflicts * fix: changes from debugging sim tests * refactor: minimize changes in afterProcessEpoch * chore: fix lint * chore: fix check-types * chore: fix check-types * feat: add diff utility * fix: bug in spec tests from invalid nextActiveIndices * refactor: add/remove comments * refactor: remove this.activeIndicesLength from EpochCache * refactor: simplify shufflingCache.getSync * refactor: remove unnecessary undefined's * refactor: clean up ShufflingCache unit test * feat: add metrics for ShufflingCache * feat: add shufflingCache metrics to state-transition * chore: lint * fix: metric name clash * refactor: add comment about not having ShufflingCache in EpochCache * refactor: rename shuffling decision root functions * refactor: remove unused comment * feat: async add nextShuffling to EpochCache after its built * feat: make ShufflingCache.set private * feat: chance metrics to nextShufflingNotOnEpochCache instead of positive case * refactor: move diff to separate PR * chore: fix tests using shufflingCache.set method * feat: remove minTimeDelayToBuild * feat: return promise from insertPromise and then through build * fix: update metrics names and help field * feat: move build of shuffling to beforeProcessEpoch * feat: allow calc of pivot slot before slot increment * fix: calc of pivot slot before slot increment * Revert "fix: calc of pivot slot before slot increment" This reverts commit 5e65f7efa85fad169a6263d1bebc1b4f8d3701d4. * Revert "feat: allow calc of pivot slot before slot increment" This reverts commit ed850ee0ced72029b643db4e86d82600cfb7cf43. * feat: allow getting current block root for shuffling calculation * fix: get nextShufflingDecisionRoot directly from state.blockRoots * fix: convert toRootHex * docs: add comment about pulling decisionRoot directly from state * feat: add back metrics for regen attestation cache hit/miss * docs: fix docstring on shufflingCache.build * refactor: change validatorIndices to Uint32Array * refactor: remove comment and change variable name * fix: use toRootHex instead of toHexString * refactor: deduplicate moved function computeAnchorCheckpoint * fix: touch up metrics per PR comments * fix: merge conflict * chore: lint * refactor: add scope around activeIndices to GC arrays * feat: directly use Uint32Array instead of transcribing number array to Uint32Array * refactor: activeIndices per tuyen comment * refactor: rename to epochAfterNext * chore: review PR * feat: update no shuffling ApiError to 500 status * fix: add back unnecessary eslint directive. to be remove under separate PR * feat: update no shuffling ApiError to 500 status * docs: add comment about upcomingEpoch --------- Co-authored-by: Cayman Co-authored-by: Tuyen Nguyen --- .../src/api/impl/beacon/state/index.ts | 9 +- .../src/api/impl/validator/index.ts | 11 +- .../src/chain/blocks/importBlock.ts | 7 - packages/beacon-node/src/chain/chain.ts | 25 +- .../beacon-node/src/chain/forkChoice/index.ts | 2 +- packages/beacon-node/src/chain/initState.ts | 38 +- .../beacon-node/src/chain/shufflingCache.ts | 183 ++++++---- .../stateCache/persistentCheckpointsCache.ts | 15 +- .../src/metrics/metrics/lodestar.ts | 47 ++- .../src/node/utils/interop/state.ts | 1 + packages/beacon-node/src/node/utils/state.ts | 3 + .../beacon-node/src/sync/backfill/backfill.ts | 3 +- .../opPools/aggregatedAttestationPool.test.ts | 2 +- .../unit/chain/forkChoice/forkChoice.test.ts | 3 +- .../test/unit/chain/shufflingCache.test.ts | 42 +-- packages/beacon-node/test/utils/state.ts | 1 + .../test/utils/validationData/attestation.ts | 27 +- packages/params/src/index.ts | 2 + .../state-transition/src/cache/epochCache.ts | 336 +++++++++++++----- .../src/cache/epochTransitionCache.ts | 40 ++- .../state-transition/src/cache/stateCache.ts | 3 +- .../src/epoch/processSyncCommitteeUpdates.ts | 2 +- .../src/slot/upgradeStateToAltair.ts | 2 +- .../state-transition/src/stateTransition.ts | 19 + .../src/util/calculateCommitteeAssignments.ts | 43 +++ .../src/util/computeAnchorCheckpoint.ts | 38 ++ .../src/util/epochShuffling.ts | 83 ++++- packages/state-transition/src/util/index.ts | 2 + .../test/perf/epoch/epochAltair.test.ts | 6 +- .../test/perf/epoch/epochCapella.test.ts | 6 +- .../test/perf/epoch/epochPhase0.test.ts | 6 +- .../perf/util/loadState/loadState.test.ts | 6 +- .../test/perf/util/shufflings.test.ts | 15 +- .../test/unit/cachedBeaconState.test.ts | 34 +- 34 files changed, 700 insertions(+), 362 deletions(-) create mode 100644 packages/state-transition/src/util/calculateCommitteeAssignments.ts create mode 100644 packages/state-transition/src/util/computeAnchorCheckpoint.ts diff --git a/packages/beacon-node/src/api/impl/beacon/state/index.ts b/packages/beacon-node/src/api/impl/beacon/state/index.ts index 9d9646ee8cf3..77e2fd5aab46 100644 --- a/packages/beacon-node/src/api/impl/beacon/state/index.ts +++ b/packages/beacon-node/src/api/impl/beacon/state/index.ts @@ -202,7 +202,14 @@ export function getBeaconStateApi({ const epoch = filters.epoch ?? computeEpochAtSlot(state.slot); const startSlot = computeStartSlotAtEpoch(epoch); - const shuffling = stateCached.epochCtx.getShufflingAtEpoch(epoch); + const decisionRoot = stateCached.epochCtx.getShufflingDecisionRoot(epoch); + const shuffling = await chain.shufflingCache.get(epoch, decisionRoot); + if (!shuffling) { + throw new ApiError( + 500, + `No shuffling found to calculate committees for epoch: ${epoch} and decisionRoot: ${decisionRoot}` + ); + } const committees = shuffling.committees; const committeesFlat = committees.flatMap((slotCommittees, slotInEpoch) => { const slot = startSlot + slotInEpoch; diff --git a/packages/beacon-node/src/api/impl/validator/index.ts b/packages/beacon-node/src/api/impl/validator/index.ts index a17c1418809e..d2ce6672c89f 100644 --- a/packages/beacon-node/src/api/impl/validator/index.ts +++ b/packages/beacon-node/src/api/impl/validator/index.ts @@ -3,6 +3,7 @@ import {ApplicationMethods} from "@lodestar/api/server"; import { CachedBeaconStateAllForks, computeStartSlotAtEpoch, + calculateCommitteeAssignments, proposerShufflingDecisionRoot, attesterShufflingDecisionRoot, getBlockRootAtSlot, @@ -995,7 +996,15 @@ export function getValidatorApi( // Check that all validatorIndex belong to the state before calling getCommitteeAssignments() const pubkeys = getPubkeysForIndices(state.validators, indices); - const committeeAssignments = state.epochCtx.getCommitteeAssignments(epoch, indices); + const decisionRoot = state.epochCtx.getShufflingDecisionRoot(epoch); + const shuffling = await chain.shufflingCache.get(epoch, decisionRoot); + if (!shuffling) { + throw new ApiError( + 500, + `No shuffling found to calculate committee assignments for epoch: ${epoch} and decisionRoot: ${decisionRoot}` + ); + } + const committeeAssignments = calculateCommitteeAssignments(shuffling, indices); const duties: routes.validator.AttesterDuty[] = []; for (let i = 0, len = indices.length; i < len; i++) { const validatorIndex = indices[i]; diff --git a/packages/beacon-node/src/chain/blocks/importBlock.ts b/packages/beacon-node/src/chain/blocks/importBlock.ts index 4c46bdae53ee..d19d6a60c564 100644 --- a/packages/beacon-node/src/chain/blocks/importBlock.ts +++ b/packages/beacon-node/src/chain/blocks/importBlock.ts @@ -64,7 +64,6 @@ export async function importBlock( const blockRootHex = toRootHex(blockRoot); const currentEpoch = computeEpochAtSlot(this.forkChoice.getTime()); const blockEpoch = computeEpochAtSlot(blockSlot); - const parentEpoch = computeEpochAtSlot(parentBlockSlot); const prevFinalizedEpoch = this.forkChoice.getFinalizedCheckpoint().epoch; const blockDelaySec = (fullyVerifiedBlock.seenTimestampSec - postState.genesisTime) % this.config.SECONDS_PER_SLOT; const recvToValLatency = Date.now() / 1000 - (opts.seenTimestampSec ?? Date.now() / 1000); @@ -335,12 +334,6 @@ export async function importBlock( this.logger.verbose("After importBlock caching postState without SSZ cache", {slot: postState.slot}); } - if (parentEpoch < blockEpoch) { - // current epoch and previous epoch are likely cached in previous states - this.shufflingCache.processState(postState, postState.epochCtx.nextShuffling.epoch); - this.logger.verbose("Processed shuffling for next epoch", {parentEpoch, blockEpoch, slot: blockSlot}); - } - if (blockSlot % SLOTS_PER_EPOCH === 0) { // Cache state to preserve epoch transition work const checkpointState = postState; diff --git a/packages/beacon-node/src/chain/chain.ts b/packages/beacon-node/src/chain/chain.ts index ee70231c7d40..0b0ac30edf40 100644 --- a/packages/beacon-node/src/chain/chain.ts +++ b/packages/beacon-node/src/chain/chain.ts @@ -13,6 +13,7 @@ import { PubkeyIndexMap, EpochShuffling, computeEndSlotAtEpoch, + computeAnchorCheckpoint, } from "@lodestar/state-transition"; import {BeaconConfig} from "@lodestar/config"; import { @@ -60,7 +61,6 @@ import { import {IChainOptions} from "./options.js"; import {QueuedStateRegenerator, RegenCaller} from "./regen/index.js"; import {initializeForkChoice} from "./forkChoice/index.js"; -import {computeAnchorCheckpoint} from "./initState.js"; import {IBlsVerifier, BlsSingleThreadVerifier, BlsMultiThreadWorkerPool} from "./bls/index.js"; import { SeenAttesters, @@ -246,7 +246,6 @@ export class BeaconChain implements IBeaconChain { this.beaconProposerCache = new BeaconProposerCache(opts); this.checkpointBalancesCache = new CheckpointBalancesCache(); - this.shufflingCache = new ShufflingCache(metrics, this.opts); // Restore state caches // anchorState may already by a CachedBeaconState. If so, don't create the cache again, since deserializing all @@ -261,9 +260,21 @@ export class BeaconChain implements IBeaconChain { pubkey2index: new PubkeyIndexMap(), index2pubkey: [], }); - this.shufflingCache.processState(cachedState, cachedState.epochCtx.previousShuffling.epoch); - this.shufflingCache.processState(cachedState, cachedState.epochCtx.currentShuffling.epoch); - this.shufflingCache.processState(cachedState, cachedState.epochCtx.nextShuffling.epoch); + + this.shufflingCache = cachedState.epochCtx.shufflingCache = new ShufflingCache(metrics, logger, this.opts, [ + { + shuffling: cachedState.epochCtx.previousShuffling, + decisionRoot: cachedState.epochCtx.previousDecisionRoot, + }, + { + shuffling: cachedState.epochCtx.currentShuffling, + decisionRoot: cachedState.epochCtx.currentDecisionRoot, + }, + { + shuffling: cachedState.epochCtx.nextShuffling, + decisionRoot: cachedState.epochCtx.nextDecisionRoot, + }, + ]); // Persist single global instance of state caches this.pubkey2index = cachedState.epochCtx.pubkey2index; @@ -902,8 +913,8 @@ export class BeaconChain implements IBeaconChain { state = await this.regen.getState(attHeadBlock.stateRoot, regenCaller); } - // resolve the promise to unblock other calls of the same epoch and dependent root - return this.shufflingCache.processState(state, attEpoch); + // should always be the current epoch of the active context so no need to await a result from the ShufflingCache + return state.epochCtx.getShufflingAtEpoch(attEpoch); } /** diff --git a/packages/beacon-node/src/chain/forkChoice/index.ts b/packages/beacon-node/src/chain/forkChoice/index.ts index d57b7f86cb98..346a4afe1e7f 100644 --- a/packages/beacon-node/src/chain/forkChoice/index.ts +++ b/packages/beacon-node/src/chain/forkChoice/index.ts @@ -14,10 +14,10 @@ import { getEffectiveBalanceIncrementsZeroInactive, isExecutionStateType, isMergeTransitionComplete, + computeAnchorCheckpoint, } from "@lodestar/state-transition"; import {Logger, toRootHex} from "@lodestar/utils"; -import {computeAnchorCheckpoint} from "../initState.js"; import {ChainEventEmitter} from "../emitter.js"; import {ChainEvent} from "../emitter.js"; import {GENESIS_SLOT} from "../../constants/index.js"; diff --git a/packages/beacon-node/src/chain/initState.ts b/packages/beacon-node/src/chain/initState.ts index e413bdff0f7d..311806fb1be7 100644 --- a/packages/beacon-node/src/chain/initState.ts +++ b/packages/beacon-node/src/chain/initState.ts @@ -1,15 +1,13 @@ import { - blockToHeader, computeEpochAtSlot, BeaconStateAllForks, CachedBeaconStateAllForks, - computeCheckpointEpochAtStateSlot, computeStartSlotAtEpoch, } from "@lodestar/state-transition"; -import {SignedBeaconBlock, phase0, ssz} from "@lodestar/types"; +import {SignedBeaconBlock} from "@lodestar/types"; import {ChainForkConfig} from "@lodestar/config"; import {Logger, toHex, toRootHex} from "@lodestar/utils"; -import {GENESIS_SLOT, ZERO_HASH} from "../constants/index.js"; +import {GENESIS_SLOT} from "../constants/index.js"; import {IBeaconDb} from "../db/index.js"; import {Eth1Provider} from "../eth1/index.js"; import {Metrics} from "../metrics/index.js"; @@ -204,35 +202,3 @@ export function initBeaconMetrics(metrics: Metrics, state: BeaconStateAllForks): metrics.currentJustifiedEpoch.set(state.currentJustifiedCheckpoint.epoch); metrics.finalizedEpoch.set(state.finalizedCheckpoint.epoch); } - -export function computeAnchorCheckpoint( - config: ChainForkConfig, - anchorState: BeaconStateAllForks -): {checkpoint: phase0.Checkpoint; blockHeader: phase0.BeaconBlockHeader} { - let blockHeader; - let root; - const blockTypes = config.getForkTypes(anchorState.latestBlockHeader.slot); - - if (anchorState.latestBlockHeader.slot === GENESIS_SLOT) { - const block = blockTypes.BeaconBlock.defaultValue(); - block.stateRoot = anchorState.hashTreeRoot(); - blockHeader = blockToHeader(config, block); - root = ssz.phase0.BeaconBlockHeader.hashTreeRoot(blockHeader); - } else { - blockHeader = ssz.phase0.BeaconBlockHeader.clone(anchorState.latestBlockHeader); - if (ssz.Root.equals(blockHeader.stateRoot, ZERO_HASH)) { - blockHeader.stateRoot = anchorState.hashTreeRoot(); - } - root = ssz.phase0.BeaconBlockHeader.hashTreeRoot(blockHeader); - } - - return { - checkpoint: { - root, - // the checkpoint epoch = computeEpochAtSlot(anchorState.slot) + 1 if slot is not at epoch boundary - // this is similar to a process_slots() call - epoch: computeCheckpointEpochAtStateSlot(anchorState.slot), - }, - blockHeader, - }; -} diff --git a/packages/beacon-node/src/chain/shufflingCache.ts b/packages/beacon-node/src/chain/shufflingCache.ts index 12dd1bf3e9ae..6c42228b5356 100644 --- a/packages/beacon-node/src/chain/shufflingCache.ts +++ b/packages/beacon-node/src/chain/shufflingCache.ts @@ -1,9 +1,14 @@ -import {CachedBeaconStateAllForks, EpochShuffling, getShufflingDecisionBlock} from "@lodestar/state-transition"; -import {Epoch, RootHex, ssz} from "@lodestar/types"; -import {MapDef, pruneSetToMax, toRootHex} from "@lodestar/utils"; -import {GENESIS_SLOT} from "@lodestar/params"; +import { + BeaconStateAllForks, + EpochShuffling, + IShufflingCache, + ShufflingBuildProps, + computeEpochShuffling, +} from "@lodestar/state-transition"; +import {Epoch, RootHex} from "@lodestar/types"; +import {LodestarError, Logger, MapDef, pruneSetToMax} from "@lodestar/utils"; import {Metrics} from "../metrics/metrics.js"; -import {computeAnchorCheckpoint} from "./initState.js"; +import {callInNextEventLoop} from "../util/eventLoop.js"; /** * Same value to CheckpointBalancesCache, with the assumption that we don't have to use it for old epochs. In the worse case: @@ -31,6 +36,7 @@ type ShufflingCacheItem = { type PromiseCacheItem = { type: CacheItemType.promise; + timeInsertedMs: number; promise: Promise; resolveFn: (shuffling: EpochShuffling) => void; }; @@ -47,7 +53,7 @@ export type ShufflingCacheOpts = { * - if a shuffling is not available (which does not happen with default chain option of maxSkipSlots = 32), track a promise to make sure we don't compute the same shuffling twice * - skip computing shuffling when loading state bytes from disk */ -export class ShufflingCache { +export class ShufflingCache implements IShufflingCache { /** LRU cache implemented as a map, pruned every time we add an item */ private readonly itemsByDecisionRootByEpoch: MapDef> = new MapDef( () => new Map() @@ -56,8 +62,10 @@ export class ShufflingCache { private readonly maxEpochs: number; constructor( - private readonly metrics: Metrics | null = null, - opts: ShufflingCacheOpts = {} + readonly metrics: Metrics | null = null, + readonly logger: Logger | null = null, + opts: ShufflingCacheOpts = {}, + precalculatedShufflings?: {shuffling: EpochShuffling | null; decisionRoot: RootHex}[] ) { if (metrics) { metrics.shufflingCache.size.addCollect(() => @@ -68,66 +76,25 @@ export class ShufflingCache { } this.maxEpochs = opts.maxShufflingCacheEpochs ?? MAX_EPOCHS; - } - - /** - * Extract shuffling from state and add to cache - */ - processState(state: CachedBeaconStateAllForks, shufflingEpoch: Epoch): EpochShuffling { - const decisionBlockHex = getDecisionBlock(state, shufflingEpoch); - let shuffling: EpochShuffling; - switch (shufflingEpoch) { - case state.epochCtx.nextShuffling.epoch: - shuffling = state.epochCtx.nextShuffling; - break; - case state.epochCtx.currentShuffling.epoch: - shuffling = state.epochCtx.currentShuffling; - break; - case state.epochCtx.previousShuffling.epoch: - shuffling = state.epochCtx.previousShuffling; - break; - default: - throw new Error(`Shuffling not found from state ${state.slot} for epoch ${shufflingEpoch}`); - } - let cacheItem = this.itemsByDecisionRootByEpoch.getOrDefault(shufflingEpoch).get(decisionBlockHex); - if (cacheItem !== undefined) { - // update existing promise - if (isPromiseCacheItem(cacheItem)) { - // unblock consumers of this promise - cacheItem.resolveFn(shuffling); - // then update item type to shuffling - cacheItem = { - type: CacheItemType.shuffling, - shuffling, - }; - this.add(shufflingEpoch, decisionBlockHex, cacheItem); - // we updated type to CacheItemType.shuffling so the above fields are not used anyway - this.metrics?.shufflingCache.processStateUpdatePromise.inc(); - } else { - // ShufflingCacheItem, do nothing - this.metrics?.shufflingCache.processStateNoOp.inc(); + precalculatedShufflings?.map(({shuffling, decisionRoot}) => { + if (shuffling !== null) { + this.set(shuffling, decisionRoot); } - } else { - // not found, new shuffling - this.add(shufflingEpoch, decisionBlockHex, {type: CacheItemType.shuffling, shuffling}); - this.metrics?.shufflingCache.processStateInsertNew.inc(); - } - - return shuffling; + }); } /** * Insert a promise to make sure we don't regen state for the same shuffling. * Bound by MAX_SHUFFLING_PROMISE to make sure our node does not blow up. */ - insertPromise(shufflingEpoch: Epoch, decisionRootHex: RootHex): void { + insertPromise(epoch: Epoch, decisionRoot: RootHex): void { const promiseCount = Array.from(this.itemsByDecisionRootByEpoch.values()) .flatMap((innerMap) => Array.from(innerMap.values())) .filter((item) => isPromiseCacheItem(item)).length; if (promiseCount >= MAX_PROMISES) { throw new Error( - `Too many shuffling promises: ${promiseCount}, shufflingEpoch: ${shufflingEpoch}, decisionRootHex: ${decisionRootHex}` + `Too many shuffling promises: ${promiseCount}, shufflingEpoch: ${epoch}, decisionRootHex: ${decisionRoot}` ); } let resolveFn: ((shuffling: EpochShuffling) => void) | null = null; @@ -140,10 +107,11 @@ export class ShufflingCache { const cacheItem: PromiseCacheItem = { type: CacheItemType.promise, + timeInsertedMs: Date.now(), promise, resolveFn, }; - this.add(shufflingEpoch, decisionRootHex, cacheItem); + this.itemsByDecisionRootByEpoch.getOrDefault(epoch).set(decisionRoot, cacheItem); this.metrics?.shufflingCache.insertPromiseCount.inc(); } @@ -152,39 +120,95 @@ export class ShufflingCache { * If there's a promise, it means we are computing the same shuffling, so we wait for the promise to resolve. * Return null if we don't have a shuffling for this epoch and dependentRootHex. */ - async get(shufflingEpoch: Epoch, decisionRootHex: RootHex): Promise { - const cacheItem = this.itemsByDecisionRootByEpoch.getOrDefault(shufflingEpoch).get(decisionRootHex); + async get(epoch: Epoch, decisionRoot: RootHex): Promise { + const cacheItem = this.itemsByDecisionRootByEpoch.getOrDefault(epoch).get(decisionRoot); if (cacheItem === undefined) { + this.metrics?.shufflingCache.miss.inc(); return null; } if (isShufflingCacheItem(cacheItem)) { + this.metrics?.shufflingCache.hit.inc(); return cacheItem.shuffling; } else { - // promise + this.metrics?.shufflingCache.shufflingPromiseNotResolved.inc(); return cacheItem.promise; } } /** - * Same to get() function but synchronous. + * Gets a cached shuffling via the epoch and decision root. If the shuffling is not + * available it will build it synchronously and return the shuffling. + * + * NOTE: If a shuffling is already queued and not calculated it will build and resolve + * the promise but the already queued build will happen at some later time */ - getSync(shufflingEpoch: Epoch, decisionRootHex: RootHex): EpochShuffling | null { - const cacheItem = this.itemsByDecisionRootByEpoch.getOrDefault(shufflingEpoch).get(decisionRootHex); - if (cacheItem === undefined) { - return null; + getSync( + epoch: Epoch, + decisionRoot: RootHex, + buildProps?: T + ): T extends ShufflingBuildProps ? EpochShuffling : EpochShuffling | null { + const cacheItem = this.itemsByDecisionRootByEpoch.getOrDefault(epoch).get(decisionRoot); + if (!cacheItem) { + this.metrics?.shufflingCache.miss.inc(); + } else if (isShufflingCacheItem(cacheItem)) { + this.metrics?.shufflingCache.hit.inc(); + return cacheItem.shuffling; + } else if (buildProps) { + // TODO: (@matthewkeil) This should possible log a warning?? + this.metrics?.shufflingCache.shufflingPromiseNotResolvedAndThrownAway.inc(); + } else { + this.metrics?.shufflingCache.shufflingPromiseNotResolved.inc(); } - if (isShufflingCacheItem(cacheItem)) { - return cacheItem.shuffling; + let shuffling: EpochShuffling | null = null; + if (buildProps) { + const timer = this.metrics?.shufflingCache.shufflingCalculationTime.startTimer({source: "getSync"}); + shuffling = computeEpochShuffling(buildProps.state, buildProps.activeIndices, epoch); + timer?.(); + this.set(shuffling, decisionRoot); } + return shuffling as T extends ShufflingBuildProps ? EpochShuffling : EpochShuffling | null; + } - // ignore promise - return null; + /** + * Queue asynchronous build for an EpochShuffling, triggered from state-transition + */ + build(epoch: number, decisionRoot: string, state: BeaconStateAllForks, activeIndices: Uint32Array): void { + this.insertPromise(epoch, decisionRoot); + /** + * TODO: (@matthewkeil) This will get replaced by a proper build queue and a worker to do calculations + * on a NICE thread with a rust implementation + */ + callInNextEventLoop(() => { + const timer = this.metrics?.shufflingCache.shufflingCalculationTime.startTimer({source: "build"}); + const shuffling = computeEpochShuffling(state, activeIndices, epoch); + timer?.(); + this.set(shuffling, decisionRoot); + }); } - private add(shufflingEpoch: Epoch, decisionBlock: RootHex, cacheItem: CacheItem): void { - this.itemsByDecisionRootByEpoch.getOrDefault(shufflingEpoch).set(decisionBlock, cacheItem); + /** + * Add an EpochShuffling to the ShufflingCache. If a promise for the shuffling is present it will + * resolve the promise with the built shuffling + */ + private set(shuffling: EpochShuffling, decisionRoot: string): void { + const shufflingAtEpoch = this.itemsByDecisionRootByEpoch.getOrDefault(shuffling.epoch); + // if a pending shuffling promise exists, resolve it + const cacheItem = shufflingAtEpoch.get(decisionRoot); + if (cacheItem) { + if (isPromiseCacheItem(cacheItem)) { + cacheItem.resolveFn(shuffling); + this.metrics?.shufflingCache.shufflingPromiseResolutionTime.observe( + (Date.now() - cacheItem.timeInsertedMs) / 1000 + ); + } else { + this.metrics?.shufflingCache.shufflingBuiltMultipleTimes.inc(); + } + } + // set the shuffling + shufflingAtEpoch.set(decisionRoot, {type: CacheItemType.shuffling, shuffling}); + // prune the cache pruneSetToMax(this.itemsByDecisionRootByEpoch, this.maxEpochs); } } @@ -197,13 +221,14 @@ function isPromiseCacheItem(item: CacheItem): item is PromiseCacheItem { return item.type === CacheItemType.promise; } -/** - * Get the shuffling decision block root for the given epoch of given state - * - Special case close to genesis block, return the genesis block root - * - This is similar to forkchoice.getDependentRoot() function, otherwise we cannot get cached shuffing in attestation verification when syncing from genesis. - */ -function getDecisionBlock(state: CachedBeaconStateAllForks, epoch: Epoch): RootHex { - return state.slot > GENESIS_SLOT - ? getShufflingDecisionBlock(state, epoch) - : toRootHex(ssz.phase0.BeaconBlockHeader.hashTreeRoot(computeAnchorCheckpoint(state.config, state).blockHeader)); +export enum ShufflingCacheErrorCode { + NO_SHUFFLING_FOUND = "SHUFFLING_CACHE_ERROR_NO_SHUFFLING_FOUND", } + +type ShufflingCacheErrorType = { + code: ShufflingCacheErrorCode.NO_SHUFFLING_FOUND; + epoch: Epoch; + decisionRoot: RootHex; +}; + +export class ShufflingCacheError extends LodestarError {} diff --git a/packages/beacon-node/src/chain/stateCache/persistentCheckpointsCache.ts b/packages/beacon-node/src/chain/stateCache/persistentCheckpointsCache.ts index d8769374a29c..74e85e6fa574 100644 --- a/packages/beacon-node/src/chain/stateCache/persistentCheckpointsCache.ts +++ b/packages/beacon-node/src/chain/stateCache/persistentCheckpointsCache.ts @@ -212,20 +212,7 @@ export class PersistentCheckpointStateCache implements CheckpointStateCache { } sszTimer?.(); const timer = this.metrics?.stateReloadDuration.startTimer(); - const newCachedState = loadCachedBeaconState( - seedState, - stateBytes, - { - shufflingGetter: (shufflingEpoch, decisionRootHex) => { - const shuffling = this.shufflingCache.getSync(shufflingEpoch, decisionRootHex); - if (shuffling == null) { - this.metrics?.stateReloadShufflingCacheMiss.inc(); - } - return shuffling; - }, - }, - validatorsBytes - ); + const newCachedState = loadCachedBeaconState(seedState, stateBytes, {}, validatorsBytes); newCachedState.commit(); const stateRoot = toRootHex(newCachedState.hashTreeRoot()); timer?.(); diff --git a/packages/beacon-node/src/metrics/metrics/lodestar.ts b/packages/beacon-node/src/metrics/metrics/lodestar.ts index 737a900e5f64..4b076471dcab 100644 --- a/packages/beacon-node/src/metrics/metrics/lodestar.ts +++ b/packages/beacon-node/src/metrics/metrics/lodestar.ts @@ -1297,22 +1297,45 @@ export function createLodestarMetrics( name: "lodestar_shuffling_cache_size", help: "Shuffling cache size", }), - processStateInsertNew: register.gauge({ - name: "lodestar_shuffling_cache_process_state_insert_new_total", - help: "Total number of times processState is called resulting a new shuffling", - }), - processStateUpdatePromise: register.gauge({ - name: "lodestar_shuffling_cache_process_state_update_promise_total", - help: "Total number of times processState is called resulting a promise being updated with shuffling", - }), - processStateNoOp: register.gauge({ - name: "lodestar_shuffling_cache_process_state_no_op_total", - help: "Total number of times processState is called resulting no changes", - }), insertPromiseCount: register.gauge({ name: "lodestar_shuffling_cache_insert_promise_count", help: "Total number of times insertPromise is called", }), + hit: register.gauge({ + name: "lodestar_shuffling_cache_hit_count", + help: "Count of shuffling cache hit", + }), + miss: register.gauge({ + name: "lodestar_shuffling_cache_miss_count", + help: "Count of shuffling cache miss", + }), + shufflingBuiltMultipleTimes: register.gauge({ + name: "lodestar_shuffling_cache_recalculated_shuffling_count", + help: "Count of shuffling that were build multiple times", + }), + shufflingPromiseNotResolvedAndThrownAway: register.gauge({ + name: "lodestar_shuffling_cache_promise_not_resolved_and_thrown_away_count", + help: "Count of shuffling cache promises that were discarded and the shuffling was built synchronously", + }), + shufflingPromiseNotResolved: register.gauge({ + name: "lodestar_shuffling_cache_promise_not_resolved_count", + help: "Count of shuffling cache promises that were requested before the promise was resolved", + }), + nextShufflingNotOnEpochCache: register.gauge({ + name: "lodestar_shuffling_cache_next_shuffling_not_on_epoch_cache", + help: "The next shuffling was not on the epoch cache before the epoch transition", + }), + shufflingPromiseResolutionTime: register.histogram({ + name: "lodestar_shuffling_cache_promise_resolution_time_seconds", + help: "Time from promise insertion until promise resolution when shuffling was ready in seconds", + buckets: [0.5, 1, 1.5, 2], + }), + shufflingCalculationTime: register.histogram<{source: "build" | "getSync"}>({ + name: "lodestar_shuffling_cache_shuffling_calculation_time_seconds", + help: "Run time of shuffling calculation", + buckets: [0.5, 0.75, 1, 1.25, 1.5], + labelNames: ["source"], + }), }, seenCache: { diff --git a/packages/beacon-node/src/node/utils/interop/state.ts b/packages/beacon-node/src/node/utils/interop/state.ts index 6528bd392bc7..fe26afef2013 100644 --- a/packages/beacon-node/src/node/utils/interop/state.ts +++ b/packages/beacon-node/src/node/utils/interop/state.ts @@ -20,6 +20,7 @@ export type InteropStateOpts = { withEth1Credentials?: boolean; }; +// TODO: (@matthewkeil) - Only used by initDevState. Consider combining into that function export function getInteropState( config: ChainForkConfig, { diff --git a/packages/beacon-node/src/node/utils/state.ts b/packages/beacon-node/src/node/utils/state.ts index 25bd77c82274..05da7042eef4 100644 --- a/packages/beacon-node/src/node/utils/state.ts +++ b/packages/beacon-node/src/node/utils/state.ts @@ -5,6 +5,9 @@ import {IBeaconDb} from "../../db/index.js"; import {interopDeposits} from "./interop/deposits.js"; import {getInteropState, InteropStateOpts} from "./interop/state.js"; +/** + * Builds state for `dev` command, for sim testing and some other tests + */ export function initDevState( config: ChainForkConfig, validatorCount: number, diff --git a/packages/beacon-node/src/sync/backfill/backfill.ts b/packages/beacon-node/src/sync/backfill/backfill.ts index 38258fde07fd..77d2836bdcc3 100644 --- a/packages/beacon-node/src/sync/backfill/backfill.ts +++ b/packages/beacon-node/src/sync/backfill/backfill.ts @@ -1,6 +1,6 @@ import {EventEmitter} from "events"; import {StrictEventEmitter} from "strict-event-emitter-types"; -import {BeaconStateAllForks, blockToHeader} from "@lodestar/state-transition"; +import {BeaconStateAllForks, blockToHeader, computeAnchorCheckpoint} from "@lodestar/state-transition"; import {BeaconConfig, ChainForkConfig} from "@lodestar/config"; import {phase0, Root, SignedBeaconBlock, Slot, ssz} from "@lodestar/types"; import {ErrorAborted, Logger, sleep, toRootHex} from "@lodestar/utils"; @@ -15,7 +15,6 @@ import {PeerIdStr} from "../../util/peerId.js"; import {shuffleOne} from "../../util/shuffle.js"; import {Metrics} from "../../metrics/metrics"; import {byteArrayEquals} from "../../util/bytes.js"; -import {computeAnchorCheckpoint} from "../../chain/initState.js"; import {verifyBlockProposerSignature, verifyBlockSequence, BackfillBlockHeader, BackfillBlock} from "./verify.js"; import {BackfillSyncError, BackfillSyncErrorCode} from "./errors.js"; /** diff --git a/packages/beacon-node/test/perf/chain/opPools/aggregatedAttestationPool.test.ts b/packages/beacon-node/test/perf/chain/opPools/aggregatedAttestationPool.test.ts index 63fc4ee2e12c..45fc07281c3b 100644 --- a/packages/beacon-node/test/perf/chain/opPools/aggregatedAttestationPool.test.ts +++ b/packages/beacon-node/test/perf/chain/opPools/aggregatedAttestationPool.test.ts @@ -2,6 +2,7 @@ import {itBench} from "@dapplion/benchmark"; import {BitArray, toHexString} from "@chainsafe/ssz"; import { CachedBeaconStateAltair, + computeAnchorCheckpoint, computeEpochAtSlot, computeStartSlotAtEpoch, getBlockRootAtSlot, @@ -15,7 +16,6 @@ import {createChainForkConfig, defaultChainConfig} from "@lodestar/config"; // eslint-disable-next-line import/no-relative-packages import {generatePerfTestCachedStateAltair} from "../../../../../state-transition/test/perf/util.js"; import {AggregatedAttestationPool} from "../../../../src/chain/opPools/aggregatedAttestationPool.js"; -import {computeAnchorCheckpoint} from "../../../../src/chain/initState.js"; const vc = 1_500_000; diff --git a/packages/beacon-node/test/unit/chain/forkChoice/forkChoice.test.ts b/packages/beacon-node/test/unit/chain/forkChoice/forkChoice.test.ts index 6b96a0d1172f..611673086ce5 100644 --- a/packages/beacon-node/test/unit/chain/forkChoice/forkChoice.test.ts +++ b/packages/beacon-node/test/unit/chain/forkChoice/forkChoice.test.ts @@ -5,12 +5,13 @@ import {CheckpointWithHex, ExecutionStatus, ForkChoice, DataAvailabilityStatus} import {FAR_FUTURE_EPOCH, MAX_EFFECTIVE_BALANCE} from "@lodestar/params"; import { CachedBeaconStateAllForks, + computeAnchorCheckpoint, computeEpochAtSlot, getEffectiveBalanceIncrementsZeroed, } from "@lodestar/state-transition"; import {phase0, Slot, ssz, ValidatorIndex} from "@lodestar/types"; import {getTemporaryBlockHeader, processSlots} from "@lodestar/state-transition"; -import {ChainEventEmitter, computeAnchorCheckpoint, initializeForkChoice} from "../../../../src/chain/index.js"; +import {ChainEventEmitter, initializeForkChoice} from "../../../../src/chain/index.js"; import {generateSignedBlockAtSlot} from "../../../utils/typeGenerator.js"; import {createCachedBeaconStateTest} from "../../../utils/cachedBeaconState.js"; import {generateState} from "../../../utils/state.js"; diff --git a/packages/beacon-node/test/unit/chain/shufflingCache.test.ts b/packages/beacon-node/test/unit/chain/shufflingCache.test.ts index 6295a993c072..62b02cbf2b12 100644 --- a/packages/beacon-node/test/unit/chain/shufflingCache.test.ts +++ b/packages/beacon-node/test/unit/chain/shufflingCache.test.ts @@ -1,6 +1,4 @@ import {describe, it, expect, beforeEach} from "vitest"; - -import {getShufflingDecisionBlock} from "@lodestar/state-transition"; // eslint-disable-next-line import/no-relative-packages import {generateTestCachedBeaconStateOnlyValidators} from "../../../../state-transition/test/perf/util.js"; import {ShufflingCache} from "../../../src/chain/shufflingCache.js"; @@ -9,39 +7,43 @@ describe("ShufflingCache", function () { const vc = 64; const stateSlot = 100; const state = generateTestCachedBeaconStateOnlyValidators({vc, slot: stateSlot}); - const currentEpoch = state.epochCtx.currentShuffling.epoch; + const currentEpoch = state.epochCtx.epoch; + const currentDecisionRoot = state.epochCtx.currentDecisionRoot; let shufflingCache: ShufflingCache; beforeEach(() => { - shufflingCache = new ShufflingCache(null, {maxShufflingCacheEpochs: 1}); - shufflingCache.processState(state, currentEpoch); + shufflingCache = new ShufflingCache(null, null, {maxShufflingCacheEpochs: 1}, [ + { + shuffling: state.epochCtx.currentShuffling, + decisionRoot: currentDecisionRoot, + }, + ]); }); it("should get shuffling from cache", async function () { - const decisionRoot = getShufflingDecisionBlock(state, currentEpoch); - expect(await shufflingCache.get(currentEpoch, decisionRoot)).toEqual(state.epochCtx.currentShuffling); + expect(await shufflingCache.get(currentEpoch, currentDecisionRoot)).toEqual(state.epochCtx.currentShuffling); }); it("should bound by maxSize(=1)", async function () { - const decisionRoot = getShufflingDecisionBlock(state, currentEpoch); - expect(await shufflingCache.get(currentEpoch, decisionRoot)).toEqual(state.epochCtx.currentShuffling); + expect(await shufflingCache.get(currentEpoch, currentDecisionRoot)).toEqual(state.epochCtx.currentShuffling); // insert promises at the same epoch does not prune the cache shufflingCache.insertPromise(currentEpoch, "0x00"); - expect(await shufflingCache.get(currentEpoch, decisionRoot)).toEqual(state.epochCtx.currentShuffling); - // insert shufflings at other epochs does prune the cache - shufflingCache.processState(state, currentEpoch + 1); + expect(await shufflingCache.get(currentEpoch, currentDecisionRoot)).toEqual(state.epochCtx.currentShuffling); + // insert shuffling at other epochs does prune the cache + shufflingCache["set"](state.epochCtx.previousShuffling, state.epochCtx.previousDecisionRoot); // the current shuffling is not available anymore - expect(await shufflingCache.get(currentEpoch, decisionRoot)).toBeNull(); + expect(await shufflingCache.get(currentEpoch, currentDecisionRoot)).toBeNull(); }); it("should return shuffling from promise", async function () { - const nextDecisionRoot = getShufflingDecisionBlock(state, currentEpoch + 1); - shufflingCache.insertPromise(currentEpoch + 1, nextDecisionRoot); - const shufflingRequest0 = shufflingCache.get(currentEpoch + 1, nextDecisionRoot); - const shufflingRequest1 = shufflingCache.get(currentEpoch + 1, nextDecisionRoot); - shufflingCache.processState(state, currentEpoch + 1); - expect(await shufflingRequest0).toEqual(state.epochCtx.nextShuffling); - expect(await shufflingRequest1).toEqual(state.epochCtx.nextShuffling); + const previousEpoch = state.epochCtx.epoch - 1; + const previousDecisionRoot = state.epochCtx.previousDecisionRoot; + shufflingCache.insertPromise(previousEpoch, previousDecisionRoot); + const shufflingRequest0 = shufflingCache.get(previousEpoch, previousDecisionRoot); + const shufflingRequest1 = shufflingCache.get(previousEpoch, previousDecisionRoot); + shufflingCache["set"](state.epochCtx.previousShuffling, previousDecisionRoot); + expect(await shufflingRequest0).toEqual(state.epochCtx.previousShuffling); + expect(await shufflingRequest1).toEqual(state.epochCtx.previousShuffling); }); it("should support up to 2 promises at a time", async function () { diff --git a/packages/beacon-node/test/utils/state.ts b/packages/beacon-node/test/utils/state.ts index bb55adca1eb0..49a27435bdd7 100644 --- a/packages/beacon-node/test/utils/state.ts +++ b/packages/beacon-node/test/utils/state.ts @@ -106,6 +106,7 @@ export function generateState( /** * This generates state with default pubkey + * TODO: (@matthewkeil) - this is duplicated and exists in state-transition as well */ export function generateCachedState(opts?: TestBeaconState): CachedBeaconStateAllForks { const config = getConfig(ForkName.phase0); diff --git a/packages/beacon-node/test/utils/validationData/attestation.ts b/packages/beacon-node/test/utils/validationData/attestation.ts index c33d942dabc5..22f551cbb663 100644 --- a/packages/beacon-node/test/utils/validationData/attestation.ts +++ b/packages/beacon-node/test/utils/validationData/attestation.ts @@ -1,10 +1,5 @@ import {BitArray, toHexString} from "@chainsafe/ssz"; -import { - computeEpochAtSlot, - computeSigningRoot, - computeStartSlotAtEpoch, - getShufflingDecisionBlock, -} from "@lodestar/state-transition"; +import {computeEpochAtSlot, computeSigningRoot, computeStartSlotAtEpoch} from "@lodestar/state-transition"; import {ProtoBlock, IForkChoice, ExecutionStatus, DataAvailabilityStatus} from "@lodestar/fork-choice"; import {DOMAIN_BEACON_ATTESTER} from "@lodestar/params"; import {phase0, Slot, ssz} from "@lodestar/types"; @@ -81,10 +76,20 @@ export function getAttestationValidData(opts: AttestationValidDataOpts): { dataAvailabilityStatus: DataAvailabilityStatus.PreData, }; - const shufflingCache = new ShufflingCache(); - shufflingCache.processState(state, state.epochCtx.currentShuffling.epoch); - shufflingCache.processState(state, state.epochCtx.nextShuffling.epoch); - const dependentRoot = getShufflingDecisionBlock(state, state.epochCtx.currentShuffling.epoch); + const shufflingCache = new ShufflingCache(null, null, {}, [ + { + shuffling: state.epochCtx.previousShuffling, + decisionRoot: state.epochCtx.previousDecisionRoot, + }, + { + shuffling: state.epochCtx.currentShuffling, + decisionRoot: state.epochCtx.currentDecisionRoot, + }, + { + shuffling: state.epochCtx.nextShuffling, + decisionRoot: state.epochCtx.nextDecisionRoot, + }, + ]); const forkChoice = { getBlock: (root) => { @@ -95,7 +100,7 @@ export function getAttestationValidData(opts: AttestationValidDataOpts): { if (rootHex !== toHexString(beaconBlockRoot)) return null; return headBlock; }, - getDependentRoot: () => dependentRoot, + getDependentRoot: () => state.epochCtx.currentDecisionRoot, } as Partial as IForkChoice; const committeeIndices = state.epochCtx.getBeaconCommittee(attSlot, attIndex); diff --git a/packages/params/src/index.ts b/packages/params/src/index.ts index a44fd5d0e0cd..dd5c24ac3a54 100644 --- a/packages/params/src/index.ts +++ b/packages/params/src/index.ts @@ -124,6 +124,8 @@ export const FAR_FUTURE_EPOCH = Infinity; export const BASE_REWARDS_PER_EPOCH = 4; export const DEPOSIT_CONTRACT_TREE_DEPTH = 2 ** 5; // 32 export const JUSTIFICATION_BITS_LENGTH = 4; +export const ZERO_HASH = Buffer.alloc(32, 0); +export const ZERO_HASH_HEX = "0x" + "00".repeat(32); // Withdrawal prefixes // Since the prefixes are just 1 byte, we define and use them as number diff --git a/packages/state-transition/src/cache/epochCache.ts b/packages/state-transition/src/cache/epochCache.ts index ba8ec9b05ab5..3783c7f91f0d 100644 --- a/packages/state-transition/src/cache/epochCache.ts +++ b/packages/state-transition/src/cache/epochCache.ts @@ -7,6 +7,7 @@ import { Slot, ValidatorIndex, phase0, + RootHex, SyncPeriod, Attestation, IndexedAttestation, @@ -37,12 +38,19 @@ import { computeProposers, getActivationChurnLimit, } from "../util/index.js"; -import {computeEpochShuffling, EpochShuffling, getShufflingDecisionBlock} from "../util/epochShuffling.js"; +import { + computeEpochShuffling, + EpochShuffling, + calculateShufflingDecisionRoot, + IShufflingCache, +} from "../util/epochShuffling.js"; import {computeBaseRewardPerIncrement, computeSyncParticipantReward} from "../util/syncCommittee.js"; import {sumTargetUnslashedBalanceIncrements} from "../util/targetUnslashedBalance.js"; import {getTotalSlashingsByIncrement} from "../epoch/processSlashings.js"; +import {AttesterDuty, calculateCommitteeAssignments} from "../util/calculateCommitteeAssignments.js"; import {EpochCacheMetrics} from "../metrics.js"; import {EffectiveBalanceIncrements, getEffectiveBalanceIncrementsWithLen} from "./effectiveBalanceIncrements.js"; +import {BeaconStateAllForks, BeaconStateAltair} from "./types.js"; import { Index2PubkeyCache, PubkeyIndexMap, @@ -52,13 +60,13 @@ import { PubkeyHex, newUnfinalizedPubkeyIndexMap, } from "./pubkeyCache.js"; -import {BeaconStateAllForks, BeaconStateAltair, ShufflingGetter} from "./types.js"; import { computeSyncCommitteeCache, getSyncCommitteeCache, SyncCommitteeCache, SyncCommitteeCacheEmpty, } from "./syncCommitteeCache.js"; +import {CachedBeaconStateAllForks} from "./stateCache.js"; /** `= PROPOSER_WEIGHT / (WEIGHT_DENOMINATOR - PROPOSER_WEIGHT)` */ export const PROPOSER_WEIGHT_FACTOR = PROPOSER_WEIGHT / (WEIGHT_DENOMINATOR - PROPOSER_WEIGHT); @@ -67,12 +75,12 @@ export type EpochCacheImmutableData = { config: BeaconConfig; pubkey2index: PubkeyIndexMap; index2pubkey: Index2PubkeyCache; + shufflingCache?: IShufflingCache; }; export type EpochCacheOpts = { skipSyncCommitteeCache?: boolean; skipSyncPubkeys?: boolean; - shufflingGetter?: ShufflingGetter; }; /** Defers computing proposers by persisting only the seed, and dropping it once indexes are computed */ @@ -127,6 +135,11 @@ export class EpochCache { * Unique pubkey registry shared in the same fork. There should only exist one for the fork. */ unfinalizedPubkey2index: UnfinalizedPubkeyIndexMap; + /** + * ShufflingCache is passed in from `beacon-node` so should be available at runtime but may not be + * present during testing. + */ + shufflingCache?: IShufflingCache; /** * Indexes of the block proposers for the current epoch. @@ -145,6 +158,12 @@ export class EpochCache { */ proposersNextEpoch: ProposersDeferred; + /** + * Epoch decision roots to look up correct shuffling from the Shuffling Cache + */ + previousDecisionRoot: RootHex; + currentDecisionRoot: RootHex; + nextDecisionRoot: RootHex; /** * Shuffling of validator indexes. Immutable through the epoch, then it's replaced entirely. * Note: Per spec definition, shuffling will always be defined. They are never called before loadState() @@ -155,7 +174,12 @@ export class EpochCache { /** Same as previousShuffling */ currentShuffling: EpochShuffling; /** Same as previousShuffling */ - nextShuffling: EpochShuffling; + nextShuffling: EpochShuffling | null; + /** + * Cache nextActiveIndices so that in afterProcessEpoch the next shuffling can be build synchronously + * in case it is not built or the ShufflingCache is not available + */ + nextActiveIndices: Uint32Array; /** * Effective balances, for altair processAttestations() */ @@ -227,7 +251,6 @@ export class EpochCache { nextSyncCommitteeIndexed: SyncCommitteeCache; // TODO: Helper stats - epoch: Epoch; syncPeriod: SyncPeriod; /** * state.validators.length of every state at epoch boundary @@ -239,17 +262,28 @@ export class EpochCache { */ historicalValidatorLengths: immutable.List; + epoch: Epoch; + + get nextEpoch(): Epoch { + return this.epoch + 1; + } + constructor(data: { config: BeaconConfig; pubkey2index: PubkeyIndexMap; index2pubkey: Index2PubkeyCache; unfinalizedPubkey2index: UnfinalizedPubkeyIndexMap; + shufflingCache?: IShufflingCache; proposers: number[]; proposersPrevEpoch: number[] | null; proposersNextEpoch: ProposersDeferred; + previousDecisionRoot: RootHex; + currentDecisionRoot: RootHex; + nextDecisionRoot: RootHex; previousShuffling: EpochShuffling; currentShuffling: EpochShuffling; - nextShuffling: EpochShuffling; + nextShuffling: EpochShuffling | null; + nextActiveIndices: Uint32Array; effectiveBalanceIncrements: EffectiveBalanceIncrements; totalSlashingsByIncrement: number; syncParticipantReward: number; @@ -272,12 +306,17 @@ export class EpochCache { this.pubkey2index = data.pubkey2index; this.index2pubkey = data.index2pubkey; this.unfinalizedPubkey2index = data.unfinalizedPubkey2index; + this.shufflingCache = data.shufflingCache; this.proposers = data.proposers; this.proposersPrevEpoch = data.proposersPrevEpoch; this.proposersNextEpoch = data.proposersNextEpoch; + this.previousDecisionRoot = data.previousDecisionRoot; + this.currentDecisionRoot = data.currentDecisionRoot; + this.nextDecisionRoot = data.nextDecisionRoot; this.previousShuffling = data.previousShuffling; this.currentShuffling = data.currentShuffling; this.nextShuffling = data.nextShuffling; + this.nextActiveIndices = data.nextActiveIndices; this.effectiveBalanceIncrements = data.effectiveBalanceIncrements; this.totalSlashingsByIncrement = data.totalSlashingsByIncrement; this.syncParticipantReward = data.syncParticipantReward; @@ -305,7 +344,7 @@ export class EpochCache { */ static createFromState( state: BeaconStateAllForks, - {config, pubkey2index, index2pubkey}: EpochCacheImmutableData, + {config, pubkey2index, index2pubkey, shufflingCache}: EpochCacheImmutableData, opts?: EpochCacheOpts ): EpochCache { const currentEpoch = computeEpochAtSlot(state.slot); @@ -328,18 +367,18 @@ export class EpochCache { const effectiveBalanceIncrements = getEffectiveBalanceIncrementsWithLen(validatorCount); const totalSlashingsByIncrement = getTotalSlashingsByIncrement(state); - const previousActiveIndices: ValidatorIndex[] = []; - const currentActiveIndices: ValidatorIndex[] = []; - const nextActiveIndices: ValidatorIndex[] = []; + const previousActiveIndicesAsNumberArray: ValidatorIndex[] = []; + const currentActiveIndicesAsNumberArray: ValidatorIndex[] = []; + const nextActiveIndicesAsNumberArray: ValidatorIndex[] = []; // BeaconChain could provide a shuffling cache to avoid re-computing shuffling every epoch // in that case, we don't need to compute shufflings again - const previousShufflingDecisionBlock = getShufflingDecisionBlock(state, previousEpoch); - const cachedPreviousShuffling = opts?.shufflingGetter?.(previousEpoch, previousShufflingDecisionBlock); - const currentShufflingDecisionBlock = getShufflingDecisionBlock(state, currentEpoch); - const cachedCurrentShuffling = opts?.shufflingGetter?.(currentEpoch, currentShufflingDecisionBlock); - const nextShufflingDecisionBlock = getShufflingDecisionBlock(state, nextEpoch); - const cachedNextShuffling = opts?.shufflingGetter?.(nextEpoch, nextShufflingDecisionBlock); + const previousDecisionRoot = calculateShufflingDecisionRoot(config, state, previousEpoch); + const cachedPreviousShuffling = shufflingCache?.getSync(previousEpoch, previousDecisionRoot); + const currentDecisionRoot = calculateShufflingDecisionRoot(config, state, currentEpoch); + const cachedCurrentShuffling = shufflingCache?.getSync(currentEpoch, currentDecisionRoot); + const nextDecisionRoot = calculateShufflingDecisionRoot(config, state, nextEpoch); + const cachedNextShuffling = shufflingCache?.getSync(nextEpoch, nextDecisionRoot); for (let i = 0; i < validatorCount; i++) { const validator = validators[i]; @@ -350,17 +389,17 @@ export class EpochCache { // we only need to track active indices for previous, current and next epoch if we have to compute shufflings // skip doing that if we already have cached shufflings if (cachedPreviousShuffling == null && isActiveValidator(validator, previousEpoch)) { - previousActiveIndices.push(i); + previousActiveIndicesAsNumberArray.push(i); } if (isActiveValidator(validator, currentEpoch)) { if (cachedCurrentShuffling == null) { - currentActiveIndices.push(i); + currentActiveIndicesAsNumberArray.push(i); } // We track totalActiveBalanceIncrements as ETH to fit total network balance in a JS number (53 bits) totalActiveBalanceIncrements += effectiveBalanceIncrements[i]; } if (cachedNextShuffling == null && isActiveValidator(validator, nextEpoch)) { - nextActiveIndices.push(i); + nextActiveIndicesAsNumberArray.push(i); } const {exitEpoch} = validator; @@ -382,16 +421,48 @@ export class EpochCache { throw Error("totalActiveBalanceIncrements >= Number.MAX_SAFE_INTEGER. MAX_EFFECTIVE_BALANCE is too low."); } - const currentShuffling = - cachedCurrentShuffling ?? - computeEpochShuffling(state, currentActiveIndices, currentActiveIndices.length, currentEpoch); - const previousShuffling = - cachedPreviousShuffling ?? - (isGenesis - ? currentShuffling - : computeEpochShuffling(state, previousActiveIndices, previousActiveIndices.length, previousEpoch)); - const nextShuffling = - cachedNextShuffling ?? computeEpochShuffling(state, nextActiveIndices, nextActiveIndices.length, nextEpoch); + const nextActiveIndices = new Uint32Array(nextActiveIndicesAsNumberArray); + let previousShuffling: EpochShuffling; + let currentShuffling: EpochShuffling; + let nextShuffling: EpochShuffling; + + if (!shufflingCache) { + // Only for testing. shufflingCache should always be available in prod + previousShuffling = computeEpochShuffling( + state, + new Uint32Array(previousActiveIndicesAsNumberArray), + previousEpoch + ); + + currentShuffling = isGenesis + ? previousShuffling + : computeEpochShuffling(state, new Uint32Array(currentActiveIndicesAsNumberArray), currentEpoch); + + nextShuffling = computeEpochShuffling(state, nextActiveIndices, nextEpoch); + } else { + currentShuffling = cachedCurrentShuffling + ? cachedCurrentShuffling + : shufflingCache.getSync(currentEpoch, currentDecisionRoot, { + state, + activeIndices: new Uint32Array(currentActiveIndicesAsNumberArray), + }); + + previousShuffling = cachedPreviousShuffling + ? cachedPreviousShuffling + : isGenesis + ? currentShuffling + : shufflingCache.getSync(previousEpoch, previousDecisionRoot, { + state, + activeIndices: new Uint32Array(previousActiveIndicesAsNumberArray), + }); + + nextShuffling = cachedNextShuffling + ? cachedNextShuffling + : shufflingCache.getSync(nextEpoch, nextDecisionRoot, { + state, + activeIndices: nextActiveIndices, + }); + } const currentProposerSeed = getSeed(state, currentEpoch, DOMAIN_BEACON_PROPOSER); @@ -482,13 +553,18 @@ export class EpochCache { index2pubkey, // `createFromFinalizedState()` creates cache with empty unfinalizedPubkey2index. Be cautious to only pass in finalized state unfinalizedPubkey2index: newUnfinalizedPubkeyIndexMap(), + shufflingCache, proposers, // On first epoch, set to null to prevent unnecessary work since this is only used for metrics proposersPrevEpoch: null, proposersNextEpoch, + previousDecisionRoot, + currentDecisionRoot, + nextDecisionRoot, previousShuffling, currentShuffling, nextShuffling, + nextActiveIndices, effectiveBalanceIncrements, totalSlashingsByIncrement, syncParticipantReward, @@ -523,13 +599,18 @@ export class EpochCache { index2pubkey: this.index2pubkey, // No need to clone this reference. On each mutation the `unfinalizedPubkey2index` reference is replaced, @see `addPubkey` unfinalizedPubkey2index: this.unfinalizedPubkey2index, + shufflingCache: this.shufflingCache, // Immutable data proposers: this.proposers, proposersPrevEpoch: this.proposersPrevEpoch, proposersNextEpoch: this.proposersNextEpoch, + previousDecisionRoot: this.previousDecisionRoot, + currentDecisionRoot: this.currentDecisionRoot, + nextDecisionRoot: this.nextDecisionRoot, previousShuffling: this.previousShuffling, currentShuffling: this.currentShuffling, nextShuffling: this.nextShuffling, + nextActiveIndices: this.nextActiveIndices, // Uint8Array, requires cloning, but it is cloned only when necessary before an epoch transition // See EpochCache.beforeEpochTransition() effectiveBalanceIncrements: this.effectiveBalanceIncrements, @@ -555,46 +636,98 @@ export class EpochCache { /** * Called to re-use information, such as the shuffling of the next epoch, after transitioning into a - * new epoch. + * new epoch. Also handles pre-computation of values that may change during the upcoming epoch and + * that get used in the following epoch transition. Often those pre-computations are not used by the + * chain but are courtesy values that are served via the API for epoch look ahead of duties. + * + * Steps for afterProcessEpoch + * 1) update previous/current/next values of cached items */ afterProcessEpoch( - state: BeaconStateAllForks, + state: CachedBeaconStateAllForks, epochTransitionCache: { - indicesEligibleForActivationQueue: ValidatorIndex[]; - nextEpochShufflingActiveValidatorIndices: ValidatorIndex[]; - nextEpochShufflingActiveIndicesLength: number; + nextShufflingDecisionRoot: RootHex; + nextShufflingActiveIndices: Uint32Array; nextEpochTotalActiveBalanceByIncrement: number; } ): void { + // Because the slot was incremented before entering this function the "next epoch" is actually the "current epoch" + // in this context but that is not actually true because the state transition happens in the last 4 seconds of the + // epoch. For the context of this function "upcoming epoch" is used to denote the epoch that will begin after this + // function returns. The epoch that is "next" once the state transition is complete is referred to as the + // epochAfterUpcoming for the same reason to help minimize confusion. + const upcomingEpoch = this.nextEpoch; + const epochAfterUpcoming = upcomingEpoch + 1; + + // move current to previous this.previousShuffling = this.currentShuffling; - this.currentShuffling = this.nextShuffling; - const currEpoch = this.currentShuffling.epoch; - const nextEpoch = currEpoch + 1; - - this.nextShuffling = computeEpochShuffling( - state, - epochTransitionCache.nextEpochShufflingActiveValidatorIndices, - epochTransitionCache.nextEpochShufflingActiveIndicesLength, - nextEpoch - ); - - // Roll current proposers into previous proposers for metrics + this.previousDecisionRoot = this.currentDecisionRoot; this.proposersPrevEpoch = this.proposers; - const currentProposerSeed = getSeed(state, this.currentShuffling.epoch, DOMAIN_BEACON_PROPOSER); + // move next to current or calculate upcoming + this.currentDecisionRoot = this.nextDecisionRoot; + if (this.nextShuffling) { + // was already pulled from the ShufflingCache to the EpochCache (should be in most cases) + this.currentShuffling = this.nextShuffling; + } else { + this.shufflingCache?.metrics?.shufflingCache.nextShufflingNotOnEpochCache.inc(); + this.currentShuffling = + this.shufflingCache?.getSync(upcomingEpoch, this.currentDecisionRoot, { + state, + // have to use the "nextActiveIndices" that were saved in the last transition here to calculate + // the upcoming shuffling if it is not already built (similar condition to the below computation) + activeIndices: this.nextActiveIndices, + }) ?? + // allow for this case during testing where the ShufflingCache is not present, may affect perf testing + // so should be taken into account when structuring tests. Should not affect unit or other tests though + computeEpochShuffling(state, this.nextActiveIndices, upcomingEpoch); + } + const upcomingProposerSeed = getSeed(state, upcomingEpoch, DOMAIN_BEACON_PROPOSER); + // next epoch was moved to current epoch so use current here this.proposers = computeProposers( - this.config.getForkSeqAtEpoch(currEpoch), - currentProposerSeed, + this.config.getForkSeqAtEpoch(upcomingEpoch), + upcomingProposerSeed, this.currentShuffling, this.effectiveBalanceIncrements ); + // handle next values + this.nextDecisionRoot = epochTransitionCache.nextShufflingDecisionRoot; + this.nextActiveIndices = epochTransitionCache.nextShufflingActiveIndices; + if (this.shufflingCache) { + this.nextShuffling = null; + // This promise will resolve immediately after the synchronous code of the state-transition runs. Until + // the build is done on a worker thread it will be calculated immediately after the epoch transition + // completes. Once the work is done concurrently it should be ready by time this get runs so the promise + // will resolve directly on the next spin of the event loop because the epoch transition and shuffling take + // about the same time to calculate so theoretically its ready now. Do not await here though in case it + // is not ready yet as the transition must not be asynchronous. + this.shufflingCache + .get(epochAfterUpcoming, this.nextDecisionRoot) + .then((shuffling) => { + if (!shuffling) { + throw new Error("EpochShuffling not returned from get in afterProcessEpoch"); + } + this.nextShuffling = shuffling; + }) + .catch((err) => { + this.shufflingCache?.logger?.error( + "EPOCH_CONTEXT_SHUFFLING_BUILD_ERROR", + {epoch: epochAfterUpcoming, decisionRoot: epochTransitionCache.nextShufflingDecisionRoot}, + err + ); + }); + } else { + // Only for testing. shufflingCache should always be available in prod + this.nextShuffling = computeEpochShuffling(state, this.nextActiveIndices, epochAfterUpcoming); + } + // Only pre-compute the seed since it's very cheap. Do the expensive computeProposers() call only on demand. - this.proposersNextEpoch = {computed: false, seed: getSeed(state, this.nextShuffling.epoch, DOMAIN_BEACON_PROPOSER)}; + this.proposersNextEpoch = {computed: false, seed: getSeed(state, epochAfterUpcoming, DOMAIN_BEACON_PROPOSER)}; // TODO: DEDUPLICATE from createEpochCache // - // Precompute churnLimit for efficient initiateValidatorExit() during block proposing MUST be recompute everytime the + // Precompute churnLimit for efficient initiateValidatorExit() during block proposing MUST be recompute every time the // active validator indices set changes in size. Validators change active status only when: // - validator.activation_epoch is set. Only changes in process_registry_updates() if validator can be activated. If // the value changes it will be set to `epoch + 1 + MAX_SEED_LOOKAHEAD`. @@ -616,14 +749,14 @@ export class EpochCache { ); // Maybe advance exitQueueEpoch at the end of the epoch if there haven't been any exists for a while - const exitQueueEpoch = computeActivationExitEpoch(currEpoch); + const exitQueueEpoch = computeActivationExitEpoch(upcomingEpoch); if (exitQueueEpoch > this.exitQueueEpoch) { this.exitQueueEpoch = exitQueueEpoch; this.exitQueueChurn = 0; } this.totalActiveBalanceIncrements = epochTransitionCache.nextEpochTotalActiveBalanceByIncrement; - if (currEpoch >= this.config.ALTAIR_FORK_EPOCH) { + if (upcomingEpoch >= this.config.ALTAIR_FORK_EPOCH) { this.syncParticipantReward = computeSyncParticipantReward(this.totalActiveBalanceIncrements); this.syncProposerReward = Math.floor(this.syncParticipantReward * PROPOSER_WEIGHT_FACTOR); this.baseRewardPerIncrement = computeBaseRewardPerIncrement(this.totalActiveBalanceIncrements); @@ -644,7 +777,7 @@ export class EpochCache { // Only keep validatorLength for epochs after finalized cpState.epoch // eg. [100(epoch 1), 102(epoch 2)].push(104(epoch 3)), this.epoch = 3, finalized cp epoch = 1 // We keep the last (3 - 1) items = [102, 104] - if (currEpoch >= this.config.ELECTRA_FORK_EPOCH) { + if (upcomingEpoch >= this.config.ELECTRA_FORK_EPOCH) { this.historicalValidatorLengths = this.historicalValidatorLengths.push(state.validators.length); // If number of validatorLengths we want to keep exceeds the current list size, it implies @@ -786,7 +919,7 @@ export class EpochCache { const indexes = computeProposers( this.config.getForkSeqAtEpoch(this.epoch + 1), this.proposersNextEpoch.seed, - this.nextShuffling, + this.getShufflingAtEpoch(this.nextEpoch), this.effectiveBalanceIncrements ); this.proposersNextEpoch = {computed: true, indexes}; @@ -840,30 +973,8 @@ export class EpochCache { epoch: Epoch, requestedValidatorIndices: ValidatorIndex[] ): Map { - const requestedValidatorIndicesSet = new Set(requestedValidatorIndices); - const duties = new Map(); - - const epochCommittees = this.getShufflingAtEpoch(epoch).committees; - for (let epochSlot = 0; epochSlot < SLOTS_PER_EPOCH; epochSlot++) { - const slotCommittees = epochCommittees[epochSlot]; - for (let i = 0, committeesAtSlot = slotCommittees.length; i < committeesAtSlot; i++) { - for (let j = 0, committeeLength = slotCommittees[i].length; j < committeeLength; j++) { - const validatorIndex = slotCommittees[i][j]; - if (requestedValidatorIndicesSet.has(validatorIndex)) { - duties.set(validatorIndex, { - validatorIndex, - committeeLength, - committeesAtSlot, - validatorCommitteeIndex: j, - committeeIndex: i, - slot: epoch * SLOTS_PER_EPOCH + epochSlot, - }); - } - } - } - } - - return duties; + const shuffling = this.getShufflingAtEpoch(epoch); + return calculateCommitteeAssignments(shuffling, requestedValidatorIndices); } /** @@ -987,6 +1098,13 @@ export class EpochCache { getShufflingAtEpoch(epoch: Epoch): EpochShuffling { const shuffling = this.getShufflingAtEpochOrNull(epoch); if (shuffling === null) { + if (epoch === this.nextEpoch) { + throw new EpochCacheError({ + code: EpochCacheErrorCode.NEXT_SHUFFLING_NOT_AVAILABLE, + epoch: epoch, + decisionRoot: this.getShufflingDecisionRoot(this.nextEpoch), + }); + } throw new EpochCacheError({ code: EpochCacheErrorCode.COMMITTEE_EPOCH_OUT_OF_RANGE, currentEpoch: this.currentShuffling.epoch, @@ -997,15 +1115,37 @@ export class EpochCache { return shuffling; } + getShufflingDecisionRoot(epoch: Epoch): RootHex { + switch (epoch) { + case this.epoch - 1: + return this.previousDecisionRoot; + case this.epoch: + return this.currentDecisionRoot; + case this.nextEpoch: + return this.nextDecisionRoot; + default: + throw new EpochCacheError({ + code: EpochCacheErrorCode.DECISION_ROOT_EPOCH_OUT_OF_RANGE, + currentEpoch: this.epoch, + requestedEpoch: epoch, + }); + } + } + getShufflingAtEpochOrNull(epoch: Epoch): EpochShuffling | null { - if (epoch === this.previousShuffling.epoch) { - return this.previousShuffling; - } else if (epoch === this.currentShuffling.epoch) { - return this.currentShuffling; - } else if (epoch === this.nextShuffling.epoch) { - return this.nextShuffling; - } else { - return null; + switch (epoch) { + case this.epoch - 1: + return this.previousShuffling; + case this.epoch: + return this.currentShuffling; + case this.nextEpoch: + if (!this.nextShuffling) { + this.nextShuffling = + this.shufflingCache?.getSync(this.nextEpoch, this.getShufflingDecisionRoot(this.nextEpoch)) ?? null; + } + return this.nextShuffling; + default: + return null; } } @@ -1102,19 +1242,11 @@ function getEffectiveBalanceIncrementsByteLen(validatorCount: number): number { return 1024 * Math.ceil(validatorCount / 1024); } -// Copied from lodestar-api package to avoid depending on the package -type AttesterDuty = { - validatorIndex: ValidatorIndex; - committeeIndex: CommitteeIndex; - committeeLength: number; - committeesAtSlot: number; - validatorCommitteeIndex: number; - slot: Slot; -}; - export enum EpochCacheErrorCode { COMMITTEE_INDEX_OUT_OF_RANGE = "EPOCH_CONTEXT_ERROR_COMMITTEE_INDEX_OUT_OF_RANGE", COMMITTEE_EPOCH_OUT_OF_RANGE = "EPOCH_CONTEXT_ERROR_COMMITTEE_EPOCH_OUT_OF_RANGE", + DECISION_ROOT_EPOCH_OUT_OF_RANGE = "EPOCH_CONTEXT_ERROR_DECISION_ROOT_EPOCH_OUT_OF_RANGE", + NEXT_SHUFFLING_NOT_AVAILABLE = "EPOCH_CONTEXT_ERROR_NEXT_SHUFFLING_NOT_AVAILABLE", NO_SYNC_COMMITTEE = "EPOCH_CONTEXT_ERROR_NO_SYNC_COMMITTEE", PROPOSER_EPOCH_MISMATCH = "EPOCH_CONTEXT_ERROR_PROPOSER_EPOCH_MISMATCH", } @@ -1130,6 +1262,16 @@ type EpochCacheErrorType = requestedEpoch: Epoch; currentEpoch: Epoch; } + | { + code: EpochCacheErrorCode.DECISION_ROOT_EPOCH_OUT_OF_RANGE; + requestedEpoch: Epoch; + currentEpoch: Epoch; + } + | { + code: EpochCacheErrorCode.NEXT_SHUFFLING_NOT_AVAILABLE; + epoch: Epoch; + decisionRoot: RootHex; + } | { code: EpochCacheErrorCode.NO_SYNC_COMMITTEE; epoch: Epoch; diff --git a/packages/state-transition/src/cache/epochTransitionCache.ts b/packages/state-transition/src/cache/epochTransitionCache.ts index 6f27ad96d1c8..27b781e8a6a1 100644 --- a/packages/state-transition/src/cache/epochTransitionCache.ts +++ b/packages/state-transition/src/cache/epochTransitionCache.ts @@ -1,6 +1,12 @@ -import {Epoch, ValidatorIndex, phase0} from "@lodestar/types"; -import {intDiv} from "@lodestar/utils"; -import {EPOCHS_PER_SLASHINGS_VECTOR, FAR_FUTURE_EPOCH, ForkSeq, MIN_ACTIVATION_BALANCE} from "@lodestar/params"; +import {phase0, Epoch, RootHex, ValidatorIndex} from "@lodestar/types"; +import {intDiv, toRootHex} from "@lodestar/utils"; +import { + EPOCHS_PER_SLASHINGS_VECTOR, + FAR_FUTURE_EPOCH, + ForkSeq, + SLOTS_PER_HISTORICAL_ROOT, + MIN_ACTIVATION_BALANCE, +} from "@lodestar/params"; import { hasMarkers, @@ -155,12 +161,12 @@ export interface EpochTransitionCache { * | beforeProcessEpoch | calculate during the validator loop| * | afterEpochTransitionCache | read it | */ - nextEpochShufflingActiveValidatorIndices: ValidatorIndex[]; + nextShufflingActiveIndices: Uint32Array; /** - * We do not use up to `nextEpochShufflingActiveValidatorIndices.length`, use this to control that + * Shuffling decision root that gets set on the EpochCache in afterProcessEpoch */ - nextEpochShufflingActiveIndicesLength: number; + nextShufflingDecisionRoot: RootHex; /** * Altair specific, this is total active balances for the next epoch. @@ -360,6 +366,24 @@ export function beforeProcessEpoch( } } + // Trigger async build of shuffling for epoch after next (nextShuffling post epoch transition) + const epochAfterNext = state.epochCtx.nextEpoch + 1; + // cannot call calculateShufflingDecisionRoot here because spec prevent getting current slot + // as a decision block. we are part way through the transition though and this was added in + // process slot beforeProcessEpoch happens so it available and valid + const nextShufflingDecisionRoot = toRootHex(state.blockRoots.get(state.slot % SLOTS_PER_HISTORICAL_ROOT)); + const nextShufflingActiveIndices = new Uint32Array(nextEpochShufflingActiveIndicesLength); + if (nextEpochShufflingActiveIndicesLength > nextEpochShufflingActiveValidatorIndices.length) { + throw new Error( + `Invalid activeValidatorCount: ${nextEpochShufflingActiveIndicesLength} > ${nextEpochShufflingActiveValidatorIndices.length}` + ); + } + // only the first `activeValidatorCount` elements are copied to `activeIndices` + for (let i = 0; i < nextEpochShufflingActiveIndicesLength; i++) { + nextShufflingActiveIndices[i] = nextEpochShufflingActiveValidatorIndices[i]; + } + state.epochCtx.shufflingCache?.build(epochAfterNext, nextShufflingDecisionRoot, state, nextShufflingActiveIndices); + if (totalActiveStakeByIncrement < 1) { totalActiveStakeByIncrement = 1; } else if (totalActiveStakeByIncrement >= Number.MAX_SAFE_INTEGER) { @@ -483,8 +507,8 @@ export function beforeProcessEpoch( indicesEligibleForActivationQueue, indicesEligibleForActivation, indicesToEject, - nextEpochShufflingActiveValidatorIndices, - nextEpochShufflingActiveIndicesLength, + nextShufflingDecisionRoot, + nextShufflingActiveIndices, // to be updated in processEffectiveBalanceUpdates nextEpochTotalActiveBalanceByIncrement: 0, isActivePrevEpoch, diff --git a/packages/state-transition/src/cache/stateCache.ts b/packages/state-transition/src/cache/stateCache.ts index 0435e8829d21..5412675352e9 100644 --- a/packages/state-transition/src/cache/stateCache.ts +++ b/packages/state-transition/src/cache/stateCache.ts @@ -175,7 +175,7 @@ export function loadCachedBeaconState { + const requestedValidatorIndicesSet = new Set(requestedValidatorIndices); + const duties = new Map(); + + const epochCommittees = epochShuffling.committees; + for (let epochSlot = 0; epochSlot < SLOTS_PER_EPOCH; epochSlot++) { + const slotCommittees = epochCommittees[epochSlot]; + for (let i = 0, committeesAtSlot = slotCommittees.length; i < committeesAtSlot; i++) { + for (let j = 0, committeeLength = slotCommittees[i].length; j < committeeLength; j++) { + const validatorIndex = slotCommittees[i][j]; + if (requestedValidatorIndicesSet.has(validatorIndex)) { + duties.set(validatorIndex, { + validatorIndex, + committeeLength, + committeesAtSlot, + validatorCommitteeIndex: j, + committeeIndex: i, + slot: epochShuffling.epoch * SLOTS_PER_EPOCH + epochSlot, + }); + } + } + } + } + + return duties; +} diff --git a/packages/state-transition/src/util/computeAnchorCheckpoint.ts b/packages/state-transition/src/util/computeAnchorCheckpoint.ts new file mode 100644 index 000000000000..e2efc18952c2 --- /dev/null +++ b/packages/state-transition/src/util/computeAnchorCheckpoint.ts @@ -0,0 +1,38 @@ +import {ChainForkConfig} from "@lodestar/config"; +import {ssz, phase0} from "@lodestar/types"; +import {GENESIS_SLOT, ZERO_HASH} from "@lodestar/params"; +import {BeaconStateAllForks} from "../types.js"; +import {blockToHeader} from "./blockRoot.js"; +import {computeCheckpointEpochAtStateSlot} from "./epoch.js"; + +export function computeAnchorCheckpoint( + config: ChainForkConfig, + anchorState: BeaconStateAllForks +): {checkpoint: phase0.Checkpoint; blockHeader: phase0.BeaconBlockHeader} { + let blockHeader; + let root; + const blockTypes = config.getForkTypes(anchorState.latestBlockHeader.slot); + + if (anchorState.latestBlockHeader.slot === GENESIS_SLOT) { + const block = blockTypes.BeaconBlock.defaultValue(); + block.stateRoot = anchorState.hashTreeRoot(); + blockHeader = blockToHeader(config, block); + root = ssz.phase0.BeaconBlockHeader.hashTreeRoot(blockHeader); + } else { + blockHeader = ssz.phase0.BeaconBlockHeader.clone(anchorState.latestBlockHeader); + if (ssz.Root.equals(blockHeader.stateRoot, ZERO_HASH)) { + blockHeader.stateRoot = anchorState.hashTreeRoot(); + } + root = ssz.phase0.BeaconBlockHeader.hashTreeRoot(blockHeader); + } + + return { + checkpoint: { + root, + // the checkpoint epoch = computeEpochAtSlot(anchorState.slot) + 1 if slot is not at epoch boundary + // this is similar to a process_slots() call + epoch: computeCheckpointEpochAtStateSlot(anchorState.slot), + }, + blockHeader, + }; +} diff --git a/packages/state-transition/src/util/epochShuffling.ts b/packages/state-transition/src/util/epochShuffling.ts index 856721d8d083..c26c62fd2079 100644 --- a/packages/state-transition/src/util/epochShuffling.ts +++ b/packages/state-transition/src/util/epochShuffling.ts @@ -1,16 +1,60 @@ -import {Epoch, RootHex, ValidatorIndex} from "@lodestar/types"; -import {intDiv, toRootHex} from "@lodestar/utils"; +import {Epoch, RootHex, ssz, ValidatorIndex} from "@lodestar/types"; +import {GaugeExtra, intDiv, Logger, NoLabels, toRootHex} from "@lodestar/utils"; import { DOMAIN_BEACON_ATTESTER, + GENESIS_SLOT, MAX_COMMITTEES_PER_SLOT, SLOTS_PER_EPOCH, TARGET_COMMITTEE_SIZE, } from "@lodestar/params"; +import {BeaconConfig} from "@lodestar/config"; import {BeaconStateAllForks} from "../types.js"; import {getSeed} from "./seed.js"; import {unshuffleList} from "./shuffle.js"; import {computeStartSlotAtEpoch} from "./epoch.js"; import {getBlockRootAtSlot} from "./blockRoot.js"; +import {computeAnchorCheckpoint} from "./computeAnchorCheckpoint.js"; + +export interface ShufflingBuildProps { + state: BeaconStateAllForks; + activeIndices: Uint32Array; +} + +export interface PublicShufflingCacheMetrics { + shufflingCache: { + nextShufflingNotOnEpochCache: GaugeExtra; + }; +} +export interface IShufflingCache { + metrics: PublicShufflingCacheMetrics | null; + logger: Logger | null; + /** + * Gets a cached shuffling via the epoch and decision root. If the state and + * activeIndices are passed and a shuffling is not available it will be built + * synchronously. If the state is not passed and the shuffling is not available + * nothing will be returned. + * + * NOTE: If a shuffling is already queued and not calculated it will build and resolve + * the promise but the already queued build will happen at some later time + */ + getSync( + epoch: Epoch, + decisionRoot: RootHex, + buildProps?: T + ): T extends ShufflingBuildProps ? EpochShuffling : EpochShuffling | null; + + /** + * Gets a cached shuffling via the epoch and decision root. Returns a promise + * for the shuffling if it hs not calculated yet. Returns null if a build has + * not been queued nor a shuffling was calculated. + */ + get(epoch: Epoch, decisionRoot: RootHex): Promise; + + /** + * Queue asynchronous build for an EpochShuffling + */ + build(epoch: Epoch, decisionRoot: RootHex, state: BeaconStateAllForks, activeIndices: Uint32Array): void; +} /** * Readonly interface for EpochShuffling. @@ -60,21 +104,13 @@ export function computeCommitteeCount(activeValidatorCount: number): number { export function computeEpochShuffling( state: BeaconStateAllForks, - activeIndices: ArrayLike, - activeValidatorCount: number, + activeIndices: Uint32Array, epoch: Epoch ): EpochShuffling { - const seed = getSeed(state, epoch, DOMAIN_BEACON_ATTESTER); + const activeValidatorCount = activeIndices.length; - if (activeValidatorCount > activeIndices.length) { - throw new Error(`Invalid activeValidatorCount: ${activeValidatorCount} > ${activeIndices.length}`); - } - // only the first `activeValidatorCount` elements are copied to `activeIndices` - const _activeIndices = new Uint32Array(activeValidatorCount); - for (let i = 0; i < activeValidatorCount; i++) { - _activeIndices[i] = activeIndices[i]; - } - const shuffling = _activeIndices.slice(); + const shuffling = activeIndices.slice(); + const seed = getSeed(state, epoch, DOMAIN_BEACON_ATTESTER); unshuffleList(shuffling, seed); const committeesPerSlot = computeCommitteeCount(activeValidatorCount); @@ -98,14 +134,29 @@ export function computeEpochShuffling( return { epoch, - activeIndices: _activeIndices, + activeIndices, shuffling, committees, committeesPerSlot, }; } -export function getShufflingDecisionBlock(state: BeaconStateAllForks, epoch: Epoch): RootHex { +function calculateDecisionRoot(state: BeaconStateAllForks, epoch: Epoch): RootHex { const pivotSlot = computeStartSlotAtEpoch(epoch - 1) - 1; return toRootHex(getBlockRootAtSlot(state, pivotSlot)); } + +/** + * Get the shuffling decision block root for the given epoch of given state + * - Special case close to genesis block, return the genesis block root + * - This is similar to forkchoice.getDependentRoot() function, otherwise we cannot get cached shuffing in attestation verification when syncing from genesis. + */ +export function calculateShufflingDecisionRoot( + config: BeaconConfig, + state: BeaconStateAllForks, + epoch: Epoch +): RootHex { + return state.slot > GENESIS_SLOT + ? calculateDecisionRoot(state, epoch) + : toRootHex(ssz.phase0.BeaconBlockHeader.hashTreeRoot(computeAnchorCheckpoint(config, state).blockHeader)); +} diff --git a/packages/state-transition/src/util/index.ts b/packages/state-transition/src/util/index.ts index 9b9916f1d49e..5f8d9e5cdcfc 100644 --- a/packages/state-transition/src/util/index.ts +++ b/packages/state-transition/src/util/index.ts @@ -4,7 +4,9 @@ export * from "./attestation.js"; export * from "./attesterStatus.js"; export * from "./balance.js"; export * from "./blindedBlock.js"; +export * from "./calculateCommitteeAssignments.js"; export * from "./capella.js"; +export * from "./computeAnchorCheckpoint.js"; export * from "./execution.js"; export * from "./blockRoot.js"; export * from "./domain.js"; diff --git a/packages/state-transition/test/perf/epoch/epochAltair.test.ts b/packages/state-transition/test/perf/epoch/epochAltair.test.ts index 15cde849ce9f..5a10fd4d8bbd 100644 --- a/packages/state-transition/test/perf/epoch/epochAltair.test.ts +++ b/packages/state-transition/test/perf/epoch/epochAltair.test.ts @@ -46,6 +46,7 @@ describe(`altair processEpoch - ${stateId}`, () => { fn: (state) => { const cache = beforeProcessEpoch(state); processEpoch(fork, state as CachedBeaconStateAltair, cache); + state.slot++; state.epochCtx.afterProcessEpoch(state, cache); // Simulate root computation through the next block to account for changes // 74184 hash64 ops - 92.730 ms @@ -187,6 +188,9 @@ function benchmarkAltairEpochSteps(stateOg: LazyValue return {state, cache: cacheAfter}; }, beforeEach: ({state, cache}) => ({state: state.clone(), cache}), - fn: ({state, cache}) => state.epochCtx.afterProcessEpoch(state, cache), + fn: ({state, cache}) => { + state.slot++; + state.epochCtx.afterProcessEpoch(state, cache); + }, }); } diff --git a/packages/state-transition/test/perf/epoch/epochCapella.test.ts b/packages/state-transition/test/perf/epoch/epochCapella.test.ts index 61bfad20b1ee..a4daf308aaa0 100644 --- a/packages/state-transition/test/perf/epoch/epochCapella.test.ts +++ b/packages/state-transition/test/perf/epoch/epochCapella.test.ts @@ -46,6 +46,7 @@ describe(`capella processEpoch - ${stateId}`, () => { fn: (state) => { const cache = beforeProcessEpoch(state); processEpoch(fork, state as CachedBeaconStateCapella, cache); + state.slot++; state.epochCtx.afterProcessEpoch(state, cache); // Simulate root computation through the next block to account for changes // 74184 hash64 ops - 92.730 ms @@ -159,6 +160,9 @@ function benchmarkAltairEpochSteps(stateOg: LazyValue return {state, cache: cacheAfter}; }, beforeEach: ({state, cache}) => ({state: state.clone(), cache}), - fn: ({state, cache}) => state.epochCtx.afterProcessEpoch(state, cache), + fn: ({state, cache}) => { + state.slot++; + state.epochCtx.afterProcessEpoch(state, cache); + }, }); } diff --git a/packages/state-transition/test/perf/epoch/epochPhase0.test.ts b/packages/state-transition/test/perf/epoch/epochPhase0.test.ts index 3af3d4d4a832..5c19b347af62 100644 --- a/packages/state-transition/test/perf/epoch/epochPhase0.test.ts +++ b/packages/state-transition/test/perf/epoch/epochPhase0.test.ts @@ -43,6 +43,7 @@ describe(`phase0 processEpoch - ${stateId}`, () => { fn: (state) => { const cache = beforeProcessEpoch(state); processEpoch(fork, state as CachedBeaconStatePhase0, cache); + state.slot++; state.epochCtx.afterProcessEpoch(state, cache); // Simulate root computation through the next block to account for changes state.hashTreeRoot(); @@ -162,6 +163,9 @@ function benchmarkPhase0EpochSteps(stateOg: LazyValue return {state, cache: cacheAfter}; }, beforeEach: ({state, cache}) => ({state: state.clone(), cache}), - fn: ({state, cache}) => state.epochCtx.afterProcessEpoch(state, cache), + fn: ({state, cache}) => { + state.slot++; + state.epochCtx.afterProcessEpoch(state, cache); + }, }); } diff --git a/packages/state-transition/test/perf/util/loadState/loadState.test.ts b/packages/state-transition/test/perf/util/loadState/loadState.test.ts index a8a1b1399dc5..25b43e242d02 100644 --- a/packages/state-transition/test/perf/util/loadState/loadState.test.ts +++ b/packages/state-transition/test/perf/util/loadState/loadState.test.ts @@ -79,17 +79,15 @@ describe("loadState", function () { pubkey2index.set(pubkey, validatorIndex); index2pubkey[validatorIndex] = PublicKey.fromBytes(pubkey); } - // skip computimg shuffling in performance test because in reality we have a ShufflingCache - // eslint-disable-next-line @typescript-eslint/explicit-function-return-type - const shufflingGetter = () => seedState.epochCtx.currentShuffling; createCachedBeaconState( migratedState, { config: seedState.config, pubkey2index, index2pubkey, + shufflingCache: seedState.epochCtx.shufflingCache, }, - {skipSyncPubkeys: true, skipSyncCommitteeCache: true, shufflingGetter} + {skipSyncPubkeys: true, skipSyncCommitteeCache: true} ); }, }); diff --git a/packages/state-transition/test/perf/util/shufflings.test.ts b/packages/state-transition/test/perf/util/shufflings.test.ts index 24be96c4676d..41767c184349 100644 --- a/packages/state-transition/test/perf/util/shufflings.test.ts +++ b/packages/state-transition/test/perf/util/shufflings.test.ts @@ -27,17 +27,17 @@ describe("epoch shufflings", () => { itBench({ id: `computeProposers - vc ${numValidators}`, fn: () => { - const epochSeed = getSeed(state, state.epochCtx.nextShuffling.epoch, DOMAIN_BEACON_PROPOSER); + const epochSeed = getSeed(state, state.epochCtx.epoch, DOMAIN_BEACON_PROPOSER); const fork = state.config.getForkSeq(state.slot); - computeProposers(fork, epochSeed, state.epochCtx.nextShuffling, state.epochCtx.effectiveBalanceIncrements); + computeProposers(fork, epochSeed, state.epochCtx.currentShuffling, state.epochCtx.effectiveBalanceIncrements); }, }); itBench({ id: `computeEpochShuffling - vc ${numValidators}`, fn: () => { - const {activeIndices} = state.epochCtx.nextShuffling; - computeEpochShuffling(state, activeIndices, activeIndices.length, nextEpoch); + const {nextActiveIndices} = state.epochCtx; + computeEpochShuffling(state, nextActiveIndices, nextEpoch); }, }); @@ -45,12 +45,7 @@ describe("epoch shufflings", () => { id: `getNextSyncCommittee - vc ${numValidators}`, fn: () => { const fork = state.config.getForkSeq(state.slot); - getNextSyncCommittee( - fork, - state, - state.epochCtx.nextShuffling.activeIndices, - state.epochCtx.effectiveBalanceIncrements - ); + getNextSyncCommittee(fork, state, state.epochCtx.nextActiveIndices, state.epochCtx.effectiveBalanceIncrements); }, }); }); diff --git a/packages/state-transition/test/unit/cachedBeaconState.test.ts b/packages/state-transition/test/unit/cachedBeaconState.test.ts index 77c5da7a5f4a..092dda321610 100644 --- a/packages/state-transition/test/unit/cachedBeaconState.test.ts +++ b/packages/state-transition/test/unit/cachedBeaconState.test.ts @@ -1,6 +1,6 @@ import {fromHexString} from "@chainsafe/ssz"; import {describe, it, expect} from "vitest"; -import {Epoch, ssz, RootHex} from "@lodestar/types"; +import {ssz} from "@lodestar/types"; import {toHexString} from "@lodestar/utils"; import {config as defaultConfig} from "@lodestar/config/default"; import {createBeaconConfig, createChainForkConfig} from "@lodestar/config"; @@ -9,7 +9,6 @@ import {PubkeyIndexMap} from "../../src/cache/pubkeyCache.js"; import {createCachedBeaconState, loadCachedBeaconState} from "../../src/cache/stateCache.js"; import {interopPubkeysCached} from "../utils/interop.js"; import {modifyStateSameValidator, newStateWithValidators} from "../utils/capella.js"; -import {EpochShuffling, getShufflingDecisionBlock} from "../../src/util/epochShuffling.js"; describe("CachedBeaconState", () => { it("Clone and mutate", () => { @@ -189,42 +188,21 @@ describe("CachedBeaconState", () => { // confirm loadState() result const stateBytes = state.serialize(); - const newCachedState = loadCachedBeaconState(seedState, stateBytes, {skipSyncCommitteeCache: true}); + const newCachedState = loadCachedBeaconState(seedState, stateBytes, { + skipSyncCommitteeCache: true, + }); const newStateBytes = newCachedState.serialize(); expect(newStateBytes).toEqual(stateBytes); expect(newCachedState.hashTreeRoot()).toEqual(state.hashTreeRoot()); - const shufflingGetter = (shufflingEpoch: Epoch, dependentRoot: RootHex): EpochShuffling | null => { - if ( - shufflingEpoch === seedState.epochCtx.epoch - 1 && - dependentRoot === getShufflingDecisionBlock(seedState, shufflingEpoch) - ) { - return seedState.epochCtx.previousShuffling; - } - - if ( - shufflingEpoch === seedState.epochCtx.epoch && - dependentRoot === getShufflingDecisionBlock(seedState, shufflingEpoch) - ) { - return seedState.epochCtx.currentShuffling; - } - - if ( - shufflingEpoch === seedState.epochCtx.epoch + 1 && - dependentRoot === getShufflingDecisionBlock(seedState, shufflingEpoch) - ) { - return seedState.epochCtx.nextShuffling; - } - - return null; - }; const cachedState = createCachedBeaconState( state, { config, pubkey2index: new PubkeyIndexMap(), index2pubkey: [], + shufflingCache: seedState.epochCtx.shufflingCache, }, - {skipSyncCommitteeCache: true, shufflingGetter} + {skipSyncCommitteeCache: true} ); // validatorCountDelta < 0 is unrealistic and shuffling computation results in a different result if (validatorCountDelta >= 0) { From 0dceb831ca7c44ee8ebfdb667a793a042f0b93c4 Mon Sep 17 00:00:00 2001 From: Nico Flaig Date: Mon, 23 Sep 2024 17:35:45 +0100 Subject: [PATCH 16/52] chore: clean up from electra review (#7102) --- packages/beacon-node/src/api/impl/validator/index.ts | 2 +- packages/beacon-node/src/metrics/metrics/beacon.ts | 2 +- packages/beacon-node/src/metrics/metrics/lodestar.ts | 4 ++-- packages/beacon-node/test/unit/util/sszBytes.test.ts | 2 +- packages/params/src/presets/mainnet.ts | 1 - packages/params/src/presets/minimal.ts | 1 - 6 files changed, 5 insertions(+), 7 deletions(-) diff --git a/packages/beacon-node/src/api/impl/validator/index.ts b/packages/beacon-node/src/api/impl/validator/index.ts index d2ce6672c89f..4876975c1bea 100644 --- a/packages/beacon-node/src/api/impl/validator/index.ts +++ b/packages/beacon-node/src/api/impl/validator/index.ts @@ -1087,7 +1087,7 @@ export function getValidatorApi( await waitForSlot(slot); // Must never request for a future slot > currentSlot - const dataRootHex = toHex(attestationDataRoot); + const dataRootHex = toRootHex(attestationDataRoot); const aggregate = chain.attestationPool.getAggregate(slot, null, dataRootHex); const fork = chain.config.getForkName(slot); diff --git a/packages/beacon-node/src/metrics/metrics/beacon.ts b/packages/beacon-node/src/metrics/metrics/beacon.ts index 96bb6bea4174..949999dbb1f4 100644 --- a/packages/beacon-node/src/metrics/metrics/beacon.ts +++ b/packages/beacon-node/src/metrics/metrics/beacon.ts @@ -122,7 +122,7 @@ export function createBeaconMetrics(register: RegistryMetricCreator) { headState: { unfinalizedPubkeyCacheSize: register.gauge({ - name: "head_state_unfinalized_pubkey_cache_size", + name: "beacon_head_state_unfinalized_pubkey_cache_size", help: "Current size of the unfinalizedPubkey2Index cache in the head state", }), }, diff --git a/packages/beacon-node/src/metrics/metrics/lodestar.ts b/packages/beacon-node/src/metrics/metrics/lodestar.ts index 4b076471dcab..fb4ea61b6523 100644 --- a/packages/beacon-node/src/metrics/metrics/lodestar.ts +++ b/packages/beacon-node/src/metrics/metrics/lodestar.ts @@ -381,11 +381,11 @@ export function createLodestarMetrics( epochCache: { finalizedPubkeyDuplicateInsert: register.gauge({ - name: "lodestar_epoch_cache_finalized_pubkey_duplicate_insert", + name: "lodestar_epoch_cache_finalized_pubkey_duplicate_insert_total", help: "Total count of duplicate insert of finalized pubkeys", }), newUnFinalizedPubkey: register.gauge({ - name: "lodestar_epoch_cache_new_unfinalized_pubkey", + name: "lodestar_epoch_cache_new_unfinalized_pubkey_total", help: "Total count of unfinalized pubkeys added", }), }, diff --git a/packages/beacon-node/test/unit/util/sszBytes.test.ts b/packages/beacon-node/test/unit/util/sszBytes.test.ts index 612eea5a4388..8b72c31df6c8 100644 --- a/packages/beacon-node/test/unit/util/sszBytes.test.ts +++ b/packages/beacon-node/test/unit/util/sszBytes.test.ts @@ -6,7 +6,7 @@ import {ForkName, MAX_COMMITTEES_PER_SLOT} from "@lodestar/params"; import { getAttDataFromAttestationSerialized, getAttDataFromSignedAggregateAndProofPhase0, - getAggregationBitsFromAttestationSerialized as getAggregationBitsFromAttestationSerialized, + getAggregationBitsFromAttestationSerialized, getBlockRootFromAttestationSerialized, getBlockRootFromSignedAggregateAndProofSerialized, getSlotFromAttestationSerialized, diff --git a/packages/params/src/presets/mainnet.ts b/packages/params/src/presets/mainnet.ts index a4a88aac1f58..ca599e990df4 100644 --- a/packages/params/src/presets/mainnet.ts +++ b/packages/params/src/presets/mainnet.ts @@ -127,7 +127,6 @@ export const mainnetPreset: BeaconPreset = { MAX_PENDING_PARTIALS_PER_WITHDRAWALS_SWEEP: 8, // 2**11 * 10**9 (= 2,048,000,000,000) Gwei MAX_EFFECTIVE_BALANCE_ELECTRA: 2048000000000, - // 2**16 (= 65536) MIN_SLASHING_PENALTY_QUOTIENT_ELECTRA: 4096, MIN_ACTIVATION_BALANCE: 32000000000, PENDING_BALANCE_DEPOSITS_LIMIT: 134217728, diff --git a/packages/params/src/presets/minimal.ts b/packages/params/src/presets/minimal.ts index 97eff53cf013..5dc8fc10d803 100644 --- a/packages/params/src/presets/minimal.ts +++ b/packages/params/src/presets/minimal.ts @@ -128,7 +128,6 @@ export const minimalPreset: BeaconPreset = { MAX_PENDING_PARTIALS_PER_WITHDRAWALS_SWEEP: 1, // 2**11 * 10**9 (= 2,048,000,000,000) Gwei MAX_EFFECTIVE_BALANCE_ELECTRA: 2048000000000, - // 2**16 (= 65536) MIN_SLASHING_PENALTY_QUOTIENT_ELECTRA: 4096, MIN_ACTIVATION_BALANCE: 32000000000, PENDING_BALANCE_DEPOSITS_LIMIT: 134217728, From d0ba6bc3ccf203307bcbf0087d82749dff81699b Mon Sep 17 00:00:00 2001 From: Nico Flaig Date: Mon, 23 Sep 2024 21:54:20 +0100 Subject: [PATCH 17/52] chore: upgrade fastify to v5 (#7101) * chore: upgrade fastify to v5 * Upgrade fastify plugins * Clean up yarn lock --- packages/api/package.json | 2 +- packages/api/src/utils/schema.ts | 12 +- packages/api/src/utils/server/parser.ts | 14 +- packages/beacon-node/package.json | 10 +- packages/cli/package.json | 2 +- packages/light-client/package.json | 2 +- yarn.lock | 394 +++++++++++++----------- 7 files changed, 228 insertions(+), 208 deletions(-) diff --git a/packages/api/package.json b/packages/api/package.json index d2f8a621f02e..7d851d9513ba 100644 --- a/packages/api/package.json +++ b/packages/api/package.json @@ -83,7 +83,7 @@ "@types/eventsource": "^1.1.11", "@types/qs": "^6.9.7", "ajv": "^8.12.0", - "fastify": "^4.27.0" + "fastify": "^5.0.0" }, "keywords": [ "ethereum", diff --git a/packages/api/src/utils/schema.ts b/packages/api/src/utils/schema.ts index 2d086fd8dfa9..3f297db6f665 100644 --- a/packages/api/src/utils/schema.ts +++ b/packages/api/src/utils/schema.ts @@ -1,3 +1,4 @@ +import {MediaType} from "./headers.js"; import {Endpoint, HeaderParams, PathParams, QueryParams} from "./types.js"; // Reasoning: Allows to declare JSON schemas for server routes in a succinct typesafe way. @@ -91,7 +92,16 @@ export function getFastifySchema(schemaDef: Schem const schema: {params?: JsonSchemaObj; querystring?: JsonSchemaObj; headers?: JsonSchemaObj; body?: JsonSchema} = {}; if (schemaDef.body != null) { - schema.body = getJsonSchemaItem(schemaDef.body); + schema.body = { + content: { + [MediaType.json]: { + schema: getJsonSchemaItem(schemaDef.body), + }, + [MediaType.ssz]: { + schema: {}, + }, + }, + }; } if (schemaDef.params) { diff --git a/packages/api/src/utils/server/parser.ts b/packages/api/src/utils/server/parser.ts index fd668b63757e..3300575a4845 100644 --- a/packages/api/src/utils/server/parser.ts +++ b/packages/api/src/utils/server/parser.ts @@ -2,22 +2,10 @@ import type * as fastify from "fastify"; import {MediaType} from "../headers.js"; export function addSszContentTypeParser(server: fastify.FastifyInstance): void { - // Cache body schema symbol, does not change per request - let bodySchemaSymbol: symbol | undefined; - server.addContentTypeParser( MediaType.ssz, {parseAs: "buffer"}, - async (request: fastify.FastifyRequest, payload: Buffer) => { - if (bodySchemaSymbol === undefined) { - // Get body schema symbol to be able to access validation function - // https://github.com/fastify/fastify/blob/af2ccb5ff681c1d0ac22eb7314c6fa803f73c873/lib/symbols.js#L25 - bodySchemaSymbol = Object.getOwnPropertySymbols(request.context).find((s) => s.description === "body-schema"); - } - // JSON schema validation will be applied to `Buffer` object, it is required to override validation function - // See https://github.com/fastify/help/issues/1012, it is not possible right now to define a schema per content type - (request.context as unknown as Record)[bodySchemaSymbol as symbol] = () => true; - + async (_request: fastify.FastifyRequest, payload: Buffer) => { // We could just return the `Buffer` here which is a subclass of `Uint8Array` but downstream code does not require it // and it's better to convert it here to avoid unexpected behavior such as `Buffer.prototype.slice` not copying memory // See https://github.com/nodejs/node/issues/41588#issuecomment-1016269584 diff --git a/packages/beacon-node/package.json b/packages/beacon-node/package.json index ade89ebc6cc1..f101206bfd9e 100644 --- a/packages/beacon-node/package.json +++ b/packages/beacon-node/package.json @@ -106,10 +106,10 @@ "@chainsafe/ssz": "^0.17.1", "@chainsafe/threads": "^1.11.1", "@ethersproject/abi": "^5.7.0", - "@fastify/bearer-auth": "^9.0.0", - "@fastify/cors": "^8.2.1", - "@fastify/swagger": "^8.10.0", - "@fastify/swagger-ui": "^1.9.3", + "@fastify/bearer-auth": "^10.0.1", + "@fastify/cors": "^10.0.1", + "@fastify/swagger": "^9.0.0", + "@fastify/swagger-ui": "^5.0.1", "@libp2p/bootstrap": "^10.0.21", "@libp2p/identify": "^1.0.20", "@libp2p/interface": "^1.3.0", @@ -136,7 +136,7 @@ "datastore-core": "^9.1.1", "datastore-level": "^10.1.1", "deepmerge": "^4.3.1", - "fastify": "^4.27.0", + "fastify": "^5.0.0", "interface-datastore": "^8.2.7", "it-all": "^3.0.4", "it-pipe": "^3.0.1", diff --git a/packages/cli/package.json b/packages/cli/package.json index 579725eba04e..a5527a8eee87 100644 --- a/packages/cli/package.json +++ b/packages/cli/package.json @@ -94,6 +94,6 @@ "@types/inquirer": "^9.0.3", "@types/proper-lockfile": "^4.1.4", "@types/yargs": "^17.0.24", - "fastify": "^4.27.0" + "fastify": "^5.0.0" } } diff --git a/packages/light-client/package.json b/packages/light-client/package.json index 940a78ae66d5..2eda3a45d455 100644 --- a/packages/light-client/package.json +++ b/packages/light-client/package.json @@ -87,7 +87,7 @@ "devDependencies": { "@chainsafe/as-sha256": "^0.5.0", "@types/qs": "^6.9.7", - "fastify": "^4.27.0", + "fastify": "^5.0.0", "qs": "^6.11.1", "uint8arrays": "^5.0.1" }, diff --git a/yarn.lock b/yarn.lock index 38e6bae97d60..f546d770acd8 100644 --- a/yarn.lock +++ b/yarn.lock @@ -1285,108 +1285,104 @@ "@ethersproject/properties" "^5.7.0" "@ethersproject/strings" "^5.7.0" -"@fastify/accept-negotiator@^1.0.0": - version "1.1.0" - resolved "https://registry.yarnpkg.com/@fastify/accept-negotiator/-/accept-negotiator-1.1.0.tgz#c1c66b3b771c09742a54dd5bc87c582f6b0630ff" - integrity sha512-OIHZrb2ImZ7XG85HXOONLcJWGosv7sIvM2ifAPQVhg9Lv7qdmMBNVaai4QTdyuaqbKM5eO6sLSQOYI7wEQeCJQ== +"@fastify/accept-negotiator@^2.0.0": + version "2.0.0" + resolved "https://registry.yarnpkg.com/@fastify/accept-negotiator/-/accept-negotiator-2.0.0.tgz#efce76b4d658e7ee669e681c2d79bffc9a654fdb" + integrity sha512-/Sce/kBzuTxIq5tJh85nVNOq9wKD8s+viIgX0fFMDBdw95gnpf53qmF1oBgJym3cPFliWUuSloVg/1w/rH0FcQ== -"@fastify/ajv-compiler@^3.5.0": - version "3.5.0" - resolved "https://registry.yarnpkg.com/@fastify/ajv-compiler/-/ajv-compiler-3.5.0.tgz#459bff00fefbf86c96ec30e62e933d2379e46670" - integrity sha512-ebbEtlI7dxXF5ziNdr05mOY8NnDiPB1XvAlLHctRt/Rc+C3LCOVW5imUVX+mhvUhnNzmPBHewUkOFgGlCxgdAA== +"@fastify/ajv-compiler@^4.0.0": + version "4.0.1" + resolved "https://registry.yarnpkg.com/@fastify/ajv-compiler/-/ajv-compiler-4.0.1.tgz#9567b4c09149a0f342e931c7196a8ed9dc292954" + integrity sha512-DxrBdgsjNLP0YM6W5Hd6/Fmj43S8zMKiFJYgi+Ri3htTGAowPVG/tG1wpnWLMjufEnehRivUCKZ1pLDIoZdTuw== dependencies: - ajv "^8.11.0" - ajv-formats "^2.1.1" - fast-uri "^2.0.0" + ajv "^8.12.0" + ajv-formats "^3.0.1" + fast-uri "^3.0.0" -"@fastify/bearer-auth@^9.0.0": - version "9.0.0" - resolved "https://registry.yarnpkg.com/@fastify/bearer-auth/-/bearer-auth-9.0.0.tgz#9a75abcb1d54751dc04e97b37db5363e325c0f90" - integrity sha512-I1egwg1LRdIvhjL/P+3UEfyK7A3YTnN3goTyf8MJ+v7vVkwyyd8ieccFKI0SzEuxMmfQh/p4yNyLZWcMVwpInA== +"@fastify/bearer-auth@^10.0.1": + version "10.0.1" + resolved "https://registry.yarnpkg.com/@fastify/bearer-auth/-/bearer-auth-10.0.1.tgz#893466052fa566c24eb4f44a3c6aacb50db96ecd" + integrity sha512-i2snRkAJsMmfFcsRS/fFIovcLL3WeZtxJP9pprx2NvB8N/l+fjMNmKeWWyX0hDS2Q0zEPqLz/G0DK92nqJYAJQ== dependencies: - fastify-plugin "^4.0.0" + "@fastify/error" "^4.0.0" + fastify-plugin "^5.0.0" "@fastify/busboy@^2.0.0": version "2.1.1" resolved "https://registry.yarnpkg.com/@fastify/busboy/-/busboy-2.1.1.tgz#b9da6a878a371829a0502c9b6c1c143ef6663f4d" integrity sha512-vBZP4NlzfOlerQTnba4aqZoMhE/a9HY7HRqoOPaETQcSQuWEIyZMHGfVu6w9wGtGK5fED5qRs2DteVCjOH60sA== -"@fastify/cors@^8.2.1": - version "8.2.1" - resolved "https://registry.yarnpkg.com/@fastify/cors/-/cors-8.2.1.tgz#dd348162bcbfb87dff4b492e2bef32d41244006a" - integrity sha512-2H2MrDD3ea7g707g1CNNLWb9/tYbmw7HS+MK2SDcgjxwzbOFR93JortelTIO8DBFsZqFtEpKNxiZfSyrGgYcbw== +"@fastify/cors@^10.0.1": + version "10.0.1" + resolved "https://registry.yarnpkg.com/@fastify/cors/-/cors-10.0.1.tgz#c208fa5f672db31a8383400349e9852762903d64" + integrity sha512-O8JIf6448uQbOgzSkCqhClw6gFTAqrdfeA6R3fc/3gwTJGUp7gl8/3tbNB+6INuu4RmgVOq99BmvdGbtu5pgOA== dependencies: - fastify-plugin "^4.0.0" - mnemonist "0.39.5" + fastify-plugin "^5.0.0" + mnemonist "0.39.8" -"@fastify/deepmerge@^1.0.0": - version "1.3.0" - resolved "https://registry.yarnpkg.com/@fastify/deepmerge/-/deepmerge-1.3.0.tgz#8116858108f0c7d9fd460d05a7d637a13fe3239a" - integrity sha512-J8TOSBq3SoZbDhM9+R/u77hP93gz/rajSA+K2kGyijPpORPWUXHUpTaleoj+92As0S9uPRP7Oi8IqMf0u+ro6A== - -"@fastify/error@^3.3.0", "@fastify/error@^3.4.0": - version "3.4.1" - resolved "https://registry.yarnpkg.com/@fastify/error/-/error-3.4.1.tgz#b14bb4cac3dd4ec614becbc643d1511331a6425c" - integrity sha512-wWSvph+29GR783IhmvdwWnN4bUxTD01Vm5Xad4i7i1VuAOItLvbPAb69sb0IQ2N57yprvhNIwAP5B6xfKTmjmQ== +"@fastify/error@^4.0.0": + version "4.0.0" + resolved "https://registry.yarnpkg.com/@fastify/error/-/error-4.0.0.tgz#7842d6161fbce78953638318be99033a0c2d5070" + integrity sha512-OO/SA8As24JtT1usTUTKgGH7uLvhfwZPwlptRi2Dp5P4KKmJI3gvsZ8MIHnNwDs4sLf/aai5LzTyl66xr7qMxA== -"@fastify/fast-json-stringify-compiler@^4.3.0": - version "4.3.0" - resolved "https://registry.yarnpkg.com/@fastify/fast-json-stringify-compiler/-/fast-json-stringify-compiler-4.3.0.tgz#5df89fa4d1592cbb8780f78998355feb471646d5" - integrity sha512-aZAXGYo6m22Fk1zZzEUKBvut/CIIQe/BapEORnxiD5Qr0kPHqqI69NtEMCme74h+at72sPhbkb4ZrLd1W3KRLA== +"@fastify/fast-json-stringify-compiler@^5.0.0": + version "5.0.1" + resolved "https://registry.yarnpkg.com/@fastify/fast-json-stringify-compiler/-/fast-json-stringify-compiler-5.0.1.tgz#659c74f3181fb4f984fe27dcc95d14366ae85ca0" + integrity sha512-f2d3JExJgFE3UbdFcpPwqNUEoHWmt8pAKf8f+9YuLESdefA0WgqxeT6DrGL4Yrf/9ihXNSKOqpjEmurV405meA== dependencies: - fast-json-stringify "^5.7.0" + fast-json-stringify "^6.0.0" -"@fastify/merge-json-schemas@^0.1.0": +"@fastify/merge-json-schemas@^0.1.1": version "0.1.1" resolved "https://registry.yarnpkg.com/@fastify/merge-json-schemas/-/merge-json-schemas-0.1.1.tgz#3551857b8a17a24e8c799e9f51795edb07baa0bc" integrity sha512-fERDVz7topgNjtXsJTTW1JKLy0rhuLRcquYqNR9rF7OcVpCa2OVW49ZPDIhaRRCaUuvVxI+N416xUoF76HNSXA== dependencies: fast-deep-equal "^3.1.3" -"@fastify/send@^2.0.0": - version "2.1.0" - resolved "https://registry.yarnpkg.com/@fastify/send/-/send-2.1.0.tgz#1aa269ccb4b0940a2dadd1f844443b15d8224ea0" - integrity sha512-yNYiY6sDkexoJR0D8IDy3aRP3+L4wdqCpvx5WP+VtEU58sn7USmKynBzDQex5X42Zzvw2gNzzYgP90UfWShLFA== +"@fastify/send@^3.1.0": + version "3.1.1" + resolved "https://registry.yarnpkg.com/@fastify/send/-/send-3.1.1.tgz#455a8fa56ae005c4c387ddf111364f346b848117" + integrity sha512-LdiV2mle/2tH8vh6GwGl0ubfUAgvY+9yF9oGI1iiwVyNUVOQamvw5n+OFu6iCNNoyuCY80FFURBn4TZCbTe8LA== dependencies: - "@lukeed/ms" "^2.0.1" + "@lukeed/ms" "^2.0.2" escape-html "~1.0.3" fast-decode-uri-component "^1.0.1" - http-errors "2.0.0" - mime "^3.0.0" - -"@fastify/static@^6.0.0": - version "6.11.2" - resolved "https://registry.yarnpkg.com/@fastify/static/-/static-6.11.2.tgz#1fe40c40daf055a28d29db807b459fcff431d9b6" - integrity sha512-EH7mh7q4MfNdT7N07ZVlwsX/ObngMvQ7KBP0FXAuPov99Fjn80KSJMdxQhhYKAKWW1jXiFdrk8X7d6uGWdZFxg== - dependencies: - "@fastify/accept-negotiator" "^1.0.0" - "@fastify/send" "^2.0.0" - content-disposition "^0.5.3" - fastify-plugin "^4.0.0" - glob "^8.0.1" - p-limit "^3.1.0" + http-errors "^2.0.0" + mime "^3" -"@fastify/swagger-ui@^1.9.3": - version "1.9.3" - resolved "https://registry.yarnpkg.com/@fastify/swagger-ui/-/swagger-ui-1.9.3.tgz#1ec03ea2595cb2e7d6de6ae7c949bebcff8370a5" - integrity sha512-YYqce4CydjDIEry6Zo4JLjVPe5rjS8iGnk3fHiIQnth9sFSLeyG0U1DCH+IyYmLddNDg1uWJOuErlVqnu/jI3w== +"@fastify/static@^8.0.0": + version "8.0.1" + resolved "https://registry.yarnpkg.com/@fastify/static/-/static-8.0.1.tgz#137059a4625c64cce8ee7eb513961c5e23018805" + integrity sha512-7idyhbcgf14v4bjWzUeHEFvnVxvNJ1n5cyGPgFtwTZjnjUQ1wgC7a2FQai7OGKqCKywDEjzbPhAZRW+uEK1LMg== dependencies: - "@fastify/static" "^6.0.0" - fastify-plugin "^4.0.0" - openapi-types "^12.0.2" - rfdc "^1.3.0" - yaml "^2.2.2" + "@fastify/accept-negotiator" "^2.0.0" + "@fastify/send" "^3.1.0" + content-disposition "^0.5.4" + fastify-plugin "^5.0.0" + fastq "^1.17.1" + glob "^11.0.0" -"@fastify/swagger@^8.10.0": - version "8.10.0" - resolved "https://registry.yarnpkg.com/@fastify/swagger/-/swagger-8.10.0.tgz#d978ae9f2d802ab652955d02be7a125f7f6d9f05" - integrity sha512-0o6nd0qWpJbVSv/vbK4bzHSYe7l+PTGPqrQVwWIXVGd7CvXr585SBx+h8EgrMOY80bcOnGreqnjYFOV0osGP5A== +"@fastify/swagger-ui@^5.0.1": + version "5.0.1" + resolved "https://registry.yarnpkg.com/@fastify/swagger-ui/-/swagger-ui-5.0.1.tgz#76c348bbaf7e49e3cfb62ebe3cc3fb15ef0eefb3" + integrity sha512-nCDV5l0OTziK8nIeHaLZ30ENFFftZ4Pcs7GHDcqOO6Jp3qSnyOsqBg1/EosM+d1mrCvH4vSlM09xolkjrbuJQQ== dependencies: - fastify-plugin "^4.0.0" + "@fastify/static" "^8.0.0" + fastify-plugin "^5.0.0" + openapi-types "^12.1.3" + rfdc "^1.3.1" + yaml "^2.4.1" + +"@fastify/swagger@^9.0.0": + version "9.0.0" + resolved "https://registry.yarnpkg.com/@fastify/swagger/-/swagger-9.0.0.tgz#a6013ee3cf4ec0f2562e1455face9eb6ef787d89" + integrity sha512-E7TQbBCbhvS2djGLxJ7t2OFbhc2F+KCsOZCNhh6xQIlJxq9H4ZR5KuLKG+vn6COVqkLxRVUOZ9qtbbzdf5Jfqw== + dependencies: + fastify-plugin "^5.0.0" json-schema-resolver "^2.0.0" - openapi-types "^12.0.0" - rfdc "^1.3.0" - yaml "^2.2.2" + openapi-types "^12.1.3" + rfdc "^1.3.1" + yaml "^2.4.2" "@gar/promisify@^1.0.1", "@gar/promisify@^1.1.3": version "1.1.3" @@ -1857,10 +1853,10 @@ race-signal "^1.0.2" uint8arraylist "^2.4.8" -"@lukeed/ms@^2.0.1": - version "2.0.1" - resolved "https://registry.yarnpkg.com/@lukeed/ms/-/ms-2.0.1.tgz#3c2bbc258affd9cc0e0cc7828477383c73afa6ee" - integrity sha512-Xs/4RZltsAL7pkvaNStUQt7netTkyxrS0K+RILcVr3TRMS/ToOg4I6uNfhB9SlGsnWBym4U+EaXq0f0cEMNkHA== +"@lukeed/ms@^2.0.2": + version "2.0.2" + resolved "https://registry.yarnpkg.com/@lukeed/ms/-/ms-2.0.2.tgz#07f09e59a74c52f4d88c6db5c1054e819538e2a8" + integrity sha512-9I2Zn6+NJLfaGoz9jN3lpwDgAYvfGeNYdbAIjJOqzs4Tpc+VU3Jqq4IofSUBKajiDS8k9fZIg18/z13mpk1bsA== "@microsoft/api-extractor-model@7.28.13": version "7.28.13" @@ -3887,10 +3883,10 @@ aggregate-error@^3.0.0: clean-stack "^2.0.0" indent-string "^4.0.0" -ajv-formats@^2.1.1: - version "2.1.1" - resolved "https://registry.yarnpkg.com/ajv-formats/-/ajv-formats-2.1.1.tgz#6e669400659eb74973bbf2e33327180a0996b520" - integrity sha512-Wx0Kx52hxE7C18hkMEggYlEifqWZtYaRgouJor+WMdPnQyEK13vgEWyVNup7SoeeoLMsr4kf5h6dOW11I15MUA== +ajv-formats@^3.0.1: + version "3.0.1" + resolved "https://registry.yarnpkg.com/ajv-formats/-/ajv-formats-3.0.1.tgz#3d5dc762bca17679c3c2ea7e90ad6b7532309578" + integrity sha512-8iUql50EUR+uUcdRQ3HDqa6EVyo3docL8g5WJ3FNcWmu62IbkGUue/pEyLBW8VGKKucTPgqeks4fIU1DA4yowQ== dependencies: ajv "^8.0.0" @@ -3904,7 +3900,7 @@ ajv@^6.12.4, ajv@~6.12.6: json-schema-traverse "^0.4.1" uri-js "^4.2.2" -ajv@^8.0.0, ajv@^8.10.0, ajv@^8.11.0, ajv@^8.12.0: +ajv@^8.0.0, ajv@^8.12.0: version "8.12.0" resolved "https://registry.yarnpkg.com/ajv/-/ajv-8.12.0.tgz#d1a0527323e22f53562c567c00991577dfbe19d1" integrity sha512-sRu1kpcO9yLtYxBKvqfTeh9KzZEwO3STyX1HT+4CaDzC6HpTGYhIhPIzj9XuKU7KYDwnaeh5hcOwjy1QuJzBPA== @@ -4060,11 +4056,6 @@ archiver@^7.0.0: tar-stream "^3.0.0" zip-stream "^6.0.1" -archy@^1.0.0: - version "1.0.0" - resolved "https://registry.npmjs.org/archy/-/archy-1.0.0.tgz" - integrity sha1-+cjBN1fMHde8N5rHeyxipcKGjEA= - are-we-there-yet@^3.0.0: version "3.0.0" resolved "https://registry.npmjs.org/are-we-there-yet/-/are-we-there-yet-3.0.0.tgz" @@ -4287,14 +4278,12 @@ available-typed-arrays@^1.0.5: resolved "https://registry.yarnpkg.com/available-typed-arrays/-/available-typed-arrays-1.0.5.tgz#92f95616501069d07d10edb2fc37d3e1c65123b7" integrity sha512-DMD0KiN46eipeziST1LPP/STfDU0sufISXmjSgvVsoU2tqxctQeASejWcfNtxYKqETM1UxQ8sp2OrSBWpHY6sw== -avvio@^8.3.0: - version "8.3.0" - resolved "https://registry.yarnpkg.com/avvio/-/avvio-8.3.0.tgz#1e019433d935730b814978a583eefac41a65082f" - integrity sha512-VBVH0jubFr9LdFASy/vNtm5giTrnbVquWBhT0fyizuNK2rQ7e7ONU2plZQWUNqtE1EmxFEb+kbSkFRkstiaS9Q== +avvio@^9.0.0: + version "9.0.0" + resolved "https://registry.yarnpkg.com/avvio/-/avvio-9.0.0.tgz#3ae02fb318377006e0e06a3f47842c98d8668607" + integrity sha512-UbYrOXgE/I+knFG+3kJr9AgC7uNo8DG+FGGODpH9Bj1O1kL/QDjBXnTem9leD3VdQKtaHjV3O85DQ7hHh4IIHw== dependencies: - "@fastify/error" "^3.3.0" - archy "^1.0.0" - debug "^4.0.0" + "@fastify/error" "^4.0.0" fastq "^1.17.1" aws-sdk@^2.932.0: @@ -5236,7 +5225,7 @@ constants-browserify@^1.0.0: resolved "https://registry.npmjs.org/constants-browserify/-/constants-browserify-1.0.0.tgz" integrity sha1-wguW2MYXdIqvHBYCF2DNJ/y4y3U= -content-disposition@^0.5.3: +content-disposition@^0.5.4: version "0.5.4" resolved "https://registry.yarnpkg.com/content-disposition/-/content-disposition-0.5.4.tgz#8b82b4efac82512a02bb0b1dcec9d2c5e8eb5bfe" integrity sha512-FveZTNuGw04cxlAiWbzi6zTAL/lhehaWbTtgluJh4/E95DqMwTmha3KZN1aAWA8cFIhHzMZUvLevkw5Rqk+tSQ== @@ -5558,7 +5547,7 @@ de-indent@^1.0.2: resolved "https://registry.yarnpkg.com/de-indent/-/de-indent-1.0.2.tgz#b2038e846dc33baa5796128d0804b455b8c1e21d" integrity sha512-e/1zu3xH5MQryN2zdVaF0OrdNLUbvWxzMbi+iNA6Bky7l1RoP8a2fIbRocyHclXt/arDrrR6lL3TqFD9pMQTsg== -debug@4, debug@4.3.4, debug@^4.0.0, debug@^4.1.0, debug@^4.1.1, debug@^4.2.0, debug@^4.3.1, debug@^4.3.2, debug@^4.3.3, debug@^4.3.4: +debug@4, debug@4.3.4, debug@^4.1.0, debug@^4.1.1, debug@^4.2.0, debug@^4.3.1, debug@^4.3.2, debug@^4.3.3, debug@^4.3.4: version "4.3.4" resolved "https://registry.yarnpkg.com/debug/-/debug-4.3.4.tgz#1319f6579357f2338d3337d2cdd4914bb5dcc865" integrity sha512-PRWFHuSU3eDtQJPvnNY7Jcket1j0t5OuOsFzPPzsekD52Zl8qUfFIPEiswXqIvHWGVHOgX+7G/vCNNhehwxfkQ== @@ -6568,11 +6557,6 @@ extract-zip@^2.0.1: optionalDependencies: "@types/yauzl" "^2.9.1" -fast-content-type-parse@^1.1.0: - version "1.1.0" - resolved "https://registry.yarnpkg.com/fast-content-type-parse/-/fast-content-type-parse-1.1.0.tgz#4087162bf5af3294d4726ff29b334f72e3a1092c" - integrity sha512-fBHHqSTFLVnR61C+gltJuE5GkVQMV0S2nqUO8TJ+5Z3qAKG8vAx4FKai1s5jq/inV1+sREynIWSuQ6HgoSXpDQ== - fast-decode-uri-component@^1.0.1: version "1.0.1" resolved "https://registry.npmjs.org/fast-decode-uri-component/-/fast-decode-uri-component-1.0.1.tgz" @@ -6614,28 +6598,16 @@ fast-json-stable-stringify@^2.0.0: resolved "https://registry.yarnpkg.com/fast-json-stable-stringify/-/fast-json-stable-stringify-2.1.0.tgz#874bf69c6f404c2b5d99c481341399fd55892633" integrity sha512-lhd/wF+Lk98HZoTCtlVraHtfh5XYijIjalXck7saUtuanSDyLMxnHhSXEDJqHxD7msR8D0uCmqlkwjCV8xvwHw== -fast-json-stringify@^5.7.0: - version "5.7.0" - resolved "https://registry.yarnpkg.com/fast-json-stringify/-/fast-json-stringify-5.7.0.tgz#b0a04c848fdeb6ecd83440c71a4db35067023bed" - integrity sha512-sBVPTgnAZseLu1Qgj6lUbQ0HfjFhZWXAmpZ5AaSGkyLh5gAXBga/uPJjQPHpDFjC9adWIpdOcCLSDTgrZ7snoQ== - dependencies: - "@fastify/deepmerge" "^1.0.0" - ajv "^8.10.0" - ajv-formats "^2.1.1" - fast-deep-equal "^3.1.3" - fast-uri "^2.1.0" - rfdc "^1.2.0" - -fast-json-stringify@^5.8.0: - version "5.13.0" - resolved "https://registry.yarnpkg.com/fast-json-stringify/-/fast-json-stringify-5.13.0.tgz#3eafc02168713ef934d75000a8cf749492729fe8" - integrity sha512-XjTDWKHP3GoMQUOfnjYUbqeHeEt+PvYgvBdG2fRSmYaORILbSr8xTJvZX+w1YSAP5pw2NwKrGRmQleYueZEoxw== +fast-json-stringify@^6.0.0: + version "6.0.0" + resolved "https://registry.yarnpkg.com/fast-json-stringify/-/fast-json-stringify-6.0.0.tgz#15c5e85b567ead695773bf55938b56aaaa57d805" + integrity sha512-FGMKZwniMTgZh7zQp9b6XnBVxUmKVahQLQeRQHqwYmPDqDhcEKZ3BaQsxelFFI5PY7nN71OEeiL47/zUWcYe1A== dependencies: - "@fastify/merge-json-schemas" "^0.1.0" - ajv "^8.10.0" - ajv-formats "^2.1.1" + "@fastify/merge-json-schemas" "^0.1.1" + ajv "^8.12.0" + ajv-formats "^3.0.1" fast-deep-equal "^3.1.3" - fast-uri "^2.1.0" + fast-uri "^2.3.0" json-schema-ref-resolver "^1.0.1" rfdc "^1.2.0" @@ -6661,37 +6633,41 @@ fast-safe-stringify@^2.1.1: resolved "https://registry.yarnpkg.com/fast-safe-stringify/-/fast-safe-stringify-2.1.1.tgz#c406a83b6e70d9e35ce3b30a81141df30aeba884" integrity sha512-W+KJc2dmILlPplD/H4K9l9LcAHAfPtP6BY84uVLXQ6Evcz9Lcg33Y2z1IVblT6xdY54PXYVHEv+0Wpq8Io6zkA== -fast-uri@^2.0.0, fast-uri@^2.1.0: - version "2.2.0" - resolved "https://registry.yarnpkg.com/fast-uri/-/fast-uri-2.2.0.tgz#519a0f849bef714aad10e9753d69d8f758f7445a" - integrity sha512-cIusKBIt/R/oI6z/1nyfe2FvGKVTohVRfvkOhvx0nCEW+xf5NoCXjAHcWp93uOUBchzYcsvPlrapAdX1uW+YGg== +fast-uri@^2.3.0: + version "2.4.0" + resolved "https://registry.yarnpkg.com/fast-uri/-/fast-uri-2.4.0.tgz#67eae6fbbe9f25339d5d3f4c4234787b65d7d55e" + integrity sha512-ypuAmmMKInk5q7XcepxlnUWDLWv4GFtaJqAzWKqn62IpQ3pejtr5dTVbt3vwqVaMKmkNR55sTT+CqUKIaT21BA== -fastify-plugin@^4.0.0: - version "4.5.0" - resolved "https://registry.yarnpkg.com/fastify-plugin/-/fastify-plugin-4.5.0.tgz#8b853923a0bba6ab6921bb8f35b81224e6988d91" - integrity sha512-79ak0JxddO0utAXAQ5ccKhvs6vX2MGyHHMMsmZkBANrq3hXc1CHzvNPHOcvTsVMEPl5I+NT+RO4YKMGehOfSIg== +fast-uri@^3.0.0: + version "3.0.1" + resolved "https://registry.yarnpkg.com/fast-uri/-/fast-uri-3.0.1.tgz#cddd2eecfc83a71c1be2cc2ef2061331be8a7134" + integrity sha512-MWipKbbYiYI0UC7cl8m/i/IWTqfC8YXsqjzybjddLsFjStroQzsHXkc73JutMvBiXmOvapk+axIl79ig5t55Bw== -fastify@^4.27.0: - version "4.27.0" - resolved "https://registry.yarnpkg.com/fastify/-/fastify-4.27.0.tgz#e4a9b2a0a7b9efaeaf1140d47fdd4f91b5fcacb1" - integrity sha512-ci9IXzbigB8dyi0mSy3faa3Bsj0xWAPb9JeT4KRzubdSb6pNhcADRUaXCBml6V1Ss/a05kbtQls5LBmhHydoTA== +fastify-plugin@^5.0.0: + version "5.0.1" + resolved "https://registry.yarnpkg.com/fastify-plugin/-/fastify-plugin-5.0.1.tgz#82d44e6fe34d1420bb5a4f7bee434d501e41939f" + integrity sha512-HCxs+YnRaWzCl+cWRYFnHmeRFyR5GVnJTAaCJQiYzQSDwK9MgJdyAsuL3nh0EWRCYMgQ5MeziymvmAhUHYHDUQ== + +fastify@^5.0.0: + version "5.0.0" + resolved "https://registry.yarnpkg.com/fastify/-/fastify-5.0.0.tgz#f8f80bd741bde2de1997c25dbe31e61c91978111" + integrity sha512-Qe4dU+zGOzg7vXjw4EvcuyIbNnMwTmcuOhlOrOJsgwzvjEZmsM/IeHulgJk+r46STjdJS/ZJbxO8N70ODXDMEQ== dependencies: - "@fastify/ajv-compiler" "^3.5.0" - "@fastify/error" "^3.4.0" - "@fastify/fast-json-stringify-compiler" "^4.3.0" + "@fastify/ajv-compiler" "^4.0.0" + "@fastify/error" "^4.0.0" + "@fastify/fast-json-stringify-compiler" "^5.0.0" abstract-logging "^2.0.1" - avvio "^8.3.0" - fast-content-type-parse "^1.1.0" - fast-json-stringify "^5.8.0" - find-my-way "^8.0.0" - light-my-request "^5.11.0" + avvio "^9.0.0" + fast-json-stringify "^6.0.0" + find-my-way "^9.0.0" + light-my-request "^6.0.0" pino "^9.0.0" - process-warning "^3.0.0" + process-warning "^4.0.0" proxy-addr "^2.0.7" - rfdc "^1.3.0" + rfdc "^1.3.1" secure-json-parse "^2.7.0" - semver "^7.5.4" - toad-cache "^3.3.0" + semver "^7.6.0" + toad-cache "^3.7.0" fastq@^1.17.1: version "1.17.1" @@ -6782,14 +6758,14 @@ fill-range@^7.1.1: dependencies: to-regex-range "^5.0.1" -find-my-way@^8.0.0: - version "8.2.2" - resolved "https://registry.yarnpkg.com/find-my-way/-/find-my-way-8.2.2.tgz#f3e78bc6ead2da4fdaa201335da3228600ed0285" - integrity sha512-Dobi7gcTEq8yszimcfp/R7+owiT4WncAJ7VTTgFH1jYJ5GaG1FbhjwDG820hptN0QDFvzVY3RfCzdInvGPGzjA== +find-my-way@^9.0.0: + version "9.0.1" + resolved "https://registry.yarnpkg.com/find-my-way/-/find-my-way-9.0.1.tgz#991c3a7af36734480d48cd4ad0889ed168ed6c40" + integrity sha512-/5NN/R0pFWuff16TMajeKt2JyiW+/OE8nOO8vo1DwZTxLaIURb7lcBYPIgRPh61yCNh9l8voeKwcrkUzmB00vw== dependencies: fast-deep-equal "^3.1.3" fast-querystring "^1.0.0" - safe-regex2 "^3.1.0" + safe-regex2 "^4.0.0" find-up@5.0.0, find-up@^5.0.0: version "5.0.0" @@ -7277,6 +7253,18 @@ glob@^10.4.1: package-json-from-dist "^1.0.0" path-scurry "^1.11.1" +glob@^11.0.0: + version "11.0.0" + resolved "https://registry.yarnpkg.com/glob/-/glob-11.0.0.tgz#6031df0d7b65eaa1ccb9b29b5ced16cea658e77e" + integrity sha512-9UiX/Bl6J2yaBbxKoEBRm4Cipxgok8kQYcOPEhScPwebu2I0HoQOuYdIO6S3hLuWoZgpDpwQZMzTFxgpkyT76g== + dependencies: + foreground-child "^3.1.0" + jackspeak "^4.0.1" + minimatch "^10.0.0" + minipass "^7.1.2" + package-json-from-dist "^1.0.0" + path-scurry "^2.0.0" + glob@^7.1.3, glob@^7.1.4: version "7.2.3" resolved "https://registry.yarnpkg.com/glob/-/glob-7.2.3.tgz#b8df0fb802bbfa8e89bd1d938b4e16578ed44f2b" @@ -7573,7 +7561,7 @@ http-cache-semantics@^4.0.0, http-cache-semantics@^4.1.0, http-cache-semantics@^ resolved "https://registry.yarnpkg.com/http-cache-semantics/-/http-cache-semantics-4.1.1.tgz#abe02fcb2985460bf0323be664436ec3476a6d5a" integrity sha512-er295DKPVsV82j5kw1Gjt+ADA/XYHsajl82cGNQG2eyoPkvgUhX+nDIyelzhIWbbsXP39EHcI6l5tYs2FYqYXQ== -http-errors@2.0.0: +http-errors@^2.0.0: version "2.0.0" resolved "https://registry.yarnpkg.com/http-errors/-/http-errors-2.0.0.tgz#b7774a1486ef73cf7667ac9ae0858c012c57b9d3" integrity sha512-FtwrG/euBzaEjYeRqOgly7G0qviiXoJWnvEH2Z1plBdXgbyjv34pHTSb9zoeHMyDy33+DWy5Wt9Wo+TURtOYSQ== @@ -8440,6 +8428,15 @@ jackspeak@^3.1.2: optionalDependencies: "@pkgjs/parseargs" "^0.11.0" +jackspeak@^4.0.1: + version "4.0.1" + resolved "https://registry.yarnpkg.com/jackspeak/-/jackspeak-4.0.1.tgz#9fca4ce961af6083e259c376e9e3541431f5287b" + integrity sha512-cub8rahkh0Q/bw1+GxP7aeSe29hHHn2V4m29nnDlvCdlgU+3UGxkZp7Z53jLUdpX3jdTO0nJZUDl3xvbWc2Xog== + dependencies: + "@isaacs/cliui" "^8.0.2" + optionalDependencies: + "@pkgjs/parseargs" "^0.11.0" + jake@^10.8.5: version "10.8.5" resolved "https://registry.yarnpkg.com/jake/-/jake-10.8.5.tgz#f2183d2c59382cb274226034543b9c03b8164c46" @@ -8829,14 +8826,14 @@ libp2p@1.4.3: multiformats "^13.1.0" uint8arrays "^5.0.3" -light-my-request@^5.11.0: - version "5.12.0" - resolved "https://registry.yarnpkg.com/light-my-request/-/light-my-request-5.12.0.tgz#e42ed02ddbfa587f82031b21459c6841a6948dfa" - integrity sha512-P526OX6E7aeCIfw/9UyJNsAISfcFETghysaWHQAlQYayynShT08MOj4c6fBCvTWBrHXSvqBAKDp3amUPSCQI4w== +light-my-request@^6.0.0: + version "6.0.0" + resolved "https://registry.yarnpkg.com/light-my-request/-/light-my-request-6.0.0.tgz#97c6d0d5448ea2fc37836f0aefe94298f5a87dde" + integrity sha512-kFkFXrmKCL0EEeOmJybMH5amWFd+AFvlvMlvFTRxCUwbhfapZqDmeLMPoWihntnYY6JpoQDE9k+vOzObF1fDqg== dependencies: cookie "^0.6.0" - process-warning "^3.0.0" - set-cookie-parser "^2.4.1" + process-warning "^4.0.0" + set-cookie-parser "^2.6.0" lines-and-columns@^1.1.6: version "1.2.4" @@ -9066,6 +9063,11 @@ lru-cache@^10.2.0: resolved "https://registry.yarnpkg.com/lru-cache/-/lru-cache-10.4.3.tgz#410fc8a17b70e598013df257c2446b7f3383f119" integrity sha512-JNAzZcXrCt42VGLuYz0zfAzDfAvJWW6AfYlDBQyDV5DClI2m5sAmK+OIO7s59XfsRsWHp02jAJrRadPRGTt6SQ== +lru-cache@^11.0.0: + version "11.0.1" + resolved "https://registry.yarnpkg.com/lru-cache/-/lru-cache-11.0.1.tgz#3a732fbfedb82c5ba7bca6564ad3f42afcb6e147" + integrity sha512-CgeuL5uom6j/ZVrg7G/+1IXqRY8JXX4Hghfy5YE0EhoYQWvndP1kufu58cmZLNIDKnRhZrXfdS9urVWx98AipQ== + lru-cache@^5.1.1: version "5.1.1" resolved "https://registry.yarnpkg.com/lru-cache/-/lru-cache-5.1.1.tgz#1da27e6710271947695daf6848e847f01d84b920" @@ -9320,7 +9322,7 @@ mime@2.6.0: resolved "https://registry.yarnpkg.com/mime/-/mime-2.6.0.tgz#a2a682a95cd4d0cb1d6257e28f83da7e35800367" integrity sha512-USPkMeET31rOMiarsBNIHZKLGgvKc/LrjofAnBlOttf5ajRvqiRA8QsenbcooctK6d6Ts6aqZXBA+XbkKthiQg== -mime@^3.0.0: +mime@^3: version "3.0.0" resolved "https://registry.yarnpkg.com/mime/-/mime-3.0.0.tgz#b374550dca3a0c18443b0c950a6a58f1931cf7a7" integrity sha512-jSCU7/VB1loIWBZe14aEYHU/+1UMEHoaO7qxCOVJOw9GgH72VAWppxNcjU+x9a2k3GSIBXNKxXQFqRvvZ7vr3A== @@ -9386,6 +9388,13 @@ minimatch@9.0.3, minimatch@^9.0.0, minimatch@^9.0.1: dependencies: brace-expansion "^2.0.1" +minimatch@^10.0.0: + version "10.0.1" + resolved "https://registry.yarnpkg.com/minimatch/-/minimatch-10.0.1.tgz#ce0521856b453c86e25f2c4c0d03e6ff7ddc440b" + integrity sha512-ethXTt3SGGR+95gudmqJ1eNhRO7eGEGIgYA9vnPatK4/etz2MEVDno5GMCibdMTuBMyElzIlgxMna3K94XDIDQ== + dependencies: + brace-expansion "^2.0.1" + minimatch@^3.0.4, minimatch@^3.0.5, minimatch@^3.1.1, minimatch@^3.1.2: version "3.1.2" resolved "https://registry.yarnpkg.com/minimatch/-/minimatch-3.1.2.tgz#19cd194bfd3e428f049a70817c038d89ab4be35b" @@ -9568,10 +9577,10 @@ mkdirp@^1.0.3, mkdirp@^1.0.4: resolved "https://registry.yarnpkg.com/mkdirp/-/mkdirp-1.0.4.tgz#3eb5ed62622756d79a5f0e2a221dfebad75c2f7e" integrity sha512-vVqVZQyf3WLx2Shd0qJ9xuvqgAyKPLAiqITEtqW0oIUjzo3PePDd6fW9iFz30ef7Ysp/oiWqbhszeGWW2T6Gzw== -mnemonist@0.39.5: - version "0.39.5" - resolved "https://registry.yarnpkg.com/mnemonist/-/mnemonist-0.39.5.tgz#5850d9b30d1b2bc57cc8787e5caa40f6c3420477" - integrity sha512-FPUtkhtJ0efmEFGpU14x7jGbTB+s18LrzRL2KgoWz9YvcY3cPomz8tih01GbHwnGk/OmkOKfqd/RAQoc8Lm7DQ== +mnemonist@0.39.8: + version "0.39.8" + resolved "https://registry.yarnpkg.com/mnemonist/-/mnemonist-0.39.8.tgz#9078cd8386081afd986cca34b52b5d84ea7a4d38" + integrity sha512-vyWo2K3fjrUw8YeeZ1zF0fy6Mu59RHokURlld8ymdUPjMlD9EC9ov1/YPqTgqRvUN9nTr3Gqfz29LYAmu0PHPQ== dependencies: obliterator "^2.0.1" @@ -10276,7 +10285,7 @@ open@^8.4.0: is-docker "^2.1.1" is-wsl "^2.2.0" -openapi-types@^12.0.0, openapi-types@^12.0.2: +openapi-types@^12.1.3: version "12.1.3" resolved "https://registry.yarnpkg.com/openapi-types/-/openapi-types-12.1.3.tgz#471995eb26c4b97b7bd356aacf7b91b73e777dd3" integrity sha512-N4YtSYJqghVu4iek2ZUvcN/0aqH1kRDuNqzcycDxhOUpg7GdvLa2F3DgS6yBNhInhv2r/6I0Flkn7CqL8+nIcw== @@ -10372,7 +10381,7 @@ p-limit@^2.2.0: dependencies: p-try "^2.0.0" -p-limit@^3.0.2, p-limit@^3.1.0: +p-limit@^3.0.2: version "3.1.0" resolved "https://registry.npmjs.org/p-limit/-/p-limit-3.1.0.tgz" integrity sha512-TYOanM3wGwNGsZN2cVTYPArw454xnXj5qmWF1bEoAc4+cU/ol7GVh7odevjp1FNHduHc3KZMcFduxU5Xc6uJRQ== @@ -10660,6 +10669,14 @@ path-scurry@^1.11.1: lru-cache "^10.2.0" minipass "^5.0.0 || ^6.0.2 || ^7.0.0" +path-scurry@^2.0.0: + version "2.0.0" + resolved "https://registry.yarnpkg.com/path-scurry/-/path-scurry-2.0.0.tgz#9f052289f23ad8bf9397a2a0425e7b8615c58580" + integrity sha512-ypGJsmGtdXUOeM5u93TyeIEfEhM6s+ljAhrk5vAvSx8uyY/02OvrZnA0YNGUrPXfpJMgI1ODd3nwz8Npx4O4cg== + dependencies: + lru-cache "^11.0.0" + minipass "^7.1.2" + path-to-regexp@^6.2.0: version "6.3.0" resolved "https://registry.yarnpkg.com/path-to-regexp/-/path-to-regexp-6.3.0.tgz#2b6a26a337737a8e1416f9272ed0766b1c0389f4" @@ -10846,6 +10863,11 @@ process-warning@^3.0.0: resolved "https://registry.yarnpkg.com/process-warning/-/process-warning-3.0.0.tgz#96e5b88884187a1dce6f5c3166d611132058710b" integrity sha512-mqn0kFRl0EoqhnL0GQ0veqFHyIN1yig9RHh/InzORTUiZHFRAur+aMtRkELNwGs9aNwKS6tg/An4NYBPGwvtzQ== +process-warning@^4.0.0: + version "4.0.0" + resolved "https://registry.yarnpkg.com/process-warning/-/process-warning-4.0.0.tgz#581e3a7a1fb456c5f4fd239f76bce75897682d5a" + integrity sha512-/MyYDxttz7DfGMMHiysAsFE4qF+pQYAA8ziO/3NcRVrQ5fSk+Mns4QZA/oRPFzvcqNoVJXQNWNAsdwBXLUkQKw== + process@^0.11.10: version "0.11.10" resolved "https://registry.yarnpkg.com/process/-/process-0.11.10.tgz#7332300e840161bda3e69a1d1d91a7d4bc16f182" @@ -11358,10 +11380,10 @@ restore-cursor@^4.0.0: onetime "^5.1.0" signal-exit "^3.0.2" -ret@~0.4.0: - version "0.4.3" - resolved "https://registry.yarnpkg.com/ret/-/ret-0.4.3.tgz#5243fa30e704a2e78a9b9b1e86079e15891aa85c" - integrity sha512-0f4Memo5QP7WQyUEAYUO3esD/XjOc3Zjjg5CPsAq1p8sIu0XPeMbHJemKA0BO7tV0X7+A0FoEpbmHXWxPyD3wQ== +ret@~0.5.0: + version "0.5.0" + resolved "https://registry.yarnpkg.com/ret/-/ret-0.5.0.tgz#30a4d38a7e704bd96dc5ffcbe7ce2a9274c41c95" + integrity sha512-I1XxrZSQ+oErkRR4jYbAyEEu2I0avBvvMM5JN+6EBprOGRCs63ENqZ3vjavq8fBw2+62G5LF5XelKwuJpcvcxw== retry@^0.12.0: version "0.12.0" @@ -11387,10 +11409,10 @@ rewiremock@^3.14.5: wipe-node-cache "^2.1.2" wipe-webpack-cache "^2.1.0" -rfdc@^1.1.4, rfdc@^1.2.0, rfdc@^1.3.0: - version "1.3.0" - resolved "https://registry.npmjs.org/rfdc/-/rfdc-1.3.0.tgz" - integrity sha512-V2hovdzFbOi77/WajaSMXk2OLm+xNIeQdMMuB7icj7bk6zi2F8GGAxigcnDFpJHbNyNcgyJDiP+8nOrY5cZGrA== +rfdc@^1.1.4, rfdc@^1.2.0, rfdc@^1.3.1: + version "1.4.1" + resolved "https://registry.yarnpkg.com/rfdc/-/rfdc-1.4.1.tgz#778f76c4fb731d93414e8f925fbecf64cce7f6ca" + integrity sha512-q1b3N5QkRUWUl7iyylaaj3kOpIT0N2i9MqIEQXP73GVsN9cw3fdx8X63cEmWhJGi2PPCF23Ijp7ktmd39rawIA== rgb2hex@0.2.5: version "0.2.5" @@ -11550,12 +11572,12 @@ safe-regex-test@^1.0.0: get-intrinsic "^1.1.3" is-regex "^1.1.4" -safe-regex2@^3.1.0: - version "3.1.0" - resolved "https://registry.yarnpkg.com/safe-regex2/-/safe-regex2-3.1.0.tgz#fd7ec23908e2c730e1ce7359a5b72883a87d2763" - integrity sha512-RAAZAGbap2kBfbVhvmnTFv73NWLMvDGOITFYTZBAaY8eR+Ir4ef7Up/e7amo+y1+AH+3PtLkrt9mvcTsG9LXug== +safe-regex2@^4.0.0: + version "4.0.0" + resolved "https://registry.yarnpkg.com/safe-regex2/-/safe-regex2-4.0.0.tgz#5e04d8362cd4884753c8bce9715d4759a5239c0a" + integrity sha512-Hvjfv25jPDVr3U+4LDzBuZPPOymELG3PYcSk5hcevooo1yxxamQL/bHs/GrEPGmMoMEwRrHVGiCA1pXi97B8Ew== dependencies: - ret "~0.4.0" + ret "~0.5.0" safe-stable-stringify@^2.3.1: version "2.4.2" @@ -11654,10 +11676,10 @@ set-blocking@^2.0.0: resolved "https://registry.npmjs.org/set-blocking/-/set-blocking-2.0.0.tgz" integrity sha1-BF+XgtARrppoA93TgrJDkrPYkPc= -set-cookie-parser@^2.4.1: - version "2.4.8" - resolved "https://registry.npmjs.org/set-cookie-parser/-/set-cookie-parser-2.4.8.tgz" - integrity sha512-edRH8mBKEWNVIVMKejNnuJxleqYE/ZSdcT8/Nem9/mmosx12pctd80s2Oy00KNZzrogMZS5mauK2/ymL1bvlvg== +set-cookie-parser@^2.6.0: + version "2.7.0" + resolved "https://registry.yarnpkg.com/set-cookie-parser/-/set-cookie-parser-2.7.0.tgz#ef5552b56dc01baae102acb5fc9fb8cd060c30f9" + integrity sha512-lXLOiqpkUumhRdFF3k1osNXCy9akgx/dyPZ5p8qAg9seJzXr5ZrlqZuWIMuY6ejOsVLE6flJ5/h3lsn57fQ/PQ== set-function-length@^1.1.1: version "1.2.0" @@ -12529,7 +12551,7 @@ to-regex-range@^5.0.1: dependencies: is-number "^7.0.0" -toad-cache@^3.3.0: +toad-cache@^3.7.0: version "3.7.0" resolved "https://registry.yarnpkg.com/toad-cache/-/toad-cache-3.7.0.tgz#b9b63304ea7c45ec34d91f1d2fa513517025c441" integrity sha512-/m8M+2BJUpoJdgAHoG+baCwBT+tf2VraSfkBgl0Y00qIWt41DJ8R5B8nsEw0I58YwF5IZH6z24/2TobDKnqSWw== @@ -13843,10 +13865,10 @@ yallist@^4.0.0: resolved "https://registry.yarnpkg.com/yallist/-/yallist-4.0.0.tgz#9bb92790d9c0effec63be73519e11a35019a3a72" integrity sha512-3wdGidZyq5PB084XLES5TpOSRA3wjXAlIWMhum2kRcv/41Sn2emQ0dycQW4uZXLejwKvg6EsvbdlVL+FYEct7A== -yaml@^2.2.2: - version "2.3.2" - resolved "https://registry.yarnpkg.com/yaml/-/yaml-2.3.2.tgz#f522db4313c671a0ca963a75670f1c12ea909144" - integrity sha512-N/lyzTPaJasoDmfV7YTrYCI0G/3ivm/9wdG0aHuheKowWQwGTsK0Eoiw6utmzAnI6pkJa0DUVygvp3spqqEKXg== +yaml@^2.2.2, yaml@^2.4.1, yaml@^2.4.2: + version "2.5.1" + resolved "https://registry.yarnpkg.com/yaml/-/yaml-2.5.1.tgz#c9772aacf62cb7494a95b0c4f1fb065b563db130" + integrity sha512-bLQOjaX/ADgQ20isPJRvF0iRUHIxVhYvr53Of7wGcWlO2jvtUlH5m87DsmulFVxRpNLOnI4tB6p/oh8D7kpn9Q== yargs-parser@20.2.4: version "20.2.4" From ad4ec7713d0ab39c54ea1ffa28d6f6f997769fa0 Mon Sep 17 00:00:00 2001 From: NC <17676176+ensi321@users.noreply.github.com> Date: Tue, 24 Sep 2024 18:33:43 -0700 Subject: [PATCH 18/52] feat: move requests from execution payload to beacon block body (#7094) * Move requests from payload to block body * Lint * Add execution requests to engine api * Remove engine_getPayloadBodies*V2 * Update spec test version * Lint * Fix unit test and polish * Remove todo --- .../blocks/verifyBlocksExecutionPayloads.ts | 7 +- .../chain/produceBlock/produceBlockBody.ts | 10 +- .../beacon-node/src/execution/engine/http.ts | 41 ++++-- .../src/execution/engine/interface.ts | 10 +- .../beacon-node/src/execution/engine/mock.ts | 2 - .../src/execution/engine/payloadIdCache.ts | 20 --- .../beacon-node/src/execution/engine/types.ts | 135 ++++++++---------- .../test/sim/electra-interop.test.ts | 8 +- .../test/spec/specTestVersioning.ts | 2 +- .../test/spec/utils/specTestIterator.ts | 2 + .../upgradeLightClientHeader.test.ts | 2 +- .../test/unit/executionEngine/http.test.ts | 12 -- packages/light-client/src/spec/utils.ts | 17 +-- .../src/block/processOperations.ts | 6 +- .../src/slot/upgradeStateToElectra.ts | 9 +- .../state-transition/src/util/execution.ts | 10 +- packages/types/src/electra/sszTypes.ts | 66 +++------ packages/types/src/electra/types.ts | 6 +- packages/types/src/types.ts | 18 ++- packages/types/src/utils/typeguards.ts | 6 +- 20 files changed, 160 insertions(+), 229 deletions(-) diff --git a/packages/beacon-node/src/chain/blocks/verifyBlocksExecutionPayloads.ts b/packages/beacon-node/src/chain/blocks/verifyBlocksExecutionPayloads.ts index 284d4c0976ee..e641ff9ae6d9 100644 --- a/packages/beacon-node/src/chain/blocks/verifyBlocksExecutionPayloads.ts +++ b/packages/beacon-node/src/chain/blocks/verifyBlocksExecutionPayloads.ts @@ -5,7 +5,7 @@ import { isMergeTransitionBlock as isMergeTransitionBlockFn, isExecutionEnabled, } from "@lodestar/state-transition"; -import {bellatrix, Slot, deneb, SignedBeaconBlock} from "@lodestar/types"; +import {bellatrix, Slot, deneb, SignedBeaconBlock, electra} from "@lodestar/types"; import { IForkChoice, assertValidTerminalPowBlock, @@ -302,6 +302,8 @@ export async function verifyBlockExecutionPayload( ? (block.message.body as deneb.BeaconBlockBody).blobKzgCommitments.map(kzgCommitmentToVersionedHash) : undefined; const parentBlockRoot = ForkSeq[fork] >= ForkSeq.deneb ? block.message.parentRoot : undefined; + const executionRequests = + ForkSeq[fork] >= ForkSeq.electra ? (block.message.body as electra.BeaconBlockBody).executionRequests : undefined; const logCtx = {slot: block.message.slot, executionBlock: executionPayloadEnabled.blockNumber}; chain.logger.debug("Call engine api newPayload", logCtx); @@ -309,7 +311,8 @@ export async function verifyBlockExecutionPayload( fork, executionPayloadEnabled, versionedHashes, - parentBlockRoot + parentBlockRoot, + executionRequests ); chain.logger.debug("Receive engine api newPayload result", {...logCtx, status: execResult.status}); diff --git a/packages/beacon-node/src/chain/produceBlock/produceBlockBody.ts b/packages/beacon-node/src/chain/produceBlock/produceBlockBody.ts index ba560d5a7ff0..ff8221a326e9 100644 --- a/packages/beacon-node/src/chain/produceBlock/produceBlockBody.ts +++ b/packages/beacon-node/src/chain/produceBlock/produceBlockBody.ts @@ -17,6 +17,7 @@ import { BlindedBeaconBlockBody, BlindedBeaconBlock, sszTypesFor, + electra, } from "@lodestar/types"; import { CachedBeaconStateAllForks, @@ -258,7 +259,7 @@ export async function produceBlockBody( } const engineRes = await this.executionEngine.getPayload(fork, payloadId); - const {executionPayload, blobsBundle} = engineRes; + const {executionPayload, blobsBundle, executionRequests} = engineRes; shouldOverrideBuilder = engineRes.shouldOverrideBuilder; (blockBody as BeaconBlockBody).executionPayload = executionPayload; @@ -298,6 +299,13 @@ export async function produceBlockBody( } else { blobsResult = {type: BlobsResultType.preDeneb}; } + + if (ForkSeq[fork] >= ForkSeq.electra) { + if (executionRequests === undefined) { + throw Error(`Missing executionRequests response from getPayload at fork=${fork}`); + } + (blockBody as electra.BeaconBlockBody).executionRequests = executionRequests; + } } } catch (e) { this.metrics?.blockPayload.payloadFetchErrors.inc(); diff --git a/packages/beacon-node/src/execution/engine/http.ts b/packages/beacon-node/src/execution/engine/http.ts index a69a5b94bd65..b42424b28998 100644 --- a/packages/beacon-node/src/execution/engine/http.ts +++ b/packages/beacon-node/src/execution/engine/http.ts @@ -1,4 +1,4 @@ -import {ExecutionPayload, Root, RootHex, Wei} from "@lodestar/types"; +import {ExecutionPayload, ExecutionRequests, Root, RootHex, Wei} from "@lodestar/types"; import {SLOTS_PER_EPOCH, ForkName, ForkSeq} from "@lodestar/params"; import {Logger} from "@lodestar/logger"; import { @@ -37,6 +37,7 @@ import { ExecutionPayloadBody, assertReqSizeLimit, deserializeExecutionPayloadBody, + serializeExecutionRequests, } from "./types.js"; import {getExecutionEngineState} from "./utils.js"; @@ -195,7 +196,8 @@ export class ExecutionEngineHttp implements IExecutionEngine { fork: ForkName, executionPayload: ExecutionPayload, versionedHashes?: VersionedHashes, - parentBlockRoot?: Root + parentBlockRoot?: Root, + executionRequests?: ExecutionRequests ): Promise { const method = ForkSeq[fork] >= ForkSeq.electra @@ -220,12 +222,28 @@ export class ExecutionEngineHttp implements IExecutionEngine { const serializedVersionedHashes = serializeVersionedHashes(versionedHashes); const parentBeaconBlockRoot = serializeBeaconBlockRoot(parentBlockRoot); - const method = ForkSeq[fork] >= ForkSeq.electra ? "engine_newPayloadV4" : "engine_newPayloadV3"; - engineRequest = { - method, - params: [serializedExecutionPayload, serializedVersionedHashes, parentBeaconBlockRoot], - methodOpts: notifyNewPayloadOpts, - }; + if (ForkSeq[fork] >= ForkSeq.electra) { + if (executionRequests === undefined) { + throw Error(`executionRequests required in notifyNewPayload for fork=${fork}`); + } + const serializedExecutionRequests = serializeExecutionRequests(executionRequests); + engineRequest = { + method: "engine_newPayloadV4", + params: [ + serializedExecutionPayload, + serializedVersionedHashes, + parentBeaconBlockRoot, + serializedExecutionRequests, + ], + methodOpts: notifyNewPayloadOpts, + }; + } else { + engineRequest = { + method: "engine_newPayloadV3", + params: [serializedExecutionPayload, serializedVersionedHashes, parentBeaconBlockRoot], + methodOpts: notifyNewPayloadOpts, + }; + } } else { const method = ForkSeq[fork] >= ForkSeq.capella ? "engine_newPayloadV2" : "engine_newPayloadV1"; engineRequest = { @@ -391,6 +409,7 @@ export class ExecutionEngineHttp implements IExecutionEngine { executionPayload: ExecutionPayload; executionPayloadValue: Wei; blobsBundle?: BlobsBundle; + executionRequests?: ExecutionRequests; shouldOverrideBuilder?: boolean; }> { const method = @@ -419,8 +438,7 @@ export class ExecutionEngineHttp implements IExecutionEngine { } async getPayloadBodiesByHash(fork: ForkName, blockHashes: RootHex[]): Promise<(ExecutionPayloadBody | null)[]> { - const method = - ForkSeq[fork] >= ForkSeq.electra ? "engine_getPayloadBodiesByHashV2" : "engine_getPayloadBodiesByHashV1"; + const method = "engine_getPayloadBodiesByHashV1"; assertReqSizeLimit(blockHashes.length, 32); const response = await this.rpc.fetchWithRetries< EngineApiRpcReturnTypes[typeof method], @@ -434,8 +452,7 @@ export class ExecutionEngineHttp implements IExecutionEngine { startBlockNumber: number, blockCount: number ): Promise<(ExecutionPayloadBody | null)[]> { - const method = - ForkSeq[fork] >= ForkSeq.electra ? "engine_getPayloadBodiesByRangeV2" : "engine_getPayloadBodiesByRangeV1"; + const method = "engine_getPayloadBodiesByRangeV1"; assertReqSizeLimit(blockCount, 32); const start = numToQuantity(startBlockNumber); const count = numToQuantity(blockCount); diff --git a/packages/beacon-node/src/execution/engine/interface.ts b/packages/beacon-node/src/execution/engine/interface.ts index 5226a46ac720..e6f9cfee526b 100644 --- a/packages/beacon-node/src/execution/engine/interface.ts +++ b/packages/beacon-node/src/execution/engine/interface.ts @@ -1,12 +1,12 @@ import {ForkName} from "@lodestar/params"; import {KZGCommitment, Blob, KZGProof} from "@lodestar/types/deneb"; -import {Root, RootHex, capella, Wei, ExecutionPayload} from "@lodestar/types"; +import {Root, RootHex, capella, Wei, ExecutionPayload, ExecutionRequests} from "@lodestar/types"; import {DATA} from "../../eth1/provider/utils.js"; -import {PayloadIdCache, PayloadId, WithdrawalV1, DepositRequestV1} from "./payloadIdCache.js"; +import {PayloadIdCache, PayloadId, WithdrawalV1} from "./payloadIdCache.js"; import {ExecutionPayloadBody} from "./types.js"; -export {PayloadIdCache, type PayloadId, type WithdrawalV1, type DepositRequestV1}; +export {PayloadIdCache, type PayloadId, type WithdrawalV1}; export enum ExecutionPayloadStatus { /** given payload is valid */ @@ -134,7 +134,8 @@ export interface IExecutionEngine { fork: ForkName, executionPayload: ExecutionPayload, versionedHashes?: VersionedHashes, - parentBeaconBlockRoot?: Root + parentBeaconBlockRoot?: Root, + executionRequests?: ExecutionRequests ): Promise; /** @@ -171,6 +172,7 @@ export interface IExecutionEngine { executionPayload: ExecutionPayload; executionPayloadValue: Wei; blobsBundle?: BlobsBundle; + executionRequests?: ExecutionRequests; shouldOverrideBuilder?: boolean; }>; diff --git a/packages/beacon-node/src/execution/engine/mock.ts b/packages/beacon-node/src/execution/engine/mock.ts index 9fed781fa523..4cff2a8d00f4 100644 --- a/packages/beacon-node/src/execution/engine/mock.ts +++ b/packages/beacon-node/src/execution/engine/mock.ts @@ -98,10 +98,8 @@ export class ExecutionEngineMockBackend implements JsonRpcBackend { engine_getPayloadV3: this.getPayload.bind(this), engine_getPayloadV4: this.getPayload.bind(this), engine_getPayloadBodiesByHashV1: this.getPayloadBodiesByHash.bind(this), - engine_getPayloadBodiesByHashV2: this.getPayloadBodiesByHash.bind(this), engine_getPayloadBodiesByRangeV1: this.getPayloadBodiesByRange.bind(this), engine_getClientVersionV1: this.getClientVersionV1.bind(this), - engine_getPayloadBodiesByRangeV2: this.getPayloadBodiesByRange.bind(this), }; } diff --git a/packages/beacon-node/src/execution/engine/payloadIdCache.ts b/packages/beacon-node/src/execution/engine/payloadIdCache.ts index 005a1ef14322..ea37e0922e9c 100644 --- a/packages/beacon-node/src/execution/engine/payloadIdCache.ts +++ b/packages/beacon-node/src/execution/engine/payloadIdCache.ts @@ -18,26 +18,6 @@ export type WithdrawalV1 = { amount: QUANTITY; }; -export type DepositRequestV1 = { - pubkey: DATA; - withdrawalCredentials: DATA; - amount: QUANTITY; - signature: DATA; - index: QUANTITY; -}; - -export type WithdrawalRequestV1 = { - sourceAddress: DATA; - validatorPubkey: DATA; - amount: QUANTITY; -}; - -export type ConsolidationRequestV1 = { - sourceAddress: DATA; - sourcePubkey: DATA; - targetPubkey: DATA; -}; - type FcuAttributes = {headBlockHash: DATA; finalizedBlockHash: DATA} & Omit; export class PayloadIdCache { diff --git a/packages/beacon-node/src/execution/engine/types.ts b/packages/beacon-node/src/execution/engine/types.ts index 139fc6822780..32fe4cb79d3d 100644 --- a/packages/beacon-node/src/execution/engine/types.ts +++ b/packages/beacon-node/src/execution/engine/types.ts @@ -1,4 +1,4 @@ -import {capella, deneb, electra, Wei, bellatrix, Root, ExecutionPayload} from "@lodestar/types"; +import {capella, deneb, electra, Wei, bellatrix, Root, ExecutionPayload, ExecutionRequests} from "@lodestar/types"; import { BYTES_PER_LOGS_BLOOM, FIELD_ELEMENTS_PER_BLOB, @@ -17,7 +17,7 @@ import { quantityToBigint, } from "../../eth1/provider/utils.js"; import {ExecutionPayloadStatus, BlobsBundle, PayloadAttributes, VersionedHashes} from "./interface.js"; -import {WithdrawalV1, DepositRequestV1, WithdrawalRequestV1, ConsolidationRequestV1} from "./payloadIdCache.js"; +import {WithdrawalV1} from "./payloadIdCache.js"; /* eslint-disable @typescript-eslint/naming-convention */ @@ -28,7 +28,7 @@ export type EngineApiRpcParamTypes = { engine_newPayloadV1: [ExecutionPayloadRpc]; engine_newPayloadV2: [ExecutionPayloadRpc]; engine_newPayloadV3: [ExecutionPayloadRpc, VersionedHashesRpc, DATA]; - engine_newPayloadV4: [ExecutionPayloadRpc, VersionedHashesRpc, DATA]; + engine_newPayloadV4: [ExecutionPayloadRpc, VersionedHashesRpc, DATA, ExecutionRequestsRpc]; /** * 1. Object - Payload validity status with respect to the consensus rules: * - blockHash: DATA, 32 Bytes - block hash value of the payload @@ -58,7 +58,6 @@ export type EngineApiRpcParamTypes = { * 1. Array of DATA - Array of block_hash field values of the ExecutionPayload structure * */ engine_getPayloadBodiesByHashV1: DATA[][]; - engine_getPayloadBodiesByHashV2: DATA[][]; /** * 1. start: QUANTITY, 64 bits - Starting block number @@ -70,7 +69,6 @@ export type EngineApiRpcParamTypes = { * Object - Instance of ClientVersion */ engine_getClientVersionV1: [ClientVersionRpc]; - engine_getPayloadBodiesByRangeV2: [start: QUANTITY, count: QUANTITY]; }; export type PayloadStatus = { @@ -109,12 +107,10 @@ export type EngineApiRpcReturnTypes = { engine_getPayloadV4: ExecutionPayloadResponse; engine_getPayloadBodiesByHashV1: (ExecutionPayloadBodyRpc | null)[]; - engine_getPayloadBodiesByHashV2: (ExecutionPayloadBodyRpc | null)[]; engine_getPayloadBodiesByRangeV1: (ExecutionPayloadBodyRpc | null)[]; engine_getClientVersionV1: ClientVersionRpc[]; - engine_getPayloadBodiesByRangeV2: (ExecutionPayloadBodyRpc | null)[]; }; type ExecutionPayloadRpcWithValue = { @@ -122,6 +118,7 @@ type ExecutionPayloadRpcWithValue = { // even though CL tracks this as executionPayloadValue, EL returns this as blockValue blockValue: QUANTITY; blobsBundle?: BlobsBundleRpc; + requests?: ExecutionRequestsRpc; shouldOverrideBuilder?: boolean; }; type ExecutionPayloadResponse = ExecutionPayloadRpc | ExecutionPayloadRpcWithValue; @@ -129,19 +126,11 @@ type ExecutionPayloadResponse = ExecutionPayloadRpc | ExecutionPayloadRpcWithVal export type ExecutionPayloadBodyRpc = { transactions: DATA[]; withdrawals: WithdrawalV1[] | null | undefined; - // currently there is a discepancy between EL and CL field name references for deposit requests - // its likely CL receipt will be renamed to requests - depositRequests: DepositRequestV1[] | null | undefined; - withdrawalRequests: WithdrawalRequestV1[] | null | undefined; - consolidationRequests: ConsolidationRequestV1[] | null | undefined; }; export type ExecutionPayloadBody = { transactions: bellatrix.Transaction[]; withdrawals: capella.Withdrawals | null; - depositRequests: electra.DepositRequests | null; - withdrawalRequests: electra.WithdrawalRequests | null; - consolidationRequests: electra.ConsolidationRequests | null; }; export type ExecutionPayloadRpc = { @@ -163,9 +152,6 @@ export type ExecutionPayloadRpc = { blobGasUsed?: QUANTITY; // DENEB excessBlobGas?: QUANTITY; // DENEB parentBeaconBlockRoot?: QUANTITY; // DENEB - depositRequests?: DepositRequestRpc[]; // ELECTRA - withdrawalRequests?: WithdrawalRequestRpc[]; // ELECTRA - consolidationRequests?: ConsolidationRequestRpc[]; // ELECTRA }; export type WithdrawalRpc = { @@ -175,9 +161,29 @@ export type WithdrawalRpc = { amount: QUANTITY; }; -export type DepositRequestRpc = DepositRequestV1; -export type WithdrawalRequestRpc = WithdrawalRequestV1; -export type ConsolidationRequestRpc = ConsolidationRequestV1; +export type ExecutionRequestsRpc = { + deposits: DepositRequestRpc[]; + withdrawals: WithdrawalRequestRpc[]; + consolidations: ConsolidationRequestRpc[]; +}; + +export type DepositRequestRpc = { + pubkey: DATA; + withdrawalCredentials: DATA; + amount: QUANTITY; + signature: DATA; + index: QUANTITY; +}; +export type WithdrawalRequestRpc = { + sourceAddress: DATA; + validatorPubkey: DATA; + amount: QUANTITY; +}; +export type ConsolidationRequestRpc = { + sourceAddress: DATA; + sourcePubkey: DATA; + targetPubkey: DATA; +}; export type VersionedHashesRpc = DATA[]; @@ -241,13 +247,7 @@ export function serializeExecutionPayload(fork: ForkName, data: ExecutionPayload payload.excessBlobGas = numToQuantity(excessBlobGas); } - // ELECTRA adds depositRequests/depositRequests to the ExecutionPayload - if (ForkSeq[fork] >= ForkSeq.electra) { - const {depositRequests, withdrawalRequests, consolidationRequests} = data as electra.ExecutionPayload; - payload.depositRequests = depositRequests.map(serializeDepositRequest); - payload.withdrawalRequests = withdrawalRequests.map(serializeWithdrawalRequest); - payload.consolidationRequests = consolidationRequests.map(serializeConsolidationRequest); - } + // No changes in Electra return payload; } @@ -267,23 +267,27 @@ export function parseExecutionPayload( executionPayload: ExecutionPayload; executionPayloadValue: Wei; blobsBundle?: BlobsBundle; + executionRequests?: ExecutionRequests; shouldOverrideBuilder?: boolean; } { let data: ExecutionPayloadRpc; let executionPayloadValue: Wei; let blobsBundle: BlobsBundle | undefined; + let executionRequests: ExecutionRequests | undefined; let shouldOverrideBuilder: boolean; if (hasPayloadValue(response)) { executionPayloadValue = quantityToBigint(response.blockValue); data = response.executionPayload; blobsBundle = response.blobsBundle ? parseBlobsBundle(response.blobsBundle) : undefined; + executionRequests = response.requests ? deserializeExecutionRequests(response.requests) : undefined; shouldOverrideBuilder = response.shouldOverrideBuilder ?? false; } else { data = response; // Just set it to zero as default executionPayloadValue = BigInt(0); blobsBundle = undefined; + executionRequests = undefined; shouldOverrideBuilder = false; } @@ -334,36 +338,9 @@ export function parseExecutionPayload( (executionPayload as deneb.ExecutionPayload).excessBlobGas = quantityToBigint(excessBlobGas); } - if (ForkSeq[fork] >= ForkSeq.electra) { - // electra adds depositRequests/depositRequests - const {depositRequests, withdrawalRequests, consolidationRequests} = data; - // Geth can also reply with null - if (depositRequests == null) { - throw Error( - `depositRequests missing for ${fork} >= electra executionPayload number=${executionPayload.blockNumber} hash=${data.blockHash}` - ); - } - (executionPayload as electra.ExecutionPayload).depositRequests = depositRequests.map(deserializeDepositRequest); - - if (withdrawalRequests == null) { - throw Error( - `withdrawalRequests missing for ${fork} >= electra executionPayload number=${executionPayload.blockNumber} hash=${data.blockHash}` - ); - } - (executionPayload as electra.ExecutionPayload).withdrawalRequests = - withdrawalRequests.map(deserializeWithdrawalRequest); - - if (consolidationRequests == null) { - throw Error( - `consolidationRequests missing for ${fork} >= electra executionPayload number=${executionPayload.blockNumber} hash=${data.blockHash}` - ); - } - (executionPayload as electra.ExecutionPayload).consolidationRequests = consolidationRequests.map( - deserializeConsolidationRequest - ); - } + // No changes in Electra - return {executionPayload, executionPayloadValue, blobsBundle, shouldOverrideBuilder}; + return {executionPayload, executionPayloadValue, blobsBundle, executionRequests, shouldOverrideBuilder}; } export function serializePayloadAttributes(data: PayloadAttributes): PayloadAttributesRpc { @@ -429,7 +406,7 @@ export function deserializeWithdrawal(serialized: WithdrawalRpc): capella.Withdr } as capella.Withdrawal; } -export function serializeDepositRequest(depositRequest: electra.DepositRequest): DepositRequestRpc { +function serializeDepositRequest(depositRequest: electra.DepositRequest): DepositRequestRpc { return { pubkey: bytesToData(depositRequest.pubkey), withdrawalCredentials: bytesToData(depositRequest.withdrawalCredentials), @@ -439,7 +416,7 @@ export function serializeDepositRequest(depositRequest: electra.DepositRequest): }; } -export function deserializeDepositRequest(serialized: DepositRequestRpc): electra.DepositRequest { +function deserializeDepositRequest(serialized: DepositRequestRpc): electra.DepositRequest { return { pubkey: dataToBytes(serialized.pubkey, 48), withdrawalCredentials: dataToBytes(serialized.withdrawalCredentials, 32), @@ -449,7 +426,7 @@ export function deserializeDepositRequest(serialized: DepositRequestRpc): electr } as electra.DepositRequest; } -export function serializeWithdrawalRequest(withdrawalRequest: electra.WithdrawalRequest): WithdrawalRequestRpc { +function serializeWithdrawalRequest(withdrawalRequest: electra.WithdrawalRequest): WithdrawalRequestRpc { return { sourceAddress: bytesToData(withdrawalRequest.sourceAddress), validatorPubkey: bytesToData(withdrawalRequest.validatorPubkey), @@ -457,7 +434,7 @@ export function serializeWithdrawalRequest(withdrawalRequest: electra.Withdrawal }; } -export function deserializeWithdrawalRequest(withdrawalRequest: WithdrawalRequestRpc): electra.WithdrawalRequest { +function deserializeWithdrawalRequest(withdrawalRequest: WithdrawalRequestRpc): electra.WithdrawalRequest { return { sourceAddress: dataToBytes(withdrawalRequest.sourceAddress, 20), validatorPubkey: dataToBytes(withdrawalRequest.validatorPubkey, 48), @@ -465,9 +442,7 @@ export function deserializeWithdrawalRequest(withdrawalRequest: WithdrawalReques }; } -export function serializeConsolidationRequest( - consolidationRequest: electra.ConsolidationRequest -): ConsolidationRequestRpc { +function serializeConsolidationRequest(consolidationRequest: electra.ConsolidationRequest): ConsolidationRequestRpc { return { sourceAddress: bytesToData(consolidationRequest.sourceAddress), sourcePubkey: bytesToData(consolidationRequest.sourcePubkey), @@ -475,9 +450,7 @@ export function serializeConsolidationRequest( }; } -export function deserializeConsolidationRequest( - consolidationRequest: ConsolidationRequestRpc -): electra.ConsolidationRequest { +function deserializeConsolidationRequest(consolidationRequest: ConsolidationRequestRpc): electra.ConsolidationRequest { return { sourceAddress: dataToBytes(consolidationRequest.sourceAddress, 20), sourcePubkey: dataToBytes(consolidationRequest.sourcePubkey, 48), @@ -485,16 +458,29 @@ export function deserializeConsolidationRequest( }; } +export function serializeExecutionRequests(executionRequests: ExecutionRequests): ExecutionRequestsRpc { + const {deposits, withdrawals, consolidations} = executionRequests; + return { + deposits: deposits.map(serializeDepositRequest), + withdrawals: withdrawals.map(serializeWithdrawalRequest), + consolidations: consolidations.map(serializeConsolidationRequest), + }; +} + +export function deserializeExecutionRequests(executionRequests: ExecutionRequestsRpc): ExecutionRequests { + const {deposits, withdrawals, consolidations} = executionRequests; + return { + deposits: deposits.map(deserializeDepositRequest), + withdrawals: withdrawals.map(deserializeWithdrawalRequest), + consolidations: consolidations.map(deserializeConsolidationRequest), + }; +} + export function deserializeExecutionPayloadBody(data: ExecutionPayloadBodyRpc | null): ExecutionPayloadBody | null { return data ? { transactions: data.transactions.map((tran) => dataToBytes(tran, null)), withdrawals: data.withdrawals ? data.withdrawals.map(deserializeWithdrawal) : null, - depositRequests: data.depositRequests ? data.depositRequests.map(deserializeDepositRequest) : null, - withdrawalRequests: data.withdrawalRequests ? data.withdrawalRequests.map(deserializeWithdrawalRequest) : null, - consolidationRequests: data.consolidationRequests - ? data.consolidationRequests.map(deserializeConsolidationRequest) - : null, } : null; } @@ -504,11 +490,6 @@ export function serializeExecutionPayloadBody(data: ExecutionPayloadBody | null) ? { transactions: data.transactions.map((tran) => bytesToData(tran)), withdrawals: data.withdrawals ? data.withdrawals.map(serializeWithdrawal) : null, - depositRequests: data.depositRequests ? data.depositRequests.map(serializeDepositRequest) : null, - withdrawalRequests: data.withdrawalRequests ? data.withdrawalRequests.map(serializeWithdrawalRequest) : null, - consolidationRequests: data.consolidationRequests - ? data.consolidationRequests.map(serializeConsolidationRequest) - : null, } : null; } diff --git a/packages/beacon-node/test/sim/electra-interop.test.ts b/packages/beacon-node/test/sim/electra-interop.test.ts index d0c00e75fd59..2d08428df558 100644 --- a/packages/beacon-node/test/sim/electra-interop.test.ts +++ b/packages/beacon-node/test/sim/electra-interop.test.ts @@ -171,7 +171,6 @@ describe("executionEngine / ExecutionEngineHttp", function () { blockHash: dataToBytes(newPayloadBlockHash, 32), receiptsRoot: dataToBytes("0x0b67bea29f17eeb290685e01e9a2e4cd77a83471d9985a8ce27997a7ed3ee3f8", 32), blobGasUsed: 0n, - withdrawalRequests: [], }; const parentBeaconBlockRoot = dataToBytes("0x0000000000000000000000000000000000000000000000000000000000000000", 32); const payloadResult = await executionEngine.notifyNewPayload( @@ -208,6 +207,7 @@ describe("executionEngine / ExecutionEngineHttp", function () { await sleep(1000); const payloadAndBlockValue = await executionEngine.getPayload(ForkName.electra, payloadId2); const payload = payloadAndBlockValue.executionPayload as electra.ExecutionPayload; + const depositRequests = payloadAndBlockValue.executionRequests?.deposits; if (payload.transactions.length !== 1) { throw Error(`Number of transactions mismatched. Expected: 1, actual: ${payload.transactions.length}`); @@ -219,11 +219,11 @@ describe("executionEngine / ExecutionEngineHttp", function () { } } - if (payload.depositRequests.length !== 1) { - throw Error(`Number of depositRequests mismatched. Expected: 1, actual: ${payload.depositRequests.length}`); + if (depositRequests === undefined || depositRequests.length !== 1) { + throw Error(`Number of depositRequests mismatched. Expected: 1, actual: ${depositRequests?.length}`); } - const actualDepositRequest = payload.depositRequests[0]; + const actualDepositRequest = depositRequests[0]; assert.deepStrictEqual( actualDepositRequest, depositRequestB, diff --git a/packages/beacon-node/test/spec/specTestVersioning.ts b/packages/beacon-node/test/spec/specTestVersioning.ts index 7229a0236d84..d4bc192f6cad 100644 --- a/packages/beacon-node/test/spec/specTestVersioning.ts +++ b/packages/beacon-node/test/spec/specTestVersioning.ts @@ -15,7 +15,7 @@ import {DownloadTestsOptions} from "@lodestar/spec-test-util/downloadTests"; const __dirname = path.dirname(fileURLToPath(import.meta.url)); export const ethereumConsensusSpecsTests: DownloadTestsOptions = { - specVersion: "v1.5.0-alpha.5", + specVersion: "v1.5.0-alpha.6", // Target directory is the host package root: 'packages/*/spec-tests' outputDir: path.join(__dirname, "../../spec-tests"), specTestsRepoUrl: "https://github.com/ethereum/consensus-spec-tests", diff --git a/packages/beacon-node/test/spec/utils/specTestIterator.ts b/packages/beacon-node/test/spec/utils/specTestIterator.ts index d8b4f9c0574c..bd5142627e3f 100644 --- a/packages/beacon-node/test/spec/utils/specTestIterator.ts +++ b/packages/beacon-node/test/spec/utils/specTestIterator.ts @@ -66,6 +66,8 @@ export const defaultSkipOpts: SkipOpts = { /^capella\/light_client\/single_merkle_proof\/BeaconBlockBody.*/, /^deneb\/light_client\/single_merkle_proof\/BeaconBlockBody.*/, /^electra\/light_client\/single_merkle_proof\/BeaconBlockBody.*/, + // TODO Electra: slashings tests to be enabled in PR#7071 + /^electra\/epoch_processing\/slashings.*/, ], skippedTests: [], skippedRunners: ["merkle_proof", "networking"], diff --git a/packages/beacon-node/test/unit/chain/lightclient/upgradeLightClientHeader.test.ts b/packages/beacon-node/test/unit/chain/lightclient/upgradeLightClientHeader.test.ts index abb520bddafb..6da728be46e9 100644 --- a/packages/beacon-node/test/unit/chain/lightclient/upgradeLightClientHeader.test.ts +++ b/packages/beacon-node/test/unit/chain/lightclient/upgradeLightClientHeader.test.ts @@ -28,7 +28,7 @@ describe("UpgradeLightClientHeader", function () { capella: ssz.capella.LightClientHeader.defaultValue(), bellatrix: ssz.altair.LightClientHeader.defaultValue(), deneb: ssz.deneb.LightClientHeader.defaultValue(), - electra: ssz.electra.LightClientHeader.defaultValue(), + electra: ssz.deneb.LightClientHeader.defaultValue(), }; testSlots = { diff --git a/packages/beacon-node/test/unit/executionEngine/http.test.ts b/packages/beacon-node/test/unit/executionEngine/http.test.ts index 5ac4fd4ca670..c9f4ae671e53 100644 --- a/packages/beacon-node/test/unit/executionEngine/http.test.ts +++ b/packages/beacon-node/test/unit/executionEngine/http.test.ts @@ -193,9 +193,6 @@ describe("ExecutionEngine / http", () => { amount: "0x7b", }, ], - depositRequests: null, // depositRequests is null pre-electra - withdrawalRequests: null, - consolidationRequests: null, }, null, // null returned for missing blocks { @@ -204,9 +201,6 @@ describe("ExecutionEngine / http", () => { "0xb084c10440f05f5a23a55d1d7ebcb1b3892935fb56f23cdc9a7f42c348eed174", ], withdrawals: null, // withdrawals is null pre-capella - depositRequests: null, // depositRequests is null pre-electra - withdrawalRequests: null, - consolidationRequests: null, }, ], }; @@ -254,9 +248,6 @@ describe("ExecutionEngine / http", () => { amount: "0x7b", }, ], - depositRequests: null, // depositRequests is null pre-electra - withdrawalRequests: null, - consolidationRequests: null, }, null, // null returned for missing blocks { @@ -265,9 +256,6 @@ describe("ExecutionEngine / http", () => { "0xb084c10440f05f5a23a55d1d7ebcb1b3892935fb56f23cdc9a7f42c348eed174", ], withdrawals: null, // withdrawals is null pre-capella - depositRequests: null, // depositRequests is null pre-electra - withdrawalRequests: null, - consolidationRequests: null, }, ], }; diff --git a/packages/light-client/src/spec/utils.ts b/packages/light-client/src/spec/utils.ts index 872aa5d9f910..408412464606 100644 --- a/packages/light-client/src/spec/utils.ts +++ b/packages/light-client/src/spec/utils.ts @@ -128,12 +128,7 @@ export function upgradeLightClientHeader( // eslint-disable-next-line no-fallthrough case ForkName.electra: - (upgradedHeader as LightClientHeader).execution.depositRequestsRoot = - ssz.electra.LightClientHeader.fields.execution.fields.depositRequestsRoot.defaultValue(); - (upgradedHeader as LightClientHeader).execution.withdrawalRequestsRoot = - ssz.electra.LightClientHeader.fields.execution.fields.withdrawalRequestsRoot.defaultValue(); - (upgradedHeader as LightClientHeader).execution.consolidationRequestsRoot = - ssz.electra.LightClientHeader.fields.execution.fields.consolidationRequestsRoot.defaultValue(); + // No changes to LightClientHeader in Electra // Break if no further upgrades is required else fall through if (ForkSeq[targetFork] <= ForkSeq.electra) break; @@ -170,16 +165,6 @@ export function isValidLightClientHeader(config: ChainForkConfig, header: LightC } } - if (epoch < config.ELECTRA_FORK_EPOCH) { - if ( - (header as LightClientHeader).execution.depositRequestsRoot !== undefined || - (header as LightClientHeader).execution.withdrawalRequestsRoot !== undefined || - (header as LightClientHeader).execution.consolidationRequestsRoot !== undefined - ) { - return false; - } - } - return isValidMerkleBranch( config .getExecutionForkTypes(header.beacon.slot) diff --git a/packages/state-transition/src/block/processOperations.ts b/packages/state-transition/src/block/processOperations.ts index 6f61e7c242fb..bb52af14ba32 100644 --- a/packages/state-transition/src/block/processOperations.ts +++ b/packages/state-transition/src/block/processOperations.ts @@ -67,15 +67,15 @@ export function processOperations( const stateElectra = state as CachedBeaconStateElectra; const bodyElectra = body as electra.BeaconBlockBody; - for (const depositRequest of bodyElectra.executionPayload.depositRequests) { + for (const depositRequest of bodyElectra.executionRequests.deposits) { processDepositRequest(fork, stateElectra, depositRequest); } - for (const elWithdrawalRequest of bodyElectra.executionPayload.withdrawalRequests) { + for (const elWithdrawalRequest of bodyElectra.executionRequests.withdrawals) { processWithdrawalRequest(fork, stateElectra, elWithdrawalRequest); } - for (const elConsolidationRequest of bodyElectra.executionPayload.consolidationRequests) { + for (const elConsolidationRequest of bodyElectra.executionRequests.consolidations) { processConsolidationRequest(stateElectra, elConsolidationRequest); } } diff --git a/packages/state-transition/src/slot/upgradeStateToElectra.ts b/packages/state-transition/src/slot/upgradeStateToElectra.ts index 6600ad98e80a..0bd36a909b46 100644 --- a/packages/state-transition/src/slot/upgradeStateToElectra.ts +++ b/packages/state-transition/src/slot/upgradeStateToElectra.ts @@ -48,17 +48,11 @@ export function upgradeStateToElectra(stateDeneb: CachedBeaconStateDeneb): Cache stateElectraView.inactivityScores = stateElectraCloned.inactivityScores; stateElectraView.currentSyncCommittee = stateElectraCloned.currentSyncCommittee; stateElectraView.nextSyncCommittee = stateElectraCloned.nextSyncCommittee; - stateElectraView.latestExecutionPayloadHeader = ssz.electra.BeaconState.fields.latestExecutionPayloadHeader.toViewDU({ - ...stateElectraCloned.latestExecutionPayloadHeader.toValue(), - depositRequestsRoot: ssz.Root.defaultValue(), - withdrawalRequestsRoot: ssz.Root.defaultValue(), - consolidationRequestsRoot: ssz.Root.defaultValue(), - }); + stateElectraView.latestExecutionPayloadHeader = stateElectraCloned.latestExecutionPayloadHeader; stateElectraView.nextWithdrawalIndex = stateDeneb.nextWithdrawalIndex; stateElectraView.nextWithdrawalValidatorIndex = stateDeneb.nextWithdrawalValidatorIndex; stateElectraView.historicalSummaries = stateElectraCloned.historicalSummaries; - // latestExecutionPayloadHeader's depositRequestsRoot and withdrawalRequestsRoot set to zeros by default // default value of depositRequestsStartIndex is UNSET_DEPOSIT_REQUESTS_START_INDEX stateElectraView.depositRequestsStartIndex = UNSET_DEPOSIT_REQUESTS_START_INDEX; stateElectraView.depositBalanceToConsume = BigInt(0); @@ -137,7 +131,6 @@ export function upgradeStateToElectraOriginal(stateDeneb: CachedBeaconStateDeneb epoch: stateDeneb.epochCtx.epoch, }); - // latestExecutionPayloadHeader's depositRequestsRoot and withdrawalRequestsRoot set to zeros by default // default value of depositRequestsStartIndex is UNSET_DEPOSIT_REQUESTS_START_INDEX stateElectra.depositRequestsStartIndex = UNSET_DEPOSIT_REQUESTS_START_INDEX; diff --git a/packages/state-transition/src/util/execution.ts b/packages/state-transition/src/util/execution.ts index 06e654f9f1d2..b9243ebe7874 100644 --- a/packages/state-transition/src/util/execution.ts +++ b/packages/state-transition/src/util/execution.ts @@ -2,7 +2,6 @@ import { bellatrix, capella, deneb, - electra, isBlindedBeaconBlockBody, ssz, BeaconBlock, @@ -171,14 +170,7 @@ export function executionPayloadToPayloadHeader(fork: ForkSeq, payload: Executio ).excessBlobGas; } - if (fork >= ForkSeq.electra) { - (bellatrixPayloadFields as electra.ExecutionPayloadHeader).depositRequestsRoot = - ssz.electra.DepositRequests.hashTreeRoot((payload as electra.ExecutionPayload).depositRequests); - (bellatrixPayloadFields as electra.ExecutionPayloadHeader).withdrawalRequestsRoot = - ssz.electra.WithdrawalRequests.hashTreeRoot((payload as electra.ExecutionPayload).withdrawalRequests); - (bellatrixPayloadFields as electra.ExecutionPayloadHeader).consolidationRequestsRoot = - ssz.electra.ConsolidationRequests.hashTreeRoot((payload as electra.ExecutionPayload).consolidationRequests); - } + // No change in Electra return bellatrixPayloadFields; } diff --git a/packages/types/src/electra/sszTypes.ts b/packages/types/src/electra/sszTypes.ts index 522f7245cc1b..9d995c38efd5 100644 --- a/packages/types/src/electra/sszTypes.ts +++ b/packages/types/src/electra/sszTypes.ts @@ -8,7 +8,6 @@ import { } from "@chainsafe/ssz"; import { HISTORICAL_ROOTS_LIMIT, - BLOCK_BODY_EXECUTION_PAYLOAD_DEPTH as EXECUTION_PAYLOAD_DEPTH, EPOCHS_PER_SYNC_COMMITTEE_PERIOD, SLOTS_PER_EPOCH, MAX_DEPOSIT_REQUESTS_PER_PAYLOAD, @@ -149,25 +148,18 @@ export const ConsolidationRequests = new ListCompositeType( MAX_CONSOLIDATION_REQUESTS_PER_PAYLOAD ); -export const ExecutionPayload = new ContainerType( +export const ExecutionRequests = new ContainerType( { - ...denebSsz.ExecutionPayload.fields, - depositRequests: DepositRequests, // New in ELECTRA - withdrawalRequests: WithdrawalRequests, // New in ELECTRA - consolidationRequests: ConsolidationRequests, // New in ELECTRA + deposits: DepositRequests, + withdrawals: WithdrawalRequests, + consolidations: ConsolidationRequests, }, - {typeName: "ExecutionPayload", jsonCase: "eth2"} + {typeName: "ExecutionRequests", jsonCase: "eth2"} ); -export const ExecutionPayloadHeader = new ContainerType( - { - ...denebSsz.ExecutionPayloadHeader.fields, - depositRequestsRoot: Root, // New in ELECTRA - withdrawalRequestsRoot: Root, // New in ELECTRA - consolidationRequestsRoot: Root, // New in ELECTRA - }, - {typeName: "ExecutionPayloadHeader", jsonCase: "eth2"} -); +// Explicitly defining electra containers for consistency's sake +export const ExecutionPayloadHeader = denebSsz.ExecutionPayloadHeader; +export const ExecutionPayload = denebSsz.ExecutionPayload; // We have to preserve Fields ordering while changing the type of ExecutionPayload export const BeaconBlockBody = new ContainerType( @@ -181,9 +173,10 @@ export const BeaconBlockBody = new ContainerType( deposits: phase0Ssz.BeaconBlockBody.fields.deposits, voluntaryExits: phase0Ssz.BeaconBlockBody.fields.voluntaryExits, syncAggregate: altairSsz.BeaconBlockBody.fields.syncAggregate, - executionPayload: ExecutionPayload, // Modified in ELECTRA + executionPayload: ExecutionPayload, blsToExecutionChanges: capellaSsz.BeaconBlockBody.fields.blsToExecutionChanges, blobKzgCommitments: denebSsz.BeaconBlockBody.fields.blobKzgCommitments, + executionRequests: ExecutionRequests, // New in ELECTRA:EIP7251 }, {typeName: "BeaconBlockBody", jsonCase: "eth2", cachePermanentRootStruct: true} ); @@ -215,7 +208,7 @@ export const BlindedBeaconBlockBody = new ContainerType( deposits: phase0Ssz.BeaconBlockBody.fields.deposits, voluntaryExits: phase0Ssz.BeaconBlockBody.fields.voluntaryExits, syncAggregate: altairSsz.SyncAggregate, - executionPayloadHeader: ExecutionPayloadHeader, // Modified in ELECTRA + executionPayloadHeader: ExecutionPayloadHeader, blsToExecutionChanges: capellaSsz.BeaconBlockBody.fields.blsToExecutionChanges, blobKzgCommitments: denebSsz.BeaconBlockBody.fields.blobKzgCommitments, }, @@ -256,14 +249,6 @@ export const SignedBuilderBid = new ContainerType( {typeName: "SignedBuilderBid", jsonCase: "eth2"} ); -export const ExecutionPayloadAndBlobsBundle = new ContainerType( - { - executionPayload: ExecutionPayload, // Modified in ELECTRA - blobsBundle: denebSsz.BlobsBundle, - }, - {typeName: "ExecutionPayloadAndBlobsBundle", jsonCase: "eth2"} -); - export const PendingBalanceDeposit = new ContainerType( { index: ValidatorIndex, @@ -328,7 +313,7 @@ export const BeaconState = new ContainerType( currentSyncCommittee: altairSsz.SyncCommittee, nextSyncCommittee: altairSsz.SyncCommittee, // Execution - latestExecutionPayloadHeader: ExecutionPayloadHeader, // Modified in ELECTRA + latestExecutionPayloadHeader: ExecutionPayloadHeader, // Withdrawals nextWithdrawalIndex: capellaSsz.BeaconState.fields.nextWithdrawalIndex, nextWithdrawalValidatorIndex: capellaSsz.BeaconState.fields.nextWithdrawalValidatorIndex, @@ -347,30 +332,21 @@ export const BeaconState = new ContainerType( {typeName: "BeaconState", jsonCase: "eth2"} ); -export const LightClientHeader = new ContainerType( - { - beacon: phase0Ssz.BeaconBlockHeader, - execution: ExecutionPayloadHeader, // Modified in ELECTRA - executionBranch: new VectorCompositeType(Bytes32, EXECUTION_PAYLOAD_DEPTH), - }, - {typeName: "LightClientHeader", jsonCase: "eth2"} -); - export const LightClientBootstrap = new ContainerType( { - header: LightClientHeader, // Modified in ELECTRA + header: denebSsz.LightClientHeader, currentSyncCommittee: altairSsz.SyncCommittee, - currentSyncCommitteeBranch: new VectorCompositeType(Bytes32, NEXT_SYNC_COMMITTEE_DEPTH_ELECTRA), // Modified in ELECTRA + currentSyncCommitteeBranch: new VectorCompositeType(Bytes32, NEXT_SYNC_COMMITTEE_DEPTH_ELECTRA), }, {typeName: "LightClientBootstrap", jsonCase: "eth2"} ); export const LightClientUpdate = new ContainerType( { - attestedHeader: LightClientHeader, // Modified in ELECTRA + attestedHeader: denebSsz.LightClientHeader, nextSyncCommittee: altairSsz.SyncCommittee, nextSyncCommitteeBranch: new VectorCompositeType(Bytes32, NEXT_SYNC_COMMITTEE_DEPTH_ELECTRA), // Modified in ELECTRA - finalizedHeader: LightClientHeader, // Modified in ELECTRA + finalizedHeader: denebSsz.LightClientHeader, finalityBranch: new VectorCompositeType(Bytes32, FINALIZED_ROOT_DEPTH_ELECTRA), // Modified in ELECTRA syncAggregate: altairSsz.SyncAggregate, signatureSlot: Slot, @@ -380,8 +356,8 @@ export const LightClientUpdate = new ContainerType( export const LightClientFinalityUpdate = new ContainerType( { - attestedHeader: LightClientHeader, - finalizedHeader: LightClientHeader, + attestedHeader: denebSsz.LightClientHeader, + finalizedHeader: denebSsz.LightClientHeader, finalityBranch: new VectorCompositeType(Bytes32, FINALIZED_ROOT_DEPTH_ELECTRA), // Modified in ELECTRA syncAggregate: altairSsz.SyncAggregate, signatureSlot: Slot, @@ -391,7 +367,7 @@ export const LightClientFinalityUpdate = new ContainerType( export const LightClientOptimisticUpdate = new ContainerType( { - attestedHeader: LightClientHeader, // Modified in ELECTRA + attestedHeader: denebSsz.LightClientHeader, syncAggregate: altairSsz.SyncAggregate, signatureSlot: Slot, }, @@ -400,8 +376,8 @@ export const LightClientOptimisticUpdate = new ContainerType( export const LightClientStore = new ContainerType( { - snapshot: LightClientBootstrap, // Modified in ELECTRA - validUpdates: new ListCompositeType(LightClientUpdate, EPOCHS_PER_SYNC_COMMITTEE_PERIOD * SLOTS_PER_EPOCH), // Modified in ELECTRA + snapshot: LightClientBootstrap, + validUpdates: new ListCompositeType(LightClientUpdate, EPOCHS_PER_SYNC_COMMITTEE_PERIOD * SLOTS_PER_EPOCH), }, {typeName: "LightClientStore", jsonCase: "eth2"} ); diff --git a/packages/types/src/electra/types.ts b/packages/types/src/electra/types.ts index 9a81aec43b53..f7996cf336f9 100644 --- a/packages/types/src/electra/types.ts +++ b/packages/types/src/electra/types.ts @@ -20,8 +20,7 @@ export type ConsolidationRequests = ValueOf; export type ExecutionPayload = ValueOf; export type ExecutionPayloadHeader = ValueOf; - -export type ExecutionPayloadAndBlobsBundle = ValueOf; +export type ExecutionRequests = ValueOf; export type BeaconBlockBody = ValueOf; export type BeaconBlock = ValueOf; @@ -33,13 +32,10 @@ export type BlindedBeaconBlockBody = ValueOf; export type BlindedBeaconBlock = ValueOf; export type SignedBlindedBeaconBlock = ValueOf; -export type FullOrBlindedExecutionPayload = ExecutionPayload | ExecutionPayloadHeader; - export type BuilderBid = ValueOf; export type SignedBuilderBid = ValueOf; export type SSEPayloadAttributes = ValueOf; -export type LightClientHeader = ValueOf; export type LightClientBootstrap = ValueOf; export type LightClientUpdate = ValueOf; export type LightClientFinalityUpdate = ValueOf; diff --git a/packages/types/src/types.ts b/packages/types/src/types.ts index 1071eed79a10..08fc06ac6cb9 100644 --- a/packages/types/src/types.ts +++ b/packages/types/src/types.ts @@ -1,4 +1,12 @@ -import {ForkAll, ForkBlobs, ForkExecution, ForkLightClient, ForkName, ForkPreBlobs} from "@lodestar/params"; +import { + ForkAll, + ForkBlobs, + ForkExecution, + ForkLightClient, + ForkName, + ForkPostElectra, + ForkPreBlobs, +} from "@lodestar/params"; import {ts as phase0} from "./phase0/index.js"; import {ts as altair} from "./altair/index.js"; import {ts as bellatrix} from "./bellatrix/index.js"; @@ -172,7 +180,7 @@ type TypesByFork = { BeaconState: electra.BeaconState; SignedBeaconBlock: electra.SignedBeaconBlock; Metadata: altair.Metadata; - LightClientHeader: electra.LightClientHeader; + LightClientHeader: deneb.LightClientHeader; LightClientBootstrap: electra.LightClientBootstrap; LightClientUpdate: electra.LightClientUpdate; LightClientFinalityUpdate: electra.LightClientFinalityUpdate; @@ -181,8 +189,8 @@ type TypesByFork = { BlindedBeaconBlock: electra.BlindedBeaconBlock; BlindedBeaconBlockBody: electra.BlindedBeaconBlockBody; SignedBlindedBeaconBlock: electra.SignedBlindedBeaconBlock; - ExecutionPayload: electra.ExecutionPayload; - ExecutionPayloadHeader: electra.ExecutionPayloadHeader; + ExecutionPayload: deneb.ExecutionPayload; + ExecutionPayloadHeader: deneb.ExecutionPayloadHeader; BuilderBid: electra.BuilderBid; SignedBuilderBid: electra.SignedBuilderBid; SSEPayloadAttributes: electra.SSEPayloadAttributes; @@ -199,6 +207,7 @@ type TypesByFork = { AttesterSlashing: electra.AttesterSlashing; AggregateAndProof: electra.AggregateAndProof; SignedAggregateAndProof: electra.SignedAggregateAndProof; + ExecutionRequests: electra.ExecutionRequests; }; }; @@ -233,6 +242,7 @@ export type SignedBeaconBlockOrContents = TypesByFork[F]["ExecutionPayload"]; export type ExecutionPayloadHeader = TypesByFork[F]["ExecutionPayloadHeader"]; +export type ExecutionRequests = TypesByFork[F]["ExecutionRequests"]; export type BlobsBundle = TypesByFork[F]["BlobsBundle"]; export type Contents = TypesByFork[F]["Contents"]; diff --git a/packages/types/src/utils/typeguards.ts b/packages/types/src/utils/typeguards.ts index a5f5b7808ae5..a892c3a0c9c0 100644 --- a/packages/types/src/utils/typeguards.ts +++ b/packages/types/src/utils/typeguards.ts @@ -1,4 +1,4 @@ -import {ForkBlobs, ForkExecution, ForkPostElectra} from "@lodestar/params"; +import {FINALIZED_ROOT_DEPTH_ELECTRA, ForkBlobs, ForkExecution, ForkPostElectra} from "@lodestar/params"; import { BlockContents, SignedBeaconBlock, @@ -76,7 +76,7 @@ export function isElectraAttestation(attestation: Attestation): attestation is A export function isElectraLightClientUpdate(update: LightClientUpdate): update is LightClientUpdate { const updatePostElectra = update as LightClientUpdate; return ( - updatePostElectra.attestedHeader.execution !== undefined && - updatePostElectra.attestedHeader.execution.depositRequestsRoot !== undefined + updatePostElectra.finalityBranch !== undefined && + updatePostElectra.finalityBranch.length === FINALIZED_ROOT_DEPTH_ELECTRA ); } From f1a77eadb7b00218bd8b4eecbbf6ca638ffe3552 Mon Sep 17 00:00:00 2001 From: Nico Flaig Date: Wed, 25 Sep 2024 13:19:34 +0100 Subject: [PATCH 19/52] feat: set proper user-agent in validator client http requests (#7106) --- packages/cli/src/cmds/validator/handler.ts | 1 + 1 file changed, 1 insertion(+) diff --git a/packages/cli/src/cmds/validator/handler.ts b/packages/cli/src/cmds/validator/handler.ts index 01c15126b796..53250c2c9a86 100644 --- a/packages/cli/src/cmds/validator/handler.ts +++ b/packages/cli/src/cmds/validator/handler.ts @@ -157,6 +157,7 @@ export async function validatorHandler(args: IValidatorCliArgs & GlobalArgs): Pr globalInit: { requestWireFormat: parseWireFormat(args, "http.requestWireFormat"), responseWireFormat: parseWireFormat(args, "http.responseWireFormat"), + headers: {"User-Agent": `Lodestar/${version}`}, }, }, logger, From bf607863e11dd96a255e1ab61792d764a6d0dd2a Mon Sep 17 00:00:00 2001 From: Nico Flaig Date: Wed, 25 Sep 2024 21:39:48 +0100 Subject: [PATCH 20/52] chore: remove signing domain for consolidations (#7092) --- packages/beacon-node/src/api/impl/config/constants.ts | 2 -- packages/params/src/index.ts | 1 - 2 files changed, 3 deletions(-) diff --git a/packages/beacon-node/src/api/impl/config/constants.ts b/packages/beacon-node/src/api/impl/config/constants.ts index 4b239ee4cac6..14ecade15b2e 100644 --- a/packages/beacon-node/src/api/impl/config/constants.ts +++ b/packages/beacon-node/src/api/impl/config/constants.ts @@ -37,7 +37,6 @@ import { BLOB_TX_TYPE, VERSIONED_HASH_VERSION_KZG, COMPOUNDING_WITHDRAWAL_PREFIX, - DOMAIN_CONSOLIDATION, UNSET_DEPOSIT_REQUESTS_START_INDEX, FULL_EXIT_REQUEST_AMOUNT, } from "@lodestar/params"; @@ -71,7 +70,6 @@ export const specConstants = { DOMAIN_SELECTION_PROOF, DOMAIN_AGGREGATE_AND_PROOF, DOMAIN_APPLICATION_BUILDER, - DOMAIN_CONSOLIDATION, // phase0/validator.md TARGET_AGGREGATORS_PER_COMMITTEE, diff --git a/packages/params/src/index.ts b/packages/params/src/index.ts index dd5c24ac3a54..aa6e97641526 100644 --- a/packages/params/src/index.ts +++ b/packages/params/src/index.ts @@ -146,7 +146,6 @@ export const DOMAIN_SYNC_COMMITTEE = Uint8Array.from([7, 0, 0, 0]); export const DOMAIN_SYNC_COMMITTEE_SELECTION_PROOF = Uint8Array.from([8, 0, 0, 0]); export const DOMAIN_CONTRIBUTION_AND_PROOF = Uint8Array.from([9, 0, 0, 0]); export const DOMAIN_BLS_TO_EXECUTION_CHANGE = Uint8Array.from([10, 0, 0, 0]); -export const DOMAIN_CONSOLIDATION = Uint8Array.from([11, 0, 0, 0]); // Application specific domains From bb8204606762282036aebb15c216617a4c7df41f Mon Sep 17 00:00:00 2001 From: Nico Flaig Date: Thu, 26 Sep 2024 21:01:37 +0100 Subject: [PATCH 21/52] feat: add electra support for remote signer (#7100) --- .../validator/src/services/validatorStore.ts | 10 +++--- .../src/util/externalSignerClient.ts | 33 +++++++++++++++--- .../validator/test/e2e/web3signer.test.ts | 34 ++++++++++++------- 3 files changed, 56 insertions(+), 21 deletions(-) diff --git a/packages/validator/src/services/validatorStore.ts b/packages/validator/src/services/validatorStore.ts index 6da4f597d87c..ce507349689f 100644 --- a/packages/validator/src/services/validatorStore.ts +++ b/packages/validator/src/services/validatorStore.ts @@ -562,13 +562,13 @@ export class ValidatorStore { const signingSlot = aggregate.data.slot; const domain = this.config.getDomain(signingSlot, DOMAIN_AGGREGATE_AND_PROOF); - const signingRoot = - this.config.getForkSeq(duty.slot) >= ForkSeq.electra - ? computeSigningRoot(ssz.electra.AggregateAndProof, aggregateAndProof, domain) - : computeSigningRoot(ssz.phase0.AggregateAndProof, aggregateAndProof, domain); + const isPostElectra = this.config.getForkSeq(duty.slot) >= ForkSeq.electra; + const signingRoot = isPostElectra + ? computeSigningRoot(ssz.electra.AggregateAndProof, aggregateAndProof, domain) + : computeSigningRoot(ssz.phase0.AggregateAndProof, aggregateAndProof, domain); const signableMessage: SignableMessage = { - type: SignableMessageType.AGGREGATE_AND_PROOF, + type: isPostElectra ? SignableMessageType.AGGREGATE_AND_PROOF_V2 : SignableMessageType.AGGREGATE_AND_PROOF, data: aggregateAndProof, }; diff --git a/packages/validator/src/util/externalSignerClient.ts b/packages/validator/src/util/externalSignerClient.ts index 4fd615ce5280..1d9778375b88 100644 --- a/packages/validator/src/util/externalSignerClient.ts +++ b/packages/validator/src/util/externalSignerClient.ts @@ -1,11 +1,23 @@ import {ContainerType, ValueOf} from "@chainsafe/ssz"; import {fetch} from "@lodestar/api"; -import {phase0, altair, capella, BeaconBlock, BlindedBeaconBlock} from "@lodestar/types"; -import {ForkSeq} from "@lodestar/params"; +import { + phase0, + altair, + capella, + BeaconBlock, + BlindedBeaconBlock, + AggregateAndProof, + sszTypesFor, + ssz, + Slot, + Epoch, + RootHex, + Root, +} from "@lodestar/types"; +import {ForkPreExecution, ForkSeq} from "@lodestar/params"; import {ValidatorRegistrationV1} from "@lodestar/types/bellatrix"; import {BeaconConfig} from "@lodestar/config"; import {computeEpochAtSlot, blindedOrFullBlockToHeader} from "@lodestar/state-transition"; -import {Epoch, Root, RootHex, Slot, ssz} from "@lodestar/types"; import {toHex, toRootHex} from "@lodestar/utils"; import {PubkeyHex} from "../types.js"; @@ -14,6 +26,7 @@ import {PubkeyHex} from "../types.js"; export enum SignableMessageType { AGGREGATION_SLOT = "AGGREGATION_SLOT", AGGREGATE_AND_PROOF = "AGGREGATE_AND_PROOF", + AGGREGATE_AND_PROOF_V2 = "AGGREGATE_AND_PROOF_V2", ATTESTATION = "ATTESTATION", BLOCK_V2 = "BLOCK_V2", DEPOSIT = "DEPOSIT", @@ -63,8 +76,9 @@ const SyncAggregatorSelectionDataType = new ContainerType( export type SignableMessage = | {type: SignableMessageType.AGGREGATION_SLOT; data: {slot: Slot}} | {type: SignableMessageType.AGGREGATE_AND_PROOF; data: phase0.AggregateAndProof} + | {type: SignableMessageType.AGGREGATE_AND_PROOF_V2; data: AggregateAndProof} | {type: SignableMessageType.ATTESTATION; data: phase0.AttestationData} - | {type: SignableMessageType.BLOCK_V2; data: BeaconBlock | BlindedBeaconBlock} + | {type: SignableMessageType.BLOCK_V2; data: BeaconBlock | BlindedBeaconBlock} | {type: SignableMessageType.DEPOSIT; data: ValueOf} | {type: SignableMessageType.RANDAO_REVEAL; data: {epoch: Epoch}} | {type: SignableMessageType.VOLUNTARY_EXIT; data: phase0.VoluntaryExit} @@ -77,6 +91,7 @@ export type SignableMessage = const requiresForkInfo: Record = { [SignableMessageType.AGGREGATION_SLOT]: true, [SignableMessageType.AGGREGATE_AND_PROOF]: true, + [SignableMessageType.AGGREGATE_AND_PROOF_V2]: true, [SignableMessageType.ATTESTATION]: true, [SignableMessageType.BLOCK_V2]: true, [SignableMessageType.DEPOSIT]: false, @@ -203,6 +218,16 @@ function serializerSignableMessagePayload(config: BeaconConfig, payload: Signabl case SignableMessageType.AGGREGATE_AND_PROOF: return {aggregate_and_proof: ssz.phase0.AggregateAndProof.toJson(payload.data)}; + case SignableMessageType.AGGREGATE_AND_PROOF_V2: { + const fork = config.getForkName(payload.data.aggregate.data.slot); + return { + aggregate_and_proof: { + version: fork.toUpperCase(), + data: sszTypesFor(fork).AggregateAndProof.toJson(payload.data), + }, + }; + } + case SignableMessageType.ATTESTATION: return {attestation: ssz.phase0.AttestationData.toJson(payload.data)}; diff --git a/packages/validator/test/e2e/web3signer.test.ts b/packages/validator/test/e2e/web3signer.test.ts index 326dbae8c4f7..ae22bc31446b 100644 --- a/packages/validator/test/e2e/web3signer.test.ts +++ b/packages/validator/test/e2e/web3signer.test.ts @@ -5,7 +5,7 @@ import {computeStartSlotAtEpoch, interopSecretKey, interopSecretKeys} from "@lod import {createBeaconConfig} from "@lodestar/config"; import {genesisData} from "@lodestar/config/networks"; import {getClient, routes} from "@lodestar/api"; -import {ssz} from "@lodestar/types"; +import {ssz, sszTypesFor} from "@lodestar/types"; import {ForkSeq} from "@lodestar/params"; import {getKeystoresStr, StartedExternalSigner, startExternalSigner} from "@lodestar/test-utils"; import {Interchange, ISlashingProtection, Signer, SignerType, ValidatorStore} from "../../src/index.js"; @@ -93,17 +93,27 @@ describe("web3signer signature test", function () { await assertSameSignature("signAttestation", duty, attestationData, epoch); }); - it("signAggregateAndProof", async () => { - const aggregateAndProof = ssz.phase0.AggregateAndProof.defaultValue(); - aggregateAndProof.aggregate.data.slot = duty.slot; - aggregateAndProof.aggregate.data.index = duty.committeeIndex; - await assertSameSignature( - "signAggregateAndProof", - duty, - aggregateAndProof.selectionProof, - aggregateAndProof.aggregate - ); - }); + for (const fork of config.forksAscendingEpochOrder) { + it(`signAggregateAndProof ${fork.name}`, async ({skip}) => { + // Only test till the fork the signer version supports + if (ForkSeq[fork.name] > externalSigner.supportedForkSeq) { + skip(); + return; + } + + const aggregateAndProof = sszTypesFor(fork.name).AggregateAndProof.defaultValue(); + const slot = computeStartSlotAtEpoch(fork.epoch); + aggregateAndProof.aggregate.data.slot = slot; + aggregateAndProof.aggregate.data.index = duty.committeeIndex; + + await assertSameSignature( + "signAggregateAndProof", + {...duty, slot}, + aggregateAndProof.selectionProof, + aggregateAndProof.aggregate + ); + }); + } it("signSyncCommitteeSignature", async () => { const beaconBlockRoot = ssz.phase0.BeaconBlockHeader.defaultValue().bodyRoot; From 58dea7543c846e912a0d7422aee0b836f57a3b7a Mon Sep 17 00:00:00 2001 From: Nico Flaig Date: Thu, 26 Sep 2024 21:59:20 +0100 Subject: [PATCH 22/52] feat: use POST variant to get validators from state (#6897) * feat: use POST variant to get validators from state * Fix api handler used during testing * Update more calls to use POST variant --- .../test/e2e/api/impl/lightclient/endpoint.test.ts | 2 +- .../cli/src/cmds/validator/blsToExecutionChange.ts | 2 +- packages/cli/src/cmds/validator/voluntaryExit.ts | 2 +- packages/cli/test/sim/endpoints.test.ts | 10 +++++----- packages/flare/src/cmds/selfSlashAttester.ts | 4 ++-- packages/flare/src/cmds/selfSlashProposer.ts | 4 ++-- packages/validator/src/services/indices.ts | 12 +++++++----- packages/validator/src/validator.ts | 4 +++- .../validator/test/unit/services/attestation.test.ts | 2 +- .../test/unit/services/attestationDuties.test.ts | 2 +- .../test/unit/services/syncCommitteDuties.test.ts | 2 +- .../test/unit/services/syncCommittee.test.ts | 2 +- packages/validator/test/utils/apiStub.ts | 1 + 13 files changed, 27 insertions(+), 22 deletions(-) diff --git a/packages/beacon-node/test/e2e/api/impl/lightclient/endpoint.test.ts b/packages/beacon-node/test/e2e/api/impl/lightclient/endpoint.test.ts index 81154005af68..c746746741cf 100644 --- a/packages/beacon-node/test/e2e/api/impl/lightclient/endpoint.test.ts +++ b/packages/beacon-node/test/e2e/api/impl/lightclient/endpoint.test.ts @@ -122,7 +122,7 @@ describe("lightclient api", function () { const committeeRes = await lightclient.getLightClientCommitteeRoot({startPeriod: 0, count: 1}); committeeRes.assertOk(); const client = getClient({baseUrl: `http://127.0.0.1:${restPort}`}, {config}).beacon; - const validators = (await client.getStateValidators({stateId: "head"})).value(); + const validators = (await client.postStateValidators({stateId: "head"})).value(); const pubkeys = validators.map((v) => v.validator.pubkey); expect(pubkeys.length).toBe(validatorCount); // only 2 validators spreading to 512 committee slots diff --git a/packages/cli/src/cmds/validator/blsToExecutionChange.ts b/packages/cli/src/cmds/validator/blsToExecutionChange.ts index dc55647fda80..7fbdbb029bf5 100644 --- a/packages/cli/src/cmds/validator/blsToExecutionChange.ts +++ b/packages/cli/src/cmds/validator/blsToExecutionChange.ts @@ -60,7 +60,7 @@ like to choose for BLS To Execution Change.", const {genesisValidatorsRoot} = (await client.beacon.getGenesis()).value(); const config = createBeaconConfig(chainForkConfig, genesisValidatorsRoot); - const validators = (await client.beacon.getStateValidators({stateId: "head", validatorIds: [publicKey]})).value(); + const validators = (await client.beacon.postStateValidators({stateId: "head", validatorIds: [publicKey]})).value(); const validator = validators[0]; if (validator === undefined) { throw new Error(`Validator pubkey ${publicKey} not found in state`); diff --git a/packages/cli/src/cmds/validator/voluntaryExit.ts b/packages/cli/src/cmds/validator/voluntaryExit.ts index a399a763662d..02f1591b59ed 100644 --- a/packages/cli/src/cmds/validator/voluntaryExit.ts +++ b/packages/cli/src/cmds/validator/voluntaryExit.ts @@ -207,7 +207,7 @@ function selectSignersToExit(args: VoluntaryExitArgs, signers: Signer[]): Signer async function resolveValidatorIndexes(client: ApiClient, signersToExit: SignerPubkey[]) { const pubkeys = signersToExit.map(({pubkey}) => pubkey); - const validators = (await client.beacon.getStateValidators({stateId: "head", validatorIds: pubkeys})).value(); + const validators = (await client.beacon.postStateValidators({stateId: "head", validatorIds: pubkeys})).value(); const dataByPubkey = new Map(validators.map((item) => [toPubkeyHex(item.validator.pubkey), item])); diff --git a/packages/cli/test/sim/endpoints.test.ts b/packages/cli/test/sim/endpoints.test.ts index 07cd5fec0cc4..a42b9568f9a3 100644 --- a/packages/cli/test/sim/endpoints.test.ts +++ b/packages/cli/test/sim/endpoints.test.ts @@ -40,7 +40,7 @@ await env.start({runTimeoutMs: estimatedTimeoutMs}); const node = env.nodes[0].beacon; await waitForSlot("Wait for 2 slots before checking endpoints", {env, slot: 2}); -const validators = (await node.api.beacon.getStateValidators({stateId: "head"})).value(); +const validators = (await node.api.beacon.postStateValidators({stateId: "head"})).value(); await env.tracker.assert("should have correct validators count called without filters", async () => { assert.equal(validators.length, validatorCount); @@ -55,12 +55,12 @@ await env.tracker.assert("should have correct validator index for second validat }); await env.tracker.assert( - "should return correct number of filtered validators when getStateValidators called with filters", + "should return correct number of filtered validators when postStateValidators called with filters", async () => { const filterPubKey = "0xa99a76ed7796f7be22d5b7e85deeb7c5677e88e511e0b337618f8c4eb61349b4bf2d153f649f7b53359fe8b94a38e44c"; - const res = await node.api.beacon.getStateValidators({stateId: "head", validatorIds: [filterPubKey]}); + const res = await node.api.beacon.postStateValidators({stateId: "head", validatorIds: [filterPubKey]}); assert.equal(res.value().length, 1); @@ -71,12 +71,12 @@ await env.tracker.assert( ); await env.tracker.assert( - "should return correct filtered validators when getStateValidators called with filters", + "should return correct filtered validators when postStateValidators called with filters", async () => { const filterPubKey = "0xa99a76ed7796f7be22d5b7e85deeb7c5677e88e511e0b337618f8c4eb61349b4bf2d153f649f7b53359fe8b94a38e44c"; - const res = await node.api.beacon.getStateValidators({stateId: "head", validatorIds: [filterPubKey]}); + const res = await node.api.beacon.postStateValidators({stateId: "head", validatorIds: [filterPubKey]}); assert.equal(toHexString(res.value()[0].validator.pubkey), filterPubKey); } diff --git a/packages/flare/src/cmds/selfSlashAttester.ts b/packages/flare/src/cmds/selfSlashAttester.ts index a37c6c765bd3..6ccc9d80a98f 100644 --- a/packages/flare/src/cmds/selfSlashAttester.ts +++ b/packages/flare/src/cmds/selfSlashAttester.ts @@ -79,7 +79,7 @@ export async function selfSlashAttesterHandler(args: SelfSlashArgs): Promise sk.toPublicKey().toHex()); - const validators = (await client.beacon.getStateValidators({stateId: "head", validatorIds: pksHex})).value(); + const validators = (await client.beacon.postStateValidators({stateId: "head", validatorIds: pksHex})).value(); // All validators in the batch will be part of the same AttesterSlashing const attestingIndices = validators.map((v) => v.index); @@ -92,7 +92,7 @@ export async function selfSlashAttesterHandler(args: SelfSlashArgs): Promise sk.toPublicKey().toHex()); - const validators = (await client.beacon.getStateValidators({stateId: "head", validatorIds: pksHex})).value(); + const validators = (await client.beacon.postStateValidators({stateId: "head", validatorIds: pksHex})).value(); // Submit all ProposerSlashing for range at once await Promise.all( @@ -88,7 +88,7 @@ export async function selfSlashProposerHandler(args: SelfSlashArgs): Promise { - const validators = (await this.api.beacon.getStateValidators({stateId: "head", validatorIds: pubkeysHex})).value(); + const validators = (await this.api.beacon.postStateValidators({stateId: "head", validatorIds: pubkeysHex})).value(); const newIndices = []; diff --git a/packages/validator/src/validator.ts b/packages/validator/src/validator.ts index 980e64f7eac2..6ffebff2b3bd 100644 --- a/packages/validator/src/validator.ts +++ b/packages/validator/src/validator.ts @@ -372,7 +372,9 @@ export class Validator { * Create a signed voluntary exit message for the given validator by its key. */ async signVoluntaryExit(publicKey: string, exitEpoch?: number): Promise { - const validators = (await this.api.beacon.getStateValidators({stateId: "head", validatorIds: [publicKey]})).value(); + const validators = ( + await this.api.beacon.postStateValidators({stateId: "head", validatorIds: [publicKey]}) + ).value(); const validator = validators[0]; if (validator === undefined) { diff --git a/packages/validator/test/unit/services/attestation.test.ts b/packages/validator/test/unit/services/attestation.test.ts index 356503cbdd09..66b722273102 100644 --- a/packages/validator/test/unit/services/attestation.test.ts +++ b/packages/validator/test/unit/services/attestation.test.ts @@ -105,7 +105,7 @@ describe("AttestationService", function () { ]; // Return empty replies to duties service - api.beacon.getStateValidators.mockResolvedValue( + api.beacon.postStateValidators.mockResolvedValue( mockApiResponse({data: [], meta: {executionOptimistic: false, finalized: false}}) ); api.validator.getAttesterDuties.mockResolvedValue( diff --git a/packages/validator/test/unit/services/attestationDuties.test.ts b/packages/validator/test/unit/services/attestationDuties.test.ts index 751ebcf11205..a9d50eaf42c6 100644 --- a/packages/validator/test/unit/services/attestationDuties.test.ts +++ b/packages/validator/test/unit/services/attestationDuties.test.ts @@ -52,7 +52,7 @@ describe("AttestationDutiesService", function () { index, validator: {...defaultValidator.validator, pubkey: pubkeys[0]}, }; - api.beacon.getStateValidators.mockResolvedValue( + api.beacon.postStateValidators.mockResolvedValue( mockApiResponse({data: [validatorResponse], meta: {executionOptimistic: false, finalized: false}}) ); }); diff --git a/packages/validator/test/unit/services/syncCommitteDuties.test.ts b/packages/validator/test/unit/services/syncCommitteDuties.test.ts index 10bac3ab2fe9..dc43502d5b57 100644 --- a/packages/validator/test/unit/services/syncCommitteDuties.test.ts +++ b/packages/validator/test/unit/services/syncCommitteDuties.test.ts @@ -60,7 +60,7 @@ describe("SyncCommitteeDutiesService", function () { index: indices[i], validator: {...defaultValidator.validator, pubkey: pubkeys[i]}, })); - api.beacon.getStateValidators.mockResolvedValue( + api.beacon.postStateValidators.mockResolvedValue( mockApiResponse({data: validatorResponses, meta: {executionOptimistic: false, finalized: false}}) ); }); diff --git a/packages/validator/test/unit/services/syncCommittee.test.ts b/packages/validator/test/unit/services/syncCommittee.test.ts index 66e63ab72a6c..449f826c3806 100644 --- a/packages/validator/test/unit/services/syncCommittee.test.ts +++ b/packages/validator/test/unit/services/syncCommittee.test.ts @@ -102,7 +102,7 @@ describe("SyncCommitteeService", function () { ]; // Return empty replies to duties service - api.beacon.getStateValidators.mockResolvedValue( + api.beacon.postStateValidators.mockResolvedValue( mockApiResponse({data: [], meta: {executionOptimistic: false, finalized: false}}) ); api.validator.getSyncCommitteeDuties.mockResolvedValue( diff --git a/packages/validator/test/utils/apiStub.ts b/packages/validator/test/utils/apiStub.ts index ef615af03369..4443dab5c4ac 100644 --- a/packages/validator/test/utils/apiStub.ts +++ b/packages/validator/test/utils/apiStub.ts @@ -16,6 +16,7 @@ export function getApiClientStub(): ApiClientStub { return { beacon: { getStateValidators: vi.fn(), + postStateValidators: vi.fn(), publishBlindedBlockV2: vi.fn(), publishBlockV2: vi.fn(), submitPoolSyncCommitteeSignatures: vi.fn(), From 77006ea0ce9ac043b71b7aaa07b9fae6f38f5250 Mon Sep 17 00:00:00 2001 From: twoeths Date: Fri, 27 Sep 2024 08:15:21 +0700 Subject: [PATCH 23/52] fix: state serialization time (#7109) * fix: release memory to BufferPool * fix: correct the serializeState metric * fix: check types * chore: fix lint --- .../src/chain/archiver/archiveStates.ts | 13 ++++-- .../beacon-node/src/chain/archiver/index.ts | 6 ++- packages/beacon-node/src/chain/chain.ts | 2 +- .../beacon-node/src/chain/serializeState.ts | 11 +++-- .../stateCache/persistentCheckpointsCache.ts | 45 +++++++++++-------- .../src/metrics/metrics/lodestar.ts | 11 ++--- .../stateCache/nHistoricalStates.test.ts | 7 ++- 7 files changed, 55 insertions(+), 40 deletions(-) diff --git a/packages/beacon-node/src/chain/archiver/archiveStates.ts b/packages/beacon-node/src/chain/archiver/archiveStates.ts index 53f2033d80e8..8fd9081ab243 100644 --- a/packages/beacon-node/src/chain/archiver/archiveStates.ts +++ b/packages/beacon-node/src/chain/archiver/archiveStates.ts @@ -8,6 +8,7 @@ import {IStateRegenerator} from "../regen/interface.js"; import {getStateSlotFromBytes} from "../../util/multifork.js"; import {serializeState} from "../serializeState.js"; import {AllocSource, BufferPool} from "../../util/bufferPool.js"; +import {Metrics} from "../../metrics/metrics.js"; /** * Minimum number of epochs between single temp archived states @@ -48,13 +49,13 @@ export class StatesArchiver { * epoch - 1024*2 epoch - 1024 epoch - 32 epoch * ``` */ - async maybeArchiveState(finalized: CheckpointWithHex): Promise { + async maybeArchiveState(finalized: CheckpointWithHex, metrics?: Metrics | null): Promise { const lastStoredSlot = await this.db.stateArchive.lastKey(); const lastStoredEpoch = computeEpochAtSlot(lastStoredSlot ?? 0); const {archiveStateEpochFrequency} = this.opts; if (finalized.epoch - lastStoredEpoch >= Math.min(PERSIST_TEMP_STATE_EVERY_EPOCHS, archiveStateEpochFrequency)) { - await this.archiveState(finalized); + await this.archiveState(finalized, metrics); // Only check the current and previous intervals const minEpoch = Math.max( @@ -86,7 +87,7 @@ export class StatesArchiver { * Archives finalized states from active bucket to archive bucket. * Only the new finalized state is stored to disk */ - async archiveState(finalized: CheckpointWithHex): Promise { + async archiveState(finalized: CheckpointWithHex, metrics?: Metrics | null): Promise { // starting from Mar 2024, the finalized state could be from disk or in memory const finalizedStateOrBytes = await this.regen.getCheckpointStateOrBytes(finalized); const {rootHex} = finalized; @@ -99,10 +100,14 @@ export class StatesArchiver { this.logger.verbose("Archived finalized state bytes", {epoch: finalized.epoch, slot, root: rootHex}); } else { // serialize state using BufferPool if provided + const timer = metrics?.stateSerializeDuration.startTimer({source: AllocSource.ARCHIVE_STATE}); await serializeState( finalizedStateOrBytes, AllocSource.ARCHIVE_STATE, - (stateBytes) => this.db.stateArchive.putBinary(finalizedStateOrBytes.slot, stateBytes), + (stateBytes) => { + timer?.(); + return this.db.stateArchive.putBinary(finalizedStateOrBytes.slot, stateBytes); + }, this.bufferPool ); // don't delete states before the finalized state, auto-prune will take care of it diff --git a/packages/beacon-node/src/chain/archiver/index.ts b/packages/beacon-node/src/chain/archiver/index.ts index 294c2281e19b..45169b2fa802 100644 --- a/packages/beacon-node/src/chain/archiver/index.ts +++ b/packages/beacon-node/src/chain/archiver/index.ts @@ -4,6 +4,7 @@ import {IBeaconDb} from "../../db/index.js"; import {JobItemQueue} from "../../util/queue/index.js"; import {IBeaconChain} from "../interface.js"; import {ChainEvent} from "../emitter.js"; +import {Metrics} from "../../metrics/metrics.js"; import {StatesArchiver, StatesArchiverOpts} from "./archiveStates.js"; import {archiveBlocks} from "./archiveBlocks.js"; @@ -45,7 +46,8 @@ export class Archiver { private readonly chain: IBeaconChain, private readonly logger: Logger, signal: AbortSignal, - opts: ArchiverOpts + opts: ArchiverOpts, + private readonly metrics?: Metrics | null ) { this.archiveBlobEpochs = opts.archiveBlobEpochs; this.statesArchiver = new StatesArchiver(chain.regen, db, logger, opts, chain.bufferPool); @@ -105,7 +107,7 @@ export class Archiver { this.prevFinalized = finalized; // should be after ArchiveBlocksTask to handle restart cleanly - await this.statesArchiver.maybeArchiveState(finalized); + await this.statesArchiver.maybeArchiveState(finalized, this.metrics); this.chain.regen.pruneOnFinalized(finalizedEpoch); diff --git a/packages/beacon-node/src/chain/chain.ts b/packages/beacon-node/src/chain/chain.ts index 0b0ac30edf40..696f4bd51dc3 100644 --- a/packages/beacon-node/src/chain/chain.ts +++ b/packages/beacon-node/src/chain/chain.ts @@ -345,7 +345,7 @@ export class BeaconChain implements IBeaconChain { this.bls = bls; this.emitter = emitter; - this.archiver = new Archiver(db, this, logger, signal, opts); + this.archiver = new Archiver(db, this, logger, signal, opts, metrics); // always run PrepareNextSlotScheduler except for fork_choice spec tests if (!opts?.disablePrepareNextSlot) { new PrepareNextSlotScheduler(this, this.config, metrics, this.logger, signal); diff --git a/packages/beacon-node/src/chain/serializeState.ts b/packages/beacon-node/src/chain/serializeState.ts index cbb2ecd18cff..c6e796cd614c 100644 --- a/packages/beacon-node/src/chain/serializeState.ts +++ b/packages/beacon-node/src/chain/serializeState.ts @@ -15,19 +15,18 @@ export async function serializeState( const size = state.type.tree_serializedSize(state.node); let stateBytes: Uint8Array | null = null; if (bufferPool) { - const bufferWithKey = bufferPool.alloc(size, source); + using bufferWithKey = bufferPool.alloc(size, source); if (bufferWithKey) { stateBytes = bufferWithKey.buffer; const dataView = new DataView(stateBytes.buffer, stateBytes.byteOffset, stateBytes.byteLength); state.serializeToBytes({uint8Array: stateBytes, dataView}, 0); + return processFn(stateBytes); } + // release the buffer back to the pool automatically } - if (!stateBytes) { - // we already have metrics in BufferPool so no need to do it here - stateBytes = state.serialize(); - } + // we already have metrics in BufferPool so no need to do it here + stateBytes = state.serialize(); return processFn(stateBytes); - // release the buffer back to the pool automatically } diff --git a/packages/beacon-node/src/chain/stateCache/persistentCheckpointsCache.ts b/packages/beacon-node/src/chain/stateCache/persistentCheckpointsCache.ts index 74e85e6fa574..07c96f224bee 100644 --- a/packages/beacon-node/src/chain/stateCache/persistentCheckpointsCache.ts +++ b/packages/beacon-node/src/chain/stateCache/persistentCheckpointsCache.ts @@ -94,7 +94,7 @@ export class PersistentCheckpointStateCache implements CheckpointStateCache { private readonly cache: MapTracker; /** Epoch -> Set */ private readonly epochIndex = new MapDef>(() => new Set()); - private readonly metrics: Metrics["cpStateCache"] | null | undefined; + private readonly metrics: Metrics | null | undefined; private readonly logger: Logger; private readonly clock: IClock | null | undefined; private readonly signal: AbortSignal | undefined; @@ -123,7 +123,7 @@ export class PersistentCheckpointStateCache implements CheckpointStateCache { ) { this.cache = new MapTracker(metrics?.cpStateCache); if (metrics) { - this.metrics = metrics.cpStateCache; + this.metrics = metrics; metrics.cpStateCache.size.addCollect(() => { let persistCount = 0; let inMemoryCount = 0; @@ -194,24 +194,26 @@ export class PersistentCheckpointStateCache implements CheckpointStateCache { const {persistedKey, stateBytes} = stateOrStateBytesData; const logMeta = {persistedKey: toHex(persistedKey)}; this.logger.debug("Reload: read state successful", logMeta); - this.metrics?.stateReloadSecFromSlot.observe(this.clock?.secFromSlot(this.clock?.currentSlot ?? 0) ?? 0); + this.metrics?.cpStateCache.stateReloadSecFromSlot.observe( + this.clock?.secFromSlot(this.clock?.currentSlot ?? 0) ?? 0 + ); const seedState = this.findSeedStateToReload(cp); - this.metrics?.stateReloadEpochDiff.observe(Math.abs(seedState.epochCtx.epoch - cp.epoch)); + this.metrics?.cpStateCache.stateReloadEpochDiff.observe(Math.abs(seedState.epochCtx.epoch - cp.epoch)); this.logger.debug("Reload: found seed state", {...logMeta, seedSlot: seedState.slot}); try { // 80% of validators serialization time comes from memory allocation, this is to avoid it - const sszTimer = this.metrics?.stateReloadValidatorsSerializeDuration.startTimer(); + const sszTimer = this.metrics?.cpStateCache.stateReloadValidatorsSerializeDuration.startTimer(); // automatically free the buffer pool after this scope using validatorsBytesWithKey = this.serializeStateValidators(seedState); let validatorsBytes = validatorsBytesWithKey?.buffer; if (validatorsBytes == null) { // fallback logic in case we can't use the buffer pool - this.metrics?.stateReloadValidatorsSerializeAllocCount.inc(); + this.metrics?.cpStateCache.stateReloadValidatorsSerializeAllocCount.inc(); validatorsBytes = seedState.validators.serialize(); } sszTimer?.(); - const timer = this.metrics?.stateReloadDuration.startTimer(); + const timer = this.metrics?.cpStateCache.stateReloadDuration.startTimer(); const newCachedState = loadCachedBeaconState(seedState, stateBytes, {}, validatorsBytes); newCachedState.commit(); const stateRoot = toRootHex(newCachedState.hashTreeRoot()); @@ -275,7 +277,7 @@ export class PersistentCheckpointStateCache implements CheckpointStateCache { } const persistedKey = cacheItem.value; - const dbReadTimer = this.metrics?.stateReloadDbReadTime.startTimer(); + const dbReadTimer = this.metrics?.cpStateCache.stateReloadDbReadTime.startTimer(); const stateBytes = await this.datastore.read(persistedKey); dbReadTimer?.(); @@ -289,7 +291,7 @@ export class PersistentCheckpointStateCache implements CheckpointStateCache { * Similar to get() api without reloading from disk */ get(cpOrKey: CheckpointHex | string, opts?: StateCloneOpts): CachedBeaconStateAllForks | null { - this.metrics?.lookups.inc(); + this.metrics?.cpStateCache.lookups.inc(); const cpKey = typeof cpOrKey === "string" ? cpOrKey : toCacheKey(cpOrKey); const cacheItem = this.cache.get(cpKey); @@ -297,7 +299,7 @@ export class PersistentCheckpointStateCache implements CheckpointStateCache { return null; } - this.metrics?.hits.inc(); + this.metrics?.cpStateCache.hits.inc(); if (cpKey === this.preComputedCheckpoint) { this.preComputedCheckpointHits = (this.preComputedCheckpointHits ?? 0) + 1; @@ -305,7 +307,7 @@ export class PersistentCheckpointStateCache implements CheckpointStateCache { if (isInMemoryCacheItem(cacheItem)) { const {state} = cacheItem; - this.metrics?.stateClonedCount.observe(state.clonedCount); + this.metrics?.cpStateCache.stateClonedCount.observe(state.clonedCount); return state.clone(opts?.dontTransferCache); } @@ -319,7 +321,7 @@ export class PersistentCheckpointStateCache implements CheckpointStateCache { const cpHex = toCheckpointHex(cp); const key = toCacheKey(cpHex); const cacheItem = this.cache.get(key); - this.metrics?.adds.inc(); + this.metrics?.cpStateCache.adds.inc(); if (cacheItem !== undefined && isPersistedCacheItem(cacheItem)) { const persistedKey = cacheItem.value; // was persisted to disk, set back to memory @@ -683,7 +685,9 @@ export class PersistentCheckpointStateCache implements CheckpointStateCache { this.logger.verbose("Pruned checkpoint state from memory but no need to persist", logMeta); } else { // persist and do not update epochIndex - this.metrics?.statePersistSecFromSlot.observe(this.clock?.secFromSlot(this.clock?.currentSlot ?? 0) ?? 0); + this.metrics?.cpStateCache.statePersistSecFromSlot.observe( + this.clock?.secFromSlot(this.clock?.currentSlot ?? 0) ?? 0 + ); const cpPersist = {epoch: epoch, root: fromHex(rootHex)}; // It's not sustainable to allocate ~240MB for each state every epoch, so we use buffer pool to reuse the memory. // As monitored on holesky as of Jan 2024: @@ -691,14 +695,19 @@ export class PersistentCheckpointStateCache implements CheckpointStateCache { // - It helps stabilize persist time and save ~300ms in average (1.5s vs 1.2s) // - It also helps the state reload to save ~500ms in average (4.3s vs 3.8s) // - Also `serializeState.test.ts` perf test shows a lot of differences allocating ~240MB once vs per state serialization - const timer = this.metrics?.stateSerializeDuration.startTimer(); + const timer = this.metrics?.stateSerializeDuration.startTimer({ + source: AllocSource.PERSISTENT_CHECKPOINTS_CACHE_STATE, + }); persistedKey = await serializeState( state, AllocSource.PERSISTENT_CHECKPOINTS_CACHE_STATE, - (stateBytes) => this.datastore.write(cpPersist, stateBytes), + (stateBytes) => { + timer?.(); + return this.datastore.write(cpPersist, stateBytes); + }, this.bufferPool ); - timer?.(); + persistCount++; this.logger.verbose("Pruned checkpoint state from memory and persisted to disk", { ...logMeta, @@ -718,7 +727,7 @@ export class PersistentCheckpointStateCache implements CheckpointStateCache { this.cache.delete(cpKey); this.epochIndex.get(epoch)?.delete(rootHex); } - this.metrics?.statePruneFromMemoryCount.inc(); + this.metrics?.cpStateCache.statePruneFromMemoryCount.inc(); this.logger.verbose("Pruned checkpoint state from memory", logMeta); } } @@ -742,7 +751,7 @@ export class PersistentCheckpointStateCache implements CheckpointStateCache { if (persistedKey) { await this.datastore.remove(persistedKey); persistCount++; - this.metrics?.persistedStateRemoveCount.inc(); + this.metrics?.cpStateCache.persistedStateRemoveCount.inc(); } } this.cache.delete(key); diff --git a/packages/beacon-node/src/metrics/metrics/lodestar.ts b/packages/beacon-node/src/metrics/metrics/lodestar.ts index fb4ea61b6523..bac740b7ee04 100644 --- a/packages/beacon-node/src/metrics/metrics/lodestar.ts +++ b/packages/beacon-node/src/metrics/metrics/lodestar.ts @@ -1218,11 +1218,6 @@ export function createLodestarMetrics( help: "Histogram of cloned count per state every time state.clone() is called", buckets: [1, 2, 5, 10, 50, 250], }), - stateSerializeDuration: register.histogram({ - name: "lodestar_cp_state_cache_state_serialize_seconds", - help: "Histogram of time to serialize state to db", - buckets: [0.1, 0.5, 1, 2, 3, 4], - }), numStatesUpdated: register.histogram({ name: "lodestar_cp_state_cache_state_updated_count", help: "Histogram of number of state cache items updated every time removing and adding pubkeys to pubkey cache", @@ -1434,6 +1429,12 @@ export function createLodestarMetrics( name: "lodestar_unhandled_promise_rejections_total", help: "UnhandledPromiseRejection total count", }), + stateSerializeDuration: register.histogram<{source: AllocSource}>({ + name: "lodestar_state_serialize_seconds", + help: "Histogram of time to serialize state", + labelNames: ["source"], + buckets: [0.1, 0.5, 1, 2, 3, 4], + }), // regen.getState metrics regenGetState: { diff --git a/packages/beacon-node/test/e2e/chain/stateCache/nHistoricalStates.test.ts b/packages/beacon-node/test/e2e/chain/stateCache/nHistoricalStates.test.ts index 005b28baeefc..fd14b7b8b8c0 100644 --- a/packages/beacon-node/test/e2e/chain/stateCache/nHistoricalStates.test.ts +++ b/packages/beacon-node/test/e2e/chain/stateCache/nHistoricalStates.test.ts @@ -412,11 +412,10 @@ describe("regen/reload states with n-historical states configuration", function )?.value ).toEqual(reloadCount); - const stateSszMetricValues = await (followupBn.metrics?.cpStateCache.stateSerializeDuration as Histogram).get(); + const stateSszMetricValues = await (followupBn.metrics?.stateSerializeDuration as Histogram).get(); expect( - stateSszMetricValues?.values.find( - (value) => value.metricName === "lodestar_cp_state_cache_state_serialize_seconds_count" - )?.value + stateSszMetricValues?.values.find((value) => value.metricName === "lodestar_state_serialize_seconds_count") + ?.value ).toEqual(persistCount); // assert number of persisted/in-memory states From 94b6c5b0db4e60c7406309367f5b2d7253e8d3c5 Mon Sep 17 00:00:00 2001 From: Nico Flaig Date: Fri, 27 Sep 2024 19:39:18 +0100 Subject: [PATCH 24/52] chore: use signing slot to determine fork (#7112) --- packages/validator/src/services/validatorStore.ts | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/packages/validator/src/services/validatorStore.ts b/packages/validator/src/services/validatorStore.ts index ce507349689f..c2b18bfd7e09 100644 --- a/packages/validator/src/services/validatorStore.ts +++ b/packages/validator/src/services/validatorStore.ts @@ -531,7 +531,7 @@ export class ValidatorStore { data: attestationData, }; - if (this.config.getForkSeq(duty.slot) >= ForkSeq.electra) { + if (this.config.getForkSeq(signingSlot) >= ForkSeq.electra) { return { aggregationBits: BitArray.fromSingleBit(duty.committeeLength, duty.validatorCommitteeIndex), data: attestationData, @@ -562,7 +562,7 @@ export class ValidatorStore { const signingSlot = aggregate.data.slot; const domain = this.config.getDomain(signingSlot, DOMAIN_AGGREGATE_AND_PROOF); - const isPostElectra = this.config.getForkSeq(duty.slot) >= ForkSeq.electra; + const isPostElectra = this.config.getForkSeq(signingSlot) >= ForkSeq.electra; const signingRoot = isPostElectra ? computeSigningRoot(ssz.electra.AggregateAndProof, aggregateAndProof, domain) : computeSigningRoot(ssz.phase0.AggregateAndProof, aggregateAndProof, domain); @@ -802,7 +802,7 @@ export class ValidatorStore { throw Error(`Inconsistent duties during signing: duty.slot ${duty.slot} != att.slot ${data.slot}`); } - const isPostElectra = this.config.getForkSeq(duty.slot) >= ForkSeq.electra; + const isPostElectra = this.config.getForkSeq(data.slot) >= ForkSeq.electra; if (!isPostElectra && duty.committeeIndex != data.index) { throw Error( `Inconsistent duties during signing: duty.committeeIndex ${duty.committeeIndex} != att.committeeIndex ${data.index}` From f87ee1ab5613409748bff29c11249eae28736c4a Mon Sep 17 00:00:00 2001 From: Nico Flaig Date: Fri, 27 Sep 2024 20:05:09 +0100 Subject: [PATCH 25/52] feat: add validator identities endpoint (#7107) * feat: add validator identities endpoint * Test against official spec release from beacon-apis repo * Prepopulate validatorIdentities in else clause * Log warning if validator index can't be resolved --- .../api/src/beacon/routes/beacon/index.ts | 1 + .../api/src/beacon/routes/beacon/state.ts | 52 +++++++++++++++++++ .../api/test/unit/beacon/oapiSpec.test.ts | 4 +- .../api/test/unit/beacon/testData/beacon.ts | 7 +++ .../src/api/impl/beacon/state/index.ts | 38 +++++++++++++- 5 files changed, 99 insertions(+), 3 deletions(-) diff --git a/packages/api/src/beacon/routes/beacon/index.ts b/packages/api/src/beacon/routes/beacon/index.ts index f70792f9d76f..39d7d995dfb1 100644 --- a/packages/api/src/beacon/routes/beacon/index.ts +++ b/packages/api/src/beacon/routes/beacon/index.ts @@ -25,6 +25,7 @@ export type { export type { StateId, ValidatorId, + ValidatorIdentities, ValidatorStatus, FinalityCheckpoints, ValidatorResponse, diff --git a/packages/api/src/beacon/routes/beacon/state.ts b/packages/api/src/beacon/routes/beacon/state.ts index 4f8d414f5b6c..e3cfe2e16edf 100644 --- a/packages/api/src/beacon/routes/beacon/state.ts +++ b/packages/api/src/beacon/routes/beacon/state.ts @@ -53,6 +53,14 @@ export const ValidatorResponseType = new ContainerType({ status: new StringType(), validator: ssz.phase0.Validator, }); +export const ValidatorIdentityType = new ContainerType( + { + index: ssz.ValidatorIndex, + pubkey: ssz.BLSPubkey, + activationEpoch: ssz.UintNum64, + }, + {jsonCase: "eth2"} +); export const EpochCommitteeResponseType = new ContainerType({ index: ssz.CommitteeIndex, slot: ssz.Slot, @@ -73,6 +81,7 @@ export const EpochSyncCommitteeResponseType = new ContainerType( {jsonCase: "eth2"} ); export const ValidatorResponseListType = ArrayOf(ValidatorResponseType); +export const ValidatorIdentitiesType = ArrayOf(ValidatorIdentityType); export const EpochCommitteeResponseListType = ArrayOf(EpochCommitteeResponseType); export const ValidatorBalanceListType = ArrayOf(ValidatorBalanceType); @@ -84,6 +93,7 @@ export type ValidatorBalance = ValueOf; export type EpochSyncCommitteeResponse = ValueOf; export type ValidatorResponseList = ValueOf; +export type ValidatorIdentities = ValueOf; export type EpochCommitteeResponseList = ValueOf; export type ValidatorBalanceList = ValueOf; @@ -191,6 +201,26 @@ export type Endpoints = { ExecutionOptimisticAndFinalizedMeta >; + /** + * Get validator identities from state + * + * Returns filterable list of validators identities. + * + * Identities will be returned for all indices or public keys that match known validators. If an index or public key does not + * match any known validator, no identity will be returned but this will not cause an error. There are no guarantees for the + * returned data in terms of ordering. + */ + postStateValidatorIdentities: Endpoint< + "POST", + StateArgs & { + /** An array of values, with each value either a hex encoded public key (any bytes48 with 0x prefix) or a validator index */ + validatorIds?: ValidatorId[]; + }, + {params: {state_id: string}; body: string[]}, + ValidatorIdentities, + ExecutionOptimisticAndFinalizedMeta + >; + /** * Get validator balances from state * Returns filterable list of validator balances. @@ -404,6 +434,28 @@ export function getDefinitions(_config: ChainForkConfig): RouteDefinitions ({ + params: {state_id: stateId.toString()}, + body: toValidatorIdsStr(validatorIds) || [], + }), + parseReqJson: ({params, body = []}) => ({ + stateId: params.state_id, + validatorIds: fromValidatorIdsStr(body), + }), + schema: { + params: {state_id: Schema.StringRequired}, + body: Schema.UintOrStringArray, + }, + }), + resp: { + data: ValidatorIdentitiesType, + meta: ExecutionOptimisticAndFinalizedCodec, + }, + }, getStateValidatorBalances: { url: "/eth/v1/beacon/states/{state_id}/validator_balances", method: "GET", diff --git a/packages/api/test/unit/beacon/oapiSpec.test.ts b/packages/api/test/unit/beacon/oapiSpec.test.ts index a84b2cc36767..89079cd0768c 100644 --- a/packages/api/test/unit/beacon/oapiSpec.test.ts +++ b/packages/api/test/unit/beacon/oapiSpec.test.ts @@ -21,9 +21,9 @@ import {testData as validatorTestData} from "./testData/validator.js"; // eslint-disable-next-line @typescript-eslint/naming-convention const __dirname = path.dirname(fileURLToPath(import.meta.url)); -const version = "v2.6.0-alpha.1"; +const version = "v3.0.0-alpha.6"; const openApiFile: OpenApiFile = { - url: `https://raw.githubusercontent.com/nflaig/beacon-api-spec/main/${version}/beacon-node-oapi.json`, + url: `https://github.com/ethereum/beacon-APIs/releases/download/${version}/beacon-node-oapi.json`, filepath: path.join(__dirname, "../../../oapi-schemas/beacon-node-oapi.json"), version: RegExp(version), }; diff --git a/packages/api/test/unit/beacon/testData/beacon.ts b/packages/api/test/unit/beacon/testData/beacon.ts index b0e958f4bc58..23ab13147454 100644 --- a/packages/api/test/unit/beacon/testData/beacon.ts +++ b/packages/api/test/unit/beacon/testData/beacon.ts @@ -191,6 +191,13 @@ export const testData: GenericServerTestCases = { args: {stateId: "head", validatorIds: [pubkeyHex, 1300], statuses: ["active_ongoing"]}, res: {data: [validatorResponse], meta: {executionOptimistic: true, finalized: false}}, }, + postStateValidatorIdentities: { + args: {stateId: "head", validatorIds: [1300]}, + res: { + data: [{index: 1300, pubkey: ssz.BLSPubkey.defaultValue(), activationEpoch: 1}], + meta: {executionOptimistic: true, finalized: false}, + }, + }, getStateValidator: { args: {stateId: "head", validatorId: pubkeyHex}, res: {data: validatorResponse, meta: {executionOptimistic: true, finalized: false}}, diff --git a/packages/beacon-node/src/api/impl/beacon/state/index.ts b/packages/beacon-node/src/api/impl/beacon/state/index.ts index 77e2fd5aab46..a5e46a2da4c0 100644 --- a/packages/beacon-node/src/api/impl/beacon/state/index.ts +++ b/packages/beacon-node/src/api/impl/beacon/state/index.ts @@ -22,7 +22,8 @@ import { export function getBeaconStateApi({ chain, config, -}: Pick): ApplicationMethods { + logger, +}: Pick): ApplicationMethods { async function getState( stateId: routes.beacon.StateId ): Promise<{state: BeaconStateAllForks; executionOptimistic: boolean; finalized: boolean}> { @@ -98,6 +99,8 @@ export function getBeaconStateApi({ currentEpoch ); validatorResponses.push(validatorResponse); + } else { + logger.warn(resp.reason, {id}); } } return { @@ -130,6 +133,39 @@ export function getBeaconStateApi({ return this.getStateValidators(args, context); }, + async postStateValidatorIdentities({stateId, validatorIds = []}) { + const {state, executionOptimistic, finalized} = await getStateResponse(chain, stateId); + const {pubkey2index} = chain.getHeadState().epochCtx; + + let validatorIdentities: routes.beacon.ValidatorIdentities; + + if (validatorIds.length) { + validatorIdentities = []; + for (const id of validatorIds) { + const resp = getStateValidatorIndex(id, state, pubkey2index); + if (resp.valid) { + const index = resp.validatorIndex; + const {pubkey, activationEpoch} = state.validators.getReadonly(index); + validatorIdentities.push({index, pubkey, activationEpoch}); + } else { + logger.warn(resp.reason, {id}); + } + } + } else { + const validatorsArr = state.validators.getAllReadonlyValues(); + validatorIdentities = new Array(validatorsArr.length) as routes.beacon.ValidatorIdentities; + for (let i = 0; i < validatorsArr.length; i++) { + const {pubkey, activationEpoch} = validatorsArr[i]; + validatorIdentities[i] = {index: i, pubkey, activationEpoch}; + } + } + + return { + data: validatorIdentities, + meta: {executionOptimistic, finalized}, + }; + }, + async getStateValidator({stateId, validatorId}) { const {state, executionOptimistic, finalized} = await getStateResponse(chain, stateId); const {pubkey2index} = chain.getHeadState().epochCtx; From 13d1a378b831b9d0a3f3ced89e317aa45147023c Mon Sep 17 00:00:00 2001 From: twoeths Date: Mon, 30 Sep 2024 08:59:55 +0700 Subject: [PATCH 26/52] fix: n-historical-states state serialization panel (#7111) --- dashboards/lodestar_state_cache_regen.json | 79 ++++++++++++++-------- 1 file changed, 52 insertions(+), 27 deletions(-) diff --git a/dashboards/lodestar_state_cache_regen.json b/dashboards/lodestar_state_cache_regen.json index 426cde226022..1cca1d26c561 100644 --- a/dashboards/lodestar_state_cache_regen.json +++ b/dashboards/lodestar_state_cache_regen.json @@ -425,7 +425,32 @@ }, "mappings": [] }, - "overrides": [] + "overrides": [ + { + "__systemRef": "hideSeriesFrom", + "matcher": { + "id": "byNames", + "options": { + "mode": "exclude", + "names": [ + "epochs_in-memory" + ], + "prefix": "All except:", + "readOnly": true + } + }, + "properties": [ + { + "id": "custom.hideFrom", + "value": { + "legend": false, + "tooltip": false, + "viz": true + } + } + ] + } + ] }, "gridPos": { "h": 8, @@ -1325,30 +1350,6 @@ "value": "none" } ] - }, - { - "__systemRef": "hideSeriesFrom", - "matcher": { - "id": "byNames", - "options": { - "mode": "exclude", - "names": [ - "sec_from_slot" - ], - "prefix": "All except:", - "readOnly": true - } - }, - "properties": [ - { - "id": "custom.hideFrom", - "value": { - "legend": false, - "tooltip": false, - "viz": true - } - } - ] } ] }, @@ -1378,7 +1379,7 @@ "uid": "${DS_PROMETHEUS}" }, "editorMode": "code", - "expr": "rate(lodestar_cp_state_cache_state_serialize_seconds_sum[$rate_interval])\n/\nrate(lodestar_cp_state_cache_state_serialize_seconds_count[$rate_interval])", + "expr": "rate(lodestar_state_serialize_seconds_sum{source=\"persistent_checkpoints_cache_state\"}[$rate_interval])\n/\nrate(lodestar_state_serialize_seconds_count{source=\"persistent_checkpoints_cache_state\"}[$rate_interval])", "hide": false, "instant": false, "legendFormat": "serialize_duration", @@ -1475,6 +1476,30 @@ "id": "unit" } ] + }, + { + "__systemRef": "hideSeriesFrom", + "matcher": { + "id": "byNames", + "options": { + "mode": "exclude", + "names": [ + "reload_duration" + ], + "prefix": "All except:", + "readOnly": true + } + }, + "properties": [ + { + "id": "custom.hideFrom", + "value": { + "legend": false, + "tooltip": false, + "viz": true + } + } + ] } ] }, @@ -1618,7 +1643,7 @@ "options": { "mode": "exclude", "names": [ - "from_persistent" + "from_memory" ], "prefix": "All except:", "readOnly": true From d69d809e7ab5d5a2cf5030429e83b6af1d5af31a Mon Sep 17 00:00:00 2001 From: NC <17676176+ensi321@users.noreply.github.com> Date: Sun, 29 Sep 2024 19:58:19 -0700 Subject: [PATCH 27/52] feat: update correlation penalty computation (#7071) * Update slashing calculation to be more aligned with spec style * Update calculation * Lint * Fix rounding issue * Update calculation * Enable slashing spec test * lint --- .../beacon-node/test/spec/utils/specTestIterator.ts | 2 -- .../state-transition/src/epoch/processSlashings.ts | 12 ++++++++++-- 2 files changed, 10 insertions(+), 4 deletions(-) diff --git a/packages/beacon-node/test/spec/utils/specTestIterator.ts b/packages/beacon-node/test/spec/utils/specTestIterator.ts index bd5142627e3f..d8b4f9c0574c 100644 --- a/packages/beacon-node/test/spec/utils/specTestIterator.ts +++ b/packages/beacon-node/test/spec/utils/specTestIterator.ts @@ -66,8 +66,6 @@ export const defaultSkipOpts: SkipOpts = { /^capella\/light_client\/single_merkle_proof\/BeaconBlockBody.*/, /^deneb\/light_client\/single_merkle_proof\/BeaconBlockBody.*/, /^electra\/light_client\/single_merkle_proof\/BeaconBlockBody.*/, - // TODO Electra: slashings tests to be enabled in PR#7071 - /^electra\/epoch_processing\/slashings.*/, ], skippedTests: [], skippedRunners: ["merkle_proof", "networking"], diff --git a/packages/state-transition/src/epoch/processSlashings.ts b/packages/state-transition/src/epoch/processSlashings.ts index ba4b483dffc2..23ee815cabb3 100644 --- a/packages/state-transition/src/epoch/processSlashings.ts +++ b/packages/state-transition/src/epoch/processSlashings.ts @@ -50,6 +50,10 @@ export function processSlashings( totalBalanceByIncrement ); const increment = EFFECTIVE_BALANCE_INCREMENT; + + const penaltyPerEffectiveBalanceIncrement = Math.floor( + (adjustedTotalSlashingBalanceByIncrement * increment) / totalBalanceByIncrement + ); const penalties: number[] = []; const penaltiesByEffectiveBalanceIncrement = new Map(); @@ -57,8 +61,12 @@ export function processSlashings( const effectiveBalanceIncrement = effectiveBalanceIncrements[index]; let penalty = penaltiesByEffectiveBalanceIncrement.get(effectiveBalanceIncrement); if (penalty === undefined) { - const penaltyNumeratorByIncrement = effectiveBalanceIncrement * adjustedTotalSlashingBalanceByIncrement; - penalty = Math.floor(penaltyNumeratorByIncrement / totalBalanceByIncrement) * increment; + if (fork < ForkSeq.electra) { + const penaltyNumeratorByIncrement = effectiveBalanceIncrement * adjustedTotalSlashingBalanceByIncrement; + penalty = Math.floor(penaltyNumeratorByIncrement / totalBalanceByIncrement) * increment; + } else { + penalty = penaltyPerEffectiveBalanceIncrement * effectiveBalanceIncrement; + } penaltiesByEffectiveBalanceIncrement.set(effectiveBalanceIncrement, penalty); } From fe7e21be0459dfba49ebe04e5a3efc1b1ee836d4 Mon Sep 17 00:00:00 2001 From: twoeths Date: Mon, 30 Sep 2024 23:09:52 +0700 Subject: [PATCH 28/52] feat: use napi-rs pubkey-index-map (#7091) * feat: use napi-rs pubkey-index-map * fix: export toMemoryEfficientHexStr() * fix: state-transition CachedBeaconState unit test * chore: remove commented code --- packages/beacon-node/package.json | 1 + .../src/api/impl/beacon/state/index.ts | 3 +- .../src/api/impl/beacon/state/utils.ts | 5 +-- .../src/api/impl/validator/index.ts | 2 +- packages/beacon-node/src/chain/chain.ts | 2 +- .../historicalState/getHistoricalState.ts | 2 +- .../src/chain/historicalState/worker.ts | 8 ++--- packages/beacon-node/src/chain/interface.ts | 2 +- .../src/chain/rewards/attestationsRewards.ts | 3 +- .../updateUnfinalizedPubkeys.test.ts | 17 +++++---- .../unit/api/impl/beacon/state/utils.test.ts | 8 ++++- packages/beacon-node/test/utils/state.ts | 2 +- packages/state-transition/package.json | 1 + .../src/block/processConsolidationRequest.ts | 2 +- .../src/block/processDeposit.ts | 2 +- .../src/block/processWithdrawalRequest.ts | 2 +- .../state-transition/src/cache/epochCache.ts | 15 ++++---- .../state-transition/src/cache/pubkeyCache.ts | 21 +---------- .../src/cache/syncCommitteeCache.ts | 4 +-- packages/state-transition/src/index.ts | 2 +- packages/state-transition/test/perf/util.ts | 2 +- .../perf/util/loadState/loadState.test.ts | 3 +- .../test/unit/cachedBeaconState.test.ts | 4 +-- .../test/unit/upgradeState.test.ts | 2 +- .../test/unit/util/cachedBeaconState.test.ts | 3 +- packages/state-transition/test/utils/state.ts | 2 +- yarn.lock | 36 +++++++++++++++++++ 27 files changed, 94 insertions(+), 62 deletions(-) diff --git a/packages/beacon-node/package.json b/packages/beacon-node/package.json index f101206bfd9e..4deaf7c6ac16 100644 --- a/packages/beacon-node/package.json +++ b/packages/beacon-node/package.json @@ -105,6 +105,7 @@ "@chainsafe/prometheus-gc-stats": "^1.0.0", "@chainsafe/ssz": "^0.17.1", "@chainsafe/threads": "^1.11.1", + "@chainsafe/pubkey-index-map": "2.0.0", "@ethersproject/abi": "^5.7.0", "@fastify/bearer-auth": "^10.0.1", "@fastify/cors": "^10.0.1", diff --git a/packages/beacon-node/src/api/impl/beacon/state/index.ts b/packages/beacon-node/src/api/impl/beacon/state/index.ts index a5e46a2da4c0..669aaa9d1fb3 100644 --- a/packages/beacon-node/src/api/impl/beacon/state/index.ts +++ b/packages/beacon-node/src/api/impl/beacon/state/index.ts @@ -9,6 +9,7 @@ import { getRandaoMix, } from "@lodestar/state-transition"; import {EPOCHS_PER_HISTORICAL_VECTOR} from "@lodestar/params"; +import {fromHex} from "@lodestar/utils"; import {ApiError} from "../../errors.js"; import {ApiModules} from "../../types.js"; import { @@ -200,7 +201,7 @@ export function getBeaconStateApi({ } balances.push({index: id, balance: state.balances.get(id)}); } else { - const index = headState.epochCtx.pubkey2index.get(id); + const index = headState.epochCtx.pubkey2index.get(fromHex(id)); if (index != null && index <= state.validators.length) { balances.push({index, balance: state.balances.get(index)}); } diff --git a/packages/beacon-node/src/api/impl/beacon/state/utils.ts b/packages/beacon-node/src/api/impl/beacon/state/utils.ts index 40b1e2815263..de21c6a244ed 100644 --- a/packages/beacon-node/src/api/impl/beacon/state/utils.ts +++ b/packages/beacon-node/src/api/impl/beacon/state/utils.ts @@ -1,6 +1,7 @@ +import {PubkeyIndexMap} from "@chainsafe/pubkey-index-map"; import {routes} from "@lodestar/api"; import {FAR_FUTURE_EPOCH, GENESIS_SLOT} from "@lodestar/params"; -import {BeaconStateAllForks, PubkeyIndexMap} from "@lodestar/state-transition"; +import {BeaconStateAllForks} from "@lodestar/state-transition"; import {BLSPubkey, Epoch, phase0, RootHex, Slot, ValidatorIndex} from "@lodestar/types"; import {fromHex} from "@lodestar/utils"; import {CheckpointWithHex, IForkChoice} from "@lodestar/fork-choice"; @@ -187,7 +188,7 @@ export function getStateValidatorIndex( // typeof id === Uint8Array const validatorIndex = pubkey2index.get(id); - if (validatorIndex === undefined) { + if (validatorIndex === null) { return {valid: false, code: 404, reason: "Validator pubkey not found in state"}; } if (validatorIndex >= state.validators.length) { diff --git a/packages/beacon-node/src/api/impl/validator/index.ts b/packages/beacon-node/src/api/impl/validator/index.ts index 4876975c1bea..2347d7086d46 100644 --- a/packages/beacon-node/src/api/impl/validator/index.ts +++ b/packages/beacon-node/src/api/impl/validator/index.ts @@ -1359,7 +1359,7 @@ export function getValidatorApi( const filteredRegistrations = registrations.filter((registration) => { const {pubkey} = registration.message; const validatorIndex = headState.epochCtx.pubkey2index.get(pubkey); - if (validatorIndex === undefined) return false; + if (validatorIndex === null) return false; const validator = headState.validators.getReadonly(validatorIndex); const status = getValidatorStatus(validator, currentEpoch); diff --git a/packages/beacon-node/src/chain/chain.ts b/packages/beacon-node/src/chain/chain.ts index 696f4bd51dc3..371f660abe2e 100644 --- a/packages/beacon-node/src/chain/chain.ts +++ b/packages/beacon-node/src/chain/chain.ts @@ -1,5 +1,6 @@ import path from "node:path"; import {CompositeTypeAny, TreeView, Type} from "@chainsafe/ssz"; +import {PubkeyIndexMap} from "@chainsafe/pubkey-index-map"; import { BeaconStateAllForks, CachedBeaconStateAllForks, @@ -10,7 +11,6 @@ import { getEffectiveBalanceIncrementsZeroInactive, isCachedBeaconState, Index2PubkeyCache, - PubkeyIndexMap, EpochShuffling, computeEndSlotAtEpoch, computeAnchorCheckpoint, diff --git a/packages/beacon-node/src/chain/historicalState/getHistoricalState.ts b/packages/beacon-node/src/chain/historicalState/getHistoricalState.ts index ada4f3c284d7..1f352b3d683a 100644 --- a/packages/beacon-node/src/chain/historicalState/getHistoricalState.ts +++ b/packages/beacon-node/src/chain/historicalState/getHistoricalState.ts @@ -1,9 +1,9 @@ +import {PubkeyIndexMap} from "@chainsafe/pubkey-index-map"; import { BeaconStateAllForks, CachedBeaconStateAllForks, DataAvailableStatus, ExecutionPayloadStatus, - PubkeyIndexMap, createCachedBeaconState, stateTransition, } from "@lodestar/state-transition"; diff --git a/packages/beacon-node/src/chain/historicalState/worker.ts b/packages/beacon-node/src/chain/historicalState/worker.ts index a07207cac5f5..2ea673d0faff 100644 --- a/packages/beacon-node/src/chain/historicalState/worker.ts +++ b/packages/beacon-node/src/chain/historicalState/worker.ts @@ -1,13 +1,9 @@ import worker from "node:worker_threads"; import {Transfer, expose} from "@chainsafe/threads/worker"; +import {PubkeyIndexMap} from "@chainsafe/pubkey-index-map"; import {createBeaconConfig, chainConfigFromJson} from "@lodestar/config"; import {getNodeLogger} from "@lodestar/logger/node"; -import { - EpochTransitionStep, - PubkeyIndexMap, - StateCloneSource, - StateHashTreeRootSource, -} from "@lodestar/state-transition"; +import {EpochTransitionStep, StateCloneSource, StateHashTreeRootSource} from "@lodestar/state-transition"; import {LevelDbController} from "@lodestar/db"; import {RegistryMetricCreator, collectNodeJSMetrics} from "../../metrics/index.js"; import {JobFnQueue} from "../../util/queue/fnQueue.js"; diff --git a/packages/beacon-node/src/chain/interface.ts b/packages/beacon-node/src/chain/interface.ts index 5185662eaa4f..531f60dc0e63 100644 --- a/packages/beacon-node/src/chain/interface.ts +++ b/packages/beacon-node/src/chain/interface.ts @@ -1,4 +1,5 @@ import {CompositeTypeAny, TreeView, Type} from "@chainsafe/ssz"; +import {PubkeyIndexMap} from "@chainsafe/pubkey-index-map"; import { UintNum64, Root, @@ -21,7 +22,6 @@ import { CachedBeaconStateAllForks, EpochShuffling, Index2PubkeyCache, - PubkeyIndexMap, } from "@lodestar/state-transition"; import {BeaconConfig} from "@lodestar/config"; import {Logger} from "@lodestar/utils"; diff --git a/packages/beacon-node/src/chain/rewards/attestationsRewards.ts b/packages/beacon-node/src/chain/rewards/attestationsRewards.ts index e909e4b1b57e..70fb27de239a 100644 --- a/packages/beacon-node/src/chain/rewards/attestationsRewards.ts +++ b/packages/beacon-node/src/chain/rewards/attestationsRewards.ts @@ -24,6 +24,7 @@ import { isInInactivityLeak, } from "@lodestar/state-transition"; import {BeaconConfig} from "@lodestar/config"; +import {fromHex} from "@lodestar/utils"; export type AttestationsRewards = routes.beacon.AttestationsRewards; type IdealAttestationsReward = routes.beacon.IdealAttestationsReward; @@ -143,7 +144,7 @@ function computeTotalAttestationsRewardsAltair( const {flags} = transitionCache; const {epochCtx, config} = state; const validatorIndices = validatorIds - .map((id) => (typeof id === "number" ? id : epochCtx.pubkey2index.get(id))) + .map((id) => (typeof id === "number" ? id : epochCtx.pubkey2index.get(fromHex(id)))) .filter((index) => index !== undefined); // Validator indices to include in the result const inactivityPenaltyDenominator = config.INACTIVITY_SCORE_BIAS * INACTIVITY_PENALTY_QUOTIENT_ALTAIR; diff --git a/packages/beacon-node/test/perf/chain/stateCache/updateUnfinalizedPubkeys.test.ts b/packages/beacon-node/test/perf/chain/stateCache/updateUnfinalizedPubkeys.test.ts index 46659ab3d287..eab66d2bee53 100644 --- a/packages/beacon-node/test/perf/chain/stateCache/updateUnfinalizedPubkeys.test.ts +++ b/packages/beacon-node/test/perf/chain/stateCache/updateUnfinalizedPubkeys.test.ts @@ -1,10 +1,11 @@ import {itBench, setBenchOpts} from "@dapplion/benchmark"; -import {Map} from "immutable"; +import {Map as ImmutableMap} from "immutable"; import {toBufferBE} from "bigint-buffer"; import {digest} from "@chainsafe/as-sha256"; import {SecretKey} from "@chainsafe/blst"; -import {ssz} from "@lodestar/types"; -import {type CachedBeaconStateAllForks, PubkeyIndexMap} from "@lodestar/state-transition"; +import {PubkeyIndexMap} from "@chainsafe/pubkey-index-map"; +import {ValidatorIndex, ssz} from "@lodestar/types"; +import {type CachedBeaconStateAllForks, toMemoryEfficientHexStr} from "@lodestar/state-transition"; import {bytesToBigInt, intToBytes} from "@lodestar/utils"; import {InMemoryCheckpointStateCache, BlockStateCacheImpl} from "../../../../src/chain/stateCache/index.js"; import {BlockStateCache} from "../../../../src/chain/stateCache/types.js"; @@ -31,7 +32,7 @@ describe("updateUnfinalizedPubkeys perf tests", function () { itBench({ id: `updateUnfinalizedPubkeys - updating ${numPubkeysToBeFinalized} pubkeys`, beforeEach: async () => { - baseState.epochCtx.unfinalizedPubkey2index = Map(unfinalizedPubkey2Index.map); + baseState.epochCtx.unfinalizedPubkey2index = ImmutableMap(unfinalizedPubkey2Index); baseState.epochCtx.pubkey2index = new PubkeyIndexMap(); baseState.epochCtx.index2pubkey = []; @@ -80,12 +81,14 @@ describe("updateUnfinalizedPubkeys perf tests", function () { }); } - function generatePubkey2Index(startIndex: number, endIndex: number): PubkeyIndexMap { - const pubkey2Index = new PubkeyIndexMap(); + type PubkeyHex = string; + + function generatePubkey2Index(startIndex: number, endIndex: number): Map { + const pubkey2Index = new Map(); const pubkeys = generatePubkeys(endIndex - startIndex); for (let i = startIndex; i < endIndex; i++) { - pubkey2Index.set(pubkeys[i], i); + pubkey2Index.set(toMemoryEfficientHexStr(pubkeys[i]), i); } return pubkey2Index; diff --git a/packages/beacon-node/test/unit/api/impl/beacon/state/utils.test.ts b/packages/beacon-node/test/unit/api/impl/beacon/state/utils.test.ts index a6020c0a3c13..79a8f3383e5d 100644 --- a/packages/beacon-node/test/unit/api/impl/beacon/state/utils.test.ts +++ b/packages/beacon-node/test/unit/api/impl/beacon/state/utils.test.ts @@ -117,7 +117,13 @@ describe("beacon state api utils", function () { // "validator id not in state" expect(getStateValidatorIndex(String(state.validators.length), state, pubkey2index).valid).toBe(false); // "validator pubkey not in state" - expect(getStateValidatorIndex("0xabcd", state, pubkey2index).valid).toBe(false); + expect( + getStateValidatorIndex( + "0xa99af0913a2834ef4959637e8d7c4e17f0b63adc587d36ab43510452db3102d0771a4554ea4118a33913827d5ee80b76", + state, + pubkey2index + ).valid + ).toBe(false); }); it("should return valid: true on validator indices / pubkeys in the state", () => { diff --git a/packages/beacon-node/test/utils/state.ts b/packages/beacon-node/test/utils/state.ts index 49a27435bdd7..6ad85f3422f7 100644 --- a/packages/beacon-node/test/utils/state.ts +++ b/packages/beacon-node/test/utils/state.ts @@ -1,10 +1,10 @@ import {SecretKey} from "@chainsafe/blst"; +import {PubkeyIndexMap} from "@chainsafe/pubkey-index-map"; import {config as minimalConfig} from "@lodestar/config/default"; import { BeaconStateAllForks, CachedBeaconStateAllForks, createCachedBeaconState, - PubkeyIndexMap, CachedBeaconStateBellatrix, BeaconStateBellatrix, CachedBeaconStateElectra, diff --git a/packages/state-transition/package.json b/packages/state-transition/package.json index 2df87a522a63..6816e5679cf5 100644 --- a/packages/state-transition/package.json +++ b/packages/state-transition/package.json @@ -66,6 +66,7 @@ "@lodestar/config": "^1.22.0", "@lodestar/params": "^1.22.0", "@lodestar/types": "^1.22.0", + "@chainsafe/pubkey-index-map": "2.0.0", "@lodestar/utils": "^1.22.0", "bigint-buffer": "^1.1.5", "immutable": "^4.3.2" diff --git a/packages/state-transition/src/block/processConsolidationRequest.ts b/packages/state-transition/src/block/processConsolidationRequest.ts index 71b85e927336..691ecd5eca0b 100644 --- a/packages/state-transition/src/block/processConsolidationRequest.ts +++ b/packages/state-transition/src/block/processConsolidationRequest.ts @@ -24,7 +24,7 @@ export function processConsolidationRequest( const sourceIndex = state.epochCtx.getValidatorIndex(sourcePubkey); const targetIndex = state.epochCtx.getValidatorIndex(targetPubkey); - if (sourceIndex === undefined || targetIndex === undefined) { + if (sourceIndex === null || targetIndex === null) { return; } diff --git a/packages/state-transition/src/block/processDeposit.ts b/packages/state-transition/src/block/processDeposit.ts index 7e343d7fc33d..ee75dff0dfd1 100644 --- a/packages/state-transition/src/block/processDeposit.ts +++ b/packages/state-transition/src/block/processDeposit.ts @@ -65,7 +65,7 @@ export function applyDeposit( const {pubkey, withdrawalCredentials, amount} = deposit; const cachedIndex = epochCtx.getValidatorIndex(pubkey); - if (cachedIndex === undefined || !Number.isSafeInteger(cachedIndex) || cachedIndex >= validators.length) { + if (cachedIndex === null || !Number.isSafeInteger(cachedIndex) || cachedIndex >= validators.length) { if (isValidDepositSignature(config, pubkey, withdrawalCredentials, amount, deposit.signature)) { addValidatorToRegistry(fork, state, pubkey, withdrawalCredentials, amount); } diff --git a/packages/state-transition/src/block/processWithdrawalRequest.ts b/packages/state-transition/src/block/processWithdrawalRequest.ts index 0587a06ee179..e8a64ec63e41 100644 --- a/packages/state-transition/src/block/processWithdrawalRequest.ts +++ b/packages/state-transition/src/block/processWithdrawalRequest.ts @@ -33,7 +33,7 @@ export function processWithdrawalRequest( // bail out if validator is not in beacon state // note that we don't need to check for 6110 unfinalized vals as they won't be eligible for withdraw/exit anyway const validatorIndex = pubkey2index.get(withdrawalRequest.validatorPubkey); - if (validatorIndex === undefined) { + if (validatorIndex === null) { return; } diff --git a/packages/state-transition/src/cache/epochCache.ts b/packages/state-transition/src/cache/epochCache.ts index 3783c7f91f0d..5e901e33d992 100644 --- a/packages/state-transition/src/cache/epochCache.ts +++ b/packages/state-transition/src/cache/epochCache.ts @@ -1,5 +1,6 @@ import {PublicKey} from "@chainsafe/blst"; import * as immutable from "immutable"; +import {PubkeyIndexMap} from "@chainsafe/pubkey-index-map"; import { BLSSignature, CommitteeIndex, @@ -53,7 +54,6 @@ import {EffectiveBalanceIncrements, getEffectiveBalanceIncrementsWithLen} from " import {BeaconStateAllForks, BeaconStateAltair} from "./types.js"; import { Index2PubkeyCache, - PubkeyIndexMap, UnfinalizedPubkeyIndexMap, syncPubkeys, toMemoryEfficientHexStr, @@ -1023,9 +1023,9 @@ export class EpochCache { return this.index2pubkey[index]; } - getValidatorIndex(pubkey: Uint8Array | PubkeyHex): ValidatorIndex | undefined { + getValidatorIndex(pubkey: Uint8Array): ValidatorIndex | null { if (this.isPostElectra()) { - return this.pubkey2index.get(pubkey) ?? this.unfinalizedPubkey2index.get(toMemoryEfficientHexStr(pubkey)); + return this.pubkey2index.get(pubkey) ?? this.unfinalizedPubkey2index.get(toMemoryEfficientHexStr(pubkey)) ?? null; } else { return this.pubkey2index.get(pubkey); } @@ -1059,17 +1059,20 @@ export class EpochCache { * Add finalized validator index and pubkey into finalized cache. * Since addFinalizedPubkey() primarily takes pubkeys from unfinalized cache, it can take pubkey hex string directly */ - addFinalizedPubkey(index: ValidatorIndex, pubkey: PubkeyHex | Uint8Array, metrics?: EpochCacheMetrics): void { + addFinalizedPubkey(index: ValidatorIndex, pubkeyOrHex: PubkeyHex | Uint8Array, metrics?: EpochCacheMetrics): void { + const pubkey = typeof pubkeyOrHex === "string" ? fromHex(pubkeyOrHex) : pubkeyOrHex; const existingIndex = this.pubkey2index.get(pubkey); - if (existingIndex !== undefined) { + if (existingIndex !== null) { if (existingIndex === index) { // Repeated insert. metrics?.finalizedPubkeyDuplicateInsert.inc(); return; } else { // attempt to insert the same pubkey with different index, should never happen. - throw Error("inserted existing pubkey into finalizedPubkey2index cache with a different index"); + throw Error( + `inserted existing pubkey into finalizedPubkey2index cache with a different index, index=${index} priorIndex=${existingIndex}` + ); } } diff --git a/packages/state-transition/src/cache/pubkeyCache.ts b/packages/state-transition/src/cache/pubkeyCache.ts index 44fe6df45592..f96436ec14f4 100644 --- a/packages/state-transition/src/cache/pubkeyCache.ts +++ b/packages/state-transition/src/cache/pubkeyCache.ts @@ -1,4 +1,5 @@ import {PublicKey} from "@chainsafe/blst"; +import {PubkeyIndexMap} from "@chainsafe/pubkey-index-map"; import * as immutable from "immutable"; import {ValidatorIndex, phase0} from "@lodestar/types"; @@ -39,26 +40,6 @@ export function newUnfinalizedPubkeyIndexMap(): UnfinalizedPubkeyIndexMap { return immutable.Map(); } -export class PubkeyIndexMap { - // We don't really need the full pubkey. We could just use the first 20 bytes like an Ethereum address - readonly map = new Map(); - - get size(): number { - return this.map.size; - } - - /** - * Must support reading with string for API support where pubkeys are already strings - */ - get(key: Uint8Array | PubkeyHex): ValidatorIndex | undefined { - return this.map.get(toMemoryEfficientHexStr(key)); - } - - set(key: Uint8Array | PubkeyHex, value: ValidatorIndex): void { - this.map.set(toMemoryEfficientHexStr(key), value); - } -} - /** * Checks the pubkey indices against a state and adds missing pubkeys * diff --git a/packages/state-transition/src/cache/syncCommitteeCache.ts b/packages/state-transition/src/cache/syncCommitteeCache.ts index b0a93f121369..b9a65302c3e2 100644 --- a/packages/state-transition/src/cache/syncCommitteeCache.ts +++ b/packages/state-transition/src/cache/syncCommitteeCache.ts @@ -1,7 +1,7 @@ import {CompositeViewDU} from "@chainsafe/ssz"; +import {PubkeyIndexMap} from "@chainsafe/pubkey-index-map"; import {ssz, ValidatorIndex} from "@lodestar/types"; import {toPubkeyHex} from "@lodestar/utils"; -import {PubkeyIndexMap} from "./pubkeyCache.js"; type SyncComitteeValidatorIndexMap = Map; @@ -82,7 +82,7 @@ function computeSyncCommitteeIndices( const pubkeys = syncCommittee.pubkeys.getAllReadonly(); for (const pubkey of pubkeys) { const validatorIndex = pubkey2index.get(pubkey); - if (validatorIndex === undefined) { + if (validatorIndex === null) { throw Error(`SyncCommittee pubkey is unknown ${toPubkeyHex(pubkey)}`); } diff --git a/packages/state-transition/src/index.ts b/packages/state-transition/src/index.ts index 4ed801e3c490..600bbf173462 100644 --- a/packages/state-transition/src/index.ts +++ b/packages/state-transition/src/index.ts @@ -41,11 +41,11 @@ export { EpochCacheError, EpochCacheErrorCode, } from "./cache/epochCache.js"; +export {toMemoryEfficientHexStr} from "./cache/pubkeyCache.js"; export {type EpochTransitionCache, beforeProcessEpoch} from "./cache/epochTransitionCache.js"; // Aux data-structures export { - PubkeyIndexMap, type Index2PubkeyCache, type UnfinalizedPubkeyIndexMap, newUnfinalizedPubkeyIndexMap, diff --git a/packages/state-transition/test/perf/util.ts b/packages/state-transition/test/perf/util.ts index f3c2eaef91e5..c764e2d039f9 100644 --- a/packages/state-transition/test/perf/util.ts +++ b/packages/state-transition/test/perf/util.ts @@ -1,5 +1,6 @@ import {BitArray, fromHexString} from "@chainsafe/ssz"; import {PublicKey, SecretKey} from "@chainsafe/blst"; +import {PubkeyIndexMap} from "@chainsafe/pubkey-index-map"; import {phase0, ssz, Slot, BeaconState} from "@lodestar/types"; import {config} from "@lodestar/config/default"; import {createBeaconConfig, createChainForkConfig} from "@lodestar/config"; @@ -17,7 +18,6 @@ import { interopSecretKey, computeEpochAtSlot, getActiveValidatorIndices, - PubkeyIndexMap, newFilledArray, createCachedBeaconState, computeCommitteeCount, diff --git a/packages/state-transition/test/perf/util/loadState/loadState.test.ts b/packages/state-transition/test/perf/util/loadState/loadState.test.ts index 25b43e242d02..9f6175e95684 100644 --- a/packages/state-transition/test/perf/util/loadState/loadState.test.ts +++ b/packages/state-transition/test/perf/util/loadState/loadState.test.ts @@ -1,8 +1,9 @@ import {itBench, setBenchOpts} from "@dapplion/benchmark"; import {PublicKey} from "@chainsafe/blst"; +import {PubkeyIndexMap} from "@chainsafe/pubkey-index-map"; import {loadState} from "../../../../src/util/loadState/loadState.js"; import {createCachedBeaconState} from "../../../../src/cache/stateCache.js"; -import {Index2PubkeyCache, PubkeyIndexMap} from "../../../../src/cache/pubkeyCache.js"; +import {Index2PubkeyCache} from "../../../../src/cache/pubkeyCache.js"; import {generatePerfTestCachedStateAltair} from "../../util.js"; /** diff --git a/packages/state-transition/test/unit/cachedBeaconState.test.ts b/packages/state-transition/test/unit/cachedBeaconState.test.ts index 092dda321610..96c026340143 100644 --- a/packages/state-transition/test/unit/cachedBeaconState.test.ts +++ b/packages/state-transition/test/unit/cachedBeaconState.test.ts @@ -1,11 +1,11 @@ import {fromHexString} from "@chainsafe/ssz"; import {describe, it, expect} from "vitest"; +import {PubkeyIndexMap} from "@chainsafe/pubkey-index-map"; import {ssz} from "@lodestar/types"; import {toHexString} from "@lodestar/utils"; import {config as defaultConfig} from "@lodestar/config/default"; import {createBeaconConfig, createChainForkConfig} from "@lodestar/config"; import {createCachedBeaconStateTest} from "../utils/state.js"; -import {PubkeyIndexMap} from "../../src/cache/pubkeyCache.js"; import {createCachedBeaconState, loadCachedBeaconState} from "../../src/cache/stateCache.js"; import {interopPubkeysCached} from "../utils/interop.js"; import {modifyStateSameValidator, newStateWithValidators} from "../utils/capella.js"; @@ -83,7 +83,7 @@ describe("CachedBeaconState", () => { expect(state1.epochCtx.getValidatorIndex(pubkey1)).toBe(index1); expect(state2.epochCtx.getValidatorIndex(pubkey1)).toBe(index1); - expect(state1.epochCtx.getValidatorIndex(pubkey2)).toBe(undefined); + expect(state1.epochCtx.getValidatorIndex(pubkey2)).toBe(null); expect(state2.epochCtx.getValidatorIndex(pubkey2)).toBe(index2); }); diff --git a/packages/state-transition/test/unit/upgradeState.test.ts b/packages/state-transition/test/unit/upgradeState.test.ts index df9b052542f9..301cb105dc98 100644 --- a/packages/state-transition/test/unit/upgradeState.test.ts +++ b/packages/state-transition/test/unit/upgradeState.test.ts @@ -1,4 +1,5 @@ import {expect, describe, it} from "vitest"; +import {PubkeyIndexMap} from "@chainsafe/pubkey-index-map"; import {ssz} from "@lodestar/types"; import {ForkName} from "@lodestar/params"; import {createBeaconConfig, ChainForkConfig, createChainForkConfig} from "@lodestar/config"; @@ -7,7 +8,6 @@ import {config as chainConfig} from "@lodestar/config/default"; import {upgradeStateToDeneb} from "../../src/slot/upgradeStateToDeneb.js"; import {upgradeStateToElectra} from "../../src/slot/upgradeStateToElectra.js"; import {createCachedBeaconState} from "../../src/cache/stateCache.js"; -import {PubkeyIndexMap} from "../../src/cache/pubkeyCache.js"; describe("upgradeState", () => { it("upgradeStateToDeneb", () => { diff --git a/packages/state-transition/test/unit/util/cachedBeaconState.test.ts b/packages/state-transition/test/unit/util/cachedBeaconState.test.ts index 654e0752adb8..c85a8c7a2ffd 100644 --- a/packages/state-transition/test/unit/util/cachedBeaconState.test.ts +++ b/packages/state-transition/test/unit/util/cachedBeaconState.test.ts @@ -1,8 +1,9 @@ import {describe, it} from "vitest"; +import {PubkeyIndexMap} from "@chainsafe/pubkey-index-map"; import {createBeaconConfig} from "@lodestar/config"; import {config} from "@lodestar/config/default"; import {ssz} from "@lodestar/types"; -import {createCachedBeaconState, PubkeyIndexMap} from "../../../src/index.js"; +import {createCachedBeaconState} from "../../../src/index.js"; describe("CachedBeaconState", () => { it("Create empty CachedBeaconState", () => { diff --git a/packages/state-transition/test/utils/state.ts b/packages/state-transition/test/utils/state.ts index 29a1f98b5562..9a79faf74480 100644 --- a/packages/state-transition/test/utils/state.ts +++ b/packages/state-transition/test/utils/state.ts @@ -1,3 +1,4 @@ +import {PubkeyIndexMap} from "@chainsafe/pubkey-index-map"; import {config as minimalConfig} from "@lodestar/config/default"; import { EPOCHS_PER_HISTORICAL_VECTOR, @@ -18,7 +19,6 @@ import { CachedBeaconStateAllForks, BeaconStateAllForks, createCachedBeaconState, - PubkeyIndexMap, } from "../../src/index.js"; import {BeaconStateCache} from "../../src/cache/stateCache.js"; import {EpochCacheOpts} from "../../src/cache/epochCache.js"; diff --git a/yarn.lock b/yarn.lock index f546d770acd8..a96092ec2fff 100644 --- a/yarn.lock +++ b/yarn.lock @@ -586,6 +586,42 @@ resolved "https://registry.yarnpkg.com/@chainsafe/prometheus-gc-stats/-/prometheus-gc-stats-1.0.2.tgz#585f8f1555251db156d7e50ef8c86dd4f3e78f70" integrity sha512-h3mFKduSX85XMVbOdWOYvx9jNq99jGcRVNyW5goGOqju1CsI+ZJLhu5z4zBb/G+ksL0R4uLVulu/mIMe7Y0rNg== +"@chainsafe/pubkey-index-map-darwin-arm64@2.0.0": + version "2.0.0" + resolved "https://registry.yarnpkg.com/@chainsafe/pubkey-index-map-darwin-arm64/-/pubkey-index-map-darwin-arm64-2.0.0.tgz#e468e772787f2411ecab8e8316da6c801356b72d" + integrity sha512-7eROFdQvwN1b0zJy0YJd1wBSv8j+Sp8tc3HsyaLQvjX7w93LcPPe+2Y5QpMkECBFzD2BcvKFpYxIvkDzV2v8rw== + +"@chainsafe/pubkey-index-map-darwin-x64@2.0.0": + version "2.0.0" + resolved "https://registry.yarnpkg.com/@chainsafe/pubkey-index-map-darwin-x64/-/pubkey-index-map-darwin-x64-2.0.0.tgz#995755f71bcb49e5393a6af122c11a850aef4ce4" + integrity sha512-HfKIV83Y+AOugw0jaeUIHqe4Ikfwo47baFg97fpdcpUwPfWnw4Blej5C1zAyEX2IuUo2S1D450neTBSUgSdNCA== + +"@chainsafe/pubkey-index-map-linux-arm64-gnu@2.0.0": + version "2.0.0" + resolved "https://registry.yarnpkg.com/@chainsafe/pubkey-index-map-linux-arm64-gnu/-/pubkey-index-map-linux-arm64-gnu-2.0.0.tgz#0c25ffb451d9861515e26e68006aa08e18ebc42d" + integrity sha512-t7Tdy+m9lZF2gqs0LmxFTAztNe6tDuSxje0xS8LTYanBSWQ6ADbWjTxcp/63yBbIYGzncigePZG2iis9nxB95Q== + +"@chainsafe/pubkey-index-map-linux-x64-gnu@2.0.0": + version "2.0.0" + resolved "https://registry.yarnpkg.com/@chainsafe/pubkey-index-map-linux-x64-gnu/-/pubkey-index-map-linux-x64-gnu-2.0.0.tgz#26c3628faaeb1ef9b47952cc03ae209d7e9656d8" + integrity sha512-1DKoITe7ZwjClhCBpIZq7SOIOJbUNLxgsFuV7e0ZcBq+tz5UqhKB8SSRzNn7THoo+XRg1mJiDyFPzDKGxHxRkg== + +"@chainsafe/pubkey-index-map-win32-x64-msvc@2.0.0": + version "2.0.0" + resolved "https://registry.yarnpkg.com/@chainsafe/pubkey-index-map-win32-x64-msvc/-/pubkey-index-map-win32-x64-msvc-2.0.0.tgz#0e35c67ed9dcaaee6ff9e582ed6a733d852473e9" + integrity sha512-hnEZBtTFxTl52lytogexOtzqPQyUKKB28mLbLTZnl2OicsEfNcczJpgF6o1uQ0O0zktAn/m1Tc6/iHmQg2VuhQ== + +"@chainsafe/pubkey-index-map@2.0.0": + version "2.0.0" + resolved "https://registry.yarnpkg.com/@chainsafe/pubkey-index-map/-/pubkey-index-map-2.0.0.tgz#a8262b353e8335e9acf5e750353a53c55e5cf9be" + integrity sha512-2mVvWrHGApF3mPS7ecp8k3dI/C3QF5824bpQNSRWDsmZEU9H3HzITIj256v14QiB+22MIitpWkBc6hl2bjhJ+Q== + optionalDependencies: + "@chainsafe/pubkey-index-map-darwin-arm64" "2.0.0" + "@chainsafe/pubkey-index-map-darwin-x64" "2.0.0" + "@chainsafe/pubkey-index-map-linux-arm64-gnu" "2.0.0" + "@chainsafe/pubkey-index-map-linux-x64-gnu" "2.0.0" + "@chainsafe/pubkey-index-map-win32-x64-msvc" "2.0.0" + "@chainsafe/ssz@^0.11.1": version "0.11.1" resolved "https://registry.yarnpkg.com/@chainsafe/ssz/-/ssz-0.11.1.tgz#d4aec883af2ec5196ae67b96242c467da20b2476" From c4952eef7ee2e362e08a313c128e22e394bc44e0 Mon Sep 17 00:00:00 2001 From: twoeths Date: Tue, 1 Oct 2024 21:29:22 +0700 Subject: [PATCH 29/52] fix: adjust n-historical-states param (#7104) * fix: default params of n-historical-states config * chore: improve log * feat: enable nHistoricalStates by default * chore: fix typo in log --- packages/beacon-node/src/chain/options.ts | 2 +- packages/beacon-node/src/chain/regen/regen.ts | 2 +- .../chain/stateCache/fifoBlockStateCache.ts | 9 +++++-- .../stateCache/persistentCheckpointsCache.ts | 7 +++--- .../src/network/processor/gossipHandlers.ts | 24 ++++++++++--------- 5 files changed, 26 insertions(+), 18 deletions(-) diff --git a/packages/beacon-node/src/chain/options.ts b/packages/beacon-node/src/chain/options.ts index 7c7cfcdde75b..bc2b73256272 100644 --- a/packages/beacon-node/src/chain/options.ts +++ b/packages/beacon-node/src/chain/options.ts @@ -111,7 +111,7 @@ export const defaultChainOptions: IChainOptions = { // batching too much may block the I/O thread so if useWorker=false, suggest this value to be 32 // since this batch attestation work is designed to work with useWorker=true, make this the lowest value minSameMessageSignatureSetsToBatch: 2, - nHistoricalStates: false, + nHistoricalStates: true, nHistoricalStatesFileDataStore: false, maxBlockStates: DEFAULT_MAX_BLOCK_STATES, maxCPStateEpochsInMemory: DEFAULT_MAX_CP_STATE_EPOCHS_IN_MEMORY, diff --git a/packages/beacon-node/src/chain/regen/regen.ts b/packages/beacon-node/src/chain/regen/regen.ts index 08fda70d9184..7c663c6e0d3d 100644 --- a/packages/beacon-node/src/chain/regen/regen.ts +++ b/packages/beacon-node/src/chain/regen/regen.ts @@ -218,7 +218,7 @@ export class StateRegenerator implements IStateRegeneratorInternal { blockPromises[i] = this.modules.db.block.get(fromHex(protoBlock.blockRoot)); } - const logCtx = {stateRoot, replaySlots: replaySlots.join(",")}; + const logCtx = {stateRoot, caller, replaySlots: replaySlots.join(",")}; this.modules.logger.debug("Replaying blocks to get state", logCtx); const loadBlocksTimer = this.modules.metrics?.regenGetState.loadBlocks.startTimer({caller}); diff --git a/packages/beacon-node/src/chain/stateCache/fifoBlockStateCache.ts b/packages/beacon-node/src/chain/stateCache/fifoBlockStateCache.ts index d38fc323174c..7766daf3c5b3 100644 --- a/packages/beacon-node/src/chain/stateCache/fifoBlockStateCache.ts +++ b/packages/beacon-node/src/chain/stateCache/fifoBlockStateCache.ts @@ -13,9 +13,14 @@ export type FIFOBlockStateCacheOpts = { }; /** - * Regen state if there's a reorg distance > 32 slots. + * Given `maxSkipSlots` = 32 and `DEFAULT_EARLIEST_PERMISSIBLE_SLOT_DISTANCE` = 32, lodestar doesn't need to + * reload states in order to process a gossip block. + * + * |-----------------------------------------------|-----------------------------------------------| + * maxSkipSlots DEFAULT_EARLIEST_PERMISSIBLE_SLOT_DISTANCE ^ + * clock slot */ -export const DEFAULT_MAX_BLOCK_STATES = 32; +export const DEFAULT_MAX_BLOCK_STATES = 64; /** * New implementation of BlockStateCache that keeps the most recent n states consistently diff --git a/packages/beacon-node/src/chain/stateCache/persistentCheckpointsCache.ts b/packages/beacon-node/src/chain/stateCache/persistentCheckpointsCache.ts index 07c96f224bee..0719efcfd309 100644 --- a/packages/beacon-node/src/chain/stateCache/persistentCheckpointsCache.ts +++ b/packages/beacon-node/src/chain/stateCache/persistentCheckpointsCache.ts @@ -53,10 +53,11 @@ type CacheItem = InMemoryCacheItem | PersistedCacheItem; type LoadedStateBytesData = {persistedKey: DatastoreKey; stateBytes: Uint8Array}; /** - * Before n-historical states, lodestar keeps mostly 3 states in memory with 1 finalized state - * Since Jan 2024, lodestar stores the finalized state in disk and keeps up to 2 epochs in memory + * Before n-historical states, lodestar keeps all checkpoint states since finalized + * Since Sep 2024, lodestar stores 3 most recent checkpoint states in memory and the rest on disk. The finalized state + * may not be available in memory, and stay on disk instead. */ -export const DEFAULT_MAX_CP_STATE_EPOCHS_IN_MEMORY = 2; +export const DEFAULT_MAX_CP_STATE_EPOCHS_IN_MEMORY = 3; /** * An implementation of CheckpointStateCache that keep up to n epoch checkpoint states in memory and persist the rest to disk diff --git a/packages/beacon-node/src/network/processor/gossipHandlers.ts b/packages/beacon-node/src/network/processor/gossipHandlers.ts index 9e6f08a803c1..8df9f7b78126 100644 --- a/packages/beacon-node/src/network/processor/gossipHandlers.ts +++ b/packages/beacon-node/src/network/processor/gossipHandlers.ts @@ -144,6 +144,18 @@ function getDefaultHandlers(modules: ValidatorFnsModules, options: GossipHandler const blockInputMeta = config.getForkSeq(signedBlock.message.slot) >= ForkSeq.deneb ? blockInputRes.blockInputMeta : {}; + const logCtx = { + slot: slot, + root: blockHex, + currentSlot: chain.clock.currentSlot, + peerId: peerIdStr, + delaySec, + ...blockInputMeta, + recvToValLatency, + }; + + logger.debug("Received gossip block", {...logCtx}); + try { await validateGossipBlock(config, chain, signedBlock, fork); @@ -153,17 +165,7 @@ function getDefaultHandlers(modules: ValidatorFnsModules, options: GossipHandler metrics?.gossipBlock.gossipValidation.recvToValidation.observe(recvToValidation); metrics?.gossipBlock.gossipValidation.validationTime.observe(validationTime); - logger.debug("Received gossip block", { - slot: slot, - root: blockHex, - curentSlot: chain.clock.currentSlot, - peerId: peerIdStr, - delaySec, - ...blockInputMeta, - recvToValLatency, - recvToValidation, - validationTime, - }); + logger.debug("Validated gossip block", {...logCtx, recvToValidation, validationTime}); return blockInput; } catch (e) { From b457778eefb31ed4286a9da9597d51a0818b0f79 Mon Sep 17 00:00:00 2001 From: Nico Flaig Date: Wed, 2 Oct 2024 14:05:16 +0100 Subject: [PATCH 30/52] feat: allow to configure api client when initializing light client (#7121) --- packages/light-client/README.md | 6 +++--- packages/light-client/src/utils/api.ts | 6 +++--- 2 files changed, 6 insertions(+), 6 deletions(-) diff --git a/packages/light-client/README.md b/packages/light-client/README.md index cd3a0265008a..0323e8fc4326 100644 --- a/packages/light-client/README.md +++ b/packages/light-client/README.md @@ -62,7 +62,7 @@ import { const config = getChainForkConfigFromNetwork("sepolia"); const logger = getConsoleLogger({logDebug: Boolean(process.env.DEBUG)}); -const api = getApiFromUrl({urls: ["https://lodestar-sepolia.chainsafe.io"]}, {config}); +const api = getApiFromUrl("https://lodestar-sepolia.chainsafe.io", "sepolia"); const lightclient = await Lightclient.initializeFromCheckpointRoot({ config, @@ -82,11 +82,11 @@ await lightclient.start(); logger.info("Lightclient synced"); lightclient.emitter.on(LightclientEvent.lightClientFinalityHeader, async (finalityUpdate) => { - logger.info(finalityUpdate); + logger.info("Received finality update", {slot: finalityUpdate.beacon.slot}); }); lightclient.emitter.on(LightclientEvent.lightClientOptimisticHeader, async (optimisticUpdate) => { - logger.info(optimisticUpdate); + logger.info("Received optimistic update", {slot: optimisticUpdate.beacon.slot}); }); ``` diff --git a/packages/light-client/src/utils/api.ts b/packages/light-client/src/utils/api.ts index 7947aa96dd3e..6ccb187052e1 100644 --- a/packages/light-client/src/utils/api.ts +++ b/packages/light-client/src/utils/api.ts @@ -1,13 +1,13 @@ -import {getClient, ApiClient} from "@lodestar/api"; +import {getClient, ApiClient, ApiRequestInit} from "@lodestar/api"; import {ChainForkConfig, createChainForkConfig} from "@lodestar/config"; import {NetworkName, networksChainConfig} from "@lodestar/config/networks"; -export function getApiFromUrl(url: string, network: NetworkName): ApiClient { +export function getApiFromUrl(url: string, network: NetworkName, init?: ApiRequestInit): ApiClient { if (!(network in networksChainConfig)) { throw Error(`Invalid network name "${network}". Valid options are: ${Object.keys(networksChainConfig).join()}`); } - return getClient({urls: [url]}, {config: createChainForkConfig(networksChainConfig[network])}); + return getClient({urls: [url], globalInit: init}, {config: createChainForkConfig(networksChainConfig[network])}); } export function getChainForkConfigFromNetwork(network: NetworkName): ChainForkConfig { From bf4a25f0219481d176996b81206b0ca66f971aba Mon Sep 17 00:00:00 2001 From: Nico Flaig Date: Wed, 2 Oct 2024 16:24:08 +0100 Subject: [PATCH 31/52] fix: update HTTP error response format to be spec compliant (#7110) * fix: update HTTP error response format to be spec compliant * Fix error assertions * Remove group tag from keymanager option * Fix body has already been read * Assert deepEqual --- packages/beacon-node/src/api/rest/base.ts | 38 +++++++++++++++++-- packages/beacon-node/src/api/rest/index.ts | 1 + packages/cli/src/cmds/dev/options.ts | 4 ++ packages/cli/src/cmds/validator/handler.ts | 1 + .../src/cmds/validator/keymanager/server.ts | 1 + packages/cli/src/cmds/validator/options.ts | 6 +++ .../cli/src/options/beaconNodeOptions/api.ts | 9 +++++ packages/cli/test/sim/endpoints.test.ts | 16 +++++++- .../unit/options/beaconNodeOptions.test.ts | 2 + 9 files changed, 74 insertions(+), 4 deletions(-) diff --git a/packages/beacon-node/src/api/rest/base.ts b/packages/beacon-node/src/api/rest/base.ts index 5f191bf76beb..e8ea85f67af5 100644 --- a/packages/beacon-node/src/api/rest/base.ts +++ b/packages/beacon-node/src/api/rest/base.ts @@ -15,6 +15,7 @@ export type RestApiServerOpts = { bearerToken?: string; headerLimit?: number; bodyLimit?: number; + stacktraces?: boolean; swaggerUI?: boolean; }; @@ -29,11 +30,27 @@ export type RestApiServerMetrics = SocketMetrics & { errors: Gauge<{operationId: string}>; }; +/** + * Error response body format as defined in beacon-api spec + * + * See https://github.com/ethereum/beacon-APIs/blob/v2.5.0/types/http.yaml + */ +type ErrorResponse = { + code: number; + message: string; + stacktraces?: string[]; +}; + /** * Error code used by Fastify if media type is not supported (415) */ const INVALID_MEDIA_TYPE_CODE = errorCodes.FST_ERR_CTP_INVALID_MEDIA_TYPE().code; +/** + * Error code used by Fastify if JSON schema validation failed + */ +const SCHEMA_VALIDATION_ERROR_CODE = errorCodes.FST_ERR_VALIDATION().code; + /** * REST API powered by `fastify` server. */ @@ -71,15 +88,30 @@ export class RestApiServer { // To parse our ApiError -> statusCode server.setErrorHandler((err, _req, res) => { + const stacktraces = opts.stacktraces ? err.stack?.split("\n") : undefined; if (err.validation) { - void res.status(400).send(err.validation); + const {instancePath, message} = err.validation[0]; + const payload: ErrorResponse = { + code: err.statusCode ?? 400, + message: `${instancePath.substring(instancePath.lastIndexOf("/") + 1)} ${message}`, + stacktraces, + }; + void res.status(400).send(payload); } else { // Convert our custom ApiError into status code const statusCode = err instanceof ApiError ? err.statusCode : 500; - void res.status(statusCode).send(err); + const payload: ErrorResponse = {code: statusCode, message: err.message, stacktraces}; + void res.status(statusCode).send(payload); } }); + server.setNotFoundHandler((req, res) => { + const message = `Route ${req.raw.method}:${req.raw.url} not found`; + this.logger.warn(message); + const payload: ErrorResponse = {code: 404, message}; + void res.code(404).send(payload); + }); + if (opts.cors) { void server.register(fastifyCors, {origin: opts.cors}); } @@ -127,7 +159,7 @@ export class RestApiServer { const operationId = getOperationId(req); - if (err instanceof ApiError || err.code === INVALID_MEDIA_TYPE_CODE) { + if (err instanceof ApiError || [INVALID_MEDIA_TYPE_CODE, SCHEMA_VALIDATION_ERROR_CODE].includes(err.code)) { this.logger.warn(`Req ${req.id} ${operationId} failed`, {reason: err.message}); } else { this.logger.error(`Req ${req.id} ${operationId} error`, {}, err); diff --git a/packages/beacon-node/src/api/rest/index.ts b/packages/beacon-node/src/api/rest/index.ts index e27ed6bd9139..6beaf061588c 100644 --- a/packages/beacon-node/src/api/rest/index.ts +++ b/packages/beacon-node/src/api/rest/index.ts @@ -22,6 +22,7 @@ export const beaconRestApiServerOpts: BeaconRestApiServerOpts = { cors: "*", // beacon -> validator API is trusted, and for large amounts of keys the payload is multi-MB bodyLimit: 20 * 1024 * 1024, // 20MB for big block + blobs + stacktraces: false, }; export type BeaconRestApiServerModules = RestApiServerModules & { diff --git a/packages/cli/src/cmds/dev/options.ts b/packages/cli/src/cmds/dev/options.ts index c484150e58d7..5286b81729c6 100644 --- a/packages/cli/src/cmds/dev/options.ts +++ b/packages/cli/src/cmds/dev/options.ts @@ -90,6 +90,10 @@ const externalOptionsOverrides: Partial = { @@ -141,6 +142,11 @@ export const keymanagerOptions: CliCommandOptions = { type: "number", description: "Defines the maximum payload, in bytes, the server is allowed to accept", }, + "keymanager.stacktraces": { + hidden: true, + type: "boolean", + description: "Return stacktraces in HTTP error responses", + }, }; export const validatorOptions: CliCommandOptions = { diff --git a/packages/cli/src/options/beaconNodeOptions/api.ts b/packages/cli/src/options/beaconNodeOptions/api.ts index 996136f262ec..bed0105fd944 100644 --- a/packages/cli/src/options/beaconNodeOptions/api.ts +++ b/packages/cli/src/options/beaconNodeOptions/api.ts @@ -12,6 +12,7 @@ export type ApiArgs = { "rest.port": number; "rest.headerLimit"?: number; "rest.bodyLimit"?: number; + "rest.stacktraces"?: boolean; "rest.swaggerUI"?: boolean; }; @@ -26,6 +27,7 @@ export function parseArgs(args: ApiArgs): IBeaconNodeOptions["api"] { port: args["rest.port"], headerLimit: args["rest.headerLimit"], bodyLimit: args["rest.bodyLimit"], + stacktraces: args["rest.stacktraces"], swaggerUI: args["rest.swaggerUI"], }, }; @@ -92,6 +94,13 @@ export const options: CliCommandOptions = { description: "Defines the maximum payload, in bytes, the server is allowed to accept", }, + "rest.stacktraces": { + hidden: true, + type: "boolean", + description: "Return stacktraces in HTTP error responses", + group: "api", + }, + "rest.swaggerUI": { type: "boolean", description: "Enable Swagger UI for API exploration at http://{address}:{port}/documentation", diff --git a/packages/cli/test/sim/endpoints.test.ts b/packages/cli/test/sim/endpoints.test.ts index a42b9568f9a3..b276ad4787c6 100644 --- a/packages/cli/test/sim/endpoints.test.ts +++ b/packages/cli/test/sim/endpoints.test.ts @@ -2,7 +2,7 @@ import path from "node:path"; import assert from "node:assert"; import {toHexString} from "@chainsafe/ssz"; -import {routes} from "@lodestar/api"; +import {routes, fetch} from "@lodestar/api"; import {Simulation} from "../utils/crucible/simulation.js"; import {BeaconClient, ExecutionClient} from "../utils/crucible/interfaces.js"; import {defineSimTestConfig, logFilesDir} from "../utils/crucible/utils/index.js"; @@ -105,6 +105,20 @@ await env.tracker.assert( } ); +await env.tracker.assert("should return HTTP error responses in a spec compliant format", async () => { + // ApiError with status 400 is thrown by handler + const res1 = await node.api.beacon.getStateValidator({stateId: "current", validatorId: 1}); + assert.deepEqual(JSON.parse(await res1.errorBody()), {code: 400, message: "Invalid block id 'current'"}); + + // JSON schema validation failed + const res2 = await node.api.beacon.getPoolAttestationsV2({slot: "current" as unknown as number, committeeIndex: 123}); + assert.deepEqual(JSON.parse(await res2.errorBody()), {code: 400, message: "slot must be integer"}); + + // Route does not exist + const res3 = await fetch(`${node.restPublicUrl}/not/implemented/route`); + assert.deepEqual(JSON.parse(await res3.text()), {code: 404, message: "Route GET:/not/implemented/route not found"}); +}); + await env.tracker.assert("BN Not Synced", async () => { const expectedSyncStatus: routes.node.SyncingStatus = { headSlot: 2, diff --git a/packages/cli/test/unit/options/beaconNodeOptions.test.ts b/packages/cli/test/unit/options/beaconNodeOptions.test.ts index d74ae73b966f..f873102edf74 100644 --- a/packages/cli/test/unit/options/beaconNodeOptions.test.ts +++ b/packages/cli/test/unit/options/beaconNodeOptions.test.ts @@ -17,6 +17,7 @@ describe("options / beaconNodeOptions", () => { "rest.port": 7654, "rest.headerLimit": 16384, "rest.bodyLimit": 30e6, + "rest.stacktraces": true, "chain.blsVerifyAllMultiThread": true, "chain.blsVerifyAllMainThread": true, @@ -122,6 +123,7 @@ describe("options / beaconNodeOptions", () => { port: 7654, headerLimit: 16384, bodyLimit: 30e6, + stacktraces: true, }, }, chain: { From a19655d95b02861840430a676cebaa9e79ec023c Mon Sep 17 00:00:00 2001 From: Nico Flaig Date: Wed, 2 Oct 2024 17:11:06 +0100 Subject: [PATCH 32/52] fix: update multiple api errors to be spec compliant (#7113) * fix: update HTTP error response format to be spec compliant * Fix error assertions * Remove group tag from keymanager option * Fix body has already been read * Assert deepEqual * fix: update multiple api errors to be spec compliant * Reorder test cases * Update res numbering * Use strict deep equal --- packages/api/src/utils/client/response.ts | 5 ++- .../src/api/impl/beacon/pool/index.ts | 32 ++++++++----------- packages/beacon-node/src/api/impl/errors.ts | 13 ++++++++ packages/beacon-node/src/api/rest/base.ts | 14 +++++++- packages/cli/test/sim/endpoints.test.ts | 24 +++++++++++--- 5 files changed, 63 insertions(+), 25 deletions(-) diff --git a/packages/api/src/utils/client/response.ts b/packages/api/src/utils/client/response.ts index ed008273588a..fdcb2afda943 100644 --- a/packages/api/src/utils/client/response.ts +++ b/packages/api/src/utils/client/response.ts @@ -189,8 +189,11 @@ export class ApiResponse extends Response { private getErrorMessage(): string { const errBody = this.resolvedErrorBody(); try { - const errJson = JSON.parse(errBody) as {message?: string}; + const errJson = JSON.parse(errBody) as {message?: string; failures?: {message: string}[]}; if (errJson.message) { + if (errJson.failures) { + return `${errJson.message}\n` + errJson.failures.map((e) => e.message).join("\n"); + } return errJson.message; } else { return errBody; diff --git a/packages/beacon-node/src/api/impl/beacon/pool/index.ts b/packages/beacon-node/src/api/impl/beacon/pool/index.ts index 398238aa2508..e01b172f1e72 100644 --- a/packages/beacon-node/src/api/impl/beacon/pool/index.ts +++ b/packages/beacon-node/src/api/impl/beacon/pool/index.ts @@ -16,7 +16,7 @@ import { SyncCommitteeError, } from "../../../../chain/errors/index.js"; import {validateGossipFnRetryUnknownRoot} from "../../../../network/processor/gossipHandlers.js"; -import {ApiError} from "../../errors.js"; +import {ApiError, FailureList, IndexedError} from "../../errors.js"; export function getBeaconPoolApi({ chain, @@ -88,7 +88,7 @@ export function getBeaconPoolApi({ async submitPoolAttestationsV2({signedAttestations}) { const seenTimestampSec = Date.now() / 1000; - const errors: Error[] = []; + const failures: FailureList = []; await Promise.all( signedAttestations.map(async (attestation, i) => { @@ -127,7 +127,7 @@ export function getBeaconPoolApi({ return; } - errors.push(e as Error); + failures.push({index: i, message: (e as Error).message}); logger.error(`Error on submitPoolAttestations [${i}]`, logCtx, e as Error); if (e instanceof AttestationError && e.action === GossipAction.REJECT) { chain.persistInvalidSszValue(ssz.phase0.Attestation, attestation, "api_reject"); @@ -136,10 +136,8 @@ export function getBeaconPoolApi({ }) ); - if (errors.length > 1) { - throw Error("Multiple errors on submitPoolAttestations\n" + errors.map((e) => e.message).join("\n")); - } else if (errors.length === 1) { - throw errors[0]; + if (failures.length > 0) { + throw new IndexedError("Error processing attestations", failures); } }, @@ -168,7 +166,7 @@ export function getBeaconPoolApi({ }, async submitPoolBLSToExecutionChange({blsToExecutionChanges}) { - const errors: Error[] = []; + const failures: FailureList = []; await Promise.all( blsToExecutionChanges.map(async (blsToExecutionChange, i) => { @@ -184,7 +182,7 @@ export function getBeaconPoolApi({ await network.publishBlsToExecutionChange(blsToExecutionChange); } } catch (e) { - errors.push(e as Error); + failures.push({index: i, message: (e as Error).message}); logger.error( `Error on submitPoolBLSToExecutionChange [${i}]`, {validatorIndex: blsToExecutionChange.message.validatorIndex}, @@ -194,10 +192,8 @@ export function getBeaconPoolApi({ }) ); - if (errors.length > 1) { - throw Error("Multiple errors on submitPoolBLSToExecutionChange\n" + errors.map((e) => e.message).join("\n")); - } else if (errors.length === 1) { - throw errors[0]; + if (failures.length > 0) { + throw new IndexedError("Error processing BLS to execution changes", failures); } }, @@ -221,7 +217,7 @@ export function getBeaconPoolApi({ // TODO: Fetch states at signature slots const state = chain.getHeadState(); - const errors: Error[] = []; + const failures: FailureList = []; await Promise.all( signatures.map(async (signature, i) => { @@ -261,7 +257,7 @@ export function getBeaconPoolApi({ return; } - errors.push(e as Error); + failures.push({index: i, message: (e as Error).message}); logger.debug( `Error on submitPoolSyncCommitteeSignatures [${i}]`, {slot: signature.slot, validatorIndex: signature.validatorIndex}, @@ -274,10 +270,8 @@ export function getBeaconPoolApi({ }) ); - if (errors.length > 1) { - throw Error("Multiple errors on submitPoolSyncCommitteeSignatures\n" + errors.map((e) => e.message).join("\n")); - } else if (errors.length === 1) { - throw errors[0]; + if (failures.length > 0) { + throw new IndexedError("Error processing sync committee signatures", failures); } }, }; diff --git a/packages/beacon-node/src/api/impl/errors.ts b/packages/beacon-node/src/api/impl/errors.ts index 848691f7cf6d..609f40f83a12 100644 --- a/packages/beacon-node/src/api/impl/errors.ts +++ b/packages/beacon-node/src/api/impl/errors.ts @@ -35,3 +35,16 @@ export class OnlySupportedByDVT extends ApiError { super(501, "Only supported by distributed validator middleware clients"); } } + +// Error thrown when processing multiple items failed - https://github.com/ethereum/beacon-APIs/blob/e7f7d70423b0abfe9d9f33b701be2ec03e44eb02/types/http.yaml#L175 +export class IndexedError extends ApiError { + failures: FailureList; + + constructor(message: string, failures: FailureList) { + super(400, message); + + this.failures = failures.sort((a, b) => a.index - b.index); + } +} + +export type FailureList = {index: number; message: string}[]; diff --git a/packages/beacon-node/src/api/rest/base.ts b/packages/beacon-node/src/api/rest/base.ts index e8ea85f67af5..10318b1b3ba7 100644 --- a/packages/beacon-node/src/api/rest/base.ts +++ b/packages/beacon-node/src/api/rest/base.ts @@ -5,7 +5,7 @@ import bearerAuthPlugin from "@fastify/bearer-auth"; import {addSszContentTypeParser} from "@lodestar/api/server"; import {ErrorAborted, Gauge, Histogram, Logger} from "@lodestar/utils"; import {isLocalhostIP} from "../../util/ip.js"; -import {ApiError, NodeIsSyncing} from "../impl/errors.js"; +import {ApiError, FailureList, IndexedError, NodeIsSyncing} from "../impl/errors.js"; import {HttpActiveSocketsTracker, SocketMetrics} from "./activeSockets.js"; export type RestApiServerOpts = { @@ -41,6 +41,10 @@ type ErrorResponse = { stacktraces?: string[]; }; +type IndexedErrorResponse = ErrorResponse & { + failures?: FailureList; +}; + /** * Error code used by Fastify if media type is not supported (415) */ @@ -97,6 +101,14 @@ export class RestApiServer { stacktraces, }; void res.status(400).send(payload); + } else if (err instanceof IndexedError) { + const payload: IndexedErrorResponse = { + code: err.statusCode, + message: err.message, + failures: err.failures, + stacktraces, + }; + void res.status(err.statusCode).send(payload); } else { // Convert our custom ApiError into status code const statusCode = err instanceof ApiError ? err.statusCode : 500; diff --git a/packages/cli/test/sim/endpoints.test.ts b/packages/cli/test/sim/endpoints.test.ts index b276ad4787c6..6a119fc219d7 100644 --- a/packages/cli/test/sim/endpoints.test.ts +++ b/packages/cli/test/sim/endpoints.test.ts @@ -3,6 +3,7 @@ import path from "node:path"; import assert from "node:assert"; import {toHexString} from "@chainsafe/ssz"; import {routes, fetch} from "@lodestar/api"; +import {ssz} from "@lodestar/types"; import {Simulation} from "../utils/crucible/simulation.js"; import {BeaconClient, ExecutionClient} from "../utils/crucible/interfaces.js"; import {defineSimTestConfig, logFilesDir} from "../utils/crucible/utils/index.js"; @@ -108,15 +109,30 @@ await env.tracker.assert( await env.tracker.assert("should return HTTP error responses in a spec compliant format", async () => { // ApiError with status 400 is thrown by handler const res1 = await node.api.beacon.getStateValidator({stateId: "current", validatorId: 1}); - assert.deepEqual(JSON.parse(await res1.errorBody()), {code: 400, message: "Invalid block id 'current'"}); + assert.deepStrictEqual(JSON.parse(await res1.errorBody()), {code: 400, message: "Invalid block id 'current'"}); // JSON schema validation failed const res2 = await node.api.beacon.getPoolAttestationsV2({slot: "current" as unknown as number, committeeIndex: 123}); - assert.deepEqual(JSON.parse(await res2.errorBody()), {code: 400, message: "slot must be integer"}); + assert.deepStrictEqual(JSON.parse(await res2.errorBody()), {code: 400, message: "slot must be integer"}); + + // Error processing multiple items + const signedAttestations = Array.from({length: 3}, () => ssz.phase0.Attestation.defaultValue()); + const res3 = await node.api.beacon.submitPoolAttestationsV2({signedAttestations}); + const errBody = JSON.parse(await res3.errorBody()) as {code: number; message: string; failures: unknown[]}; + assert.equal(errBody.code, 400); + assert.equal(errBody.message, "Error processing attestations"); + assert.equal(errBody.failures.length, signedAttestations.length); + assert.deepStrictEqual(errBody.failures[0], { + index: 0, + message: "ATTESTATION_ERROR_NOT_EXACTLY_ONE_AGGREGATION_BIT_SET", + }); // Route does not exist - const res3 = await fetch(`${node.restPublicUrl}/not/implemented/route`); - assert.deepEqual(JSON.parse(await res3.text()), {code: 404, message: "Route GET:/not/implemented/route not found"}); + const res4 = await fetch(`${node.restPublicUrl}/not/implemented/route`); + assert.deepStrictEqual(JSON.parse(await res4.text()), { + code: 404, + message: "Route GET:/not/implemented/route not found", + }); }); await env.tracker.assert("BN Not Synced", async () => { From 0d1fd9c839a84cfe91e0b9e6af95c27261bb5ef0 Mon Sep 17 00:00:00 2001 From: twoeths Date: Fri, 4 Oct 2024 19:29:20 +0700 Subject: [PATCH 33/52] chore: remove IndexedGossipQueueAvgTime (#7125) --- .../network/processor/gossipQueues/index.ts | 12 +- .../processor/gossipQueues/indexedAvgTime.ts | 129 ------------------ .../network/processor/gossipQueues/types.ts | 11 +- 3 files changed, 2 insertions(+), 150 deletions(-) delete mode 100644 packages/beacon-node/src/network/processor/gossipQueues/indexedAvgTime.ts diff --git a/packages/beacon-node/src/network/processor/gossipQueues/index.ts b/packages/beacon-node/src/network/processor/gossipQueues/index.ts index 347458c91445..968c11501426 100644 --- a/packages/beacon-node/src/network/processor/gossipQueues/index.ts +++ b/packages/beacon-node/src/network/processor/gossipQueues/index.ts @@ -3,16 +3,8 @@ import {GossipType} from "../../gossip/interface.js"; import {PendingGossipsubMessage} from "../types.js"; import {getGossipAttestationIndex} from "../../../util/sszBytes.js"; import {LinearGossipQueue} from "./linear.js"; -import { - DropType, - GossipQueue, - GossipQueueOpts, - QueueType, - isIndexedGossipQueueAvgTimeOpts, - isIndexedGossipQueueMinSizeOpts, -} from "./types.js"; +import {DropType, GossipQueue, GossipQueueOpts, QueueType, isIndexedGossipQueueMinSizeOpts} from "./types.js"; import {IndexedGossipQueueMinSize} from "./indexed.js"; -import {IndexedGossipQueueAvgTime} from "./indexedAvgTime.js"; /** * In normal condition, the higher this value the more efficient the signature verification. @@ -120,8 +112,6 @@ export function createGossipQueues(beaconAttestationBatchValidation = false): { return mapValues(gossipQueueOpts, (opts) => { if (isIndexedGossipQueueMinSizeOpts(opts)) { return new IndexedGossipQueueMinSize(opts); - } else if (isIndexedGossipQueueAvgTimeOpts(opts)) { - return new IndexedGossipQueueAvgTime(opts); } else { return new LinearGossipQueue(opts); } diff --git a/packages/beacon-node/src/network/processor/gossipQueues/indexedAvgTime.ts b/packages/beacon-node/src/network/processor/gossipQueues/indexedAvgTime.ts deleted file mode 100644 index b7bba4c132bb..000000000000 --- a/packages/beacon-node/src/network/processor/gossipQueues/indexedAvgTime.ts +++ /dev/null @@ -1,129 +0,0 @@ -import {GossipQueue, IndexedGossipQueueOpts} from "./types.js"; - -type ItemList = { - items: T[]; - avgRecvTimestampMs: number; -}; - -function listScore(list: ItemList): number { - return list.items.length / Math.max(1000, Date.now() - list.avgRecvTimestampMs); -} - -/** - * An implementation of GossipQueue that tries to run the batch with highest score first. - * TODO: add unit tests - * - index items by indexFn using a map - * - compute avgRecvTimestampMs for each key every time we add new item - * - on next, pick the key with the highest score (check the score function above) - */ -export class IndexedGossipQueueAvgTime implements GossipQueue { - private _length = 0; - private indexedItems: Map> = new Map(); - - constructor(private readonly opts: IndexedGossipQueueOpts) {} - - get length(): number { - return this._length; - } - - get keySize(): number { - return this.indexedItems.size; - } - - clear(): void { - this.indexedItems = new Map(); - this._length = 0; - } - - // not implemented for this gossip queue - getDataAgeMs(): number[] { - return []; - } - - /** - * Add item to gossip queue. If queue is full, drop first item of first key. - * Return number of items dropped - */ - add(item: T): number { - const key = this.opts.indexFn(item); - if (key == null) { - // this comes from getAttDataBase64FromAttestationSerialized() return type - // should not happen - return 0; - } - item.indexed = key; - let list = this.indexedItems.get(key); - if (list == null) { - list = { - items: [], - avgRecvTimestampMs: Date.now(), - }; - this.indexedItems.set(key, list); - } else { - list.avgRecvTimestampMs = (list.avgRecvTimestampMs * list.items.length + Date.now()) / (list.items.length + 1); - list.items.push(item); - } - this._length++; - if (this._length <= this.opts.maxLength) { - return 0; - } - - // overload, need to drop more items - const firstKey = this.indexedItems.keys().next().value as string; - // there should be at least 1 key - if (firstKey == null) { - return 0; - } - const firstList = this.indexedItems.get(firstKey); - // should not happen - if (firstList == null) { - return 0; - } - - const deletedItem = firstList.items.shift(); - if (deletedItem != null) { - this._length--; - if (firstList.items.length === 0) { - this.indexedItems.delete(firstKey); - } - return 1; - } else { - return 0; - } - } - - /** - * Try to get list of items of the same key with highest score - */ - next(): T[] | null { - let maxScore = 0; - let maxScoreKey: string | undefined; - for (const [key, list] of this.indexedItems) { - const score = listScore(list); - if (score > maxScore) { - maxScore = score; - maxScoreKey = key; - } - } - - if (maxScoreKey == null) { - return null; - } - const items = this.indexedItems.get(maxScoreKey)?.items; - if (items == null) { - // should not happen - return null; - } - this.indexedItems.delete(maxScoreKey); - this._length = Math.max(0, this._length - items.length); - return items; - } - - getAll(): T[] { - const items: T[] = []; - for (const list of this.indexedItems.values()) { - items.push(...list.items); - } - return items; - } -} diff --git a/packages/beacon-node/src/network/processor/gossipQueues/types.ts b/packages/beacon-node/src/network/processor/gossipQueues/types.ts index 448f44c3f5d7..58034e82ed06 100644 --- a/packages/beacon-node/src/network/processor/gossipQueues/types.ts +++ b/packages/beacon-node/src/network/processor/gossipQueues/types.ts @@ -1,4 +1,4 @@ -export type GossipQueueOpts = LinearGossipQueueOpts | IndexedGossipQueueOpts | IndexedGossipQueueMinSizeOpts; +export type GossipQueueOpts = LinearGossipQueueOpts | IndexedGossipQueueMinSizeOpts; export type LinearGossipQueueOpts = { type: QueueType; @@ -25,15 +25,6 @@ export function isIndexedGossipQueueMinSizeOpts(opts: GossipQueueOpts): op ); } -export function isIndexedGossipQueueAvgTimeOpts(opts: GossipQueueOpts): opts is IndexedGossipQueueOpts { - const avgTimeOpts = opts as IndexedGossipQueueMinSizeOpts; - return ( - avgTimeOpts.indexFn !== undefined && - avgTimeOpts.minChunkSize === undefined && - avgTimeOpts.maxChunkSize === undefined - ); -} - export interface GossipQueue { length: number; keySize: number; From 5f7b611eeb4adab186919b042bc6422a9ba5aa75 Mon Sep 17 00:00:00 2001 From: Nico Flaig Date: Mon, 7 Oct 2024 20:26:37 +0100 Subject: [PATCH 34/52] feat: add standard endpoint to retrieve fork choice context (#7127) --- packages/api/src/beacon/routes/debug.ts | 53 +++++++++++++++++++ .../api/test/unit/beacon/oapiSpec.test.ts | 1 - .../api/test/unit/beacon/testData/debug.ts | 30 ++++++++++- .../beacon-node/src/api/impl/debug/index.ts | 31 +++++++++++ packages/beacon-node/src/api/rest/base.ts | 2 +- 5 files changed, 114 insertions(+), 3 deletions(-) diff --git a/packages/api/src/beacon/routes/debug.ts b/packages/api/src/beacon/routes/debug.ts index 8099fcac020e..590ecf71dd9c 100644 --- a/packages/api/src/beacon/routes/debug.ts +++ b/packages/api/src/beacon/routes/debug.ts @@ -58,11 +58,34 @@ const DebugChainHeadType = new ContainerType( {jsonCase: "eth2"} ); +const ForkChoiceNodeType = new ContainerType( + { + slot: ssz.Slot, + blockRoot: stringType, + parentRoot: stringType, + justifiedEpoch: ssz.Epoch, + finalizedEpoch: ssz.Epoch, + weight: ssz.UintNum64, + validity: new StringType<"valid" | "invalid" | "optimistic">(), + executionBlockHash: stringType, + }, + {jsonCase: "eth2"} +); +const ForkChoiceResponseType = new ContainerType( + { + justifiedCheckpoint: ssz.phase0.Checkpoint, + finalizedCheckpoint: ssz.phase0.Checkpoint, + forkChoiceNodes: ArrayOf(ForkChoiceNodeType), + }, + {jsonCase: "eth2"} +); + const ProtoNodeListType = ArrayOf(ProtoNodeType); const DebugChainHeadListType = ArrayOf(DebugChainHeadType); type ProtoNodeList = ValueOf; type DebugChainHeadList = ValueOf; +type ForkChoiceResponse = ValueOf; export type Endpoints = { /** @@ -77,6 +100,18 @@ export type Endpoints = { EmptyMeta >; + /** + * Retrieves all current fork choice context + */ + getDebugForkChoice: Endpoint< + // ⏎ + "GET", + EmptyArgs, + EmptyRequest, + ForkChoiceResponse, + EmptyMeta + >; + /** * Dump all ProtoArray's nodes to debug */ @@ -115,6 +150,24 @@ export function getDefinitions(_config: ChainForkConfig): RouteDefinitions ({ + ...(data as ForkChoiceResponse), + }), + fromResponse: (resp) => ({ + data: resp as ForkChoiceResponse, + }), + }, + }, + }, getProtoArrayNodes: { url: "/eth/v0/debug/forkchoice", method: "GET", diff --git a/packages/api/test/unit/beacon/oapiSpec.test.ts b/packages/api/test/unit/beacon/oapiSpec.test.ts index 89079cd0768c..2b8a8254dd6b 100644 --- a/packages/api/test/unit/beacon/oapiSpec.test.ts +++ b/packages/api/test/unit/beacon/oapiSpec.test.ts @@ -57,7 +57,6 @@ const ignoredOperations = [ /* missing route */ "getDepositSnapshot", // Won't fix for now, see https://github.com/ChainSafe/lodestar/issues/5697 "getNextWithdrawals", // https://github.com/ChainSafe/lodestar/issues/5696 - "getDebugForkChoice", // https://github.com/ChainSafe/lodestar/issues/5700 /* Must support ssz response body */ "getLightClientUpdatesByRange", // https://github.com/ChainSafe/lodestar/issues/6841 ]; diff --git a/packages/api/test/unit/beacon/testData/debug.ts b/packages/api/test/unit/beacon/testData/debug.ts index aac3b379ff4d..cb2799939ae3 100644 --- a/packages/api/test/unit/beacon/testData/debug.ts +++ b/packages/api/test/unit/beacon/testData/debug.ts @@ -4,13 +4,41 @@ import {ssz} from "@lodestar/types"; import {Endpoints} from "../../../../src/beacon/routes/debug.js"; import {GenericServerTestCases} from "../../../utils/genericServerTest.js"; -const rootHex = toHexString(Buffer.alloc(32, 1)); +const root = new Uint8Array(32).fill(1); +const rootHex = toHexString(root); export const testData: GenericServerTestCases = { getDebugChainHeadsV2: { args: undefined, res: {data: [{slot: 1, root: rootHex, executionOptimistic: true}]}, }, + getDebugForkChoice: { + args: undefined, + res: { + data: { + justifiedCheckpoint: { + epoch: 2, + root, + }, + finalizedCheckpoint: { + epoch: 1, + root, + }, + forkChoiceNodes: [ + { + slot: 1, + blockRoot: rootHex, + parentRoot: rootHex, + justifiedEpoch: 1, + finalizedEpoch: 1, + weight: 1, + validity: "valid", + executionBlockHash: rootHex, + }, + ], + }, + }, + }, getProtoArrayNodes: { args: undefined, res: { diff --git a/packages/beacon-node/src/api/impl/debug/index.ts b/packages/beacon-node/src/api/impl/debug/index.ts index 4edb8ba9b2dd..e5b6450b206f 100644 --- a/packages/beacon-node/src/api/impl/debug/index.ts +++ b/packages/beacon-node/src/api/impl/debug/index.ts @@ -1,6 +1,8 @@ import {routes} from "@lodestar/api"; import {ApplicationMethods} from "@lodestar/api/server"; +import {ExecutionStatus} from "@lodestar/fork-choice"; import {BeaconState} from "@lodestar/types"; +import {ZERO_HASH_HEX} from "@lodestar/params"; import {getStateResponseWithRegen} from "../beacon/state/utils.js"; import {ApiModules} from "../types.js"; import {isOptimisticBlock} from "../../../util/forkChoice.js"; @@ -22,6 +24,35 @@ export function getDebugApi({ }; }, + async getDebugForkChoice() { + return { + data: { + justifiedCheckpoint: chain.forkChoice.getJustifiedCheckpoint(), + finalizedCheckpoint: chain.forkChoice.getFinalizedCheckpoint(), + forkChoiceNodes: chain.forkChoice.getAllNodes().map((node) => ({ + slot: node.slot, + blockRoot: node.blockRoot, + parentRoot: node.parentRoot, + justifiedEpoch: node.justifiedEpoch, + finalizedEpoch: node.finalizedEpoch, + weight: node.weight, + validity: (() => { + switch (node.executionStatus) { + case ExecutionStatus.Valid: + return "valid"; + case ExecutionStatus.Invalid: + return "invalid"; + case ExecutionStatus.Syncing: + case ExecutionStatus.PreMerge: + return "optimistic"; + } + })(), + executionBlockHash: node.executionPayloadBlockHash ?? ZERO_HASH_HEX, + })), + }, + }; + }, + async getProtoArrayNodes() { const nodes = chain.forkChoice.getAllNodes().map((node) => ({ // if node has executionPayloadNumber, it will overwrite the below default diff --git a/packages/beacon-node/src/api/rest/base.ts b/packages/beacon-node/src/api/rest/base.ts index 10318b1b3ba7..276583dc7281 100644 --- a/packages/beacon-node/src/api/rest/base.ts +++ b/packages/beacon-node/src/api/rest/base.ts @@ -96,7 +96,7 @@ export class RestApiServer { if (err.validation) { const {instancePath, message} = err.validation[0]; const payload: ErrorResponse = { - code: err.statusCode ?? 400, + code: 400, message: `${instancePath.substring(instancePath.lastIndexOf("/") + 1)} ${message}`, stacktraces, }; From 1fa3f37ab7a6ea53888650cb23da43456886c935 Mon Sep 17 00:00:00 2001 From: twoeths Date: Tue, 8 Oct 2024 02:31:39 +0700 Subject: [PATCH 35/52] refactor: remove beaconAttestationBatchValidation flag (#7129) * chore: remove beaconAttestationBatchValidation flag * chore: refactor SequentialGossipHandlers vs BatchGossipHandlers * chore: remove unused validateGossipAttestation() function * chore: lint * chore: fix lint * chore: SequentialGossipType vs BatchGossipType * chore: simplify getGossipHandlers() --- .../src/chain/validation/attestation.ts | 46 ++---------- .../src/network/gossip/interface.ts | 19 ++--- packages/beacon-node/src/network/options.ts | 2 - .../src/network/processor/gossipHandlers.ts | 71 ++----------------- .../network/processor/gossipQueues/index.ts | 26 +++---- .../src/network/processor/index.ts | 2 +- .../perf/chain/validation/attestation.test.ts | 22 +----- .../attestation/validateAttestation.test.ts | 29 ++++---- .../src/options/beaconNodeOptions/network.ts | 9 --- .../unit/options/beaconNodeOptions.test.ts | 2 - 10 files changed, 51 insertions(+), 177 deletions(-) diff --git a/packages/beacon-node/src/chain/validation/attestation.ts b/packages/beacon-node/src/chain/validation/attestation.ts index 4ceaf64d658d..119a8ee1a899 100644 --- a/packages/beacon-node/src/chain/validation/attestation.ts +++ b/packages/beacon-node/src/chain/validation/attestation.ts @@ -38,7 +38,6 @@ import {MAXIMUM_GOSSIP_CLOCK_DISPARITY_SEC} from "../../constants/index.js"; import {RegenCaller} from "../regen/index.js"; import { getAggregationBitsFromAttestationSerialized, - getAttDataFromAttestationSerialized, getAttDataFromSignedAggregateAndProofElectra, getCommitteeBitsFromAttestationSerialized, getCommitteeBitsFromSignedAggregateAndProofElectra, @@ -75,9 +74,8 @@ export type GossipAttestation = { serializedData: Uint8Array; // available in NetworkProcessor since we check for unknown block root attestations attSlot: Slot; - // for old LIFO linear gossip queue we don't have attDataBase64 // for indexed gossip queue we have attDataBase64 - attDataBase64?: SeenAttDataKey | null; + attDataBase64: SeenAttDataKey; }; export type Step0Result = AttestationValidationResult & { @@ -85,20 +83,6 @@ export type Step0Result = AttestationValidationResult & { validatorIndex: number; }; -/** - * Validate a single gossip attestation, do not prioritize bls signature set - */ -export async function validateGossipAttestation( - fork: ForkName, - chain: IBeaconChain, - attestationOrBytes: GossipAttestation, - /** Optional, to allow verifying attestations through API with unknown subnet */ - subnet: number -): Promise { - const prioritizeBls = false; - return validateAttestation(fork, chain, attestationOrBytes, subnet, prioritizeBls); -} - /** * Verify gossip attestations of the same attestation data. The main advantage is we can batch verify bls signatures * through verifySignatureSetsSameMessage bls api to improve performance. @@ -111,7 +95,7 @@ export async function validateGossipAttestationsSameAttData( attestationOrBytesArr: GossipAttestation[], subnet: number, // for unit test, consumers do not need to pass this - step0ValidationFn = validateGossipAttestationNoSignatureCheck + step0ValidationFn = validateAttestationNoSignatureCheck ): Promise { if (attestationOrBytesArr.length === 0) { return {results: [], batchableBls: false}; @@ -213,22 +197,10 @@ export async function validateApiAttestation( attestationOrBytes: ApiAttestation ): Promise { const prioritizeBls = true; - return validateAttestation(fork, chain, attestationOrBytes, null, prioritizeBls); -} + const subnet = null; -/** - * Validate a single unaggregated attestation - * subnet is null for api attestations - */ -export async function validateAttestation( - fork: ForkName, - chain: IBeaconChain, - attestationOrBytes: AttestationOrBytes, - subnet: number | null, - prioritizeBls = false -): Promise { try { - const step0Result = await validateGossipAttestationNoSignatureCheck(fork, chain, attestationOrBytes, subnet); + const step0Result = await validateAttestationNoSignatureCheck(fork, chain, attestationOrBytes, subnet); const {attestation, signatureSet, validatorIndex} = step0Result; const isValid = await chain.bls.verifySignatureSets([signatureSet], {batchable: true, priority: prioritizeBls}); @@ -256,7 +228,7 @@ export async function validateAttestation( * Only deserialize the attestation if needed, use the cached AttestationData instead * This is to avoid deserializing similar attestation multiple times which could help the gc */ -async function validateGossipAttestationNoSignatureCheck( +async function validateAttestationNoSignatureCheck( fork: ForkName, chain: IBeaconChain, attestationOrBytes: AttestationOrBytes, @@ -801,9 +773,6 @@ export function computeSubnetForSlot(shuffling: EpochShuffling, slot: number, co * Return fork-dependent seen attestation key * - for pre-electra, it's the AttestationData base64 * - for electra and later, it's the AttestationData base64 + committeeBits base64 - * - * we always have attDataBase64 from the IndexedGossipQueue, getAttDataFromAttestationSerialized() just for backward compatible when beaconAttestationBatchValidation is false - * TODO: remove beaconAttestationBatchValidation flag since the batch attestation is stable */ export function getSeenAttDataKeyFromGossipAttestation( fork: ForkName, @@ -811,13 +780,12 @@ export function getSeenAttDataKeyFromGossipAttestation( ): SeenAttDataKey | null { const {attDataBase64, serializedData} = attestation; if (isForkPostElectra(fork)) { - const attData = attDataBase64 ?? getAttDataFromAttestationSerialized(serializedData); const committeeBits = getCommitteeBitsFromAttestationSerialized(serializedData); - return attData && committeeBits ? attDataBase64 + committeeBits : null; + return attDataBase64 && committeeBits ? attDataBase64 + committeeBits : null; } // pre-electra - return attDataBase64 ?? getAttDataFromAttestationSerialized(serializedData); + return attDataBase64; } /** diff --git a/packages/beacon-node/src/network/gossip/interface.ts b/packages/beacon-node/src/network/gossip/interface.ts index ab9b8a65978d..af5e3888d04f 100644 --- a/packages/beacon-node/src/network/gossip/interface.ts +++ b/packages/beacon-node/src/network/gossip/interface.ts @@ -36,6 +36,9 @@ export enum GossipType { bls_to_execution_change = "bls_to_execution_change", } +export type SequentialGossipType = Exclude; +export type BatchGossipType = GossipType.beacon_attestation; + export enum GossipEncoding { ssz_snappy = "ssz_snappy", } @@ -181,25 +184,25 @@ export type GossipHandlerParamGeneric = { }; export type GossipHandlers = { - [K in GossipType]: DefaultGossipHandler | BatchGossipHandler; + [K in GossipType]: SequentialGossipHandler | BatchGossipHandler; }; -export type DefaultGossipHandler = ( +export type SequentialGossipHandler = ( gossipHandlerParam: GossipHandlerParamGeneric ) => Promise; -export type DefaultGossipHandlers = { - [K in GossipType]: DefaultGossipHandler; +export type SequentialGossipHandlers = { + [K in SequentialGossipType]: SequentialGossipHandler; +}; + +export type BatchGossipHandlers = { + [K in BatchGossipType]: BatchGossipHandler; }; export type BatchGossipHandler = ( gossipHandlerParams: GossipHandlerParamGeneric[] ) => Promise<(null | GossipActionError)[]>; -export type BatchGossipHandlers = { - [K in GossipType]?: BatchGossipHandler; -}; - // eslint-disable-next-line @typescript-eslint/no-explicit-any export type ResolvedType Promise> = F extends (...args: any) => Promise ? T diff --git a/packages/beacon-node/src/network/options.ts b/packages/beacon-node/src/network/options.ts index d2070873261b..ebb321584d12 100644 --- a/packages/beacon-node/src/network/options.ts +++ b/packages/beacon-node/src/network/options.ts @@ -40,8 +40,6 @@ export const defaultNetworkOptions: NetworkOptions = { maxYoungGenerationSizeMb: 152, // subscribe 2 slots before aggregator dutied slot to get stable mesh peers as monitored on goerli slotsToSubscribeBeforeAggregatorDuty: 2, - // this should only be set to true if useWorker is true - beaconAttestationBatchValidation: true, // This will enable the light client server by default disableLightClientServer: false, }; diff --git a/packages/beacon-node/src/network/processor/gossipHandlers.ts b/packages/beacon-node/src/network/processor/gossipHandlers.ts index 8df9f7b78126..90c131a943ed 100644 --- a/packages/beacon-node/src/network/processor/gossipHandlers.ts +++ b/packages/beacon-node/src/network/processor/gossipHandlers.ts @@ -20,7 +20,7 @@ import { } from "../../chain/errors/index.js"; import { BatchGossipHandlers, - DefaultGossipHandlers, + SequentialGossipHandlers, GossipHandlerParamGeneric, GossipHandlers, GossipType, @@ -36,8 +36,6 @@ import { validateGossipBlsToExecutionChange, AggregateAndProofValidationResult, validateGossipAttestationsSameAttData, - validateGossipAttestation, - AttestationValidationResult, GossipAttestation, } from "../../chain/validation/index.js"; import {NetworkEvent, NetworkEventBus} from "../events.js"; @@ -64,8 +62,6 @@ import {AggregatorTracker} from "./aggregatorTracker.js"; export type GossipHandlerOpts = { /** By default pass gossip attestations to forkchoice */ dontSendGossipAttestationsToForkchoice?: boolean; - /** By default don't validate gossip attestations in batch */ - beaconAttestationBatchValidation?: boolean; }; export type ValidatorFnsModules = { @@ -96,20 +92,15 @@ const BLOCK_AVAILABILITY_CUTOFF_MS = 3_000; * - Ethereum Consensus gossipsub protocol strictly defined a single topic for message */ export function getGossipHandlers(modules: ValidatorFnsModules, options: GossipHandlerOpts): GossipHandlers { - const defaultHandlers = getDefaultHandlers(modules, options); - if (options.beaconAttestationBatchValidation) { - const batchHandlers = getBatchHandlers(modules, options); - return {...defaultHandlers, ...batchHandlers}; - } - return defaultHandlers; + return {...getSequentialHandlers(modules, options), ...getBatchHandlers(modules, options)}; } /** * Default handlers validate gossip messages one by one. * We only have a choice to do batch validation for beacon_attestation topic. */ -function getDefaultHandlers(modules: ValidatorFnsModules, options: GossipHandlerOpts): DefaultGossipHandlers { - const {chain, config, metrics, events, logger, core, aggregatorTracker} = modules; +function getSequentialHandlers(modules: ValidatorFnsModules, options: GossipHandlerOpts): SequentialGossipHandlers { + const {chain, config, metrics, events, logger, core} = modules; async function validateBeaconBlock( signedBlock: SignedBeaconBlock, @@ -458,58 +449,6 @@ function getDefaultHandlers(modules: ValidatorFnsModules, options: GossipHandler chain.emitter.emit(routes.events.EventType.attestation, signedAggregateAndProof.message.aggregate); }, - [GossipType.beacon_attestation]: async ({ - gossipData, - topic, - seenTimestampSec, - }: GossipHandlerParamGeneric): Promise => { - const {serializedData, msgSlot} = gossipData; - if (msgSlot == undefined) { - throw Error("msgSlot is undefined for beacon_attestation topic"); - } - const {subnet, fork} = topic; - - // do not deserialize gossipSerializedData here, it's done in validateGossipAttestation only if needed - let validationResult: AttestationValidationResult; - try { - validationResult = await validateGossipAttestation( - fork, - chain, - {attestation: null, serializedData, attSlot: msgSlot}, - subnet - ); - } catch (e) { - if (e instanceof AttestationError && e.action === GossipAction.REJECT) { - chain.persistInvalidSszBytes(ssz.phase0.Attestation.typeName, serializedData, "gossip_reject"); - } - throw e; - } - - // Handler - const {indexedAttestation, attDataRootHex, attestation, committeeIndex} = validationResult; - metrics?.registerGossipUnaggregatedAttestation(seenTimestampSec, indexedAttestation); - - try { - // Node may be subscribe to extra subnets (long-lived random subnets). For those, validate the messages - // but don't add to attestation pool, to save CPU and RAM - if (aggregatorTracker.shouldAggregate(subnet, indexedAttestation.data.slot)) { - const insertOutcome = chain.attestationPool.add(committeeIndex, attestation, attDataRootHex); - metrics?.opPool.attestationPoolInsertOutcome.inc({insertOutcome}); - } - } catch (e) { - logger.error("Error adding unaggregated attestation to pool", {subnet}, e as Error); - } - - if (!options.dontSendGossipAttestationsToForkchoice) { - try { - chain.forkChoice.onAttestation(indexedAttestation, attDataRootHex); - } catch (e) { - logger.debug("Error adding gossip unaggregated attestation to forkchoice", {subnet}, e as Error); - } - } - - chain.emitter.emit(routes.events.EventType.attestation, attestation); - }, [GossipType.attester_slashing]: async ({ gossipData, @@ -660,7 +599,7 @@ function getDefaultHandlers(modules: ValidatorFnsModules, options: GossipHandler /** * For now, only beacon_attestation topic is batched. */ -function getBatchHandlers(modules: ValidatorFnsModules, options: GossipHandlerOpts): Partial { +function getBatchHandlers(modules: ValidatorFnsModules, options: GossipHandlerOpts): BatchGossipHandlers { const {chain, metrics, logger, aggregatorTracker} = modules; return { [GossipType.beacon_attestation]: async ( diff --git a/packages/beacon-node/src/network/processor/gossipQueues/index.ts b/packages/beacon-node/src/network/processor/gossipQueues/index.ts index 968c11501426..12596a42b7a1 100644 --- a/packages/beacon-node/src/network/processor/gossipQueues/index.ts +++ b/packages/beacon-node/src/network/processor/gossipQueues/index.ts @@ -1,5 +1,5 @@ import {mapValues} from "@lodestar/utils"; -import {GossipType} from "../../gossip/interface.js"; +import {BatchGossipType, GossipType, SequentialGossipType} from "../../gossip/interface.js"; import {PendingGossipsubMessage} from "../types.js"; import {getGossipAttestationIndex} from "../../../util/sszBytes.js"; import {LinearGossipQueue} from "./linear.js"; @@ -20,8 +20,8 @@ export const MIN_SIGNATURE_SETS_TO_BATCH_VERIFY = 32; /** * Numbers from https://github.com/sigp/lighthouse/blob/b34a79dc0b02e04441ba01fd0f304d1e203d877d/beacon_node/network/src/beacon_processor/mod.rs#L69 */ -const defaultGossipQueueOpts: { - [K in GossipType]: GossipQueueOpts; +const linearGossipQueueOpts: { + [K in SequentialGossipType]: GossipQueueOpts; } = { // validation gossip block asap [GossipType.beacon_block]: {maxLength: 1024, type: QueueType.FIFO, dropOpts: {type: DropType.count, count: 1}}, @@ -37,15 +37,6 @@ const defaultGossipQueueOpts: { type: QueueType.LIFO, dropOpts: {type: DropType.count, count: 1}, }, - // lighthouse has attestation_queue 16384 and unknown_block_attestation_queue 8192, we use single queue - // this topic may cause node to be overload and drop 100% of lower priority queues - // so we want to drop it by ratio until node is stable enough (queue is empty) - // start with dropping 1% of the queue, then increase 1% more each time. Reset when queue is empty - [GossipType.beacon_attestation]: { - maxLength: 24576, - type: QueueType.LIFO, - dropOpts: {type: DropType.ratio, start: 0.01, step: 0.01}, - }, [GossipType.voluntary_exit]: {maxLength: 4096, type: QueueType.FIFO, dropOpts: {type: DropType.count, count: 1}}, [GossipType.proposer_slashing]: {maxLength: 4096, type: QueueType.FIFO, dropOpts: {type: DropType.count, count: 1}}, [GossipType.attester_slashing]: {maxLength: 4096, type: QueueType.FIFO, dropOpts: {type: DropType.count, count: 1}}, @@ -74,9 +65,11 @@ const defaultGossipQueueOpts: { }; const indexedGossipQueueOpts: { - [K in GossipType]?: GossipQueueOpts; + [K in BatchGossipType]: GossipQueueOpts; } = { [GossipType.beacon_attestation]: { + // lighthouse has attestation_queue 16384 and unknown_block_attestation_queue 8192, we use single queue + // this topic may cause node to be overload and drop 100% of lower priority queues maxLength: 24576, indexFn: (item: PendingGossipsubMessage) => { // Note indexFn is fork agnostic despite changes introduced in Electra @@ -103,12 +96,11 @@ const indexedGossipQueueOpts: { * By topic is too specific, so by type groups all similar objects in the same queue. All in the same won't allow * to customize different queue behaviours per object type (see `gossipQueueOpts`). */ -export function createGossipQueues(beaconAttestationBatchValidation = false): { +export function createGossipQueues(): { [K in GossipType]: GossipQueue; } { - const gossipQueueOpts = beaconAttestationBatchValidation - ? {...defaultGossipQueueOpts, ...indexedGossipQueueOpts} - : defaultGossipQueueOpts; + const gossipQueueOpts = {...linearGossipQueueOpts, ...indexedGossipQueueOpts}; + return mapValues(gossipQueueOpts, (opts) => { if (isIndexedGossipQueueMinSizeOpts(opts)) { return new IndexedGossipQueueMinSize(opts); diff --git a/packages/beacon-node/src/network/processor/index.ts b/packages/beacon-node/src/network/processor/index.ts index 9a1dcfb32fa0..5cfed6c20346 100644 --- a/packages/beacon-node/src/network/processor/index.ts +++ b/packages/beacon-node/src/network/processor/index.ts @@ -172,7 +172,7 @@ export class NetworkProcessor { this.metrics = metrics; this.logger = logger; this.events = events; - this.gossipQueues = createGossipQueues(this.opts.beaconAttestationBatchValidation); + this.gossipQueues = createGossipQueues(); this.gossipTopicConcurrency = mapValues(this.gossipQueues, () => 0); this.gossipValidatorFn = getGossipValidatorFn(modules.gossipHandlers ?? getGossipHandlers(modules, opts), modules); this.gossipValidatorBatchFn = getGossipValidatorBatchFn( diff --git a/packages/beacon-node/test/perf/chain/validation/attestation.test.ts b/packages/beacon-node/test/perf/chain/validation/attestation.test.ts index f285317474d6..e942e1ea17d0 100644 --- a/packages/beacon-node/test/perf/chain/validation/attestation.test.ts +++ b/packages/beacon-node/test/perf/chain/validation/attestation.test.ts @@ -3,7 +3,7 @@ import {expect} from "chai"; import {ssz} from "@lodestar/types"; // eslint-disable-next-line import/no-relative-packages import {generateTestCachedBeaconStateOnlyValidators} from "../../../../../state-transition/test/perf/util.js"; -import {validateAttestation, validateGossipAttestationsSameAttData} from "../../../../src/chain/validation/index.js"; +import {validateGossipAttestationsSameAttData} from "../../../../src/chain/validation/index.js"; import {getAttestationValidData} from "../../../utils/validationData/attestation.js"; import {getAttDataFromAttestationSerialized} from "../../../../src/util/sszBytes.js"; @@ -29,25 +29,7 @@ describe("validate gossip attestation", () => { }); const attSlot = attestation0.data.slot; - const serializedData = ssz.phase0.Attestation.serialize(attestation0); const fork = chain.config.getForkName(stateSlot); - itBench({ - id: `validate gossip attestation - vc ${vc}`, - beforeEach: () => chain.seenAttesters["validatorIndexesByEpoch"].clear(), - fn: async () => { - await validateAttestation( - fork, - chain, - { - attestation: null, - serializedData, - attSlot, - attDataBase64: getAttDataFromAttestationSerialized(serializedData), - }, - subnet0 - ); - }, - }); for (const chunkSize of [32, 64, 128, 256]) { const attestations = [attestation0]; @@ -67,7 +49,7 @@ describe("validate gossip attestation", () => { attestation: null, serializedData, attSlot, - attDataBase64: getAttDataFromAttestationSerialized(serializedData), + attDataBase64: getAttDataFromAttestationSerialized(serializedData) as string, }; }); diff --git a/packages/beacon-node/test/unit/chain/validation/attestation/validateAttestation.test.ts b/packages/beacon-node/test/unit/chain/validation/attestation/validateAttestation.test.ts index 45d293ffbb33..90d37a74289d 100644 --- a/packages/beacon-node/test/unit/chain/validation/attestation/validateAttestation.test.ts +++ b/packages/beacon-node/test/unit/chain/validation/attestation/validateAttestation.test.ts @@ -2,6 +2,7 @@ import {BitArray} from "@chainsafe/ssz"; import {describe, expect, it} from "vitest"; import {ForkName, SLOTS_PER_EPOCH} from "@lodestar/params"; import {ssz} from "@lodestar/types"; +import {LodestarError} from "@lodestar/utils"; // eslint-disable-next-line import/no-relative-packages import {generateTestCachedBeaconStateOnlyValidators} from "../../../../../../state-transition/test/perf/util.js"; import {AttestationErrorCode, GossipErrorCode} from "../../../../../src/chain/errors/index.js"; @@ -12,7 +13,7 @@ import { getSeenAttDataKeyFromGossipAttestation, getSeenAttDataKeyFromSignedAggregateAndProof, validateApiAttestation, - validateAttestation, + validateGossipAttestationsSameAttData, } from "../../../../../src/chain/validation/index.js"; import {getAttDataFromAttestationSerialized} from "../../../../../src/util/sszBytes.js"; import {memoOnce} from "../../../../utils/cache.js"; @@ -75,7 +76,7 @@ describe("validateAttestation", () => { attestation: null, serializedData, attSlot: attestation.data.slot, - attDataBase64: getAttDataFromAttestationSerialized(serializedData), + attDataBase64: getAttDataFromAttestationSerialized(serializedData) as string, }, subnet, AttestationErrorCode.BAD_TARGET_EPOCH @@ -94,7 +95,7 @@ describe("validateAttestation", () => { attestation: null, serializedData, attSlot: attestation.data.slot, - attDataBase64: getAttDataFromAttestationSerialized(serializedData), + attDataBase64: getAttDataFromAttestationSerialized(serializedData) as string, }, subnet, AttestationErrorCode.PAST_SLOT @@ -113,7 +114,7 @@ describe("validateAttestation", () => { attestation: null, serializedData, attSlot: attestation.data.slot, - attDataBase64: getAttDataFromAttestationSerialized(serializedData), + attDataBase64: getAttDataFromAttestationSerialized(serializedData) as string, }, subnet, AttestationErrorCode.FUTURE_SLOT @@ -138,7 +139,7 @@ describe("validateAttestation", () => { attestation: null, serializedData, attSlot: attestation.data.slot, - attDataBase64: getAttDataFromAttestationSerialized(serializedData), + attDataBase64: getAttDataFromAttestationSerialized(serializedData) as string, }, subnet, AttestationErrorCode.NOT_EXACTLY_ONE_AGGREGATION_BIT_SET @@ -158,7 +159,7 @@ describe("validateAttestation", () => { attestation: null, serializedData, attSlot: attestation.data.slot, - attDataBase64: getAttDataFromAttestationSerialized(serializedData), + attDataBase64: getAttDataFromAttestationSerialized(serializedData) as string, }, subnet, AttestationErrorCode.NOT_EXACTLY_ONE_AGGREGATION_BIT_SET @@ -182,7 +183,7 @@ describe("validateAttestation", () => { attestation: null, serializedData, attSlot: attestation.data.slot, - attDataBase64: getAttDataFromAttestationSerialized(serializedData), + attDataBase64: getAttDataFromAttestationSerialized(serializedData) as string, }, subnet, AttestationErrorCode.UNKNOWN_OR_PREFINALIZED_BEACON_BLOCK_ROOT @@ -202,7 +203,7 @@ describe("validateAttestation", () => { attestation: null, serializedData, attSlot: attestation.data.slot, - attDataBase64: getAttDataFromAttestationSerialized(serializedData), + attDataBase64: getAttDataFromAttestationSerialized(serializedData) as string, }, subnet, AttestationErrorCode.INVALID_TARGET_ROOT @@ -229,7 +230,7 @@ describe("validateAttestation", () => { attestation: null, serializedData, attSlot: attestation.data.slot, - attDataBase64: getAttDataFromAttestationSerialized(serializedData), + attDataBase64: getAttDataFromAttestationSerialized(serializedData) as string, }, subnet, AttestationErrorCode.WRONG_NUMBER_OF_AGGREGATION_BITS @@ -248,7 +249,7 @@ describe("validateAttestation", () => { attestation: null, serializedData, attSlot: attestation.data.slot, - attDataBase64: getAttDataFromAttestationSerialized(serializedData), + attDataBase64: getAttDataFromAttestationSerialized(serializedData) as string, }, invalidSubnet, AttestationErrorCode.INVALID_SUBNET_ID @@ -268,7 +269,7 @@ describe("validateAttestation", () => { attestation: null, serializedData, attSlot: attestation.data.slot, - attDataBase64: getAttDataFromAttestationSerialized(serializedData), + attDataBase64: getAttDataFromAttestationSerialized(serializedData) as string, }, subnet, AttestationErrorCode.ATTESTATION_ALREADY_KNOWN @@ -290,7 +291,7 @@ describe("validateAttestation", () => { attestation: null, serializedData, attSlot: attestation.data.slot, - attDataBase64: getAttDataFromAttestationSerialized(serializedData), + attDataBase64: getAttDataFromAttestationSerialized(serializedData) as string, }, subnet, AttestationErrorCode.INVALID_SIGNATURE @@ -314,7 +315,9 @@ describe("validateAttestation", () => { errorCode: string ): Promise { const fork = chain.config.getForkName(stateSlot); - await expectRejectedWithLodestarError(validateAttestation(fork, chain, attestationOrBytes, subnet), errorCode); + const {results} = await validateGossipAttestationsSameAttData(fork, chain, [attestationOrBytes], subnet); + expect(results.length).toEqual(1); + expect((results[0].err as LodestarError<{code: string}>).type.code).toEqual(errorCode); } }); diff --git a/packages/cli/src/options/beaconNodeOptions/network.ts b/packages/cli/src/options/beaconNodeOptions/network.ts index 25ba036a5dbf..bfe9c7710e86 100644 --- a/packages/cli/src/options/beaconNodeOptions/network.ts +++ b/packages/cli/src/options/beaconNodeOptions/network.ts @@ -26,7 +26,6 @@ export type NetworkArgs = { "network.connectToDiscv5Bootnodes"?: boolean; "network.discv5FirstQueryDelayMs"?: number; "network.dontSendGossipAttestationsToForkchoice"?: boolean; - "network.beaconAttestationBatchValidation"?: boolean; "network.allowPublishToZeroPeers"?: boolean; "network.gossipsubD"?: number; "network.gossipsubDLow"?: number; @@ -144,7 +143,6 @@ export function parseArgs(args: NetworkArgs): IBeaconNodeOptions["network"] { connectToDiscv5Bootnodes: args["network.connectToDiscv5Bootnodes"], discv5FirstQueryDelayMs: args["network.discv5FirstQueryDelayMs"], dontSendGossipAttestationsToForkchoice: args["network.dontSendGossipAttestationsToForkchoice"], - beaconAttestationBatchValidation: args["network.beaconAttestationBatchValidation"], allowPublishToZeroPeers: args["network.allowPublishToZeroPeers"], gossipsubD: args["network.gossipsubD"], gossipsubDLow: args["network.gossipsubDLow"], @@ -321,13 +319,6 @@ export const options: CliCommandOptions = { group: "network", }, - "network.beaconAttestationBatchValidation": { - hidden: true, - type: "boolean", - description: "Validate gossip attestations in batches", - group: "network", - }, - "network.allowPublishToZeroPeers": { hidden: true, type: "boolean", diff --git a/packages/cli/test/unit/options/beaconNodeOptions.test.ts b/packages/cli/test/unit/options/beaconNodeOptions.test.ts index f873102edf74..879b5bfa2fc9 100644 --- a/packages/cli/test/unit/options/beaconNodeOptions.test.ts +++ b/packages/cli/test/unit/options/beaconNodeOptions.test.ts @@ -95,7 +95,6 @@ describe("options / beaconNodeOptions", () => { "network.blockCountPeerLimit": 500, "network.rateTrackerTimeoutMs": 60000, "network.dontSendGossipAttestationsToForkchoice": true, - "network.beaconAttestationBatchValidation": true, "network.allowPublishToZeroPeers": true, "network.gossipsubD": 4, "network.gossipsubDLow": 2, @@ -206,7 +205,6 @@ describe("options / beaconNodeOptions", () => { connectToDiscv5Bootnodes: true, discv5FirstQueryDelayMs: 1000, dontSendGossipAttestationsToForkchoice: true, - beaconAttestationBatchValidation: true, allowPublishToZeroPeers: true, gossipsubD: 4, gossipsubDLow: 2, From c04157c9696ce7b9b12518f61ec638b872927c4b Mon Sep 17 00:00:00 2001 From: Nico Flaig Date: Tue, 8 Oct 2024 16:01:47 +0100 Subject: [PATCH 36/52] fix: ensure generated historical state slot matches requested slot (#7135) --- .../src/chain/historicalState/getHistoricalState.ts | 4 ++++ 1 file changed, 4 insertions(+) diff --git a/packages/beacon-node/src/chain/historicalState/getHistoricalState.ts b/packages/beacon-node/src/chain/historicalState/getHistoricalState.ts index 1f352b3d683a..a9f254dea3f2 100644 --- a/packages/beacon-node/src/chain/historicalState/getHistoricalState.ts +++ b/packages/beacon-node/src/chain/historicalState/getHistoricalState.ts @@ -102,6 +102,10 @@ export async function getHistoricalState( metrics?.stateTransitionBlocks.observe(blockCount); transitionTimer?.(); + if (state.slot !== slot) { + throw Error(`Failed to generate historical state for slot ${slot}`); + } + const serializeTimer = metrics?.stateSerializationTime.startTimer(); const stateBytes = state.serialize(); serializeTimer?.(); From 955f4569289d66e0a2ee171dfa7bd9984ce57ba7 Mon Sep 17 00:00:00 2001 From: Phil Ngo <58080811+philknows@users.noreply.github.com> Date: Tue, 8 Oct 2024 11:04:02 -0400 Subject: [PATCH 37/52] chore: add drips network ownership address (#7128) add drips network ownership address --- funding.json | 5 +++++ 1 file changed, 5 insertions(+) diff --git a/funding.json b/funding.json index 872321cdca5b..3ff79f54b693 100644 --- a/funding.json +++ b/funding.json @@ -1,5 +1,10 @@ { "opRetro": { "projectId": "0x8ec88058175ef4c1c9b1f26910c4d4f2cfa733d6fcd1dbd9385476a313d9e12d" + }, + "drips": { + "ethereum": { + "ownedBy": "0x94107e24Ba695aeb884fe9e896BA0Bbc14D3B509" + } } } From 068fbae928989295706443887c645d476bb95695 Mon Sep 17 00:00:00 2001 From: Nico Flaig Date: Wed, 9 Oct 2024 09:43:09 +0100 Subject: [PATCH 38/52] refactor: move validator status type and util to @lodestar/types (#7140) --- .../api/src/beacon/routes/beacon/state.ts | 14 +-- .../src/api/impl/beacon/state/index.ts | 9 +- .../src/api/impl/beacon/state/utils.ts | 36 +------ .../src/api/impl/validator/index.ts | 2 +- .../unit/api/impl/beacon/state/utils.test.ts | 100 +----------------- packages/types/src/index.ts | 1 + packages/types/src/utils/validatorStatus.ts | 46 ++++++++ .../types/test/unit/validatorStatus.test.ts | 100 ++++++++++++++++++ 8 files changed, 155 insertions(+), 153 deletions(-) create mode 100644 packages/types/src/utils/validatorStatus.ts create mode 100644 packages/types/test/unit/validatorStatus.test.ts diff --git a/packages/api/src/beacon/routes/beacon/state.ts b/packages/api/src/beacon/routes/beacon/state.ts index e3cfe2e16edf..1489f48c297e 100644 --- a/packages/api/src/beacon/routes/beacon/state.ts +++ b/packages/api/src/beacon/routes/beacon/state.ts @@ -2,7 +2,7 @@ import {ContainerType, ValueOf} from "@chainsafe/ssz"; import {ChainForkConfig} from "@lodestar/config"; import {MAX_VALIDATORS_PER_COMMITTEE} from "@lodestar/params"; -import {phase0, CommitteeIndex, Slot, Epoch, ssz, RootHex, StringType} from "@lodestar/types"; +import {phase0, CommitteeIndex, Slot, Epoch, ssz, RootHex, StringType, ValidatorStatus} from "@lodestar/types"; import {Endpoint, RequestCodec, RouteDefinitions, Schema} from "../../../utils/index.js"; import {ArrayOf, JsonOnlyReq} from "../../../utils/codecs.js"; import {ExecutionOptimisticAndFinalizedCodec, ExecutionOptimisticAndFinalizedMeta} from "../../../utils/metadata.js"; @@ -24,17 +24,7 @@ export type StateArgs = { export type ValidatorId = string | number; -export type ValidatorStatus = - | "active" - | "pending_initialized" - | "pending_queued" - | "active_ongoing" - | "active_exiting" - | "active_slashed" - | "exited_unslashed" - | "exited_slashed" - | "withdrawal_possible" - | "withdrawal_done"; +export type {ValidatorStatus}; export const RandaoResponseType = new ContainerType({ randao: ssz.Root, diff --git a/packages/beacon-node/src/api/impl/beacon/state/index.ts b/packages/beacon-node/src/api/impl/beacon/state/index.ts index 669aaa9d1fb3..2bf758a8e286 100644 --- a/packages/beacon-node/src/api/impl/beacon/state/index.ts +++ b/packages/beacon-node/src/api/impl/beacon/state/index.ts @@ -9,16 +9,11 @@ import { getRandaoMix, } from "@lodestar/state-transition"; import {EPOCHS_PER_HISTORICAL_VECTOR} from "@lodestar/params"; +import {getValidatorStatus} from "@lodestar/types"; import {fromHex} from "@lodestar/utils"; import {ApiError} from "../../errors.js"; import {ApiModules} from "../../types.js"; -import { - filterStateValidatorsByStatus, - getStateValidatorIndex, - getValidatorStatus, - getStateResponse, - toValidatorResponse, -} from "./utils.js"; +import {filterStateValidatorsByStatus, getStateValidatorIndex, getStateResponse, toValidatorResponse} from "./utils.js"; export function getBeaconStateApi({ chain, diff --git a/packages/beacon-node/src/api/impl/beacon/state/utils.ts b/packages/beacon-node/src/api/impl/beacon/state/utils.ts index de21c6a244ed..5e9d3be01221 100644 --- a/packages/beacon-node/src/api/impl/beacon/state/utils.ts +++ b/packages/beacon-node/src/api/impl/beacon/state/utils.ts @@ -1,8 +1,8 @@ import {PubkeyIndexMap} from "@chainsafe/pubkey-index-map"; import {routes} from "@lodestar/api"; -import {FAR_FUTURE_EPOCH, GENESIS_SLOT} from "@lodestar/params"; +import {GENESIS_SLOT} from "@lodestar/params"; import {BeaconStateAllForks} from "@lodestar/state-transition"; -import {BLSPubkey, Epoch, phase0, RootHex, Slot, ValidatorIndex} from "@lodestar/types"; +import {BLSPubkey, Epoch, getValidatorStatus, phase0, RootHex, Slot, ValidatorIndex} from "@lodestar/types"; import {fromHex} from "@lodestar/utils"; import {CheckpointWithHex, IForkChoice} from "@lodestar/fork-choice"; import {IBeaconChain} from "../../../../chain/index.js"; @@ -83,38 +83,6 @@ export async function getStateResponseWithRegen( return res; } -/** - * Get the status of the validator - * based on conditions outlined in https://hackmd.io/ofFJ5gOmQpu1jjHilHbdQQ - */ -export function getValidatorStatus(validator: phase0.Validator, currentEpoch: Epoch): routes.beacon.ValidatorStatus { - // pending - if (validator.activationEpoch > currentEpoch) { - if (validator.activationEligibilityEpoch === FAR_FUTURE_EPOCH) { - return "pending_initialized"; - } else if (validator.activationEligibilityEpoch < FAR_FUTURE_EPOCH) { - return "pending_queued"; - } - } - // active - if (validator.activationEpoch <= currentEpoch && currentEpoch < validator.exitEpoch) { - if (validator.exitEpoch === FAR_FUTURE_EPOCH) { - return "active_ongoing"; - } else if (validator.exitEpoch < FAR_FUTURE_EPOCH) { - return validator.slashed ? "active_slashed" : "active_exiting"; - } - } - // exited - if (validator.exitEpoch <= currentEpoch && currentEpoch < validator.withdrawableEpoch) { - return validator.slashed ? "exited_slashed" : "exited_unslashed"; - } - // withdrawal - if (validator.withdrawableEpoch <= currentEpoch) { - return validator.effectiveBalance !== 0 ? "withdrawal_possible" : "withdrawal_done"; - } - throw new Error("ValidatorStatus unknown"); -} - export function toValidatorResponse( index: ValidatorIndex, validator: phase0.Validator, diff --git a/packages/beacon-node/src/api/impl/validator/index.ts b/packages/beacon-node/src/api/impl/validator/index.ts index 2347d7086d46..8a500125ad06 100644 --- a/packages/beacon-node/src/api/impl/validator/index.ts +++ b/packages/beacon-node/src/api/impl/validator/index.ts @@ -41,6 +41,7 @@ import { BeaconBlock, BlockContents, BlindedBeaconBlock, + getValidatorStatus, } from "@lodestar/types"; import {ExecutionStatus, DataAvailabilityStatus} from "@lodestar/fork-choice"; import {fromHex, toHex, resolveOrRacePromises, prettyWeiToEth, toRootHex} from "@lodestar/utils"; @@ -61,7 +62,6 @@ import {validateSyncCommitteeGossipContributionAndProof} from "../../../chain/va import {CommitteeSubscription} from "../../../network/subnets/index.js"; import {ApiModules} from "../types.js"; import {RegenCaller} from "../../../chain/regen/index.js"; -import {getValidatorStatus} from "../beacon/state/utils.js"; import {validateGossipFnRetryUnknownRoot} from "../../../network/processor/gossipHandlers.js"; import {SCHEDULER_LOOKAHEAD_FACTOR} from "../../../chain/prepareNextSlot.js"; import {ChainEvent, CheckpointHex, CommonBlockBody} from "../../../chain/index.js"; diff --git a/packages/beacon-node/test/unit/api/impl/beacon/state/utils.test.ts b/packages/beacon-node/test/unit/api/impl/beacon/state/utils.test.ts index 79a8f3383e5d..39c936c0d025 100644 --- a/packages/beacon-node/test/unit/api/impl/beacon/state/utils.test.ts +++ b/packages/beacon-node/test/unit/api/impl/beacon/state/utils.test.ts @@ -1,107 +1,9 @@ import {describe, it, expect} from "vitest"; import {toHexString} from "@chainsafe/ssz"; -import {phase0} from "@lodestar/types"; -import {getValidatorStatus, getStateValidatorIndex} from "../../../../../../src/api/impl/beacon/state/utils.js"; +import {getStateValidatorIndex} from "../../../../../../src/api/impl/beacon/state/utils.js"; import {generateCachedAltairState} from "../../../../../utils/state.js"; describe("beacon state api utils", function () { - describe("getValidatorStatus", function () { - it("should return PENDING_INITIALIZED", function () { - const validator = { - activationEpoch: 1, - activationEligibilityEpoch: Infinity, - } as phase0.Validator; - const currentEpoch = 0; - const status = getValidatorStatus(validator, currentEpoch); - expect(status).toBe("pending_initialized"); - }); - it("should return PENDING_QUEUED", function () { - const validator = { - activationEpoch: 1, - activationEligibilityEpoch: 101010101101010, - } as phase0.Validator; - const currentEpoch = 0; - const status = getValidatorStatus(validator, currentEpoch); - expect(status).toBe("pending_queued"); - }); - it("should return ACTIVE_ONGOING", function () { - const validator = { - activationEpoch: 1, - exitEpoch: Infinity, - } as phase0.Validator; - const currentEpoch = 1; - const status = getValidatorStatus(validator, currentEpoch); - expect(status).toBe("active_ongoing"); - }); - it("should return ACTIVE_SLASHED", function () { - const validator = { - activationEpoch: 1, - exitEpoch: 101010101101010, - slashed: true, - } as phase0.Validator; - const currentEpoch = 1; - const status = getValidatorStatus(validator, currentEpoch); - expect(status).toBe("active_slashed"); - }); - it("should return ACTIVE_EXITING", function () { - const validator = { - activationEpoch: 1, - exitEpoch: 101010101101010, - slashed: false, - } as phase0.Validator; - const currentEpoch = 1; - const status = getValidatorStatus(validator, currentEpoch); - expect(status).toBe("active_exiting"); - }); - it("should return EXITED_SLASHED", function () { - const validator = { - exitEpoch: 1, - withdrawableEpoch: 3, - slashed: true, - } as phase0.Validator; - const currentEpoch = 2; - const status = getValidatorStatus(validator, currentEpoch); - expect(status).toBe("exited_slashed"); - }); - it("should return EXITED_UNSLASHED", function () { - const validator = { - exitEpoch: 1, - withdrawableEpoch: 3, - slashed: false, - } as phase0.Validator; - const currentEpoch = 2; - const status = getValidatorStatus(validator, currentEpoch); - expect(status).toBe("exited_unslashed"); - }); - it("should return WITHDRAWAL_POSSIBLE", function () { - const validator = { - withdrawableEpoch: 1, - effectiveBalance: 32, - } as phase0.Validator; - const currentEpoch = 1; - const status = getValidatorStatus(validator, currentEpoch); - expect(status).toBe("withdrawal_possible"); - }); - it("should return WITHDRAWAL_DONE", function () { - const validator = { - withdrawableEpoch: 1, - effectiveBalance: 0, - } as phase0.Validator; - const currentEpoch = 1; - const status = getValidatorStatus(validator, currentEpoch); - expect(status).toBe("withdrawal_done"); - }); - it("should error", function () { - const validator = {} as phase0.Validator; - const currentEpoch = 0; - try { - getValidatorStatus(validator, currentEpoch); - } catch (error) { - expect(error).toHaveProperty("message", "ValidatorStatus unknown"); - } - }); - }); - describe("getStateValidatorIndex", () => { const state = generateCachedAltairState(); const pubkey2index = state.epochCtx.pubkey2index; diff --git a/packages/types/src/index.ts b/packages/types/src/index.ts index e0745834c7d1..dc9139dc967e 100644 --- a/packages/types/src/index.ts +++ b/packages/types/src/index.ts @@ -9,3 +9,4 @@ export * from "./utils/typeguards.js"; export {StringType, stringType} from "./utils/stringType.js"; // Container utils export * from "./utils/container.js"; +export * from "./utils/validatorStatus.js"; diff --git a/packages/types/src/utils/validatorStatus.ts b/packages/types/src/utils/validatorStatus.ts new file mode 100644 index 000000000000..e14a4b14c412 --- /dev/null +++ b/packages/types/src/utils/validatorStatus.ts @@ -0,0 +1,46 @@ +import {FAR_FUTURE_EPOCH} from "@lodestar/params"; +import {Epoch, phase0} from "../types.js"; + +export type ValidatorStatus = + | "active" + | "pending_initialized" + | "pending_queued" + | "active_ongoing" + | "active_exiting" + | "active_slashed" + | "exited_unslashed" + | "exited_slashed" + | "withdrawal_possible" + | "withdrawal_done"; + +/** + * Get the status of the validator + * based on conditions outlined in https://hackmd.io/ofFJ5gOmQpu1jjHilHbdQQ + */ +export function getValidatorStatus(validator: phase0.Validator, currentEpoch: Epoch): ValidatorStatus { + // pending + if (validator.activationEpoch > currentEpoch) { + if (validator.activationEligibilityEpoch === FAR_FUTURE_EPOCH) { + return "pending_initialized"; + } else if (validator.activationEligibilityEpoch < FAR_FUTURE_EPOCH) { + return "pending_queued"; + } + } + // active + if (validator.activationEpoch <= currentEpoch && currentEpoch < validator.exitEpoch) { + if (validator.exitEpoch === FAR_FUTURE_EPOCH) { + return "active_ongoing"; + } else if (validator.exitEpoch < FAR_FUTURE_EPOCH) { + return validator.slashed ? "active_slashed" : "active_exiting"; + } + } + // exited + if (validator.exitEpoch <= currentEpoch && currentEpoch < validator.withdrawableEpoch) { + return validator.slashed ? "exited_slashed" : "exited_unslashed"; + } + // withdrawal + if (validator.withdrawableEpoch <= currentEpoch) { + return validator.effectiveBalance !== 0 ? "withdrawal_possible" : "withdrawal_done"; + } + throw new Error("ValidatorStatus unknown"); +} diff --git a/packages/types/test/unit/validatorStatus.test.ts b/packages/types/test/unit/validatorStatus.test.ts new file mode 100644 index 000000000000..8d04c0f98e3d --- /dev/null +++ b/packages/types/test/unit/validatorStatus.test.ts @@ -0,0 +1,100 @@ +import {describe, it, expect} from "vitest"; +import {getValidatorStatus} from "../../src/utils/validatorStatus.js"; +import {phase0} from "../../src/types.js"; + +describe("getValidatorStatus", function () { + it("should return PENDING_INITIALIZED", function () { + const validator = { + activationEpoch: 1, + activationEligibilityEpoch: Infinity, + } as phase0.Validator; + const currentEpoch = 0; + const status = getValidatorStatus(validator, currentEpoch); + expect(status).toBe("pending_initialized"); + }); + it("should return PENDING_QUEUED", function () { + const validator = { + activationEpoch: 1, + activationEligibilityEpoch: 101010101101010, + } as phase0.Validator; + const currentEpoch = 0; + const status = getValidatorStatus(validator, currentEpoch); + expect(status).toBe("pending_queued"); + }); + it("should return ACTIVE_ONGOING", function () { + const validator = { + activationEpoch: 1, + exitEpoch: Infinity, + } as phase0.Validator; + const currentEpoch = 1; + const status = getValidatorStatus(validator, currentEpoch); + expect(status).toBe("active_ongoing"); + }); + it("should return ACTIVE_SLASHED", function () { + const validator = { + activationEpoch: 1, + exitEpoch: 101010101101010, + slashed: true, + } as phase0.Validator; + const currentEpoch = 1; + const status = getValidatorStatus(validator, currentEpoch); + expect(status).toBe("active_slashed"); + }); + it("should return ACTIVE_EXITING", function () { + const validator = { + activationEpoch: 1, + exitEpoch: 101010101101010, + slashed: false, + } as phase0.Validator; + const currentEpoch = 1; + const status = getValidatorStatus(validator, currentEpoch); + expect(status).toBe("active_exiting"); + }); + it("should return EXITED_SLASHED", function () { + const validator = { + exitEpoch: 1, + withdrawableEpoch: 3, + slashed: true, + } as phase0.Validator; + const currentEpoch = 2; + const status = getValidatorStatus(validator, currentEpoch); + expect(status).toBe("exited_slashed"); + }); + it("should return EXITED_UNSLASHED", function () { + const validator = { + exitEpoch: 1, + withdrawableEpoch: 3, + slashed: false, + } as phase0.Validator; + const currentEpoch = 2; + const status = getValidatorStatus(validator, currentEpoch); + expect(status).toBe("exited_unslashed"); + }); + it("should return WITHDRAWAL_POSSIBLE", function () { + const validator = { + withdrawableEpoch: 1, + effectiveBalance: 32, + } as phase0.Validator; + const currentEpoch = 1; + const status = getValidatorStatus(validator, currentEpoch); + expect(status).toBe("withdrawal_possible"); + }); + it("should return WITHDRAWAL_DONE", function () { + const validator = { + withdrawableEpoch: 1, + effectiveBalance: 0, + } as phase0.Validator; + const currentEpoch = 1; + const status = getValidatorStatus(validator, currentEpoch); + expect(status).toBe("withdrawal_done"); + }); + it("should error", function () { + const validator = {} as phase0.Validator; + const currentEpoch = 0; + try { + getValidatorStatus(validator, currentEpoch); + } catch (error) { + expect(error).toHaveProperty("message", "ValidatorStatus unknown"); + } + }); +}); From 3cef06f17deb37ed78ff69f327ae549a944a2a0d Mon Sep 17 00:00:00 2001 From: "dependabot[bot]" <49699333+dependabot[bot]@users.noreply.github.com> Date: Thu, 10 Oct 2024 15:28:27 +0100 Subject: [PATCH 39/52] chore(deps): bump rollup from 4.16.1 to 4.22.4 (#7103) Bumps [rollup](https://github.com/rollup/rollup) from 4.16.1 to 4.22.4. - [Release notes](https://github.com/rollup/rollup/releases) - [Changelog](https://github.com/rollup/rollup/blob/master/CHANGELOG.md) - [Commits](https://github.com/rollup/rollup/compare/v4.16.1...v4.22.4) --- updated-dependencies: - dependency-name: rollup dependency-type: indirect ... Signed-off-by: dependabot[bot] Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com> --- yarn.lock | 196 +++++++++++++++++++++++++++--------------------------- 1 file changed, 98 insertions(+), 98 deletions(-) diff --git a/yarn.lock b/yarn.lock index a96092ec2fff..6d080025630a 100644 --- a/yarn.lock +++ b/yarn.lock @@ -2713,85 +2713,85 @@ estree-walker "^2.0.2" picomatch "^2.3.1" -"@rollup/rollup-android-arm-eabi@4.16.1": - version "4.16.1" - resolved "https://registry.yarnpkg.com/@rollup/rollup-android-arm-eabi/-/rollup-android-arm-eabi-4.16.1.tgz#ad76cc870b1e2bc4476dfc02b82e20cea272a09d" - integrity sha512-92/y0TqNLRYOTXpm6Z7mnpvKAG9P7qmK7yJeRJSdzElNCUnsgbpAsGqerUboYRIQKzgfq4pWu9xVkgpWLfmNsw== - -"@rollup/rollup-android-arm64@4.16.1": - version "4.16.1" - resolved "https://registry.yarnpkg.com/@rollup/rollup-android-arm64/-/rollup-android-arm64-4.16.1.tgz#e7bd4f2b8ec5e049f98edbc68d72cb05356f81d8" - integrity sha512-ttWB6ZCfRLuDIUiE0yiu5gcqOsYjA5F7kEV1ggHMj20FwLZ8A1FMeahZJFl/pnOmcnD2QL0z4AcDuo27utGU8A== - -"@rollup/rollup-darwin-arm64@4.16.1": - version "4.16.1" - resolved "https://registry.yarnpkg.com/@rollup/rollup-darwin-arm64/-/rollup-darwin-arm64-4.16.1.tgz#8fd277b4be6cc956167710e36b4ee365f8a44050" - integrity sha512-QLDvPLetbqjHojTGFw9+nuSP3YY/iz2k1cep6crYlr97sS+ZJ0W43b8Z0zC00+lnFZj6JSNxiA4DjboNQMuh1A== - -"@rollup/rollup-darwin-x64@4.16.1": - version "4.16.1" - resolved "https://registry.yarnpkg.com/@rollup/rollup-darwin-x64/-/rollup-darwin-x64-4.16.1.tgz#5ab829322926fefce42db3529649a1098b420fe3" - integrity sha512-TAUK/D8khRrRIa1KwRzo8JNKk3tcqaeXWdtsiLgA8zmACWwlWLjPCJ4DULGHQrMkeBjp1Cd3Yuwx04lZgFx5Vg== - -"@rollup/rollup-linux-arm-gnueabihf@4.16.1": - version "4.16.1" - resolved "https://registry.yarnpkg.com/@rollup/rollup-linux-arm-gnueabihf/-/rollup-linux-arm-gnueabihf-4.16.1.tgz#0154bc34e6a88fb0147adc827512add8d3a2338c" - integrity sha512-KO+WGZjrh6zyFTD1alIFkfdtxf8B4BC+hqd3kBZHscPLvE5FR/6QKsyuCT0JlERxxYBSUKNUQ/UHyX5uwO1x2A== - -"@rollup/rollup-linux-arm-musleabihf@4.16.1": - version "4.16.1" - resolved "https://registry.yarnpkg.com/@rollup/rollup-linux-arm-musleabihf/-/rollup-linux-arm-musleabihf-4.16.1.tgz#0f3fa433a81b389042555133d38b4b886b369e58" - integrity sha512-NqxbllzIB1WoAo4ThUXVtd21iiM5IHMTTXmXySKBLVcZvkU0HIZmatlP7hLzb5yQubcmdIeWmncd2NdsjocEiw== - -"@rollup/rollup-linux-arm64-gnu@4.16.1": - version "4.16.1" - resolved "https://registry.yarnpkg.com/@rollup/rollup-linux-arm64-gnu/-/rollup-linux-arm64-gnu-4.16.1.tgz#c8f2d523ac4bcff382601306989b27137d536dd6" - integrity sha512-snma5NvV8y7IECQ5rq0sr0f3UUu+92NVmG/913JXJMcXo84h9ak9TA5UI9Cl2XRM9j3m37QwDBtEYnJzRkSmxA== - -"@rollup/rollup-linux-arm64-musl@4.16.1": - version "4.16.1" - resolved "https://registry.yarnpkg.com/@rollup/rollup-linux-arm64-musl/-/rollup-linux-arm64-musl-4.16.1.tgz#86b5104635131182b6b2b6997c4aa5594ce557b7" - integrity sha512-KOvqGprlD84ueivhCi2flvcUwDRD20mAsE3vxQNVEI2Di9tnPGAfEu6UcrSPZbM+jG2w1oSr43hrPo0RNg6GGg== - -"@rollup/rollup-linux-powerpc64le-gnu@4.16.1": - version "4.16.1" - resolved "https://registry.yarnpkg.com/@rollup/rollup-linux-powerpc64le-gnu/-/rollup-linux-powerpc64le-gnu-4.16.1.tgz#5de8b20105aaaeb36eb86fab0a1020d81c7bd4d5" - integrity sha512-/gsNwtiGLqYwN4vP+EIdUC6Q6LTlpupWqokqIndvZcjn9ig/5P01WyaYCU2wvfL/2Z82jp5kX8c1mDBOvCP3zg== - -"@rollup/rollup-linux-riscv64-gnu@4.16.1": - version "4.16.1" - resolved "https://registry.yarnpkg.com/@rollup/rollup-linux-riscv64-gnu/-/rollup-linux-riscv64-gnu-4.16.1.tgz#5319629dcdcb85ba201c6f0f894c9472e7d1013d" - integrity sha512-uU8zuGkQfGqfD9w6VRJZI4IuG4JIfNxxJgEmLMAmPVHREKGsxFVfgHy5c6CexQF2vOfgjB33OsET3Vdn2lln9A== - -"@rollup/rollup-linux-s390x-gnu@4.16.1": - version "4.16.1" - resolved "https://registry.yarnpkg.com/@rollup/rollup-linux-s390x-gnu/-/rollup-linux-s390x-gnu-4.16.1.tgz#246ac211ed0d78f7a9bc5c1d0653bde4c6cd9f63" - integrity sha512-lsjLtDgtcGFEuBP6yrXwkRN5/wKlvUZtfbKZZu0yaoNpiBL4epgnO21osAALIspVRnl4qZgyLFd8xjCYYWgwfw== - -"@rollup/rollup-linux-x64-gnu@4.16.1": - version "4.16.1" - resolved "https://registry.yarnpkg.com/@rollup/rollup-linux-x64-gnu/-/rollup-linux-x64-gnu-4.16.1.tgz#d0c03203ddeb9454fc6fdde93a39b01c176ac6d9" - integrity sha512-N2ZizKhUryqqrMfdCnjhJhZRgv61C6gK+hwVtCIKC8ts8J+go+vqENnGexwg21nHIOvLN5mBM8a7DI2vlyIOPg== - -"@rollup/rollup-linux-x64-musl@4.16.1": - version "4.16.1" - resolved "https://registry.yarnpkg.com/@rollup/rollup-linux-x64-musl/-/rollup-linux-x64-musl-4.16.1.tgz#20235632e2be4689d663aadaceaaf90df03b1a33" - integrity sha512-5ICeMxqg66FrOA2AbnBQ2TJVxfvZsKLxmof0ibvPLaYtbsJqnTUtJOofgWb46Gjd4uZcA4rdsp4JCxegzQPqCg== - -"@rollup/rollup-win32-arm64-msvc@4.16.1": - version "4.16.1" - resolved "https://registry.yarnpkg.com/@rollup/rollup-win32-arm64-msvc/-/rollup-win32-arm64-msvc-4.16.1.tgz#af113ad682fc13d1f870242c5539031f8cc27cf1" - integrity sha512-1vIP6Ce02L+qWD7uZYRiFiuAJo3m9kARatWmFSnss0gZnVj2Id7OPUU9gm49JPGasgcR3xMqiH3fqBJ8t00yVg== - -"@rollup/rollup-win32-ia32-msvc@4.16.1": - version "4.16.1" - resolved "https://registry.yarnpkg.com/@rollup/rollup-win32-ia32-msvc/-/rollup-win32-ia32-msvc-4.16.1.tgz#4e7b57e757c95da8e79092056d1b428617515668" - integrity sha512-Y3M92DcVsT6LoP+wrKpoUWPaazaP1fzbNkp0a0ZSj5Y//+pQVfVe/tQdsYQQy7dwXR30ZfALUIc9PCh9Izir6w== - -"@rollup/rollup-win32-x64-msvc@4.16.1": - version "4.16.1" - resolved "https://registry.yarnpkg.com/@rollup/rollup-win32-x64-msvc/-/rollup-win32-x64-msvc-4.16.1.tgz#5068a893ba292279adbe76fc487316724b15d811" - integrity sha512-x0fvpHMuF7fK5r8oZxSi8VYXkrVmRgubXpO/wcf15Lk3xZ4Jvvh5oG+u7Su1776A7XzVKZhD2eRc4t7H50gL3w== +"@rollup/rollup-android-arm-eabi@4.22.4": + version "4.22.4" + resolved "https://registry.yarnpkg.com/@rollup/rollup-android-arm-eabi/-/rollup-android-arm-eabi-4.22.4.tgz#8b613b9725e8f9479d142970b106b6ae878610d5" + integrity sha512-Fxamp4aEZnfPOcGA8KSNEohV8hX7zVHOemC8jVBoBUHu5zpJK/Eu3uJwt6BMgy9fkvzxDaurgj96F/NiLukF2w== + +"@rollup/rollup-android-arm64@4.22.4": + version "4.22.4" + resolved "https://registry.yarnpkg.com/@rollup/rollup-android-arm64/-/rollup-android-arm64-4.22.4.tgz#654ca1049189132ff602bfcf8df14c18da1f15fb" + integrity sha512-VXoK5UMrgECLYaMuGuVTOx5kcuap1Jm8g/M83RnCHBKOqvPPmROFJGQaZhGccnsFtfXQ3XYa4/jMCJvZnbJBdA== + +"@rollup/rollup-darwin-arm64@4.22.4": + version "4.22.4" + resolved "https://registry.yarnpkg.com/@rollup/rollup-darwin-arm64/-/rollup-darwin-arm64-4.22.4.tgz#6d241d099d1518ef0c2205d96b3fa52e0fe1954b" + integrity sha512-xMM9ORBqu81jyMKCDP+SZDhnX2QEVQzTcC6G18KlTQEzWK8r/oNZtKuZaCcHhnsa6fEeOBionoyl5JsAbE/36Q== + +"@rollup/rollup-darwin-x64@4.22.4": + version "4.22.4" + resolved "https://registry.yarnpkg.com/@rollup/rollup-darwin-x64/-/rollup-darwin-x64-4.22.4.tgz#42bd19d292a57ee11734c980c4650de26b457791" + integrity sha512-aJJyYKQwbHuhTUrjWjxEvGnNNBCnmpHDvrb8JFDbeSH3m2XdHcxDd3jthAzvmoI8w/kSjd2y0udT+4okADsZIw== + +"@rollup/rollup-linux-arm-gnueabihf@4.22.4": + version "4.22.4" + resolved "https://registry.yarnpkg.com/@rollup/rollup-linux-arm-gnueabihf/-/rollup-linux-arm-gnueabihf-4.22.4.tgz#f23555ee3d8fe941c5c5fd458cd22b65eb1c2232" + integrity sha512-j63YtCIRAzbO+gC2L9dWXRh5BFetsv0j0va0Wi9epXDgU/XUi5dJKo4USTttVyK7fGw2nPWK0PbAvyliz50SCQ== + +"@rollup/rollup-linux-arm-musleabihf@4.22.4": + version "4.22.4" + resolved "https://registry.yarnpkg.com/@rollup/rollup-linux-arm-musleabihf/-/rollup-linux-arm-musleabihf-4.22.4.tgz#f3bbd1ae2420f5539d40ac1fde2b38da67779baa" + integrity sha512-dJnWUgwWBX1YBRsuKKMOlXCzh2Wu1mlHzv20TpqEsfdZLb3WoJW2kIEsGwLkroYf24IrPAvOT/ZQ2OYMV6vlrg== + +"@rollup/rollup-linux-arm64-gnu@4.22.4": + version "4.22.4" + resolved "https://registry.yarnpkg.com/@rollup/rollup-linux-arm64-gnu/-/rollup-linux-arm64-gnu-4.22.4.tgz#7abe900120113e08a1f90afb84c7c28774054d15" + integrity sha512-AdPRoNi3NKVLolCN/Sp4F4N1d98c4SBnHMKoLuiG6RXgoZ4sllseuGioszumnPGmPM2O7qaAX/IJdeDU8f26Aw== + +"@rollup/rollup-linux-arm64-musl@4.22.4": + version "4.22.4" + resolved "https://registry.yarnpkg.com/@rollup/rollup-linux-arm64-musl/-/rollup-linux-arm64-musl-4.22.4.tgz#9e655285c8175cd44f57d6a1e8e5dedfbba1d820" + integrity sha512-Gl0AxBtDg8uoAn5CCqQDMqAx22Wx22pjDOjBdmG0VIWX3qUBHzYmOKh8KXHL4UpogfJ14G4wk16EQogF+v8hmA== + +"@rollup/rollup-linux-powerpc64le-gnu@4.22.4": + version "4.22.4" + resolved "https://registry.yarnpkg.com/@rollup/rollup-linux-powerpc64le-gnu/-/rollup-linux-powerpc64le-gnu-4.22.4.tgz#9a79ae6c9e9d8fe83d49e2712ecf4302db5bef5e" + integrity sha512-3aVCK9xfWW1oGQpTsYJJPF6bfpWfhbRnhdlyhak2ZiyFLDaayz0EP5j9V1RVLAAxlmWKTDfS9wyRyY3hvhPoOg== + +"@rollup/rollup-linux-riscv64-gnu@4.22.4": + version "4.22.4" + resolved "https://registry.yarnpkg.com/@rollup/rollup-linux-riscv64-gnu/-/rollup-linux-riscv64-gnu-4.22.4.tgz#67ac70eca4ace8e2942fabca95164e8874ab8128" + integrity sha512-ePYIir6VYnhgv2C5Xe9u+ico4t8sZWXschR6fMgoPUK31yQu7hTEJb7bCqivHECwIClJfKgE7zYsh1qTP3WHUA== + +"@rollup/rollup-linux-s390x-gnu@4.22.4": + version "4.22.4" + resolved "https://registry.yarnpkg.com/@rollup/rollup-linux-s390x-gnu/-/rollup-linux-s390x-gnu-4.22.4.tgz#9f883a7440f51a22ed7f99e1d070bd84ea5005fc" + integrity sha512-GqFJ9wLlbB9daxhVlrTe61vJtEY99/xB3C8e4ULVsVfflcpmR6c8UZXjtkMA6FhNONhj2eA5Tk9uAVw5orEs4Q== + +"@rollup/rollup-linux-x64-gnu@4.22.4": + version "4.22.4" + resolved "https://registry.yarnpkg.com/@rollup/rollup-linux-x64-gnu/-/rollup-linux-x64-gnu-4.22.4.tgz#70116ae6c577fe367f58559e2cffb5641a1dd9d0" + integrity sha512-87v0ol2sH9GE3cLQLNEy0K/R0pz1nvg76o8M5nhMR0+Q+BBGLnb35P0fVz4CQxHYXaAOhE8HhlkaZfsdUOlHwg== + +"@rollup/rollup-linux-x64-musl@4.22.4": + version "4.22.4" + resolved "https://registry.yarnpkg.com/@rollup/rollup-linux-x64-musl/-/rollup-linux-x64-musl-4.22.4.tgz#f473f88219feb07b0b98b53a7923be716d1d182f" + integrity sha512-UV6FZMUgePDZrFjrNGIWzDo/vABebuXBhJEqrHxrGiU6HikPy0Z3LfdtciIttEUQfuDdCn8fqh7wiFJjCNwO+g== + +"@rollup/rollup-win32-arm64-msvc@4.22.4": + version "4.22.4" + resolved "https://registry.yarnpkg.com/@rollup/rollup-win32-arm64-msvc/-/rollup-win32-arm64-msvc-4.22.4.tgz#4349482d17f5d1c58604d1c8900540d676f420e0" + integrity sha512-BjI+NVVEGAXjGWYHz/vv0pBqfGoUH0IGZ0cICTn7kB9PyjrATSkX+8WkguNjWoj2qSr1im/+tTGRaY+4/PdcQw== + +"@rollup/rollup-win32-ia32-msvc@4.22.4": + version "4.22.4" + resolved "https://registry.yarnpkg.com/@rollup/rollup-win32-ia32-msvc/-/rollup-win32-ia32-msvc-4.22.4.tgz#a6fc39a15db618040ec3c2a24c1e26cb5f4d7422" + integrity sha512-SiWG/1TuUdPvYmzmYnmd3IEifzR61Tragkbx9D3+R8mzQqDBz8v+BvZNDlkiTtI9T15KYZhP0ehn3Dld4n9J5g== + +"@rollup/rollup-win32-x64-msvc@4.22.4": + version "4.22.4" + resolved "https://registry.yarnpkg.com/@rollup/rollup-win32-x64-msvc/-/rollup-win32-x64-msvc-4.22.4.tgz#3dd5d53e900df2a40841882c02e56f866c04d202" + integrity sha512-j8pPKp53/lq9lMXN57S8cFz0MynJk8OWNuUnXct/9KCpKU7DgU3bYMJhwWmcqC0UU29p8Lr0/7KEVcaM6bf47Q== "@rushstack/node-core-library@4.0.2": version "4.0.2" @@ -11514,28 +11514,28 @@ rollup-plugin-visualizer@^5.12.0: yargs "^17.5.1" rollup@^4.13.0: - version "4.16.1" - resolved "https://registry.yarnpkg.com/rollup/-/rollup-4.16.1.tgz#5a60230987fe95ebe68bab517297c116dbb1a88d" - integrity sha512-5CaD3MPDlPKfhqzRvWXK96G6ELJfPZNb3LHiZxTHgDdC6jvwfGz2E8nY+9g1ONk4ttHsK1WaFP19Js4PSr1E3g== + version "4.22.4" + resolved "https://registry.yarnpkg.com/rollup/-/rollup-4.22.4.tgz#4135a6446671cd2a2453e1ad42a45d5973ec3a0f" + integrity sha512-vD8HJ5raRcWOyymsR6Z3o6+RzfEPCnVLMFJ6vRslO1jt4LO6dUo5Qnpg7y4RkZFM2DMe3WUirkI5c16onjrc6A== dependencies: "@types/estree" "1.0.5" optionalDependencies: - "@rollup/rollup-android-arm-eabi" "4.16.1" - "@rollup/rollup-android-arm64" "4.16.1" - "@rollup/rollup-darwin-arm64" "4.16.1" - "@rollup/rollup-darwin-x64" "4.16.1" - "@rollup/rollup-linux-arm-gnueabihf" "4.16.1" - "@rollup/rollup-linux-arm-musleabihf" "4.16.1" - "@rollup/rollup-linux-arm64-gnu" "4.16.1" - "@rollup/rollup-linux-arm64-musl" "4.16.1" - "@rollup/rollup-linux-powerpc64le-gnu" "4.16.1" - "@rollup/rollup-linux-riscv64-gnu" "4.16.1" - "@rollup/rollup-linux-s390x-gnu" "4.16.1" - "@rollup/rollup-linux-x64-gnu" "4.16.1" - "@rollup/rollup-linux-x64-musl" "4.16.1" - "@rollup/rollup-win32-arm64-msvc" "4.16.1" - "@rollup/rollup-win32-ia32-msvc" "4.16.1" - "@rollup/rollup-win32-x64-msvc" "4.16.1" + "@rollup/rollup-android-arm-eabi" "4.22.4" + "@rollup/rollup-android-arm64" "4.22.4" + "@rollup/rollup-darwin-arm64" "4.22.4" + "@rollup/rollup-darwin-x64" "4.22.4" + "@rollup/rollup-linux-arm-gnueabihf" "4.22.4" + "@rollup/rollup-linux-arm-musleabihf" "4.22.4" + "@rollup/rollup-linux-arm64-gnu" "4.22.4" + "@rollup/rollup-linux-arm64-musl" "4.22.4" + "@rollup/rollup-linux-powerpc64le-gnu" "4.22.4" + "@rollup/rollup-linux-riscv64-gnu" "4.22.4" + "@rollup/rollup-linux-s390x-gnu" "4.22.4" + "@rollup/rollup-linux-x64-gnu" "4.22.4" + "@rollup/rollup-linux-x64-musl" "4.22.4" + "@rollup/rollup-win32-arm64-msvc" "4.22.4" + "@rollup/rollup-win32-ia32-msvc" "4.22.4" + "@rollup/rollup-win32-x64-msvc" "4.22.4" fsevents "~2.3.2" rrweb-cssom@^0.6.0: From d44c409eaacdb07d0236991f5c64d6c733c5d889 Mon Sep 17 00:00:00 2001 From: "dependabot[bot]" <49699333+dependabot[bot]@users.noreply.github.com> Date: Thu, 10 Oct 2024 15:28:58 +0100 Subject: [PATCH 40/52] chore(deps): bump micromatch from 4.0.5 to 4.0.8 in /docs (#7117) Bumps [micromatch](https://github.com/micromatch/micromatch) from 4.0.5 to 4.0.8. - [Release notes](https://github.com/micromatch/micromatch/releases) - [Changelog](https://github.com/micromatch/micromatch/blob/master/CHANGELOG.md) - [Commits](https://github.com/micromatch/micromatch/compare/4.0.5...4.0.8) --- updated-dependencies: - dependency-name: micromatch dependency-type: indirect ... Signed-off-by: dependabot[bot] Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com> --- docs/yarn.lock | 24 +++++++++++++++++++----- 1 file changed, 19 insertions(+), 5 deletions(-) diff --git a/docs/yarn.lock b/docs/yarn.lock index 27123932fe26..dad4d8ef1c07 100644 --- a/docs/yarn.lock +++ b/docs/yarn.lock @@ -3187,7 +3187,14 @@ brace-expansion@^1.1.7: balanced-match "^1.0.0" concat-map "0.0.1" -braces@^3.0.2, braces@~3.0.2: +braces@^3.0.3: + version "3.0.3" + resolved "https://registry.yarnpkg.com/braces/-/braces-3.0.3.tgz#490332f40919452272d55a8480adc0c441358789" + integrity sha512-yQbXgO/OSZVD2IsiLlro+7Hf6Q18EJrKSEsdoMzKePKXct3gvD8oLcOQdIzGupr5Fj+EDe8gO/lxc1BzfMpxvA== + dependencies: + fill-range "^7.1.1" + +braces@~3.0.2: version "3.0.2" resolved "https://registry.yarnpkg.com/braces/-/braces-3.0.2.tgz#3454e1a462ee8d599e236df336cd9ea4f8afe107" integrity sha512-b8um+L1RzM3WDSzvhm6gIz1yfTbBt6YTlcEKAvsmqCZZFw46z626lVj9j1yEPW33H5H+lBQpZMP1k8l+78Ha0A== @@ -4772,6 +4779,13 @@ fill-range@^7.0.1: dependencies: to-regex-range "^5.0.1" +fill-range@^7.1.1: + version "7.1.1" + resolved "https://registry.yarnpkg.com/fill-range/-/fill-range-7.1.1.tgz#44265d3cac07e3ea7dc247516380643754a05292" + integrity sha512-YsGpe3WHLK8ZYi4tWDg2Jy3ebRz2rXowDxnld4bkQB00cc/1Zw9AWnC0i9ztDJitivtQvaI9KaLyKrc+hBW0yg== + dependencies: + to-regex-range "^5.0.1" + finalhandler@1.3.1: version "1.3.1" resolved "https://registry.yarnpkg.com/finalhandler/-/finalhandler-1.3.1.tgz#0c575f1d1d324ddd1da35ad7ece3df7d19088019" @@ -6965,11 +6979,11 @@ micromark@^4.0.0: micromark-util-types "^2.0.0" micromatch@^4.0.2, micromatch@^4.0.4, micromatch@^4.0.5: - version "4.0.5" - resolved "https://registry.yarnpkg.com/micromatch/-/micromatch-4.0.5.tgz#bc8999a7cbbf77cdc89f132f6e467051b49090c6" - integrity sha512-DMy+ERcEW2q8Z2Po+WNXuw3c5YaUSFjAO5GsJqfEl7UjvtIuFKO6ZrKvcItdy98dwFI2N1tg3zNIdKaQT+aNdA== + version "4.0.8" + resolved "https://registry.yarnpkg.com/micromatch/-/micromatch-4.0.8.tgz#d66fa18f3a47076789320b9b1af32bd86d9fa202" + integrity sha512-PXwfBhYu0hBCPw8Dn0E+WDYb7af3dSLVWKi3HGv84IdF4TyFoC0ysxFd0Goxw7nSv4T/PzEJQxsYsEiFCKo2BA== dependencies: - braces "^3.0.2" + braces "^3.0.3" picomatch "^2.3.1" mime-db@1.52.0, "mime-db@>= 1.43.0 < 2": From 489accbc90dd88807426c5ad6751f9a53addd754 Mon Sep 17 00:00:00 2001 From: Nico Flaig Date: Thu, 10 Oct 2024 17:28:30 +0100 Subject: [PATCH 41/52] fix: allow to disable peer discovery / discv5 (#7144) * fix: allow to disable peer discovery / discv5 * Explicitly check for false --- packages/cli/src/cmds/beacon/handler.ts | 23 +++++++++++++---------- 1 file changed, 13 insertions(+), 10 deletions(-) diff --git a/packages/cli/src/cmds/beacon/handler.ts b/packages/cli/src/cmds/beacon/handler.ts index d51af66e37d0..81536d7c7b41 100644 --- a/packages/cli/src/cmds/beacon/handler.ts +++ b/packages/cli/src/cmds/beacon/handler.ts @@ -175,14 +175,6 @@ export async function beaconHandlerInit(args: BeaconArgs & GlobalArgs) { // Add detailed version string for API node/version endpoint beaconNodeOptions.set({api: {commit, version}}); - // Combine bootnodes from different sources - const bootnodes = (beaconNodeOptions.get().network?.discv5?.bootEnrs ?? []).concat( - args.bootnodesFile ? readBootnodes(args.bootnodesFile) : [], - isKnownNetworkName(network) ? await getNetworkBootnodes(network) : [] - ); - // Deduplicate and set combined bootnodes - beaconNodeOptions.set({network: {discv5: {bootEnrs: [...new Set(bootnodes)]}}}); - // Set known depositContractDeployBlock if (isKnownNetworkName(network)) { const {depositContractDeployBlock} = getNetworkData(network); @@ -191,8 +183,19 @@ export async function beaconHandlerInit(args: BeaconArgs & GlobalArgs) { const logger = initLogger(args, beaconPaths.dataDir, config); const {peerId, enr} = await initPeerIdAndEnr(args, beaconPaths.beaconDir, logger); - // Inject ENR to beacon options - beaconNodeOptions.set({network: {discv5: {enr: enr.encodeTxt(), config: {enrUpdate: !enr.ip && !enr.ip6}}}}); + + if (args.discv5 !== false) { + // Inject ENR to beacon options + beaconNodeOptions.set({network: {discv5: {enr: enr.encodeTxt(), config: {enrUpdate: !enr.ip && !enr.ip6}}}}); + + // Combine bootnodes from different sources + const bootnodes = (beaconNodeOptions.get().network?.discv5?.bootEnrs ?? []).concat( + args.bootnodesFile ? readBootnodes(args.bootnodesFile) : [], + isKnownNetworkName(network) ? await getNetworkBootnodes(network) : [] + ); + // Deduplicate and set combined bootnodes + beaconNodeOptions.set({network: {discv5: {bootEnrs: [...new Set(bootnodes)]}}}); + } if (args.disableLightClientServer) { beaconNodeOptions.set({chain: {disableLightClientServer: true}}); From 5c359f92dcf0f46e9453b09e8948024b15affa81 Mon Sep 17 00:00:00 2001 From: Nazar Hussain Date: Thu, 10 Oct 2024 18:43:36 +0200 Subject: [PATCH 42/52] deps: migrate to biomejs from eslint (#7108) * Replace eslint with biomejs * Update the inclusion of word * Fix the formatting * Update the lint task to do all checks * Update biome rules from eslint config * Replace eslint with biomejs * Update the inclusion of word * Fix the formatting * Update the lint task to do all checks * Update biome rules from eslint config * Fix all lint issues * Fix formatting * Add extension recomendation for vscode * Enable recommended rules * Enable rule noUselessSwitchCase * Enable rule noUselessConstructor * Fix the types * Fix unit tests * Enforce import extensions * Update the cli command * Enforce useConsistentMemberAccessibility * Update rules * Fix rules * Upgrade biomejs to latest version * Update the rules * Update and format the config file * Fix types break during merge * Fix unused check * Add comment for explicit-return-type * Remove eslint file * Add _e objects for empty catch blocks * Update formatter config * Fix formatting --- .editorconfig | 9 + .eslintrc.js | 275 ------ .github/workflows/test.yml | 3 - .vscode/extensions.json | 5 + .wordlist.txt | 1 - CONTRIBUTING.md | 2 +- biome.jsonc | 376 ++++++++ package.json | 13 +- packages/api/package.json | 4 +- packages/api/src/beacon/client/events.ts | 11 +- .../api/src/beacon/routes/beacon/block.ts | 3 +- packages/api/src/beacon/routes/beacon/pool.ts | 1 - .../api/src/beacon/routes/beacon/rewards.ts | 1 - .../api/src/beacon/routes/beacon/state.ts | 3 +- packages/api/src/beacon/routes/config.ts | 1 - packages/api/src/beacon/routes/debug.ts | 1 - packages/api/src/beacon/routes/events.ts | 2 - packages/api/src/beacon/routes/lightclient.ts | 1 - packages/api/src/beacon/routes/lodestar.ts | 2 +- packages/api/src/beacon/routes/node.ts | 1 - packages/api/src/beacon/routes/proof.ts | 1 - packages/api/src/beacon/routes/validator.ts | 1 - packages/api/src/beacon/server/index.ts | 2 +- packages/api/src/builder/routes.ts | 1 - packages/api/src/keymanager/routes.ts | 1 - packages/api/src/utils/client/eventSource.ts | 1 - packages/api/src/utils/client/fetch.ts | 2 +- packages/api/src/utils/client/httpClient.ts | 3 +- packages/api/src/utils/client/response.ts | 8 +- packages/api/src/utils/codecs.ts | 4 - packages/api/src/utils/metadata.ts | 1 - packages/api/src/utils/serdes.ts | 2 +- packages/api/src/utils/server/handler.ts | 1 - packages/api/src/utils/server/method.ts | 7 +- .../test/perf/compileRouteUrlFormater.test.ts | 2 - .../beacon/genericServerTest/beacon.test.ts | 1 - .../beacon/genericServerTest/config.test.ts | 2 - .../api/test/unit/beacon/oapiSpec.test.ts | 2 - .../api/test/unit/beacon/testData/events.ts | 2 - .../api/test/unit/builder/builder.test.ts | 1 - .../api/test/unit/builder/oapiSpec.test.ts | 2 - packages/api/test/unit/client/fetch.test.ts | 1 - .../unit/client/httpClientFallback.test.ts | 1 - .../api/test/unit/client/urlFormat.test.ts | 2 - .../api/test/unit/keymanager/oapiSpec.test.ts | 1 - packages/api/test/utils/checkAgainstSpec.ts | 5 +- packages/api/test/utils/parseOpenApiSpec.ts | 1 - packages/api/test/utils/utils.ts | 1 - packages/beacon-node/package.json | 4 +- .../src/api/impl/beacon/blocks/index.ts | 22 +- .../src/api/impl/beacon/pool/index.ts | 1 - .../src/api/impl/beacon/state/utils.ts | 2 +- .../src/api/impl/config/constants.ts | 2 - .../beacon-node/src/api/impl/events/index.ts | 3 +- .../beacon-node/src/api/impl/node/utils.ts | 1 + .../src/api/impl/validator/index.ts | 1 - .../beacon-node/src/api/rest/activeSockets.ts | 2 +- .../beacon-node/src/api/rest/swaggerUI.ts | 5 +- .../blocks/verifyBlocksDataAvailability.ts | 3 +- .../src/chain/bls/multithread/index.ts | 3 +- .../src/chain/bls/multithread/poolSize.ts | 2 +- .../src/chain/bls/multithread/worker.ts | 2 +- packages/beacon-node/src/chain/emitter.ts | 2 +- packages/beacon-node/src/chain/initState.ts | 2 +- .../validateBlobsAndKzgCommitments.ts | 3 +- .../src/chain/rewards/attestationsRewards.ts | 4 +- .../src/chain/validation/aggregateAndProof.ts | 2 +- .../src/chain/validation/attesterSlashing.ts | 2 +- .../chain/validation/blsToExecutionChange.ts | 2 +- .../src/chain/validation/proposerSlashing.ts | 2 +- .../src/chain/validation/voluntaryExit.ts | 2 +- .../src/db/repositories/backfilledRanges.ts | 3 +- .../src/db/repositories/checkpointState.ts | 1 - .../src/db/repositories/depositDataRoot.ts | 3 +- .../src/db/repositories/eth1Data.ts | 3 +- .../src/db/repositories/stateArchive.ts | 2 +- .../preGenesisStateLastProcessedBlock.ts | 2 +- .../src/eth1/eth1MergeBlockTracker.ts | 2 - .../src/eth1/provider/eth1Provider.ts | 2 - .../src/eth1/provider/jsonRpcHttpClient.ts | 2 +- packages/beacon-node/src/eth1/provider/jwt.ts | 1 - .../src/execution/builder/index.ts | 1 + .../beacon-node/src/execution/engine/http.ts | 4 +- .../beacon-node/src/execution/engine/index.ts | 2 + .../beacon-node/src/execution/engine/mock.ts | 1 - .../beacon-node/src/execution/engine/types.ts | 2 - .../beacon-node/src/execution/engine/utils.ts | 5 +- .../beacon-node/src/metrics/metrics/beacon.ts | 1 - .../src/metrics/metrics/lodestar.ts | 1 - .../beacon-node/src/monitoring/service.ts | 2 +- packages/beacon-node/src/monitoring/system.ts | 1 - .../beacon-node/src/network/core/metrics.ts | 2 - .../src/network/core/networkCore.ts | 2 +- .../src/network/core/networkCoreWorker.ts | 1 - .../network/core/networkCoreWorkerHandler.ts | 2 +- .../beacon-node/src/network/core/types.ts | 2 +- .../beacon-node/src/network/discv5/index.ts | 2 +- .../beacon-node/src/network/discv5/worker.ts | 1 - packages/beacon-node/src/network/events.ts | 2 +- packages/beacon-node/src/network/forks.ts | 1 - .../src/network/gossip/gossipsub.ts | 1 - .../src/network/gossip/interface.ts | 2 +- .../beacon-node/src/network/gossip/metrics.ts | 1 - .../src/network/gossip/scoringParameters.ts | 2 - .../beacon-node/src/network/gossip/topic.ts | 5 +- .../src/network/peers/datastore.ts | 3 +- .../beacon-node/src/network/peers/discover.ts | 1 - .../src/network/peers/peerManager.ts | 8 +- .../src/network/processor/gossipHandlers.ts | 1 - .../src/network/processor/index.ts | 4 +- .../reqresp/beaconBlocksMaybeBlobsByRange.ts | 1 + .../src/network/reqresp/protocols.ts | 2 - .../src/network/reqresp/rateLimit.ts | 2 +- .../beacon-node/src/network/reqresp/score.ts | 1 - packages/beacon-node/src/network/util.ts | 1 - .../beacon-node/src/sync/backfill/backfill.ts | 5 +- packages/beacon-node/src/sync/range/range.ts | 2 +- .../src/util/asyncIterableToEvents.ts | 2 - packages/beacon-node/src/util/kzg.ts | 3 - packages/beacon-node/src/util/map.ts | 1 - packages/beacon-node/src/util/profile.ts | 2 +- packages/beacon-node/src/util/queue/errors.ts | 6 +- .../beacon-node/src/util/queue/fnQueue.ts | 4 +- .../beacon-node/src/util/queue/itemQueue.ts | 3 +- .../api/impl/beacon/node/endpoints.test.ts | 2 - .../e2e/api/impl/lightclient/endpoint.test.ts | 1 - .../test/e2e/api/lodestar/lodestar.test.ts | 1 - .../test/e2e/chain/lightclient.test.ts | 1 - .../test/e2e/chain/proposerBoostReorg.test.ts | 3 - .../stateCache/nHistoricalStates.test.ts | 1 - .../e2e/doppelganger/doppelganger.test.ts | 5 +- .../e2e/eth1/eth1ForBlockProduction.test.ts | 1 - .../e2e/eth1/eth1MergeBlockTracker.test.ts | 2 - .../test/e2e/eth1/jsonRpcHttpClient.test.ts | 1 - .../test/e2e/interop/genesisState.test.ts | 1 - .../test/e2e/network/gossipsub.test.ts | 30 +- .../beacon-node/test/e2e/network/mdns.test.ts | 2 - .../test/e2e/network/network.test.ts | 1 - .../e2e/network/peers/peerManager.test.ts | 1 - .../test/e2e/network/reqrespEncode.test.ts | 3 - .../test/e2e/sync/finalizedSync.test.ts | 3 +- .../test/e2e/sync/unknownBlockSync.test.ts | 1 - packages/beacon-node/test/globalSetup.ts | 1 - packages/beacon-node/test/memory/bytesHex.ts | 1 - .../beacon-node/test/memory/pubkeysToIndex.ts | 1 - .../test/memory/seenAttestationData.ts | 1 - .../test/memory/testRunnerMemory.ts | 2 - .../test/memory/unfinalizedPubkey2Index.ts | 1 - .../beacon-node/test/mocks/beaconSyncMock.ts | 1 - .../test/mocks/mockedBeaconChain.ts | 4 - .../beacon-node/test/mocks/mockedBeaconDb.ts | 1 - .../beacon-node/test/mocks/mockedNetwork.ts | 1 - .../perf/api/impl/validator/attester.test.ts | 1 - .../opPools/aggregatedAttestationPool.test.ts | 1 - .../test/perf/chain/opPools/opPool.test.ts | 1 - .../produceBlock/produceBlockBody.test.ts | 1 - .../validation/aggregateAndProof.test.ts | 1 - .../perf/chain/validation/attestation.test.ts | 1 - .../perf/chain/verifyImportBlocks.test.ts | 12 +- .../test/scripts/blsPubkeyBytesFrequency.ts | 3 - packages/beacon-node/test/setupPreset.ts | 1 - packages/beacon-node/test/spec/bls/bls.ts | 14 +- packages/beacon-node/test/spec/general/bls.ts | 18 +- .../test/spec/general/index.test.ts | 2 - .../test/spec/general/ssz_generic.ts | 2 +- .../test/spec/general/ssz_generic_types.ts | 2 - .../spec/presets/epoch_processing.test.ts | 4 +- .../test/spec/presets/finality.test.ts | 4 +- .../test/spec/presets/fork.test.ts | 2 +- .../test/spec/presets/fork_choice.test.ts | 2 - .../test/spec/presets/genesis.test.ts | 6 +- .../spec/presets/light_client/index.test.ts | 2 - .../light_client/single_merkle_proof.ts | 10 +- .../test/spec/presets/light_client/sync.ts | 2 - .../presets/light_client/update_ranking.ts | 2 - .../test/spec/presets/merkle.test.ts | 4 +- .../test/spec/presets/operations.test.ts | 4 +- .../test/spec/presets/rewards.test.ts | 4 +- .../test/spec/presets/sanity.test.ts | 6 +- .../test/spec/presets/ssz_static.test.ts | 3 +- .../test/spec/presets/transition.test.ts | 4 +- .../test/spec/specTestVersioning.ts | 1 - .../test/spec/utils/runValidSszTest.ts | 2 +- packages/beacon-node/test/spec/utils/types.ts | 2 - packages/beacon-node/test/tsconfig.json | 2 +- .../test/unit/api/impl/events/events.test.ts | 1 - .../api/impl/validator/produceBlockV3.test.ts | 3 +- .../test/unit/chain/beaconProposerCache.ts | 2 +- .../test/unit/chain/genesis/genesis.test.ts | 1 - .../upgradeLightClientHeader.test.ts | 1 - .../chain/opPools/attestationPool.test.ts | 1 - .../unit/chain/rewards/blockRewards.test.ts | 2 - .../seenCache/seenGossipBlockInput.test.ts | 1 - .../test/unit/chain/shufflingCache.test.ts | 1 - .../validation/aggregateAndProof.test.ts | 2 - ...hufflingForAttestationVerification.test.ts | 1 - .../attestation/validateAttestation.test.ts | 2 - .../test/unit/chain/validation/block.test.ts | 1 - .../lightClientFinalityUpdate.test.ts | 1 - .../lightClientOptimisticUpdate.test.ts | 1 - .../chain/validation/syncCommittee.test.ts | 1 - .../test/unit/db/api/repository.test.ts | 2 - .../unit/eth1/eth1MergeBlockTracker.test.ts | 2 - .../test/unit/eth1/utils/deposits.test.ts | 1 - .../optimizeNextBlockDiffForGenesis.test.ts | 3 - .../test/unit/monitoring/remoteService.ts | 2 +- .../test/unit/monitoring/service.test.ts | 1 - .../beaconBlocksMaybeBlobsByRange.test.ts | 1 - .../unit/network/peers/priorization.test.ts | 2 - .../test/unit/network/peers/score.test.ts | 1 - .../network/subnets/attnetsService.test.ts | 1 - .../test/unit/sync/backfill/verify.test.ts | 5 +- .../test/unit/sync/range/chain.test.ts | 4 +- .../test/unit/sync/unknownBlock.test.ts | 19 +- .../beacon-node/test/unit/util/kzg.test.ts | 3 +- packages/beacon-node/test/utils/clock.ts | 5 +- packages/beacon-node/test/utils/config.ts | 1 - .../beacon-node/test/utils/node/simTest.ts | 4 +- packages/beacon-node/test/utils/runEl.ts | 3 +- .../utils/validationData/aggregateAndProof.ts | 1 - .../test/utils/validationData/attestation.ts | 1 - packages/cli/docsgen/markdown.ts | 1 - packages/cli/package.json | 4 +- packages/cli/src/applyPreset.ts | 4 - packages/cli/src/cmds/beacon/handler.ts | 1 - .../cli/src/cmds/beacon/initPeerIdAndEnr.ts | 4 +- packages/cli/src/cmds/bootnode/handler.ts | 1 - .../keymanager/decryptKeystoreDefinitions.ts | 2 +- .../keymanager/decryptKeystores/poolSize.ts | 2 +- packages/cli/src/cmds/validator/options.ts | 4 +- .../cli/src/cmds/validator/voluntaryExit.ts | 1 - packages/cli/src/index.ts | 2 - packages/cli/src/networks/index.ts | 3 +- .../src/options/beaconNodeOptions/chain.ts | 2 +- .../cli/src/options/beaconNodeOptions/eth1.ts | 4 +- .../options/beaconNodeOptions/execution.ts | 4 +- .../src/options/beaconNodeOptions/network.ts | 13 +- packages/cli/src/util/file.ts | 1 - packages/cli/src/util/gitData/gitDataPath.ts | 1 - packages/cli/src/util/gitData/index.ts | 12 +- packages/cli/src/util/object.ts | 4 +- packages/cli/src/util/process.ts | 1 - packages/cli/src/util/proposerConfig.ts | 2 - packages/cli/src/util/types.ts | 3 +- packages/cli/src/util/version.ts | 1 - .../test/e2e/importKeystoresFromApi.test.ts | 1 - .../e2e/propserConfigfromKeymanager.test.ts | 1 - packages/cli/test/e2e/voluntaryExit.test.ts | 1 - .../cli/test/e2e/voluntaryExitFromApi.test.ts | 1 - .../e2e/voluntaryExitRemoteSigner.test.ts | 1 - packages/cli/test/scripts/e2e_test_env.ts | 1 - .../cli/test/sim/backupEthProvider.test.ts | 1 - packages/cli/test/sim/deneb.test.ts | 1 - packages/cli/test/sim/endpoints.test.ts | 1 - packages/cli/test/sim/mixedClient.test.ts | 1 - packages/cli/test/sim/multiFork.test.ts | 1 - packages/cli/test/unit/cmds/beacon.test.ts | 1 - .../cli/test/unit/config/beaconParams.test.ts | 8 - packages/cli/test/unit/db.test.ts | 2 - .../test/unit/options/paramsOptions.test.ts | 2 - packages/cli/test/unit/util/format.test.ts | 3 +- packages/cli/test/unit/util/gitData.test.ts | 1 - .../validator/parseProposerConfig.test.ts | 2 +- .../crucible/clients/beacon/lighthouse.ts | 1 - .../utils/crucible/clients/beacon/lodestar.ts | 1 - .../crucible/clients/validator/lodestar.ts | 1 - packages/cli/test/utils/crucible/constants.ts | 1 - .../cli/test/utils/crucible/epochClock.ts | 1 - .../utils/crucible/externalSignerServer.ts | 1 - .../cli/test/utils/crucible/interfaces.ts | 1 - .../utils/crucible/runner/dockerRunner.ts | 4 +- .../test/utils/crucible/simulationTracker.ts | 2 +- .../cli/test/utils/crucible/utils/index.ts | 3 +- .../cli/test/utils/crucible/utils/keys.ts | 1 - .../cli/test/utils/crucible/utils/network.ts | 1 - .../cli/test/utils/crucible/utils/syncing.ts | 5 +- .../cli/test/utils/mockBeaconApiServer.ts | 1 - packages/config/package.json | 4 +- .../config/src/chainConfig/configs/mainnet.ts | 1 - .../config/src/chainConfig/configs/minimal.ts | 1 - packages/config/src/chainConfig/default.ts | 3 +- .../config/src/chainConfig/networks/chiado.ts | 1 - .../src/chainConfig/networks/ephemery.ts | 1 - .../config/src/chainConfig/networks/gnosis.ts | 1 - .../src/chainConfig/networks/holesky.ts | 1 - .../src/chainConfig/networks/mainnet.ts | 1 - .../src/chainConfig/networks/sepolia.ts | 1 - packages/config/src/chainConfig/types.ts | 2 - packages/config/test/unit/index.test.ts | 1 - packages/db/package.json | 4 +- packages/db/src/abstractRepository.ts | 2 +- .../db/test/unit/controller/level.test.ts | 2 +- packages/flare/package.json | 4 +- packages/flare/src/index.ts | 2 - packages/fork-choice/package.json | 4 +- packages/fork-choice/src/forkChoice/errors.ts | 6 +- .../fork-choice/src/forkChoice/forkChoice.ts | 4 +- packages/fork-choice/src/forkChoice/store.ts | 8 +- packages/fork-choice/src/protoArray/errors.ts | 6 +- .../fork-choice/src/protoArray/protoArray.ts | 1 - .../test/unit/forkChoice/utils.test.ts | 1 - .../unit/protoArray/getCommonAncestor.test.ts | 2 +- packages/light-client/package.json | 4 +- packages/light-client/src/events.ts | 2 +- packages/light-client/src/index.ts | 1 - packages/light-client/src/spec/utils.ts | 3 - packages/light-client/src/utils/logger.ts | 2 +- .../unit/isValidLightClientHeader.test.ts | 1 - .../light-client/test/unit/sync.node.test.ts | 1 - packages/logger/package.json | 4 +- packages/logger/src/browser.ts | 2 - packages/logger/src/interface.ts | 2 - packages/logger/src/utils/consoleTransport.ts | 1 + packages/logger/src/utils/format.ts | 6 +- packages/logger/src/utils/json.ts | 1 + .../logger/test/e2e/logger/workerLogger.js | 1 - .../logger/test/e2e/logger/workerLogs.test.ts | 1 - packages/logger/test/unit/node.node.test.ts | 1 - packages/logger/test/unit/utils/json.test.ts | 3 - .../logger/test/unit/winston.node.test.ts | 1 - packages/params/package.json | 4 +- packages/params/src/presets/gnosis.ts | 1 - packages/params/src/presets/mainnet.ts | 1 - packages/params/src/presets/minimal.ts | 1 - packages/params/src/types.ts | 2 - .../test/e2e/ensure-config-is-synced.test.ts | 1 - .../params/test/e2e/overridePreset.test.ts | 1 - .../params/test/e2e/overridePresetError.ts | 1 - packages/params/test/e2e/overridePresetOk.ts | 1 - packages/params/test/e2e/setPreset.test.ts | 1 - packages/params/test/yaml.ts | 1 - packages/prover/package.json | 4 +- packages/prover/scripts/generate_fixtures.ts | 11 +- packages/prover/src/cli/applyPreset.ts | 3 - packages/prover/src/cli/cmds/start/options.ts | 4 +- packages/prover/src/cli/index.ts | 3 +- packages/prover/src/interfaces.ts | 2 +- packages/prover/src/types.ts | 7 +- packages/prover/src/utils/conversion.ts | 1 - packages/prover/src/utils/evm.ts | 2 +- packages/prover/src/utils/file.ts | 1 - .../prover/src/utils/gitData/gitDataPath.ts | 1 - packages/prover/src/utils/gitData/index.ts | 12 +- packages/prover/src/utils/process.ts | 2 +- packages/prover/src/utils/version.ts | 1 - .../prover/src/verified_requests/eth_call.ts | 1 - .../src/verified_requests/eth_estimateGas.ts | 1 - .../src/verified_requests/eth_getBalance.ts | 1 - .../verified_requests/eth_getBlockByHash.ts | 1 - .../verified_requests/eth_getBlockByNumber.ts | 1 - .../src/verified_requests/eth_getCode.ts | 1 - .../eth_getTransactionCount.ts | 2 - .../test/fixtures/mainnet/eth_call.json | 2 +- .../eth_estimateGas_contract_call.json | 2 +- .../eth_estimateGas_simple_transfer.json | 2 +- .../sepolia/eth_getBalance_contract.json | 2 +- .../fixtures/sepolia/eth_getBalance_eoa.json | 2 +- .../eth_getBlock_with_contractCreation.json | 7 +- .../eth_getBlock_with_no_accessList.json | 7 +- .../test/fixtures/sepolia/eth_getCode.json | 2 +- .../sepolia/eth_getTransactionCount.json | 2 +- packages/prover/test/mocks/request_handler.ts | 1 - packages/prover/test/tsconfig.json | 2 +- .../eth_getBlockByHash.test.ts | 8 +- .../eth_getBlockByNumber.test.ts | 9 +- packages/prover/test/utils/e2e_env.ts | 1 - packages/reqresp/package.json | 4 +- .../reqresp/src/encoders/responseDecode.ts | 3 +- .../encodingStrategies/sszSnappy/decode.ts | 2 +- .../encodingStrategies/sszSnappy/errors.ts | 6 +- .../sszSnappy/snappyFrames/uncompress.ts | 1 - packages/reqresp/src/metrics.ts | 1 - packages/reqresp/src/request/index.ts | 1 - packages/reqresp/src/response/index.ts | 2 +- packages/reqresp/src/utils/bufferedSource.ts | 2 - .../test/fixtures/encodingStrategies.ts | 1 - packages/reqresp/test/fixtures/messages.ts | 3 - packages/reqresp/test/fixtures/protocols.ts | 2 - packages/spec-test-util/package.json | 4 +- packages/spec-test-util/src/single.ts | 9 +- .../test/e2e/single/index.test.ts | 3 - packages/state-transition/package.json | 4 +- .../src/block/processDeposit.ts | 2 +- packages/state-transition/src/util/balance.ts | 2 +- .../state-transition/src/util/blindedBlock.ts | 16 +- packages/state-transition/src/util/seed.ts | 2 +- packages/state-transition/src/util/shuffle.ts | 1 - .../src/util/weakSubjectivity.ts | 1 - packages/state-transition/test/cache.ts | 1 - .../test/perf/analyzeEpochs.ts | 2 - .../perf/dataStructures/arrayish.memory.ts | 1 - .../perf/epoch/processRegistryUpdates.test.ts | 2 +- .../test/perf/misc/arrayCreation.test.ts | 1 - .../test/perf/misc/bitopts.test.ts | 1 - .../test/perf/shuffle/shuffle.test.ts | 3 +- packages/state-transition/test/perf/util.ts | 3 - .../test/unit/cachedBeaconState.test.ts | 1 - .../test/unit/upgradeState.test.ts | 1 - .../test/unit/util/aggregator.test.ts | 2 - .../test/unit/util/deposit.test.ts | 2 - .../test/utils/beforeValue.ts | 2 +- .../test/utils/beforeValueMocha.ts | 2 +- packages/state-transition/test/utils/rand.ts | 3 +- .../test/utils/specTestCases.ts | 1 - .../test/utils/testFileCache.ts | 1 - packages/test-utils/package.json | 4 +- packages/test-utils/src/childProcess.ts | 4 +- packages/test-utils/src/cli.ts | 1 - packages/test-utils/src/doubles.ts | 2 - packages/test-utils/src/externalSigner.ts | 1 - packages/test-utils/src/http.ts | 1 - packages/types/package.json | 4 +- packages/types/src/sszTypes.ts | 5 +- packages/utils/package.json | 4 +- packages/utils/src/assert.ts | 1 - packages/utils/src/command.ts | 9 +- packages/utils/src/diff.ts | 3 + packages/utils/src/err.ts | 1 - packages/utils/src/logger.ts | 1 - packages/utils/src/objects.ts | 2 +- packages/utils/src/promise.ts | 1 - packages/utils/src/yaml/int.ts | 5 - packages/utils/src/yaml/schema.ts | 2 - packages/utils/test/unit/err.test.ts | 2 +- packages/utils/test/unit/objects.test.ts | 2 - packages/validator/package.json | 4 +- packages/validator/src/genesis.ts | 1 - packages/validator/src/metrics.ts | 1 - packages/validator/src/services/emitter.ts | 2 +- .../slashingProtection/attestation/errors.ts | 6 +- .../src/slashingProtection/block/errors.ts | 6 +- .../slashingProtection/interchange/errors.ts | 6 +- .../interchange/formats/completeV4.ts | 1 - .../interchange/formats/v5.ts | 1 - .../minMaxSurround/errors.ts | 6 +- .../src/util/externalSignerClient.ts | 2 - packages/validator/src/util/params.ts | 2 - packages/validator/test/spec/params.ts | 1 - .../test/unit/services/attestation.test.ts | 1 - .../test/unit/services/doppelganger.test.ts | 4 +- .../unit/services/syncCommitteDuties.test.ts | 3 - .../test/unit/services/syncCommittee.test.ts | 2 - .../interchange/index.test.ts | 1 - .../minMaxSurround/utils.ts | 4 +- .../validator/test/unit/utils/clock.test.ts | 1 - .../test/unit/utils/interopConfigs.ts | 2 - .../validator/test/unit/utils/params.test.ts | 2 - packages/validator/test/utils/spec.ts | 1 - scripts/assert_eslintrc_sorted.mjs | 22 - scripts/release/utils.mjs | 18 +- scripts/vitest/setupFiles/dotenv.ts | 2 - types/vitest/index.d.ts | 4 +- yarn.lock | 894 +++--------------- 453 files changed, 904 insertions(+), 1861 deletions(-) create mode 100644 .editorconfig delete mode 100644 .eslintrc.js create mode 100644 .vscode/extensions.json create mode 100644 biome.jsonc delete mode 100755 scripts/assert_eslintrc_sorted.mjs diff --git a/.editorconfig b/.editorconfig new file mode 100644 index 000000000000..ba02b753af34 --- /dev/null +++ b/.editorconfig @@ -0,0 +1,9 @@ +# top-most EditorConfig file +root = true + +# Unix-style newlines with a newline ending every file +[*] +end_of_line = lf +insert_final_newline = true +indent_style = space +indent_size = 2 diff --git a/.eslintrc.js b/.eslintrc.js deleted file mode 100644 index 46aca2515c83..000000000000 --- a/.eslintrc.js +++ /dev/null @@ -1,275 +0,0 @@ -module.exports = { - root: true, - env: { - browser: true, - es6: true, - node: true, - // Performance tests still use mocha - mocha: true, - }, - globals: { - BigInt: true, - }, - parser: "@typescript-eslint/parser", - parserOptions: { - ecmaVersion: 10, - project: "./tsconfig.json", - sourceType: "module", - }, - ignorePatterns: [ - "webEsmBundle.browser.test.ts" - ], - plugins: ["@typescript-eslint", "eslint-plugin-import", "@chainsafe/eslint-plugin-node", "prettier"], - extends: [ - "eslint:recommended", - "plugin:@typescript-eslint/recommended", - "plugin:import/errors", - "plugin:import/typescript", - "plugin:import/warnings", - ], - rules: { - "@chainsafe/node/file-extension-in-import": ["error", "always", {esm: true}], - "@chainsafe/node/no-deprecated-api": "error", - "@typescript-eslint/await-thenable": "error", - "@typescript-eslint/ban-ts-comment": "error", - "@typescript-eslint/explicit-function-return-type": ["error", {allowExpressions: true}], - "@typescript-eslint/explicit-member-accessibility": ["error", {accessibility: "no-public"}], - "@typescript-eslint/func-call-spacing": "error", - // TODO after upgrading es-lint, member-ordering is now leading to lint errors. Set to warning now and fix in another PR - "@typescript-eslint/member-ordering": "off", - "@typescript-eslint/naming-convention": [ - "error", - {selector: "default", format: ["camelCase"]}, - { - selector: ["classProperty", "objectLiteralProperty", "classMethod", "parameter"], - format: ["camelCase"], - leadingUnderscore: "allow", - }, - //variable must be in camel or upper case - {selector: "variable", format: ["camelCase", "UPPER_CASE"], leadingUnderscore: "allow"}, - //classes and types must be in PascalCase - {selector: ["typeLike", "enum"], format: ["PascalCase"]}, - {selector: "enumMember", format: null}, - //ignore rule for quoted stuff - { - selector: [ - "classProperty", - "objectLiteralProperty", - "typeProperty", - "classMethod", - "objectLiteralMethod", - "typeMethod", - "accessor", - "enumMember", - ], - format: null, - modifiers: ["requiresQuotes"], - }, - //ignore rules on destructured params - {selector: "variable", modifiers: ["destructured"], format: null}, - { - selector: "import", - format: ["camelCase", "PascalCase"], - }, - ], - "@typescript-eslint/no-explicit-any": "error", - "@typescript-eslint/no-floating-promises": "error", - "@typescript-eslint/no-non-null-assertion": "error", - "@typescript-eslint/no-require-imports": "error", - // We usually type-cast these standard types because the concerned function accepts any type - // and we want to TS detect error if original variable type changes - "@typescript-eslint/no-unnecessary-type-assertion": ["error", {typesToIgnore: ["string", "bigint", "number"]}], - "@typescript-eslint/no-unsafe-assignment": "error", - "@typescript-eslint/no-unsafe-call": "error", - "@typescript-eslint/no-unsafe-member-access": "error", - "@typescript-eslint/no-unsafe-return": "error", - "@typescript-eslint/no-unused-expressions": "error", - "@typescript-eslint/no-unused-vars": ["error", {varsIgnorePattern: "^_", argsIgnorePattern: "^_"}], - "@typescript-eslint/no-use-before-define": "off", - "@typescript-eslint/restrict-template-expressions": [ - "error", - {allowNumber: true, allowBoolean: true, allowNullish: true, allowNever: true, allowRegExp: true}, - ], - "@typescript-eslint/return-await": "error", - "@typescript-eslint/semi": "error", - "@typescript-eslint/strict-boolean-expressions": [ - "error", - {allowNullableBoolean: true, allowNullableString: true, allowAny: true}, - ], - - "@typescript-eslint/type-annotation-spacing": "error", - "constructor-super": "off", - "func-call-spacing": "off", - // Force to add names to all functions to ease CPU profiling - "func-names": ["error", "always"], - "import/namespace": "off", - //if --fix is run it messes imports like /lib/presets/minimal & /lib/presets/mainnet - "import/no-duplicates": "off", - "import/no-extraneous-dependencies": [ - "error", - { - devDependencies: false, - optionalDependencies: false, - peerDependencies: false, - }, - ], - "import/no-relative-packages": "error", - // TEMP Disabled while eslint-plugin-import support ESM (Typescript does support it) https://github.com/import-js/eslint-plugin-import/issues/2170 - "import/no-unresolved": "off", - "import/order": [ - "error", - { - groups: ["builtin", "external", "internal", "parent", "sibling", "index"], - pathGroups: [ - {pattern: "@lodestar/**", group: "internal"}, - // We want mocks to be imported before any internal code - {pattern: "**/mocks/**", group: "internal"}, - ], - pathGroupsExcludedImportTypes: ["builtin"], - }, - ], - //doesnt work, it reports false errors - "new-parens": "error", - "no-bitwise": "off", - "no-caller": "error", - "no-cond-assign": "error", - "no-consecutive-blank-lines": 0, - "no-console": "error", - "no-loss-of-precision": "error", - "no-prototype-builtins": 0, - "no-restricted-globals": [ - "error", - { - name: "fetch", - message: "Please use 'fetch' from '@lodestar/api' instead.", - }, - ], - "no-restricted-imports": [ - "error", - { - patterns: ["../lib/*", "@chainsafe/*/lib/*"], - paths: [ - ...restrictNodeModuleImports( - "child_process", - "crypto", - "fs", - "http", - "net", - "os", - "path", - "stream", - "util", - "url", - "worker_threads" - ), - ], - }, - ], - "no-restricted-syntax": ["error", ...restrictImportDestructuring("node:fs", "node:os", "node:path")], - // superseded by @typescript-eslint/return-await, must be disabled as it can report incorrect errors - "no-return-await": "off", - "no-var": "error", - "object-curly-spacing": ["error", "never"], - "object-literal-sort-keys": 0, - "prefer-const": "error", - "prettier/prettier": "error", - quotes: ["error", "double"], - semi: "off", - }, - settings: { - "import/core-modules": [ - "node:child_process", - "node:crypto", - "node:fs", - "node:http", - "node:net", - "node:os", - "node:path", - "node:stream", - "node:util", - "node:url", - ], - "import/resolver": { - typescript: { - project: "packages/*/tsconfig.json", - }, - }, - }, - overrides: [ - { - files: [ - "**/*.config.js", - "**/*.config.mjs", - "**/*.config.cjs", - "**/*.config.ts", - "scripts/vitest/**/*.ts", - "scripts/vite/**/*.ts", - ], - rules: { - "@typescript-eslint/naming-convention": "off", - // Allow require in CJS modules - "@typescript-eslint/no-require-imports": "off", - // Allow require in CJS modules - "@typescript-eslint/no-var-requires": "off", - // Allow importing packages from dev dependencies - "import/no-extraneous-dependencies": "off", - // Allow importing and mixing different configurations - "import/no-relative-packages": "off", - }, - }, - { - files: ["**/test/**/*.ts"], - rules: { - "@typescript-eslint/no-explicit-any": "off", - "func-names": "off", - "import/no-extraneous-dependencies": "off", - // Turned off as it floods log with warnings. Underlying issue is not critical so switching off is acceptable - "import/no-named-as-default-member": "off", - }, - }, - { - files: ["**/perf/**/*.ts"], - rules: { - // A lot of benchmarks just need to execute expressions without using the result - "@typescript-eslint/no-unused-expressions": "off", - }, - }, - { - files: ["**/test/**/*.test.ts"], - plugins: ["vitest"], - extends: ["plugin:vitest/recommended"], - rules: { - "vitest/consistent-test-it": ["error", {fn: "it", withinDescribe: "it"}], - // We use a lot dynamic assertions so tests may not have usage of expect - "vitest/expect-expect": "off", - "vitest/no-disabled-tests": "warn", - "vitest/no-focused-tests": "error", - "vitest/prefer-called-with": "error", - "vitest/prefer-spy-on": "error", - // Our usage contains dynamic test title, this rule enforce static string value - "vitest/valid-title": "off", - }, - }, - { - files: ["**/types/**/*.ts"], - rules: { - "@typescript-eslint/naming-convention": [ - "off", - {selector: "interface", prefix: ["I"]}, - {selector: "interface", format: ["PascalCase"], prefix: ["I"]}, - ], - }, - }, - ], -}; - -function restrictNodeModuleImports(...modules) { - return modules.map((module) => ({name: module, message: `Please use 'node:${module}' instead.`})); -} - -function restrictImportDestructuring(...modules) { - return modules.map((module) => ({ - selector: `ImportDeclaration[source.value='${module}'] ImportSpecifier`, - message: `Importing from '${module}' using destructuring is restricted.`, - })); -} diff --git a/.github/workflows/test.yml b/.github/workflows/test.yml index c801b0462d60..5514f6e896b7 100644 --- a/.github/workflows/test.yml +++ b/.github/workflows/test.yml @@ -64,9 +64,6 @@ jobs: - name: Assert ESM module exports run: node scripts/assert_exports.mjs - - name: Assert eslintrc rules sorted - run: scripts/assert_eslintrc_sorted.mjs - type-checks: name: Type Checks needs: build diff --git a/.vscode/extensions.json b/.vscode/extensions.json new file mode 100644 index 000000000000..de51190cd9f3 --- /dev/null +++ b/.vscode/extensions.json @@ -0,0 +1,5 @@ +{ + "recommendations": [ + "biomejs.biome" + ] +} diff --git a/.wordlist.txt b/.wordlist.txt index 11a5a3746476..a2e642a926a0 100644 --- a/.wordlist.txt +++ b/.wordlist.txt @@ -26,7 +26,6 @@ EIPs EL ENR ENRs -ESLint ETH Edgington Erigon diff --git a/CONTRIBUTING.md b/CONTRIBUTING.md index 9592f3bb0237..24d087810980 100644 --- a/CONTRIBUTING.md +++ b/CONTRIBUTING.md @@ -31,7 +31,7 @@ To run tests: - :test_tube: Run `yarn test:spec` for spec tests. - :test_tube: Run `yarn test` to run all tests. - :test_tube: Run `yarn check-types` to check TypeScript types. -- :test_tube: Run `yarn lint` to run the linter (ESLint). +- :test_tube: Run `yarn lint` to run the linter. Note that to run `test:e2e`, first ensure that the environment is correctly setup by running the `run_e2e_env.sh` script. This script requires a running docker engine. diff --git a/biome.jsonc b/biome.jsonc new file mode 100644 index 000000000000..b49fc601600c --- /dev/null +++ b/biome.jsonc @@ -0,0 +1,376 @@ +{ + "$schema": "https://biomejs.dev/schemas/1.9.3/schema.json", + "vcs": { + "clientKind": "git", + "enabled": true, + "useIgnoreFile": true + }, + "files": { + "include": ["packages/*/src/**/*.ts", "packages/*/test/**/*.ts"] + }, + "formatter": { + "enabled": true, + "formatWithErrors": true, + "useEditorconfig": true, + "lineWidth": 120, + "attributePosition": "auto", + "bracketSpacing": false, + "ignore": ["**/lib", "**/.nyc_output", "./packages/*/spec-tests", "**/node_modules", "./packages/*/node_modules/**"] + }, + "organizeImports": { + "enabled": false + }, + "linter": { + "enabled": true, + "rules": { + "recommended": true, + "complexity": { + "noForEach": "off", + "noStaticOnlyClass": "off", + "noThisInStatic": "off", + "noUselessEmptyExport": "off", + "noUselessTypeConstraint": "error", + "useArrowFunction": "off", + "useFlatMap": "off", + "useLiteralKeys": "off", + "useOptionalChain": "off", + "useRegexLiterals": "off", + "noBannedTypes": "error", + "noUselessThisAlias": "error" + }, + "correctness": { + "noInvalidConstructorSuper": "off", + "noInvalidUseBeforeDeclaration": "off", + "noPrecisionLoss": "error", + "noUnusedVariables": "error", + "noVoidTypeReturn": "off", + "useYield": "off", + "useImportExtensions": { + "level": "error", + "options": { + "suggestedExtensions": { + "ts": { + "module": "js", + "component": "jsx" + } + } + } + }, + "useArrayLiterals": "error", + "noUndeclaredDependencies": "off", // TODO: Need to see why this rule is not detecting monorepo packages + "noUndeclaredVariables": "error" + }, + "performance": { + "noAccumulatingSpread": "off", + "noDelete": "off" + }, + "style": { + "noCommaOperator": "off", + "noInferrableTypes": "off", + "noNonNullAssertion": "error", + "noParameterAssign": "off", + "noRestrictedGlobals": { + "level": "error", + "options": { + "deniedGlobals": ["fetch"] + } + }, + "noUnusedTemplateLiteral": "off", + "noUselessElse": "off", + "noVar": "error", + "useConst": "error", + "useEnumInitializers": "off", + "useExponentiationOperator": "off", + "useExportType": "off", + "useImportType": "off", + "useLiteralEnumMembers": "off", + "useNamingConvention": { + "level": "error", + "options": { + "strictCase": false, + "conventions": [ + { + "selector": { + "kind": "any" + }, + "formats": ["camelCase"] + }, + { + "selector": { + "kind": "classProperty" + }, + "formats": ["camelCase"] + }, + { + "selector": { + "kind": "objectLiteralProperty" + }, + "formats": ["camelCase"] + }, + { + "selector": { + "kind": "classMethod" + }, + "formats": ["camelCase"] + }, + { + "selector": { + "kind": "functionParameter" + }, + "formats": ["camelCase"] + }, + { + "selector": { + "kind": "variable" + }, + "formats": ["camelCase", "CONSTANT_CASE"] + }, + { + "selector": { + "kind": "typeLike" + }, + "formats": ["PascalCase"] + }, + { + "selector": { + "kind": "enum" + }, + "formats": ["PascalCase"] + }, + { + "selector": { + "kind": "enumMember" + }, + "formats": ["PascalCase", "camelCase", "CONSTANT_CASE"] + }, + { + "selector": { + "kind": "classProperty" + }, + "formats": ["PascalCase", "camelCase", "CONSTANT_CASE"] + }, + { + "selector": { + "kind": "typeProperty" + }, + "formats": ["PascalCase", "camelCase", "CONSTANT_CASE"] + }, + { + "selector": { + "kind": "classMember" + }, + "formats": ["PascalCase", "camelCase", "CONSTANT_CASE"] + }, + { + "selector": { + "kind": "objectLiteralMethod" + }, + "formats": ["PascalCase", "camelCase", "CONSTANT_CASE"] + }, + { + "selector": { + "kind": "typeMethod" + }, + "formats": ["PascalCase", "camelCase", "CONSTANT_CASE"] + }, + { + "selector": { + "kind": "variable" + }, + "formats": ["PascalCase", "camelCase", "CONSTANT_CASE"] + }, + { + "selector": { + "kind": "importAlias" + }, + "formats": ["PascalCase", "camelCase"] + }, + { + "selector": { + "kind": "importNamespace" + }, + "formats": ["PascalCase", "camelCase"] + } + ] + } + }, + "useNumberNamespace": "off", + "useSingleVarDeclarator": "off", + "useTemplate": "off", + "noNamespace": "error", + "useAsConstAssertion": "error" + }, + "suspicious": { + "noAssignInExpressions": "error", + "noAsyncPromiseExecutor": "off", + "noConfusingVoidType": "off", + "noConsoleLog": "error", + "noDoubleEquals": "off", + "noDuplicateTestHooks": "off", + "noExplicitAny": "error", + "noExportsInTest": "off", + "noFallthroughSwitchClause": "off", + "noGlobalIsFinite": "off", + "noGlobalIsNan": "off", + "noImplicitAnyLet": "off", + "noPrototypeBuiltins": "off", + "noRedundantUseStrict": "off", + "noShadowRestrictedNames": "off", + "useDefaultSwitchClauseLast": "off", + "useGetterReturn": "off", + "noExtraNonNullAssertion": "error", + "noMisleadingInstantiator": "error", + "noUnsafeDeclarationMerging": "error", + "noEmptyBlockStatements": "off" // There is a lot of empty code blocks, should be enabled and clean up separately. + }, + "nursery": { + "useConsistentMemberAccessibility": { + "level": "error", + "options": { + "accessibility": "noPublic" + } + }, + "noCommonJs": "error", + "noRestrictedImports": { + "level": "error", + "options": { + "paths": { + "child_process": "Please use node:child_process instead.", + "crypto": "Please use node:crypto instead.", + "fs": "Please use node:fs instead.", + "http": "Please use node:https instead.", + "net": "Please use node:net instead.", + "os": "Please use node:os instead.", + "path": "Please use node:path instead.", + "stream": "Please use node:stream instead.", + "util": "Please use node:util instead.", + "url": "Please use node:url instead.", + "worker_threads": "Please use node:worker_threads instead." + } + } + }, + "noDuplicateElseIf": "error", + "noUselessEscapeInRegex": "error", + "noIrregularWhitespace": "error", + "noOctalEscape": "error", + // Need to enable this rule with exception to anonymous functions + "useExplicitFunctionReturnType": "off" + } + } + }, + "javascript": { + "formatter": { + "jsxQuoteStyle": "double", + "quoteProperties": "asNeeded", + "trailingCommas": "es5", + "semicolons": "always", + "arrowParentheses": "always", + "bracketSpacing": false, + "bracketSameLine": false, + "quoteStyle": "double", + "attributePosition": "auto", + "enabled": true + }, + "linter": { + "enabled": true + }, + "globals": ["BigInt"] + }, + "overrides": [ + { + "include": ["packages/**/test/perf/**/*.test.ts", "packages/state-transition/test/utils/beforeValueMocha.ts"], + "javascript": { + // These are used by mocha + "globals": ["describe", "it", "before", "after"] + } + }, + { + "include": ["packages/cli/src/", "packages/test-utils/src", "packages/flare/src"], + "linter": { + "rules": { + "suspicious": { + "noConsoleLog": "off" + } + } + } + }, + { + "include": [ + "**/*.config.js", + "**/*.config.mjs", + "**/*.config.cjs", + "**/*.config.ts", + "scripts/vitest/**/*.ts", + "scripts/vite/**/*.ts", + "**/types/**/*.ts", + "packages/api/src/beacon/routes/*.ts", + "packages/api/src/**/routes.ts", + "packages/api/src/utils/server/handler.ts", + "packages/api/test/unit/client/urlFormat.test.ts", + "packages/beacon-node/src/api/impl/config/constants.ts", + "packages/beacon-node/src/eth1/provider/eth1Provider.ts", + "" + ], + "linter": { + "rules": { + "style": { + "useNamingConvention": { + "level": "off", + "options": { + "strictCase": false + } + } + } + } + } + }, + { + "include": [ + "**/test/**/*.ts", + "packages/*/test/**/*.js", + "packages/api/src/utils/**/*.ts", + "packages/beacon-node/src/db/repositories/checkpointState.ts", + "packages/spec-test-util/src/single.ts" + ], + "linter": { + "rules": { + "suspicious": { + "noExplicitAny": "off" + } + } + } + }, + { + "include": ["packages/beacon-node/test/e2e/eth1/jsonRpcHttpClient.test.ts"], + "linter": { + "rules": { + "correctness": { + "noUnusedVariables": "off" + } + } + } + }, + { + "include": ["**/test/**/*.ts", "packages/*/test/**/*.js"], + "linter": { + "rules": { + "suspicious": { + "noConsoleLog": "off" + } + } + } + }, + { + "include": ["**/perf/**/*.ts"], + "linter": { + "rules": {} + } + }, + { + "include": ["**/test/**/*.test.ts"], + "linter": { + "rules": {} + } + } + ] +} diff --git a/package.json b/package.json index 85d9662ab920..7399b4ba6c1e 100644 --- a/package.json +++ b/package.json @@ -15,8 +15,8 @@ "build:bundle": "lerna run build:bundle", "build:watch": "lerna exec --parallel -- 'yarn run build:watch'", "build:ifchanged": "lerna exec -- ../../scripts/build_if_changed.sh", - "lint": "eslint --report-unused-disable-directives --color --ext .ts packages/*/src packages/*/test", - "lint:fix": "yarn lint --fix", + "lint": "biome check", + "lint:fix": "yarn lint --write", "lint-dashboards": "node scripts/lint-grafana-dashboards.mjs ./dashboards", "check-build": "lerna run check-build", "check-bundle": "lerna run check-bundle", @@ -48,22 +48,15 @@ }, "devDependencies": { "@actions/core": "^1.10.1", - "@chainsafe/eslint-plugin-node": "^11.2.3", "@dapplion/benchmark": "^0.2.4", + "@biomejs/biome": "^1.9.3", "@types/mocha": "^10.0.6", "@types/node": "^20.12.8", - "@typescript-eslint/eslint-plugin": "^7.2.0", - "@typescript-eslint/parser": "^7.2.0", "@vitest/browser": "^2.0.4", "@vitest/coverage-v8": "^2.0.4", "crypto-browserify": "^3.12.0", "dotenv": "^16.4.5", "electron": "^26.2.2", - "eslint": "^8.57.0", - "eslint-import-resolver-typescript": "^3.6.1", - "eslint-plugin-import": "^2.29.1", - "eslint-plugin-prettier": "^5.1.3", - "eslint-plugin-vitest": "^0.3.26", "https-browserify": "^1.0.0", "jsdom": "^23.0.1", "lerna": "^7.3.0", diff --git a/packages/api/package.json b/packages/api/package.json index 7d851d9513ba..58566a0b23f6 100644 --- a/packages/api/package.json +++ b/packages/api/package.json @@ -63,8 +63,8 @@ "build:release": "yarn clean && yarn run build", "check-build": "node -e \"(async function() { await import('./lib/index.js') })()\"", "check-types": "tsc", - "lint": "eslint --color --ext .ts src/ test/", - "lint:fix": "yarn run lint --fix", + "lint": "biome check src/ test/", + "lint:fix": "yarn run lint --write", "test": "yarn test:unit", "test:unit": "vitest --run --dir test/unit/", "check-readme": "typescript-docs-verifier" diff --git a/packages/api/src/beacon/client/events.ts b/packages/api/src/beacon/client/events.ts index 34f14f2e8397..9937b850b49a 100644 --- a/packages/api/src/beacon/client/events.ts +++ b/packages/api/src/beacon/client/events.ts @@ -16,10 +16,15 @@ export function getClient(config: ChainForkConfig, baseUrl: string): ApiClient { const eventSerdes = getEventSerdes(config); return { - eventstream: async ({topics, signal, onEvent, onError, onClose}) => { + eventstream: async ({ + topics, + signal, + onEvent, + onError, + onClose, + }): Promise> => { const query = stringifyQuery({topics}); const url = `${urlJoin(baseUrl, definitions.eventstream.url)}?${query}`; - // eslint-disable-next-line @typescript-eslint/naming-convention const EventSource = await getEventSource(); const eventSource = new EventSource(url); @@ -40,7 +45,7 @@ export function getClient(config: ChainForkConfig, baseUrl: string): ApiClient { // EventSource will try to reconnect always on all errors // `eventSource.onerror` events are informative but don't indicate the EventSource closed // The only way to abort the connection from the client is via eventSource.close() - eventSource.onerror = function onerror(err) { + eventSource.onerror = function onerror(err): void { const errEs = err as unknown as EventSourceError; // Ignore noisy errors due to beacon node being offline diff --git a/packages/api/src/beacon/routes/beacon/block.ts b/packages/api/src/beacon/routes/beacon/block.ts index be6789753e0f..04d42cdab81e 100644 --- a/packages/api/src/beacon/routes/beacon/block.ts +++ b/packages/api/src/beacon/routes/beacon/block.ts @@ -1,4 +1,3 @@ -/* eslint-disable @typescript-eslint/naming-convention */ import {ContainerType, ListCompositeType, ValueOf} from "@chainsafe/ssz"; import {ChainForkConfig} from "@lodestar/config"; import { @@ -225,7 +224,7 @@ export type Endpoints = { >; }; -// eslint-disable-next-line @typescript-eslint/no-explicit-any +// biome-ignore lint/suspicious/noExplicitAny: const blockIdOnlyReq: RequestCodec> = { writeReq: ({blockId}) => ({params: {block_id: blockId.toString()}}), parseReq: ({params}) => ({blockId: params.block_id}), diff --git a/packages/api/src/beacon/routes/beacon/pool.ts b/packages/api/src/beacon/routes/beacon/pool.ts index 4fe3efd4daf2..3f0b8ac74284 100644 --- a/packages/api/src/beacon/routes/beacon/pool.ts +++ b/packages/api/src/beacon/routes/beacon/pool.ts @@ -1,4 +1,3 @@ -/* eslint-disable @typescript-eslint/naming-convention */ import {ValueOf} from "@chainsafe/ssz"; import {ChainForkConfig} from "@lodestar/config"; import {isForkPostElectra} from "@lodestar/params"; diff --git a/packages/api/src/beacon/routes/beacon/rewards.ts b/packages/api/src/beacon/routes/beacon/rewards.ts index c65282625343..d41b5ef705f0 100644 --- a/packages/api/src/beacon/routes/beacon/rewards.ts +++ b/packages/api/src/beacon/routes/beacon/rewards.ts @@ -1,4 +1,3 @@ -/* eslint-disable @typescript-eslint/naming-convention */ import {ContainerType, ValueOf} from "@chainsafe/ssz"; import {ChainForkConfig} from "@lodestar/config"; import {Epoch, ssz} from "@lodestar/types"; diff --git a/packages/api/src/beacon/routes/beacon/state.ts b/packages/api/src/beacon/routes/beacon/state.ts index 1489f48c297e..4127bb1ce793 100644 --- a/packages/api/src/beacon/routes/beacon/state.ts +++ b/packages/api/src/beacon/routes/beacon/state.ts @@ -1,4 +1,3 @@ -/* eslint-disable @typescript-eslint/naming-convention */ import {ContainerType, ValueOf} from "@chainsafe/ssz"; import {ChainForkConfig} from "@lodestar/config"; import {MAX_VALIDATORS_PER_COMMITTEE} from "@lodestar/params"; @@ -269,7 +268,7 @@ export type Endpoints = { >; }; -// eslint-disable-next-line @typescript-eslint/no-explicit-any +// biome-ignore lint/suspicious/noExplicitAny: const stateIdOnlyReq: RequestCodec> = { writeReq: ({stateId}) => ({params: {state_id: stateId.toString()}}), parseReq: ({params}) => ({stateId: params.state_id}), diff --git a/packages/api/src/beacon/routes/config.ts b/packages/api/src/beacon/routes/config.ts index f8a606af1431..afce0898908c 100644 --- a/packages/api/src/beacon/routes/config.ts +++ b/packages/api/src/beacon/routes/config.ts @@ -1,4 +1,3 @@ -/* eslint-disable @typescript-eslint/naming-convention */ import {ContainerType, ValueOf} from "@chainsafe/ssz"; import {ChainForkConfig} from "@lodestar/config"; import {ssz} from "@lodestar/types"; diff --git a/packages/api/src/beacon/routes/debug.ts b/packages/api/src/beacon/routes/debug.ts index 590ecf71dd9c..349684f62ccd 100644 --- a/packages/api/src/beacon/routes/debug.ts +++ b/packages/api/src/beacon/routes/debug.ts @@ -1,4 +1,3 @@ -/* eslint-disable @typescript-eslint/naming-convention */ import {ContainerType, Type, ValueOf} from "@chainsafe/ssz"; import {ChainForkConfig} from "@lodestar/config"; import {ssz, StringType, BeaconState} from "@lodestar/types"; diff --git a/packages/api/src/beacon/routes/events.ts b/packages/api/src/beacon/routes/events.ts index 1f041aa30194..5fa218bc02f3 100644 --- a/packages/api/src/beacon/routes/events.ts +++ b/packages/api/src/beacon/routes/events.ts @@ -188,7 +188,6 @@ export type TypeJson = { }; export function getTypeByEvent(config: ChainForkConfig): {[K in EventType]: TypeJson} { - // eslint-disable-next-line @typescript-eslint/naming-convention const WithVersion = (getType: (fork: ForkName) => TypeJson): TypeJson<{data: T; version: ForkName}> => { return { toJson: ({data, version}) => ({ @@ -289,7 +288,6 @@ export function getTypeByEvent(config: ChainForkConfig): {[K in EventType]: Type }; } -// eslint-disable-next-line @typescript-eslint/explicit-function-return-type export function getEventSerdes(config: ChainForkConfig) { const typeByEvent = getTypeByEvent(config); diff --git a/packages/api/src/beacon/routes/lightclient.ts b/packages/api/src/beacon/routes/lightclient.ts index ab45323f8f64..decf8982b654 100644 --- a/packages/api/src/beacon/routes/lightclient.ts +++ b/packages/api/src/beacon/routes/lightclient.ts @@ -1,4 +1,3 @@ -/* eslint-disable @typescript-eslint/naming-convention */ import {ListCompositeType, ValueOf} from "@chainsafe/ssz"; import { LightClientBootstrap, diff --git a/packages/api/src/beacon/routes/lodestar.ts b/packages/api/src/beacon/routes/lodestar.ts index a97d065cfe4d..1d3c62ca2082 100644 --- a/packages/api/src/beacon/routes/lodestar.ts +++ b/packages/api/src/beacon/routes/lodestar.ts @@ -21,7 +21,7 @@ export type SyncChainDebugState = { status: string; startEpoch: number; peers: number; - // eslint-disable-next-line @typescript-eslint/no-explicit-any + // biome-ignore lint/suspicious/noExplicitAny: batches: any[]; }; diff --git a/packages/api/src/beacon/routes/node.ts b/packages/api/src/beacon/routes/node.ts index 0744b5f07452..c7a6c2e36361 100644 --- a/packages/api/src/beacon/routes/node.ts +++ b/packages/api/src/beacon/routes/node.ts @@ -1,4 +1,3 @@ -/* eslint-disable @typescript-eslint/naming-convention */ import {ContainerType, ValueOf} from "@chainsafe/ssz"; import {ChainForkConfig} from "@lodestar/config"; import {ssz, stringType} from "@lodestar/types"; diff --git a/packages/api/src/beacon/routes/proof.ts b/packages/api/src/beacon/routes/proof.ts index 2ef4dad15e81..0c6d5a058cea 100644 --- a/packages/api/src/beacon/routes/proof.ts +++ b/packages/api/src/beacon/routes/proof.ts @@ -1,4 +1,3 @@ -/* eslint-disable @typescript-eslint/naming-convention */ import {CompactMultiProof, ProofType} from "@chainsafe/persistent-merkle-tree"; import {ByteListType, ContainerType} from "@chainsafe/ssz"; import {fromHex, toHex} from "@lodestar/utils"; diff --git a/packages/api/src/beacon/routes/validator.ts b/packages/api/src/beacon/routes/validator.ts index a9a1423e4da2..cf30d5748a46 100644 --- a/packages/api/src/beacon/routes/validator.ts +++ b/packages/api/src/beacon/routes/validator.ts @@ -1,4 +1,3 @@ -/* eslint-disable @typescript-eslint/naming-convention */ import {ContainerType, Type, ValueOf} from "@chainsafe/ssz"; import {ChainForkConfig} from "@lodestar/config"; import {isForkBlobs, isForkPostElectra} from "@lodestar/params"; diff --git a/packages/api/src/beacon/server/index.ts b/packages/api/src/beacon/server/index.ts index 21c0607d3f14..304f4d42be17 100644 --- a/packages/api/src/beacon/server/index.ts +++ b/packages/api/src/beacon/server/index.ts @@ -25,7 +25,7 @@ export function registerRoutes( // Enforces that we are declaring routes for every routeId in `Endpoints` [K in keyof Endpoints]: () => { // The Endpoints are enforced in each getRoutes return type - // eslint-disable-next-line @typescript-eslint/no-explicit-any + // biome-ignore lint/suspicious/noExplicitAny: [K2 in keyof Endpoints[K]]: FastifyRoute; }; } = { diff --git a/packages/api/src/builder/routes.ts b/packages/api/src/builder/routes.ts index 7459e46abd0b..018110e5eded 100644 --- a/packages/api/src/builder/routes.ts +++ b/packages/api/src/builder/routes.ts @@ -1,4 +1,3 @@ -/* eslint-disable @typescript-eslint/naming-convention */ import { ssz, bellatrix, diff --git a/packages/api/src/keymanager/routes.ts b/packages/api/src/keymanager/routes.ts index b6abe8928d77..0db096d14e83 100644 --- a/packages/api/src/keymanager/routes.ts +++ b/packages/api/src/keymanager/routes.ts @@ -1,4 +1,3 @@ -/* eslint-disable @typescript-eslint/naming-convention */ import {ContainerType, ValueOf} from "@chainsafe/ssz"; import {ChainForkConfig} from "@lodestar/config"; import {Epoch, phase0, ssz, stringType} from "@lodestar/types"; diff --git a/packages/api/src/utils/client/eventSource.ts b/packages/api/src/utils/client/eventSource.ts index 6b5b75124034..2e2cf0076068 100644 --- a/packages/api/src/utils/client/eventSource.ts +++ b/packages/api/src/utils/client/eventSource.ts @@ -1,6 +1,5 @@ // This function switches between the native web implementation and a nodejs implemnetation export async function getEventSource(): Promise { - // eslint-disable-next-line @typescript-eslint/strict-boolean-expressions if (globalThis.EventSource) { return EventSource; } else { diff --git a/packages/api/src/utils/client/fetch.ts b/packages/api/src/utils/client/fetch.ts index a338d82e521f..31e52cdbd67f 100644 --- a/packages/api/src/utils/client/fetch.ts +++ b/packages/api/src/utils/client/fetch.ts @@ -6,7 +6,7 @@ async function wrappedFetch(url: string | URL, init?: RequestInit): Promise { try { // This function wraps global `fetch` which should only be directly called here - // eslint-disable-next-line no-restricted-globals + // biome-ignore lint/style/noRestrictedGlobals: return await fetch(url, init); } catch (e) { throw new FetchError(url, e); diff --git a/packages/api/src/utils/client/httpClient.ts b/packages/api/src/utils/client/httpClient.ts index e11e35dc85c7..eec86725fcaa 100644 --- a/packages/api/src/utils/client/httpClient.ts +++ b/packages/api/src/utils/client/httpClient.ts @@ -198,8 +198,7 @@ export class HttpClient implements IHttpClient { this.logger?.debug("Requesting fallback URL", {routeId, baseUrl: printableUrl, score: this.urlsScore[i]}); } - // eslint-disable-next-line @typescript-eslint/naming-convention - const i_ = i; // Keep local copy of i variable to index urlScore after requestMethod() resolves + const i_ = i; // Keep local copy of i variable to index urlScore after requestWithBody() resolves const urlInit = this.urlsInits[i]; if (urlInit === undefined) { diff --git a/packages/api/src/utils/client/response.ts b/packages/api/src/utils/client/response.ts index fdcb2afda943..7a4c4fb98ce4 100644 --- a/packages/api/src/utils/client/response.ts +++ b/packages/api/src/utils/client/response.ts @@ -26,13 +26,15 @@ export class ApiResponse extends Response { wireFormat(): WireFormat | null { if (this._wireFormat === undefined) { if (this.definition.resp.isEmpty) { - return (this._wireFormat = null); + this._wireFormat = null; + return this._wireFormat; } const contentType = this.headers.get(HttpHeader.ContentType); if (contentType === null) { if (this.status === HttpStatusCode.NO_CONTENT) { - return (this._wireFormat = null); + this._wireFormat = null; + return this._wireFormat; } else { throw Error("Content-Type header is required in response"); } @@ -198,7 +200,7 @@ export class ApiResponse extends Response { } else { return errBody; } - } catch (e) { + } catch (_e) { return errBody || this.statusText; } } diff --git a/packages/api/src/utils/codecs.ts b/packages/api/src/utils/codecs.ts index 36d905583098..54214740f435 100644 --- a/packages/api/src/utils/codecs.ts +++ b/packages/api/src/utils/codecs.ts @@ -1,4 +1,3 @@ -/* eslint-disable @typescript-eslint/naming-convention */ import {ArrayType, ListBasicType, ListCompositeType, Type, isBasicType, isCompositeType} from "@chainsafe/ssz"; import {ForkName} from "@lodestar/params"; import {objectToExpectedCase} from "@lodestar/utils"; @@ -20,11 +19,8 @@ export type EmptyRequest = Record; export type EmptyResponseData = void; export type EmptyMeta = void; -// eslint-disable-next-line @typescript-eslint/no-explicit-any export type AnyEndpoint = Endpoint; -// eslint-disable-next-line @typescript-eslint/no-explicit-any export type EmptyRequestEndpoint = Endpoint; -// eslint-disable-next-line @typescript-eslint/no-explicit-any export type EmptyResponseEndpoint = Endpoint; /** Shortcut for routes that have no params, query */ diff --git a/packages/api/src/utils/metadata.ts b/packages/api/src/utils/metadata.ts index 1eaa4132119f..2ee9b2f51f0e 100644 --- a/packages/api/src/utils/metadata.ts +++ b/packages/api/src/utils/metadata.ts @@ -1,4 +1,3 @@ -/* eslint-disable @typescript-eslint/naming-convention */ import {ContainerType, ValueOf} from "@chainsafe/ssz"; import {ForkName} from "@lodestar/params"; import {StringType, ssz, stringType} from "@lodestar/types"; diff --git a/packages/api/src/utils/serdes.ts b/packages/api/src/utils/serdes.ts index 282c2514e00d..c2080ad2d020 100644 --- a/packages/api/src/utils/serdes.ts +++ b/packages/api/src/utils/serdes.ts @@ -104,7 +104,7 @@ export function fromGraffitiHex(hex?: string): string | undefined { } try { return new TextDecoder("utf8").decode(fromHex(hex)); - } catch { + } catch (_e) { // allow malformed graffiti hex string return hex; } diff --git a/packages/api/src/utils/server/handler.ts b/packages/api/src/utils/server/handler.ts index a3cd9a43a56a..035f4328141a 100644 --- a/packages/api/src/utils/server/handler.ts +++ b/packages/api/src/utils/server/handler.ts @@ -1,4 +1,3 @@ -/* eslint-disable @typescript-eslint/naming-convention */ import type * as fastify from "fastify"; import {HttpHeader, MediaType, SUPPORTED_MEDIA_TYPES, parseAcceptHeader, parseContentTypeHeader} from "../headers.js"; import { diff --git a/packages/api/src/utils/server/method.ts b/packages/api/src/utils/server/method.ts index 080c78869798..6fc99cc49a72 100644 --- a/packages/api/src/utils/server/method.ts +++ b/packages/api/src/utils/server/method.ts @@ -12,10 +12,9 @@ type ApplicationResponseObject = { : {data: E["return"] | (E["return"] extends undefined ? undefined : Uint8Array)}) & (E["meta"] extends EmptyMeta ? {meta?: never} : {meta: E["meta"]}); -export type ApplicationResponse = - HasOnlyOptionalProps> extends true - ? ApplicationResponseObject | void - : ApplicationResponseObject; +export type ApplicationResponse = HasOnlyOptionalProps> extends true + ? ApplicationResponseObject | void + : ApplicationResponseObject; export type ApiContext = { /** diff --git a/packages/api/test/perf/compileRouteUrlFormater.test.ts b/packages/api/test/perf/compileRouteUrlFormater.test.ts index ab16e1a5d14e..60d9e3fea8ee 100644 --- a/packages/api/test/perf/compileRouteUrlFormater.test.ts +++ b/packages/api/test/perf/compileRouteUrlFormater.test.ts @@ -1,7 +1,5 @@ import {compileRouteUrlFormatter} from "../../src/utils/urlFormat.js"; -/* eslint-disable no-console */ - describe("route parse", () => { it.skip("Benchmark compileRouteUrlFormatter", () => { const path = "/eth/v1/validator/:name/attester/:epoch"; diff --git a/packages/api/test/unit/beacon/genericServerTest/beacon.test.ts b/packages/api/test/unit/beacon/genericServerTest/beacon.test.ts index a722e72a4c27..f8c13b33afb6 100644 --- a/packages/api/test/unit/beacon/genericServerTest/beacon.test.ts +++ b/packages/api/test/unit/beacon/genericServerTest/beacon.test.ts @@ -8,7 +8,6 @@ import {testData} from "../testData/beacon.js"; describe("beacon / beacon", () => { runGenericServerTest( - // eslint-disable-next-line @typescript-eslint/naming-convention createChainForkConfig({...defaultChainConfig, ALTAIR_FORK_EPOCH: 1, BELLATRIX_FORK_EPOCH: 2}), getClient, getRoutes, diff --git a/packages/api/test/unit/beacon/genericServerTest/config.test.ts b/packages/api/test/unit/beacon/genericServerTest/config.test.ts index 8b924cf07693..91075f96d1e3 100644 --- a/packages/api/test/unit/beacon/genericServerTest/config.test.ts +++ b/packages/api/test/unit/beacon/genericServerTest/config.test.ts @@ -6,8 +6,6 @@ import {getRoutes} from "../../../../src/beacon/server/config.js"; import {runGenericServerTest} from "../../../utils/genericServerTest.js"; import {testData} from "../testData/config.js"; -/* eslint-disable @typescript-eslint/naming-convention */ - describe("beacon / config", () => { runGenericServerTest(config, getClient, getRoutes, testData); diff --git a/packages/api/test/unit/beacon/oapiSpec.test.ts b/packages/api/test/unit/beacon/oapiSpec.test.ts index 2b8a8254dd6b..0478d503d517 100644 --- a/packages/api/test/unit/beacon/oapiSpec.test.ts +++ b/packages/api/test/unit/beacon/oapiSpec.test.ts @@ -18,7 +18,6 @@ import {testData as validatorTestData} from "./testData/validator.js"; // Global variable __dirname no longer available in ES6 modules. // Solutions: https://stackoverflow.com/questions/46745014/alternative-for-dirname-in-node-js-when-using-es6-modules -// eslint-disable-next-line @typescript-eslint/naming-convention const __dirname = path.dirname(fileURLToPath(import.meta.url)); const version = "v3.0.0-alpha.6"; @@ -28,7 +27,6 @@ const openApiFile: OpenApiFile = { version: RegExp(version), }; -// eslint-disable-next-line @typescript-eslint/naming-convention const config = createChainForkConfig({...defaultChainConfig, ALTAIR_FORK_EPOCH: 1, BELLATRIX_FORK_EPOCH: 2}); const definitions = { diff --git a/packages/api/test/unit/beacon/testData/events.ts b/packages/api/test/unit/beacon/testData/events.ts index 8a7610a26836..3d2ffb708965 100644 --- a/packages/api/test/unit/beacon/testData/events.ts +++ b/packages/api/test/unit/beacon/testData/events.ts @@ -5,8 +5,6 @@ import {GenericServerTestCases} from "../../../utils/genericServerTest.js"; const abortController = new AbortController(); -/* eslint-disable @typescript-eslint/naming-convention */ - export const testData: GenericServerTestCases = { eventstream: { args: {topics: [EventType.head, EventType.chainReorg], signal: abortController.signal, onEvent: () => {}}, diff --git a/packages/api/test/unit/builder/builder.test.ts b/packages/api/test/unit/builder/builder.test.ts index 045a66496b6f..d2e25916069e 100644 --- a/packages/api/test/unit/builder/builder.test.ts +++ b/packages/api/test/unit/builder/builder.test.ts @@ -10,7 +10,6 @@ describe("builder", () => { runGenericServerTest( createChainForkConfig({ ...defaultChainConfig, - /* eslint-disable @typescript-eslint/naming-convention */ ALTAIR_FORK_EPOCH: 0, BELLATRIX_FORK_EPOCH: 0, DENEB_FORK_EPOCH: 0, diff --git a/packages/api/test/unit/builder/oapiSpec.test.ts b/packages/api/test/unit/builder/oapiSpec.test.ts index 60168f71d8d8..d972b64905e5 100644 --- a/packages/api/test/unit/builder/oapiSpec.test.ts +++ b/packages/api/test/unit/builder/oapiSpec.test.ts @@ -10,7 +10,6 @@ import {testData} from "./testData.js"; // Global variable __dirname no longer available in ES6 modules. // Solutions: https://stackoverflow.com/questions/46745014/alternative-for-dirname-in-node-js-when-using-es6-modules -// eslint-disable-next-line @typescript-eslint/naming-convention const __dirname = path.dirname(fileURLToPath(import.meta.url)); const version = "v0.2.0"; @@ -23,7 +22,6 @@ const openApiFile: OpenApiFile = { }; const definitions = getDefinitions( - // eslint-disable-next-line @typescript-eslint/naming-convention createChainForkConfig({...defaultChainConfig, ALTAIR_FORK_EPOCH: 0, BELLATRIX_FORK_EPOCH: 0}) ); diff --git a/packages/api/test/unit/client/fetch.test.ts b/packages/api/test/unit/client/fetch.test.ts index 80e5f58b164a..0c08c5bbf5a3 100644 --- a/packages/api/test/unit/client/fetch.test.ts +++ b/packages/api/test/unit/client/fetch.test.ts @@ -92,7 +92,6 @@ describe("FetchError", function () { const afterHook = afterHooks.pop(); if (afterHook) await afterHook().catch((e: Error) => { - // eslint-disable-next-line no-console console.error("Error in afterEach hook", e); }); } diff --git a/packages/api/test/unit/client/httpClientFallback.test.ts b/packages/api/test/unit/client/httpClientFallback.test.ts index ea20c3f33982..244fcbe5bf23 100644 --- a/packages/api/test/unit/client/httpClientFallback.test.ts +++ b/packages/api/test/unit/client/httpClientFallback.test.ts @@ -81,7 +81,6 @@ describe("httpClient fallback", () => { fetchStub.mockClear(); - // eslint-disable-next-line no-console if (DEBUG_LOGS) console.log("completed assertions step", step); } diff --git a/packages/api/test/unit/client/urlFormat.test.ts b/packages/api/test/unit/client/urlFormat.test.ts index dc86e2674e13..5132044b7631 100644 --- a/packages/api/test/unit/client/urlFormat.test.ts +++ b/packages/api/test/unit/client/urlFormat.test.ts @@ -7,8 +7,6 @@ import { urlToTokens, } from "../../../src/utils/urlFormat.js"; -/* eslint-disable @typescript-eslint/naming-convention */ - describe("utils / urlFormat", () => { const testCases: { urlTemplate: string; diff --git a/packages/api/test/unit/keymanager/oapiSpec.test.ts b/packages/api/test/unit/keymanager/oapiSpec.test.ts index 97011f5d3660..aab4e1823ab0 100644 --- a/packages/api/test/unit/keymanager/oapiSpec.test.ts +++ b/packages/api/test/unit/keymanager/oapiSpec.test.ts @@ -9,7 +9,6 @@ import {testData} from "./testData.js"; // Global variable __dirname no longer available in ES6 modules. // Solutions: https://stackoverflow.com/questions/46745014/alternative-for-dirname-in-node-js-when-using-es6-modules -// eslint-disable-next-line @typescript-eslint/naming-convention const __dirname = path.dirname(fileURLToPath(import.meta.url)); const version = "v1.1.0"; diff --git a/packages/api/test/utils/checkAgainstSpec.ts b/packages/api/test/utils/checkAgainstSpec.ts index 5e339efcb822..85e9711ae601 100644 --- a/packages/api/test/utils/checkAgainstSpec.ts +++ b/packages/api/test/utils/checkAgainstSpec.ts @@ -127,7 +127,7 @@ export function runTestCheckAgainstSpec>( expect(reqSsz.body).toBeInstanceOf(Uint8Array); expect(reqCodec.onlySupport).not.toBe(WireFormat.json); - } catch { + } catch (_e) { throw Error("Must support ssz request body"); } } @@ -167,7 +167,7 @@ export function runTestCheckAgainstSpec>( expect(sszBytes).toBeInstanceOf(Uint8Array); expect(routeDef.resp.onlySupport).not.toBe(WireFormat.json); - } catch { + } catch (_e) { throw Error("Must support ssz response body"); } } @@ -183,7 +183,6 @@ function validateSchema(schema: Parameters[0], json: unknown try { validate = ajv.compile(schema); } catch (e) { - // eslint-disable-next-line no-console console.error(JSON.stringify(schema, null, 2)); (e as Error).message = `${id} schema - ${(e as Error).message}`; throw e; diff --git a/packages/api/test/utils/parseOpenApiSpec.ts b/packages/api/test/utils/parseOpenApiSpec.ts index 7527fb61abaa..e6e75014312b 100644 --- a/packages/api/test/utils/parseOpenApiSpec.ts +++ b/packages/api/test/utils/parseOpenApiSpec.ts @@ -105,7 +105,6 @@ export function parseOpenApiSpec(openApiJson: OpenApiJson): Map Promise< addSszContentTypeParser(server); server.addHook("onError", (_request, _reply, error, done) => { - // eslint-disable-next-line no-console console.log(`onError: ${error.toString()}`); done(); }); diff --git a/packages/beacon-node/package.json b/packages/beacon-node/package.json index 4deaf7c6ac16..8b46bc0038c7 100644 --- a/packages/beacon-node/package.json +++ b/packages/beacon-node/package.json @@ -75,8 +75,8 @@ "build:release": "yarn clean && yarn run build", "check-build": "node -e \"(async function() { await import('./lib/index.js') })()\"", "check-types": "tsc", - "lint": "eslint --color --ext .ts src/ test/", - "lint:fix": "yarn run lint --fix", + "lint": "biome check src/ test/", + "lint:fix": "yarn run lint --write", "test": "yarn test:unit && yarn test:e2e", "test:unit:minimal": "LODESTAR_PRESET=minimal vitest --run --dir test/unit/", "test:unit:mainnet": "LODESTAR_PRESET=mainnet vitest --run --dir test/unit-mainnet", diff --git a/packages/beacon-node/src/api/impl/beacon/blocks/index.ts b/packages/beacon-node/src/api/impl/beacon/blocks/index.ts index 65e7b9373a22..240f391027a9 100644 --- a/packages/beacon-node/src/api/impl/beacon/blocks/index.ts +++ b/packages/beacon-node/src/api/impl/beacon/blocks/index.ts @@ -224,15 +224,17 @@ export function getBeaconBlockApi({ () => network.publishBeaconBlock(signedBlock) as Promise, () => // there is no rush to persist block since we published it to gossip anyway - chain.processBlock(blockForImport, {...opts, eagerPersistBlock: false}).catch((e) => { - if (e instanceof BlockError && e.type.code === BlockErrorCode.PARENT_UNKNOWN) { - network.events.emit(NetworkEvent.unknownBlockParent, { - blockInput: blockForImport, - peer: IDENTITY_PEER_ID, - }); - } - throw e; - }), + chain + .processBlock(blockForImport, {...opts, eagerPersistBlock: false}) + .catch((e) => { + if (e instanceof BlockError && e.type.code === BlockErrorCode.PARENT_UNKNOWN) { + network.events.emit(NetworkEvent.unknownBlockParent, { + blockInput: blockForImport, + peer: IDENTITY_PEER_ID, + }); + } + throw e; + }), ]; await promiseAllMaybeAsync(publishPromises); }; @@ -258,7 +260,7 @@ export function getBeaconBlockApi({ chain.logger.debug("Reconstructing signedBlockOrContents", {slot, blockRoot, source}); const contents = executionPayload - ? chain.producedContentsCache.get(toRootHex(executionPayload.blockHash)) ?? null + ? (chain.producedContentsCache.get(toRootHex(executionPayload.blockHash)) ?? null) : null; const signedBlockOrContents = reconstructFullBlockOrContents(signedBlindedBlock, {executionPayload, contents}); diff --git a/packages/beacon-node/src/api/impl/beacon/pool/index.ts b/packages/beacon-node/src/api/impl/beacon/pool/index.ts index e01b172f1e72..9343dd67a399 100644 --- a/packages/beacon-node/src/api/impl/beacon/pool/index.ts +++ b/packages/beacon-node/src/api/impl/beacon/pool/index.ts @@ -94,7 +94,6 @@ export function getBeaconPoolApi({ signedAttestations.map(async (attestation, i) => { try { const fork = chain.config.getForkName(chain.clock.currentSlot); - // eslint-disable-next-line @typescript-eslint/explicit-function-return-type const validateFn = () => validateApiAttestation(fork, chain, {attestation, serializedData: null}); const {slot, beaconBlockRoot} = attestation.data; // when a validator is configured with multiple beacon node urls, this attestation data may come from another beacon node diff --git a/packages/beacon-node/src/api/impl/beacon/state/utils.ts b/packages/beacon-node/src/api/impl/beacon/state/utils.ts index 5e9d3be01221..074fa7928d91 100644 --- a/packages/beacon-node/src/api/impl/beacon/state/utils.ts +++ b/packages/beacon-node/src/api/impl/beacon/state/utils.ts @@ -134,7 +134,7 @@ export function getStateValidatorIndex( if (id.startsWith("0x")) { try { id = fromHex(id); - } catch (e) { + } catch (_e) { return {valid: false, code: 400, reason: "Invalid pubkey hex encoding"}; } } else { diff --git a/packages/beacon-node/src/api/impl/config/constants.ts b/packages/beacon-node/src/api/impl/config/constants.ts index 14ecade15b2e..e951da35bdd2 100644 --- a/packages/beacon-node/src/api/impl/config/constants.ts +++ b/packages/beacon-node/src/api/impl/config/constants.ts @@ -41,8 +41,6 @@ import { FULL_EXIT_REQUEST_AMOUNT, } from "@lodestar/params"; -/* eslint-disable @typescript-eslint/naming-convention */ - /** * Hand-picked list of constants declared in consensus-spec .md files. * This list is asserted to be up-to-date with the test `test/e2e/api/impl/config.test.ts` diff --git a/packages/beacon-node/src/api/impl/events/index.ts b/packages/beacon-node/src/api/impl/events/index.ts index 25659743ddf3..55a49fe0c7e3 100644 --- a/packages/beacon-node/src/api/impl/events/index.ts +++ b/packages/beacon-node/src/api/impl/events/index.ts @@ -10,11 +10,10 @@ export function getEventsApi({ const onAbortFns: (() => void)[] = []; for (const topic of topics) { - // eslint-disable-next-line @typescript-eslint/no-explicit-any + // biome-ignore lint/suspicious/noExplicitAny: const handler = (data: any): void => { // TODO: What happens if this handler throws? Does it break the other chain.emitter listeners? - // eslint-disable-next-line @typescript-eslint/no-unsafe-assignment onEvent({type: topic, message: data}); }; diff --git a/packages/beacon-node/src/api/impl/node/utils.ts b/packages/beacon-node/src/api/impl/node/utils.ts index f26539eb0b36..27978a03ec39 100644 --- a/packages/beacon-node/src/api/impl/node/utils.ts +++ b/packages/beacon-node/src/api/impl/node/utils.ts @@ -44,6 +44,7 @@ function getPeerState(status: StreamStatus): routes.node.PeerState { case "closing": return "disconnecting"; case "closed": + return "disconnected"; default: return "disconnected"; } diff --git a/packages/beacon-node/src/api/impl/validator/index.ts b/packages/beacon-node/src/api/impl/validator/index.ts index 8a500125ad06..f6cbc4e98e98 100644 --- a/packages/beacon-node/src/api/impl/validator/index.ts +++ b/packages/beacon-node/src/api/impl/validator/index.ts @@ -1147,7 +1147,6 @@ export function getValidatorApi( signedAggregateAndProofs.map(async (signedAggregateAndProof, i) => { try { // TODO: Validate in batch - // eslint-disable-next-line @typescript-eslint/explicit-function-return-type const validateFn = () => validateApiAggregateAndProof(fork, chain, signedAggregateAndProof); const {slot, beaconBlockRoot} = signedAggregateAndProof.message.aggregate.data; // when a validator is configured with multiple beacon node urls, this attestation may come from another beacon node diff --git a/packages/beacon-node/src/api/rest/activeSockets.ts b/packages/beacon-node/src/api/rest/activeSockets.ts index 9f1b0f1a78a3..e6a9aa382333 100644 --- a/packages/beacon-node/src/api/rest/activeSockets.ts +++ b/packages/beacon-node/src/api/rest/activeSockets.ts @@ -93,7 +93,7 @@ export class HttpActiveSocketsTracker { await waitFor(() => this.sockets.size === 0, { timeout: GRACEFUL_TERMINATION_TIMEOUT, }); - } catch { + } catch (_e) { // Ignore timeout error } finally { for (const socket of this.sockets) { diff --git a/packages/beacon-node/src/api/rest/swaggerUI.ts b/packages/beacon-node/src/api/rest/swaggerUI.ts index c48f4e51860d..b4db3e43e6b1 100644 --- a/packages/beacon-node/src/api/rest/swaggerUI.ts +++ b/packages/beacon-node/src/api/rest/swaggerUI.ts @@ -41,15 +41,13 @@ async function getAsset(name: string): Promise { const path = await import("node:path"); const fs = await import("node:fs/promises"); const url = await import("node:url"); - // eslint-disable-next-line @typescript-eslint/naming-convention const __dirname = path.dirname(url.fileURLToPath(import.meta.url)); return await fs.readFile(path.join(__dirname, "../../../../../assets/", name)); - } catch (e) { + } catch (_e) { return undefined; } } -// eslint-disable-next-line @typescript-eslint/explicit-function-return-type export async function getFavicon() { const content = await getAsset("round-icon.ico"); if (!content) { @@ -67,7 +65,6 @@ export async function getFavicon() { ]; } -// eslint-disable-next-line @typescript-eslint/explicit-function-return-type export async function getLogo() { const content = await getAsset("lodestar_icon_text_white.png"); if (!content) { diff --git a/packages/beacon-node/src/chain/blocks/verifyBlocksDataAvailability.ts b/packages/beacon-node/src/chain/blocks/verifyBlocksDataAvailability.ts index 8393c91063de..accd3df31ab0 100644 --- a/packages/beacon-node/src/chain/blocks/verifyBlocksDataAvailability.ts +++ b/packages/beacon-node/src/chain/blocks/verifyBlocksDataAvailability.ts @@ -83,7 +83,6 @@ async function maybeValidateBlobs( return {dataAvailabilityStatus: DataAvailabilityStatus.Available, availableBlockInput: blockInput}; } - // eslint-disable-next-line no-fallthrough case BlockInputType.dataPromise: { // run full validation const {block} = blockInput; @@ -136,7 +135,7 @@ async function raceWithCutoff( try { await Promise.race([availabilityPromise, cutoffTimeout]); - } catch (e) { + } catch (_e) { // throw unavailable so that the unknownblock/blobs can be triggered to pull the block throw new BlockError(block, {code: BlockErrorCode.DATA_UNAVAILABLE}); } diff --git a/packages/beacon-node/src/chain/bls/multithread/index.ts b/packages/beacon-node/src/chain/bls/multithread/index.ts index 3725fa4bcb1c..ce9b726c7693 100644 --- a/packages/beacon-node/src/chain/bls/multithread/index.ts +++ b/packages/beacon-node/src/chain/bls/multithread/index.ts @@ -3,9 +3,8 @@ import path from "node:path"; import {spawn, Worker} from "@chainsafe/threads"; // `threads` library creates self global variable which breaks `timeout-abort-controller` https://github.com/jacobheun/timeout-abort-controller/issues/9 // Don't add an eslint disable here as a reminder that this has to be fixed eventually -// eslint-disable-next-line // @ts-ignore -// eslint-disable-next-line +// biome-ignore lint/suspicious/noGlobalAssign: self = undefined; import {PublicKey} from "@chainsafe/blst"; import {Logger} from "@lodestar/utils"; diff --git a/packages/beacon-node/src/chain/bls/multithread/poolSize.ts b/packages/beacon-node/src/chain/bls/multithread/poolSize.ts index 9397f97849cd..2c683e191fd6 100644 --- a/packages/beacon-node/src/chain/bls/multithread/poolSize.ts +++ b/packages/beacon-node/src/chain/bls/multithread/poolSize.ts @@ -6,7 +6,7 @@ try { } else { defaultPoolSize = (await import("node:os")).availableParallelism(); } -} catch (e) { +} catch (_e) { defaultPoolSize = 8; } diff --git a/packages/beacon-node/src/chain/bls/multithread/worker.ts b/packages/beacon-node/src/chain/bls/multithread/worker.ts index 9073920df19c..d2794db2e6bf 100644 --- a/packages/beacon-node/src/chain/bls/multithread/worker.ts +++ b/packages/beacon-node/src/chain/bls/multithread/worker.ts @@ -75,7 +75,7 @@ function verifyManySignatureSets(workReqArr: BlsWorkReq[]): BlsWorkResult { // Re-verify all sigs nonBatchableSets.push(...batchableChunk); } - } catch (e) { + } catch (_e) { // TODO: Ignore this error expecting that the same error will happen when re-verifying the set individually // It's not ideal but '@chainsafe/blst' may throw errors on some conditions batchRetries++; diff --git a/packages/beacon-node/src/chain/emitter.ts b/packages/beacon-node/src/chain/emitter.ts index 9c3ea4a9bf52..10b6455e48f5 100644 --- a/packages/beacon-node/src/chain/emitter.ts +++ b/packages/beacon-node/src/chain/emitter.ts @@ -1,4 +1,4 @@ -import {EventEmitter} from "events"; +import {EventEmitter} from "node:events"; import {StrictEventEmitter} from "strict-event-emitter-types"; import {routes} from "@lodestar/api"; diff --git a/packages/beacon-node/src/chain/initState.ts b/packages/beacon-node/src/chain/initState.ts index 311806fb1be7..2883cdc8388e 100644 --- a/packages/beacon-node/src/chain/initState.ts +++ b/packages/beacon-node/src/chain/initState.ts @@ -132,7 +132,7 @@ export async function initStateFromEth1({ * Restore the latest beacon state from db */ export async function initStateFromDb( - config: ChainForkConfig, + _config: ChainForkConfig, db: IBeaconDb, logger: Logger ): Promise { diff --git a/packages/beacon-node/src/chain/produceBlock/validateBlobsAndKzgCommitments.ts b/packages/beacon-node/src/chain/produceBlock/validateBlobsAndKzgCommitments.ts index ba086ecafc7e..06f17c92156a 100644 --- a/packages/beacon-node/src/chain/produceBlock/validateBlobsAndKzgCommitments.ts +++ b/packages/beacon-node/src/chain/produceBlock/validateBlobsAndKzgCommitments.ts @@ -5,7 +5,8 @@ import {BlobsBundle} from "../../execution/index.js"; * Optionally sanity-check that the KZG commitments match the versioned hashes in the transactions * https://github.com/ethereum/consensus-specs/blob/11a037fd9227e29ee809c9397b09f8cc3383a8c0/specs/eip4844/validator.md#blob-kzg-commitments */ -export function validateBlobsAndKzgCommitments(payload: ExecutionPayload, blobsBundle: BlobsBundle): void { + +export function validateBlobsAndKzgCommitments(_payload: ExecutionPayload, blobsBundle: BlobsBundle): void { // sanity-check that the KZG commitments match the blobs (as produced by the execution engine) if (blobsBundle.blobs.length !== blobsBundle.commitments.length) { throw Error( diff --git a/packages/beacon-node/src/chain/rewards/attestationsRewards.ts b/packages/beacon-node/src/chain/rewards/attestationsRewards.ts index 70fb27de239a..0c74b8610f93 100644 --- a/packages/beacon-node/src/chain/rewards/attestationsRewards.ts +++ b/packages/beacon-node/src/chain/rewards/attestationsRewards.ts @@ -36,9 +36,9 @@ const defaultAttestationsReward = {head: 0, target: 0, source: 0, inclusionDelay const defaultAttestationsPenalty = {target: 0, source: 0}; export async function computeAttestationsRewards( - epoch: Epoch, + _epoch: Epoch, state: CachedBeaconStateAllForks, - config: BeaconConfig, + _config: BeaconConfig, validatorIds?: (ValidatorIndex | string)[] ): Promise { const fork = state.config.getForkName(state.slot); diff --git a/packages/beacon-node/src/chain/validation/aggregateAndProof.ts b/packages/beacon-node/src/chain/validation/aggregateAndProof.ts index 39a3700aacf9..de5f40372c9f 100644 --- a/packages/beacon-node/src/chain/validation/aggregateAndProof.ts +++ b/packages/beacon-node/src/chain/validation/aggregateAndProof.ts @@ -6,7 +6,7 @@ import { createAggregateSignatureSetFromComponents, } from "@lodestar/state-transition"; import {toRootHex} from "@lodestar/utils"; -import {IBeaconChain} from ".."; +import {IBeaconChain} from "../index.js"; import {AttestationError, AttestationErrorCode, GossipAction} from "../errors/index.js"; import {RegenCaller} from "../regen/index.js"; import {getSelectionProofSignatureSet, getAggregateAndProofSignatureSet} from "./signatureSets/index.js"; diff --git a/packages/beacon-node/src/chain/validation/attesterSlashing.ts b/packages/beacon-node/src/chain/validation/attesterSlashing.ts index 11a499c9bb53..5da146a67a86 100644 --- a/packages/beacon-node/src/chain/validation/attesterSlashing.ts +++ b/packages/beacon-node/src/chain/validation/attesterSlashing.ts @@ -4,7 +4,7 @@ import { assertValidAttesterSlashing, getAttesterSlashingSignatureSets, } from "@lodestar/state-transition"; -import {IBeaconChain} from ".."; +import {IBeaconChain} from "../index.js"; import {AttesterSlashingError, AttesterSlashingErrorCode, GossipAction} from "../errors/index.js"; export async function validateApiAttesterSlashing( diff --git a/packages/beacon-node/src/chain/validation/blsToExecutionChange.ts b/packages/beacon-node/src/chain/validation/blsToExecutionChange.ts index e5ad56daeb5c..fff399aada50 100644 --- a/packages/beacon-node/src/chain/validation/blsToExecutionChange.ts +++ b/packages/beacon-node/src/chain/validation/blsToExecutionChange.ts @@ -4,7 +4,7 @@ import { getBlsToExecutionChangeSignatureSet, CachedBeaconStateCapella, } from "@lodestar/state-transition"; -import {IBeaconChain} from ".."; +import {IBeaconChain} from "../index.js"; import {BlsToExecutionChangeError, BlsToExecutionChangeErrorCode, GossipAction} from "../errors/index.js"; export async function validateApiBlsToExecutionChange( diff --git a/packages/beacon-node/src/chain/validation/proposerSlashing.ts b/packages/beacon-node/src/chain/validation/proposerSlashing.ts index 7281302aae8d..48fe6db326c9 100644 --- a/packages/beacon-node/src/chain/validation/proposerSlashing.ts +++ b/packages/beacon-node/src/chain/validation/proposerSlashing.ts @@ -1,6 +1,6 @@ import {phase0} from "@lodestar/types"; import {assertValidProposerSlashing, getProposerSlashingSignatureSets} from "@lodestar/state-transition"; -import {IBeaconChain} from ".."; +import {IBeaconChain} from "../index.js"; import {ProposerSlashingError, ProposerSlashingErrorCode, GossipAction} from "../errors/index.js"; export async function validateApiProposerSlashing( diff --git a/packages/beacon-node/src/chain/validation/voluntaryExit.ts b/packages/beacon-node/src/chain/validation/voluntaryExit.ts index 3957b51180d9..2b38b161423e 100644 --- a/packages/beacon-node/src/chain/validation/voluntaryExit.ts +++ b/packages/beacon-node/src/chain/validation/voluntaryExit.ts @@ -1,6 +1,6 @@ import {phase0} from "@lodestar/types"; import {isValidVoluntaryExit, getVoluntaryExitSignatureSet} from "@lodestar/state-transition"; -import {IBeaconChain} from ".."; +import {IBeaconChain} from "../index.js"; import {VoluntaryExitError, VoluntaryExitErrorCode, GossipAction} from "../errors/index.js"; import {RegenCaller} from "../regen/index.js"; diff --git a/packages/beacon-node/src/db/repositories/backfilledRanges.ts b/packages/beacon-node/src/db/repositories/backfilledRanges.ts index 309909b18cb8..f86c20288099 100644 --- a/packages/beacon-node/src/db/repositories/backfilledRanges.ts +++ b/packages/beacon-node/src/db/repositories/backfilledRanges.ts @@ -23,8 +23,7 @@ export class BackfilledRanges extends Repository { return bytesToInt(super.decodeKey(data) as unknown as Uint8Array, "be"); } - // eslint-disable-next-line @typescript-eslint/no-unused-vars - getId(value: Slot): number { + getId(_value: Slot): number { throw new Error("Cannot get the db key from slot"); } } diff --git a/packages/beacon-node/src/db/repositories/checkpointState.ts b/packages/beacon-node/src/db/repositories/checkpointState.ts index 8848f4d26d3a..cb111a497f87 100644 --- a/packages/beacon-node/src/db/repositories/checkpointState.ts +++ b/packages/beacon-node/src/db/repositories/checkpointState.ts @@ -11,7 +11,6 @@ import {Bucket, getBucketNameByValue} from "../buckets.js"; export class CheckpointStateRepository extends Repository { constructor(config: ChainForkConfig, db: Db) { // Pick some type but won't be used. Casted to any because no type can match `BeaconStateAllForks` - // eslint-disable-next-line @typescript-eslint/no-unsafe-assignment, @typescript-eslint/no-explicit-any const type = ssz.phase0.BeaconState as any; const bucket = Bucket.allForks_checkpointState; super(config, db, bucket, type, getBucketNameByValue(bucket)); diff --git a/packages/beacon-node/src/db/repositories/depositDataRoot.ts b/packages/beacon-node/src/db/repositories/depositDataRoot.ts index fa8983f0e5fa..9b872c91bce4 100644 --- a/packages/beacon-node/src/db/repositories/depositDataRoot.ts +++ b/packages/beacon-node/src/db/repositories/depositDataRoot.ts @@ -21,8 +21,7 @@ export class DepositDataRootRepository extends Repository { } // depositDataRoots stored by depositData index - // eslint-disable-next-line @typescript-eslint/no-unused-vars - getId(value: Root): number { + getId(_value: Root): number { throw new Error("Unable to create depositIndex from root"); } diff --git a/packages/beacon-node/src/db/repositories/eth1Data.ts b/packages/beacon-node/src/db/repositories/eth1Data.ts index e0a6c14e4022..f87199a0b80e 100644 --- a/packages/beacon-node/src/db/repositories/eth1Data.ts +++ b/packages/beacon-node/src/db/repositories/eth1Data.ts @@ -14,8 +14,7 @@ export class Eth1DataRepository extends Repository { constructor(config: ChainForkConfig, db: Db) { // Pick some type but won't be used. Casted to any because no type can match `BeaconStateAllForks` - // eslint-disable-next-line @typescript-eslint/no-unsafe-assignment, @typescript-eslint/no-explicit-any + // biome-ignore lint/suspicious/noExplicitAny: const type = ssz.phase0.BeaconState as any; const bucket = Bucket.allForks_stateArchive; super(config, db, bucket, type, getBucketNameByValue(bucket)); diff --git a/packages/beacon-node/src/db/single/preGenesisStateLastProcessedBlock.ts b/packages/beacon-node/src/db/single/preGenesisStateLastProcessedBlock.ts index c958b9de2f0a..37dcb069acc9 100644 --- a/packages/beacon-node/src/db/single/preGenesisStateLastProcessedBlock.ts +++ b/packages/beacon-node/src/db/single/preGenesisStateLastProcessedBlock.ts @@ -10,7 +10,7 @@ export class PreGenesisStateLastProcessedBlock { private readonly db: Db; private readonly key: Uint8Array; - constructor(config: ChainForkConfig, db: Db) { + constructor(_config: ChainForkConfig, db: Db) { this.db = db; this.type = ssz.UintNum64; this.bucket = Bucket.phase0_preGenesisStateLastProcessedBlock; diff --git a/packages/beacon-node/src/eth1/eth1MergeBlockTracker.ts b/packages/beacon-node/src/eth1/eth1MergeBlockTracker.ts index 9ba4a09a5549..f2ce0a8bb2f5 100644 --- a/packages/beacon-node/src/eth1/eth1MergeBlockTracker.ts +++ b/packages/beacon-node/src/eth1/eth1MergeBlockTracker.ts @@ -167,7 +167,6 @@ export class Eth1MergeBlockTracker { this.status = {code: StatusCode.SEARCHING}; this.logger.info("Starting search for terminal POW block", { - // eslint-disable-next-line @typescript-eslint/naming-convention TERMINAL_TOTAL_DIFFICULTY: this.config.TERMINAL_TOTAL_DIFFICULTY, }); @@ -268,7 +267,6 @@ export class Eth1MergeBlockTracker { // this class can start eagerly looking for the merge block when not necessary, startPollingMergeBlock() should // only be called when there is certainty that a mergeBlock search is necessary. - // eslint-disable-next-line no-constant-condition while (true) { if (block.totalDifficulty < this.config.TERMINAL_TOTAL_DIFFICULTY) { // TTD not reached yet diff --git a/packages/beacon-node/src/eth1/provider/eth1Provider.ts b/packages/beacon-node/src/eth1/provider/eth1Provider.ts index c86991eb7d15..d284700ddb1d 100644 --- a/packages/beacon-node/src/eth1/provider/eth1Provider.ts +++ b/packages/beacon-node/src/eth1/provider/eth1Provider.ts @@ -21,8 +21,6 @@ import { } from "./jsonRpcHttpClient.js"; import {isJsonRpcTruncatedError, quantityToNum, numToQuantity, dataToBytes} from "./utils.js"; -/* eslint-disable @typescript-eslint/naming-convention */ - /** * Binds return types to Ethereum JSON RPC methods */ diff --git a/packages/beacon-node/src/eth1/provider/jsonRpcHttpClient.ts b/packages/beacon-node/src/eth1/provider/jsonRpcHttpClient.ts index cbe70ecb7e18..e1a2a001c278 100644 --- a/packages/beacon-node/src/eth1/provider/jsonRpcHttpClient.ts +++ b/packages/beacon-node/src/eth1/provider/jsonRpcHttpClient.ts @@ -1,4 +1,4 @@ -import {EventEmitter} from "events"; +import {EventEmitter} from "node:events"; import {StrictEventEmitter} from "strict-event-emitter-types"; import {fetch} from "@lodestar/api"; import {ErrorAborted, Gauge, Histogram, TimeoutError, isValidHttpUrl, retry} from "@lodestar/utils"; diff --git a/packages/beacon-node/src/eth1/provider/jwt.ts b/packages/beacon-node/src/eth1/provider/jwt.ts index da1fc1827cdd..1e267120957f 100644 --- a/packages/beacon-node/src/eth1/provider/jwt.ts +++ b/packages/beacon-node/src/eth1/provider/jwt.ts @@ -2,7 +2,6 @@ import type {TAlgorithm} from "jwt-simple"; // TODO: fix jwt-simple types import jwt from "jwt-simple"; -// eslint-disable-next-line import/no-named-as-default-member const {encode, decode} = jwt; /** diff --git a/packages/beacon-node/src/execution/builder/index.ts b/packages/beacon-node/src/execution/builder/index.ts index 2f584ad7dadd..fff66a3e8bc5 100644 --- a/packages/beacon-node/src/execution/builder/index.ts +++ b/packages/beacon-node/src/execution/builder/index.ts @@ -18,6 +18,7 @@ export function initializeExecutionBuilder( ): IExecutionBuilder { switch (opts.mode) { case "http": + return new ExecutionBuilderHttp(opts, config, metrics, logger); default: return new ExecutionBuilderHttp(opts, config, metrics, logger); } diff --git a/packages/beacon-node/src/execution/engine/http.ts b/packages/beacon-node/src/execution/engine/http.ts index b42424b28998..a8206a89250d 100644 --- a/packages/beacon-node/src/execution/engine/http.ts +++ b/packages/beacon-node/src/execution/engine/http.ts @@ -437,7 +437,7 @@ export class ExecutionEngineHttp implements IExecutionEngine { this.payloadIdCache.prune(); } - async getPayloadBodiesByHash(fork: ForkName, blockHashes: RootHex[]): Promise<(ExecutionPayloadBody | null)[]> { + async getPayloadBodiesByHash(_fork: ForkName, blockHashes: RootHex[]): Promise<(ExecutionPayloadBody | null)[]> { const method = "engine_getPayloadBodiesByHashV1"; assertReqSizeLimit(blockHashes.length, 32); const response = await this.rpc.fetchWithRetries< @@ -448,7 +448,7 @@ export class ExecutionEngineHttp implements IExecutionEngine { } async getPayloadBodiesByRange( - fork: ForkName, + _fork: ForkName, startBlockNumber: number, blockCount: number ): Promise<(ExecutionPayloadBody | null)[]> { diff --git a/packages/beacon-node/src/execution/engine/index.ts b/packages/beacon-node/src/execution/engine/index.ts index a8b878502aff..dd2de2017c22 100644 --- a/packages/beacon-node/src/execution/engine/index.ts +++ b/packages/beacon-node/src/execution/engine/index.ts @@ -55,6 +55,8 @@ export function initializeExecutionEngine( return getExecutionEngineFromBackend(new ExecutionEngineMockBackend(opts), modules); case "http": + return getExecutionEngineHttp(opts, modules); + default: return getExecutionEngineHttp(opts, modules); } diff --git a/packages/beacon-node/src/execution/engine/mock.ts b/packages/beacon-node/src/execution/engine/mock.ts index 4cff2a8d00f4..bc3a130e604e 100644 --- a/packages/beacon-node/src/execution/engine/mock.ts +++ b/packages/beacon-node/src/execution/engine/mock.ts @@ -85,7 +85,6 @@ export class ExecutionEngineMockBackend implements JsonRpcBackend { }); this.handlers = { - /* eslint-disable @typescript-eslint/naming-convention */ engine_newPayloadV1: this.notifyNewPayload.bind(this), engine_newPayloadV2: this.notifyNewPayload.bind(this), engine_newPayloadV3: this.notifyNewPayload.bind(this), diff --git a/packages/beacon-node/src/execution/engine/types.ts b/packages/beacon-node/src/execution/engine/types.ts index 32fe4cb79d3d..9b4f5e5c83e6 100644 --- a/packages/beacon-node/src/execution/engine/types.ts +++ b/packages/beacon-node/src/execution/engine/types.ts @@ -19,8 +19,6 @@ import { import {ExecutionPayloadStatus, BlobsBundle, PayloadAttributes, VersionedHashes} from "./interface.js"; import {WithdrawalV1} from "./payloadIdCache.js"; -/* eslint-disable @typescript-eslint/naming-convention */ - export type EngineApiRpcParamTypes = { /** * 1. Object - Instance of ExecutionPayload diff --git a/packages/beacon-node/src/execution/engine/utils.ts b/packages/beacon-node/src/execution/engine/utils.ts index b56f62bf602b..4d84eda52c44 100644 --- a/packages/beacon-node/src/execution/engine/utils.ts +++ b/packages/beacon-node/src/execution/engine/utils.ts @@ -12,7 +12,7 @@ import {isQueueErrorAborted} from "../../util/queue/errors.js"; import {ExecutionPayloadStatus, ExecutionEngineState} from "./interface.js"; export type JsonRpcBackend = { - // eslint-disable-next-line @typescript-eslint/no-explicit-any + // biome-ignore lint/suspicious/noExplicitAny: readonly handlers: Record any>; }; @@ -27,8 +27,7 @@ export class ExecutionEngineMockJsonRpcClient implements IJsonRpcHttpClient { if (handler === undefined) { throw Error(`Unknown method ${payload.method}`); } - - // eslint-disable-next-line @typescript-eslint/no-explicit-any + // biome-ignore lint/suspicious/noExplicitAny: return handler(...(payload.params as any[])) as R; }, payload); } diff --git a/packages/beacon-node/src/metrics/metrics/beacon.ts b/packages/beacon-node/src/metrics/metrics/beacon.ts index 949999dbb1f4..6e86328ee561 100644 --- a/packages/beacon-node/src/metrics/metrics/beacon.ts +++ b/packages/beacon-node/src/metrics/metrics/beacon.ts @@ -11,7 +11,6 @@ export type BeaconMetrics = ReturnType; * https://github.com/ethereum/beacon-metrics/ and * https://hackmd.io/D5FmoeFZScim_squBFl8oA */ -// eslint-disable-next-line @typescript-eslint/explicit-function-return-type export function createBeaconMetrics(register: RegistryMetricCreator) { return { // From https://github.com/ethereum/beacon-metrics/blob/master/metrics.md diff --git a/packages/beacon-node/src/metrics/metrics/lodestar.ts b/packages/beacon-node/src/metrics/metrics/lodestar.ts index bac740b7ee04..f15e195faa20 100644 --- a/packages/beacon-node/src/metrics/metrics/lodestar.ts +++ b/packages/beacon-node/src/metrics/metrics/lodestar.ts @@ -25,7 +25,6 @@ export type LodestarMetrics = ReturnType; /** * Extra Lodestar custom metrics */ -// eslint-disable-next-line @typescript-eslint/explicit-function-return-type export function createLodestarMetrics( register: RegistryMetricCreator, metadata?: LodestarMetadata, diff --git a/packages/beacon-node/src/monitoring/service.ts b/packages/beacon-node/src/monitoring/service.ts index 9581c5f11c92..bd2388738d1f 100644 --- a/packages/beacon-node/src/monitoring/service.ts +++ b/packages/beacon-node/src/monitoring/service.ts @@ -229,7 +229,7 @@ export class MonitoringService { } return url; - } catch { + } catch (_e) { throw new Error(`Monitoring endpoint must be a valid URL: ${endpoint}`); } } diff --git a/packages/beacon-node/src/monitoring/system.ts b/packages/beacon-node/src/monitoring/system.ts index a1a79b1bd277..83507443be01 100644 --- a/packages/beacon-node/src/monitoring/system.ts +++ b/packages/beacon-node/src/monitoring/system.ts @@ -3,7 +3,6 @@ import os from "node:os"; import path from "node:path"; // We want to keep `system` export as it's more readable and easier to understand -// eslint-disable-next-line import/no-named-as-default import system from "systeminformation"; import {Logger} from "@lodestar/utils"; diff --git a/packages/beacon-node/src/network/core/metrics.ts b/packages/beacon-node/src/network/core/metrics.ts index c267ec069d88..7d0ef47d84af 100644 --- a/packages/beacon-node/src/network/core/metrics.ts +++ b/packages/beacon-node/src/network/core/metrics.ts @@ -5,7 +5,6 @@ import {SubnetSource} from "../subnets/attnetsService.js"; export type NetworkCoreMetrics = ReturnType; -// eslint-disable-next-line @typescript-eslint/explicit-function-return-type export function createNetworkCoreMetrics(register: RegistryMetricCreator) { return { register, @@ -254,7 +253,6 @@ export function createNetworkCoreMetrics(register: RegistryMetricCreator) { export type NetworkCoreWorkerMetrics = ReturnType; -// eslint-disable-next-line @typescript-eslint/explicit-function-return-type export function getNetworkCoreWorkerMetrics(register: RegistryMetricCreator) { return { reqRespBridgeRespCallerPending: register.gauge({ diff --git a/packages/beacon-node/src/network/core/networkCore.ts b/packages/beacon-node/src/network/core/networkCore.ts index 83ef4c4fb063..1a497925e4fd 100644 --- a/packages/beacon-node/src/network/core/networkCore.ts +++ b/packages/beacon-node/src/network/core/networkCore.ts @@ -149,7 +149,7 @@ export class NetworkCore implements INetworkCore { // Bind discv5's ENR to local metadata // resolve circular dependency by setting `discv5` variable after the peer manager is instantiated - // eslint-disable-next-line prefer-const + // biome-ignore lint/style/useConst: let discv5: Discv5Worker | undefined; const onMetadataSetValue = function onMetadataSetValue(key: string, value: Uint8Array): void { discv5?.setEnrValue(key, value).catch((e) => logger.error("error on setEnrValue", {key}, e)); diff --git a/packages/beacon-node/src/network/core/networkCoreWorker.ts b/packages/beacon-node/src/network/core/networkCoreWorker.ts index 1df348335582..5e4b057402d8 100644 --- a/packages/beacon-node/src/network/core/networkCoreWorker.ts +++ b/packages/beacon-node/src/network/core/networkCoreWorker.ts @@ -28,7 +28,6 @@ import { // Cloned data from instantiation const workerData = worker.workerData as NetworkWorkerData; const parentPort = worker.parentPort; -// eslint-disable-next-line @typescript-eslint/strict-boolean-expressions if (!workerData) throw Error("workerData must be defined"); if (!parentPort) throw Error("parentPort must be defined"); diff --git a/packages/beacon-node/src/network/core/networkCoreWorkerHandler.ts b/packages/beacon-node/src/network/core/networkCoreWorkerHandler.ts index 19cca27eaaac..bd66a21e726b 100644 --- a/packages/beacon-node/src/network/core/networkCoreWorkerHandler.ts +++ b/packages/beacon-node/src/network/core/networkCoreWorkerHandler.ts @@ -136,7 +136,7 @@ export class WorkerNetworkCore implements INetworkCore { resourceLimits: {maxYoungGenerationSizeMb: opts.maxYoungGenerationSizeMb}, } as ConstructorParameters[1]); - // eslint-disable-next-line @typescript-eslint/no-explicit-any + // biome-ignore lint/suspicious/noExplicitAny: const networkThreadApi = (await spawn(worker, { // A Lodestar Node may do very expensive task at start blocking the event loop and causing // the initialization to timeout. The number below is big enough to almost disable the timeout diff --git a/packages/beacon-node/src/network/core/types.ts b/packages/beacon-node/src/network/core/types.ts index 41b7f669eaac..4eeaf96e1903 100644 --- a/packages/beacon-node/src/network/core/types.ts +++ b/packages/beacon-node/src/network/core/types.ts @@ -90,7 +90,7 @@ export type NetworkWorkerData = { */ export type NetworkWorkerApi = INetworkCorePublic & { // To satisfy the constraint of `ModuleThread` type - // eslint-disable-next-line @typescript-eslint/no-explicit-any + // biome-ignore lint/suspicious/noExplicitAny: [string: string]: (...args: any[]) => Promise | any; // Async method through worker boundary reportPeer(peer: PeerIdStr, action: PeerAction, actionName: string): Promise; diff --git a/packages/beacon-node/src/network/discv5/index.ts b/packages/beacon-node/src/network/discv5/index.ts index b2136658dfe7..745b3171c38d 100644 --- a/packages/beacon-node/src/network/discv5/index.ts +++ b/packages/beacon-node/src/network/discv5/index.ts @@ -1,4 +1,4 @@ -import EventEmitter from "events"; +import EventEmitter from "node:events"; import {PeerId, Secp256k1PeerId} from "@libp2p/interface"; import {StrictEventEmitter} from "strict-event-emitter-types"; import {exportToProtobuf} from "@libp2p/peer-id-factory"; diff --git a/packages/beacon-node/src/network/discv5/worker.ts b/packages/beacon-node/src/network/discv5/worker.ts index be8fdc4af601..8e96751d5fe7 100644 --- a/packages/beacon-node/src/network/discv5/worker.ts +++ b/packages/beacon-node/src/network/discv5/worker.ts @@ -22,7 +22,6 @@ import {enrRelevance, ENRRelevance} from "./utils.js"; // Cloned data from instatiation const workerData = worker.workerData as Discv5WorkerData; -// eslint-disable-next-line @typescript-eslint/strict-boolean-expressions if (!workerData) throw Error("workerData must be defined"); const logger = getNodeLogger(workerData.loggerOpts); diff --git a/packages/beacon-node/src/network/events.ts b/packages/beacon-node/src/network/events.ts index 45759de61073..a95b52394163 100644 --- a/packages/beacon-node/src/network/events.ts +++ b/packages/beacon-node/src/network/events.ts @@ -1,4 +1,4 @@ -import {EventEmitter} from "events"; +import {EventEmitter} from "node:events"; import {PeerId, TopicValidatorResult} from "@libp2p/interface"; import {phase0, RootHex} from "@lodestar/types"; import {BlockInput, NullBlockInput} from "../chain/blocks/types.js"; diff --git a/packages/beacon-node/src/network/forks.ts b/packages/beacon-node/src/network/forks.ts index 47575cf6d9c6..1c613f4cee94 100644 --- a/packages/beacon-node/src/network/forks.ts +++ b/packages/beacon-node/src/network/forks.ts @@ -86,7 +86,6 @@ export function getCurrentAndNextFork( } return { - // eslint-disable-next-line @typescript-eslint/strict-boolean-expressions currentFork: forks[currentForkIdx] || forks[0], nextFork: hasNextFork ? forks[nextForkIdx] : undefined, }; diff --git a/packages/beacon-node/src/network/gossip/gossipsub.ts b/packages/beacon-node/src/network/gossip/gossipsub.ts index e6977abe8ce6..1fc326ba1e58 100644 --- a/packages/beacon-node/src/network/gossip/gossipsub.ts +++ b/packages/beacon-node/src/network/gossip/gossipsub.ts @@ -26,7 +26,6 @@ import { GOSSIP_D_LOW, } from "./scoringParameters.js"; -/* eslint-disable @typescript-eslint/naming-convention */ /** As specified in https://github.com/ethereum/consensus-specs/blob/v1.1.10/specs/phase0/p2p-interface.md */ const GOSSIPSUB_HEARTBEAT_INTERVAL = 0.7 * 1000; diff --git a/packages/beacon-node/src/network/gossip/interface.ts b/packages/beacon-node/src/network/gossip/interface.ts index af5e3888d04f..ff1bfa088c17 100644 --- a/packages/beacon-node/src/network/gossip/interface.ts +++ b/packages/beacon-node/src/network/gossip/interface.ts @@ -203,7 +203,7 @@ export type BatchGossipHandler = ( gossipHandlerParams: GossipHandlerParamGeneric[] ) => Promise<(null | GossipActionError)[]>; -// eslint-disable-next-line @typescript-eslint/no-explicit-any +// biome-ignore lint/suspicious/noExplicitAny: export type ResolvedType Promise> = F extends (...args: any) => Promise ? T : never; diff --git a/packages/beacon-node/src/network/gossip/metrics.ts b/packages/beacon-node/src/network/gossip/metrics.ts index c2b5d0b32338..5ca5d22154c2 100644 --- a/packages/beacon-node/src/network/gossip/metrics.ts +++ b/packages/beacon-node/src/network/gossip/metrics.ts @@ -4,7 +4,6 @@ import {GossipType} from "./interface.js"; export type Eth2GossipsubMetrics = ReturnType; -// eslint-disable-next-line @typescript-eslint/explicit-function-return-type export function createEth2GossipsubMetrics(register: RegistryMetricCreator) { return { gossipPeer: { diff --git a/packages/beacon-node/src/network/gossip/scoringParameters.ts b/packages/beacon-node/src/network/gossip/scoringParameters.ts index 7e1be07f2ca7..3ba32614afeb 100644 --- a/packages/beacon-node/src/network/gossip/scoringParameters.ts +++ b/packages/beacon-node/src/network/gossip/scoringParameters.ts @@ -12,8 +12,6 @@ import {Eth2Context, Eth2GossipsubModules} from "./gossipsub.js"; import {GossipType} from "./interface.js"; import {stringifyGossipTopic} from "./topic.js"; -/* eslint-disable @typescript-eslint/naming-convention */ - export const GOSSIP_D = 8; export const GOSSIP_D_LOW = 6; export const GOSSIP_D_HIGH = 12; diff --git a/packages/beacon-node/src/network/gossip/topic.ts b/packages/beacon-node/src/network/gossip/topic.ts index b7c7425584c5..c44e29274bca 100644 --- a/packages/beacon-node/src/network/gossip/topic.ts +++ b/packages/beacon-node/src/network/gossip/topic.ts @@ -78,7 +78,6 @@ function stringifyGossipTopicType(topic: GossipTopic): string { } } -// eslint-disable-next-line @typescript-eslint/explicit-function-return-type export function getGossipSSZType(topic: GossipTopic) { switch (topic.type) { case GossipType.beacon_block: @@ -120,7 +119,7 @@ export function sszDeserialize(topic: T, serializedData: const sszType = getGossipSSZType(topic); try { return sszType.deserialize(serializedData) as SSZTypeOfGossipTopic; - } catch (e) { + } catch (_e) { throw new GossipActionError(GossipAction.REJECT, {code: GossipErrorCode.INVALID_SERIALIZED_BYTES_ERROR_CODE}); } } @@ -131,7 +130,7 @@ export function sszDeserialize(topic: T, serializedData: export function sszDeserializeAttestation(fork: ForkName, serializedData: Uint8Array): Attestation { try { return sszTypesFor(fork).Attestation.deserialize(serializedData); - } catch (e) { + } catch (_e) { throw new GossipActionError(GossipAction.REJECT, {code: GossipErrorCode.INVALID_SERIALIZED_BYTES_ERROR_CODE}); } } diff --git a/packages/beacon-node/src/network/peers/datastore.ts b/packages/beacon-node/src/network/peers/datastore.ts index 762e99dc45b4..88a7a6f5f2d6 100644 --- a/packages/beacon-node/src/network/peers/datastore.ts +++ b/packages/beacon-node/src/network/peers/datastore.ts @@ -147,8 +147,7 @@ export class Eth2PeerDataStore extends BaseDatastore { if (this._dirtyItems.size >= this._threshold) { try { await this._commitData(); - // eslint-disable-next-line no-empty - } catch (e) {} + } catch (_e) {} } } diff --git a/packages/beacon-node/src/network/peers/discover.ts b/packages/beacon-node/src/network/peers/discover.ts index 79603f780e3d..9e06a39b4fb4 100644 --- a/packages/beacon-node/src/network/peers/discover.ts +++ b/packages/beacon-node/src/network/peers/discover.ts @@ -304,7 +304,6 @@ export class PeerDiscovery { const {id, multiaddrs} = evt.detail; // libp2p may send us PeerInfos without multiaddrs https://github.com/libp2p/js-libp2p/issues/1873 - // eslint-disable-next-line @typescript-eslint/strict-boolean-expressions if (!multiaddrs || multiaddrs.length === 0) { this.metrics?.discovery.discoveredStatus.inc({status: DiscoveredPeerStatus.no_multiaddrs}); return; diff --git a/packages/beacon-node/src/network/peers/peerManager.ts b/packages/beacon-node/src/network/peers/peerManager.ts index 43fbee723f0e..3971e2147707 100644 --- a/packages/beacon-node/src/network/peers/peerManager.ts +++ b/packages/beacon-node/src/network/peers/peerManager.ts @@ -383,7 +383,7 @@ export class PeerManager { private async requestMetadata(peer: PeerId): Promise { try { this.onMetadata(peer, await this.reqResp.sendMetadata(peer)); - } catch (e) { + } catch (_e) { // TODO: Downvote peer here or in the reqResp layer } } @@ -395,7 +395,7 @@ export class PeerManager { // If peer replies a PING request also update lastReceivedMsg const peerData = this.connectedPeers.get(peer.toString()); if (peerData) peerData.lastReceivedMsgUnixTsMs = Date.now(); - } catch (e) { + } catch (_e) { // TODO: Downvote peer here or in the reqResp layer } } @@ -403,7 +403,7 @@ export class PeerManager { private async requestStatus(peer: PeerId, localStatus: phase0.Status): Promise { try { this.onStatus(peer, await this.reqResp.sendStatus(peer, localStatus)); - } catch (e) { + } catch (_e) { // TODO: Failed to get peer latest status: downvote but don't disconnect } } @@ -423,7 +423,7 @@ export class PeerManager { * NOTE: Discovery should only add a new query if one isn't already queued. */ private heartbeat(): void { - // timer is safe without a try {} catch {}, in case of error the metric won't register and timer is GC'ed + // timer is safe without a try {} catch (_e) {}, in case of error the metric won't register and timer is GC'ed const timer = this.metrics?.peerManager.heartbeatDuration.startTimer(); const connectedPeers = this.getConnectedPeerIds(); diff --git a/packages/beacon-node/src/network/processor/gossipHandlers.ts b/packages/beacon-node/src/network/processor/gossipHandlers.ts index 90c131a943ed..dab3af0df8ba 100644 --- a/packages/beacon-node/src/network/processor/gossipHandlers.ts +++ b/packages/beacon-node/src/network/processor/gossipHandlers.ts @@ -680,7 +680,6 @@ export async function validateGossipFnRetryUnknownRoot( blockRoot: Root ): Promise { let unknownBlockRootRetries = 0; - // eslint-disable-next-line no-constant-condition while (true) { try { return await fn(); diff --git a/packages/beacon-node/src/network/processor/index.ts b/packages/beacon-node/src/network/processor/index.ts index 5cfed6c20346..ec0edf54644f 100644 --- a/packages/beacon-node/src/network/processor/index.ts +++ b/packages/beacon-node/src/network/processor/index.ts @@ -396,7 +396,9 @@ export class NetworkProcessor { if (item) { this.gossipTopicConcurrency[topic] += numMessages; this.processPendingGossipsubMessage(item) - .finally(() => (this.gossipTopicConcurrency[topic] -= numMessages)) + .finally(() => { + this.gossipTopicConcurrency[topic] -= numMessages; + }) .catch((e) => this.logger.error("processGossipAttestations must not throw", {}, e)); jobsSubmitted += numMessages; diff --git a/packages/beacon-node/src/network/reqresp/beaconBlocksMaybeBlobsByRange.ts b/packages/beacon-node/src/network/reqresp/beaconBlocksMaybeBlobsByRange.ts index 4dae4831d716..74b6d8f13b2e 100644 --- a/packages/beacon-node/src/network/reqresp/beaconBlocksMaybeBlobsByRange.ts +++ b/packages/beacon-node/src/network/reqresp/beaconBlocksMaybeBlobsByRange.ts @@ -80,6 +80,7 @@ export function matchBlockWithBlobs( let blobSidecar: deneb.BlobSidecar; while ( + // biome-ignore lint/suspicious/noAssignInExpressions: (blobSidecar = allBlobSidecars[blobSideCarIndex])?.signedBlockHeader.message.slot === block.data.message.slot ) { blobSidecars.push(blobSidecar); diff --git a/packages/beacon-node/src/network/reqresp/protocols.ts b/packages/beacon-node/src/network/reqresp/protocols.ts index a0fa9576c93c..e63df4b1341b 100644 --- a/packages/beacon-node/src/network/reqresp/protocols.ts +++ b/packages/beacon-node/src/network/reqresp/protocols.ts @@ -3,8 +3,6 @@ import {ForkDigestContext} from "@lodestar/config"; import {ProtocolNoHandler, ReqRespMethod, Version, requestSszTypeByMethod, responseSszTypeByMethod} from "./types.js"; import {rateLimitQuotas} from "./rateLimit.js"; -/* eslint-disable @typescript-eslint/naming-convention */ - export const Goodbye = toProtocol({ method: ReqRespMethod.Goodbye, version: Version.V1, diff --git a/packages/beacon-node/src/network/reqresp/rateLimit.ts b/packages/beacon-node/src/network/reqresp/rateLimit.ts index 881ab36bc05d..b6dacd6ba8e5 100644 --- a/packages/beacon-node/src/network/reqresp/rateLimit.ts +++ b/packages/beacon-node/src/network/reqresp/rateLimit.ts @@ -76,7 +76,7 @@ function getRequestCountFn( return (reqData: Uint8Array) => { try { return (type && fn(type.deserialize(reqData))) ?? 1; - } catch (e) { + } catch (_e) { return 1; } }; diff --git a/packages/beacon-node/src/network/reqresp/score.ts b/packages/beacon-node/src/network/reqresp/score.ts index c74b645c9909..647481162c78 100644 --- a/packages/beacon-node/src/network/reqresp/score.ts +++ b/packages/beacon-node/src/network/reqresp/score.ts @@ -8,7 +8,6 @@ import {ReqRespMethod} from "./types.js"; * https://github.com/libp2p/js-libp2p/blob/6350a187c7c207086e42436ccbcabd59af6f5e3d/src/errors.js#L32 */ const libp2pErrorCodes = { - // eslint-disable-next-line @typescript-eslint/naming-convention ERR_UNSUPPORTED_PROTOCOL: "ERR_UNSUPPORTED_PROTOCOL", }; diff --git a/packages/beacon-node/src/network/util.ts b/packages/beacon-node/src/network/util.ts index dd317b5a0427..835096afbfc8 100644 --- a/packages/beacon-node/src/network/util.ts +++ b/packages/beacon-node/src/network/util.ts @@ -15,7 +15,6 @@ export function prettyPrintPeerIdStr(id: PeerIdStr): string { */ // Compat function for efficiency reasons export function getConnectionsMap(libp2p: Libp2p): Map { - // eslint-disable-next-line @typescript-eslint/no-unsafe-return return libp2p.services.components.connectionManager.getConnectionsMap()["map"]; } diff --git a/packages/beacon-node/src/sync/backfill/backfill.ts b/packages/beacon-node/src/sync/backfill/backfill.ts index 77d2836bdcc3..f60e28a19e1d 100644 --- a/packages/beacon-node/src/sync/backfill/backfill.ts +++ b/packages/beacon-node/src/sync/backfill/backfill.ts @@ -1,4 +1,4 @@ -import {EventEmitter} from "events"; +import {EventEmitter} from "node:events"; import {StrictEventEmitter} from "strict-event-emitter-types"; import {BeaconStateAllForks, blockToHeader, computeAnchorCheckpoint} from "@lodestar/state-transition"; import {BeaconConfig, ChainForkConfig} from "@lodestar/config"; @@ -13,7 +13,7 @@ import {INetwork, NetworkEvent, NetworkEventData, PeerAction} from "../../networ import {ItTrigger} from "../../util/itTrigger.js"; import {PeerIdStr} from "../../util/peerId.js"; import {shuffleOne} from "../../util/shuffle.js"; -import {Metrics} from "../../metrics/metrics"; +import {Metrics} from "../../metrics/metrics.js"; import {byteArrayEquals} from "../../util/bytes.js"; import {verifyBlockProposerSignature, verifyBlockSequence, BackfillBlockHeader, BackfillBlock} from "./verify.js"; import {BackfillSyncError, BackfillSyncErrorCode} from "./errors.js"; @@ -680,6 +680,7 @@ export class BackfillSync extends (EventEmitter as {new (): BackfillSyncEmitter} let isPrevFinWsConfirmedAnchorParent = false; while ( backCount !== this.opts.backfillBatchSize && + // biome-ignore lint/suspicious/noAssignInExpressions: (parentBlock = await this.db.blockArchive.getByRoot(anchorBlock.message.parentRoot)) ) { // Before moving anchorBlock back, we need check for prevFinalizedCheckpointBlock diff --git a/packages/beacon-node/src/sync/range/range.ts b/packages/beacon-node/src/sync/range/range.ts index 887a86a3aaf2..efdf84cf7af1 100644 --- a/packages/beacon-node/src/sync/range/range.ts +++ b/packages/beacon-node/src/sync/range/range.ts @@ -1,4 +1,4 @@ -import {EventEmitter} from "events"; +import {EventEmitter} from "node:events"; import {StrictEventEmitter} from "strict-event-emitter-types"; import {computeStartSlotAtEpoch} from "@lodestar/state-transition"; import {BeaconConfig} from "@lodestar/config"; diff --git a/packages/beacon-node/src/util/asyncIterableToEvents.ts b/packages/beacon-node/src/util/asyncIterableToEvents.ts index 0468ca2b431b..836983d8e4f0 100644 --- a/packages/beacon-node/src/util/asyncIterableToEvents.ts +++ b/packages/beacon-node/src/util/asyncIterableToEvents.ts @@ -46,7 +46,6 @@ export class AsyncIterableBridgeCaller { } getAsyncIterable(callArgs: Args): AsyncIterable { - // eslint-disable-next-line @typescript-eslint/no-this-alias const self = this; return { @@ -67,7 +66,6 @@ export class AsyncIterableBridgeCaller { return { async next() { - // eslint-disable-next-line no-constant-condition while (true) { const item = req.items.shift(); if (item !== null) { diff --git a/packages/beacon-node/src/util/kzg.ts b/packages/beacon-node/src/util/kzg.ts index e20a379d62ff..efc6dd34ee1c 100644 --- a/packages/beacon-node/src/util/kzg.ts +++ b/packages/beacon-node/src/util/kzg.ts @@ -3,8 +3,6 @@ import fs from "node:fs"; import {fileURLToPath} from "node:url"; import {fromHex, toHex} from "@lodestar/utils"; -/* eslint-disable @typescript-eslint/naming-convention */ - // "c-kzg" has hardcoded the mainnet value, do not use params export const FIELD_ELEMENTS_PER_BLOB_MAINNET = 4096; @@ -87,7 +85,6 @@ export function loadEthereumTrustedSetup(mode: TrustedFileMode = TrustedFileMode } } -/* eslint-disable @typescript-eslint/naming-convention */ export interface TrustedSetupJSON { setup_G1: string[]; setup_G2: string[]; diff --git a/packages/beacon-node/src/util/map.ts b/packages/beacon-node/src/util/map.ts index 6cc8f37155b1..1b8fc6222032 100644 --- a/packages/beacon-node/src/util/map.ts +++ b/packages/beacon-node/src/util/map.ts @@ -43,7 +43,6 @@ export class OrderedMap { } values(): IterableIterator { - // eslint-disable-next-line @typescript-eslint/no-this-alias const _self = this; return (function* generateValues() { for (const key of _self.keys()) { diff --git a/packages/beacon-node/src/util/profile.ts b/packages/beacon-node/src/util/profile.ts index 7085c329c823..ccb5b098be31 100644 --- a/packages/beacon-node/src/util/profile.ts +++ b/packages/beacon-node/src/util/profile.ts @@ -37,7 +37,7 @@ export async function profileNodeJS(durationMs: number): Promise { export async function writeHeapSnapshot(prefix: string, dirpath: string): Promise { // Lazily import NodeJS only modules const fs = await import("node:fs"); - const v8 = await import("v8"); + const v8 = await import("node:v8"); const snapshotStream = v8.getHeapSnapshot(); const filepath = `${dirpath}/${prefix}_${new Date().toISOString()}.heapsnapshot`; const fileStream = fs.createWriteStream(filepath); diff --git a/packages/beacon-node/src/util/queue/errors.ts b/packages/beacon-node/src/util/queue/errors.ts index edb0b3b87374..7117b5629372 100644 --- a/packages/beacon-node/src/util/queue/errors.ts +++ b/packages/beacon-node/src/util/queue/errors.ts @@ -7,11 +7,7 @@ export enum QueueErrorCode { export type QueueErrorCodeType = {code: QueueErrorCode.QUEUE_ABORTED} | {code: QueueErrorCode.QUEUE_MAX_LENGTH}; -export class QueueError extends LodestarError { - constructor(type: QueueErrorCodeType) { - super(type); - } -} +export class QueueError extends LodestarError {} export function isQueueErrorAborted(e: unknown): e is QueueError { return e instanceof QueueError && e.type.code === QueueErrorCode.QUEUE_ABORTED; diff --git a/packages/beacon-node/src/util/queue/fnQueue.ts b/packages/beacon-node/src/util/queue/fnQueue.ts index ec3267bdf93a..80e179f8e8f3 100644 --- a/packages/beacon-node/src/util/queue/fnQueue.ts +++ b/packages/beacon-node/src/util/queue/fnQueue.ts @@ -1,10 +1,10 @@ import {JobItemQueue} from "./itemQueue.js"; import {QueueMetrics, JobQueueOpts} from "./options.js"; -// eslint-disable-next-line @typescript-eslint/no-explicit-any +// biome-ignore lint/suspicious/noExplicitAny: type Fn = (...args: any) => Promise; -// eslint-disable-next-line @typescript-eslint/no-explicit-any +// biome-ignore lint/suspicious/noExplicitAny: export class JobFnQueue extends JobItemQueue<[Fn], any> { constructor(opts: JobQueueOpts, metrics?: QueueMetrics) { super((fn) => fn(), opts, metrics); diff --git a/packages/beacon-node/src/util/queue/itemQueue.ts b/packages/beacon-node/src/util/queue/itemQueue.ts index 7da7b6cdd8cb..f380a15f5eaf 100644 --- a/packages/beacon-node/src/util/queue/itemQueue.ts +++ b/packages/beacon-node/src/util/queue/itemQueue.ts @@ -7,7 +7,8 @@ import {defaultQueueOpts, QueueMetrics, JobQueueOpts, QueueType} from "./options * JobQueue that stores arguments in the job array instead of closures. * Supports a single itemProcessor, for arbitrary functions use the JobFnQueue */ -// eslint-disable-next-line @typescript-eslint/no-explicit-any + +// biome-ignore lint/suspicious/noExplicitAny: export class JobItemQueue { private readonly opts: Required; /** diff --git a/packages/beacon-node/test/e2e/api/impl/beacon/node/endpoints.test.ts b/packages/beacon-node/test/e2e/api/impl/beacon/node/endpoints.test.ts index 2d2a0a37c59e..0789932e61e4 100644 --- a/packages/beacon-node/test/e2e/api/impl/beacon/node/endpoints.test.ts +++ b/packages/beacon-node/test/e2e/api/impl/beacon/node/endpoints.test.ts @@ -67,9 +67,7 @@ describe("beacon node api", function () { const bnElOffline = await getDevBeaconNode({ params: { ...chainConfigDef, - // eslint-disable-next-line @typescript-eslint/naming-convention ALTAIR_FORK_EPOCH: 0, - // eslint-disable-next-line @typescript-eslint/naming-convention BELLATRIX_FORK_EPOCH: 0, }, options: { diff --git a/packages/beacon-node/test/e2e/api/impl/lightclient/endpoint.test.ts b/packages/beacon-node/test/e2e/api/impl/lightclient/endpoint.test.ts index c746746741cf..8f05ae41c468 100644 --- a/packages/beacon-node/test/e2e/api/impl/lightclient/endpoint.test.ts +++ b/packages/beacon-node/test/e2e/api/impl/lightclient/endpoint.test.ts @@ -13,7 +13,6 @@ import {getAndInitDevValidators} from "../../../../utils/node/validator.js"; import {BeaconNode} from "../../../../../src/node/nodejs.js"; import {waitForEvent} from "../../../../utils/events/resolver.js"; -/* eslint-disable @typescript-eslint/naming-convention */ describe("lightclient api", function () { const SECONDS_PER_SLOT = 1; const ALTAIR_FORK_EPOCH = 0; diff --git a/packages/beacon-node/test/e2e/api/lodestar/lodestar.test.ts b/packages/beacon-node/test/e2e/api/lodestar/lodestar.test.ts index 5cccb2aa0772..d505e38b3f9a 100644 --- a/packages/beacon-node/test/e2e/api/lodestar/lodestar.test.ts +++ b/packages/beacon-node/test/e2e/api/lodestar/lodestar.test.ts @@ -20,7 +20,6 @@ describe("api / impl / validator", function () { const validatorCount = 8; const restPort = 9596; const testParams: Pick = { - /* eslint-disable @typescript-eslint/naming-convention */ SECONDS_PER_SLOT: SECONDS_PER_SLOT, ALTAIR_FORK_EPOCH: ALTAIR_FORK_EPOCH, }; diff --git a/packages/beacon-node/test/e2e/chain/lightclient.test.ts b/packages/beacon-node/test/e2e/chain/lightclient.test.ts index c501a2618049..5e7b7f36fff2 100644 --- a/packages/beacon-node/test/e2e/chain/lightclient.test.ts +++ b/packages/beacon-node/test/e2e/chain/lightclient.test.ts @@ -34,7 +34,6 @@ describe("chain / lightclient", function () { const restPort = 9000; const testParams: Pick = { - /* eslint-disable @typescript-eslint/naming-convention */ SECONDS_PER_SLOT: 1, ALTAIR_FORK_EPOCH: 0, }; diff --git a/packages/beacon-node/test/e2e/chain/proposerBoostReorg.test.ts b/packages/beacon-node/test/e2e/chain/proposerBoostReorg.test.ts index 594e20ec4cb0..ad32e2d5b270 100644 --- a/packages/beacon-node/test/e2e/chain/proposerBoostReorg.test.ts +++ b/packages/beacon-node/test/e2e/chain/proposerBoostReorg.test.ts @@ -17,13 +17,10 @@ describe("proposer boost reorg", function () { const validatorCount = 8; const testParams: Pick = { - // eslint-disable-next-line @typescript-eslint/naming-convention SECONDS_PER_SLOT: 2, // need this to make block `reorgSlot - 1` strong enough - // eslint-disable-next-line @typescript-eslint/naming-convention REORG_PARENT_WEIGHT_THRESHOLD: 80, // need this to make block `reorgSlot + 1` to become the head - // eslint-disable-next-line @typescript-eslint/naming-convention PROPOSER_SCORE_BOOST: 120, }; diff --git a/packages/beacon-node/test/e2e/chain/stateCache/nHistoricalStates.test.ts b/packages/beacon-node/test/e2e/chain/stateCache/nHistoricalStates.test.ts index fd14b7b8b8c0..b6c5c30dace4 100644 --- a/packages/beacon-node/test/e2e/chain/stateCache/nHistoricalStates.test.ts +++ b/packages/beacon-node/test/e2e/chain/stateCache/nHistoricalStates.test.ts @@ -24,7 +24,6 @@ describe("regen/reload states with n-historical states configuration", function const validatorCount = 8; const testParams: Pick = { - // eslint-disable-next-line @typescript-eslint/naming-convention SECONDS_PER_SLOT: 2, }; diff --git a/packages/beacon-node/test/e2e/doppelganger/doppelganger.test.ts b/packages/beacon-node/test/e2e/doppelganger/doppelganger.test.ts index ab9061f1eacd..bdfcbde056cd 100644 --- a/packages/beacon-node/test/e2e/doppelganger/doppelganger.test.ts +++ b/packages/beacon-node/test/e2e/doppelganger/doppelganger.test.ts @@ -34,7 +34,6 @@ describe.skip("doppelganger / doppelganger test", function () { const validatorCount = 1; const genesisSlotsDelay = 5; const beaconParams: Pick = { - // eslint-disable-next-line @typescript-eslint/naming-convention SECONDS_PER_SLOT: 2, }; @@ -123,7 +122,7 @@ describe.skip("doppelganger / doppelganger test", function () { doppelgangerProtection: true, }); - const {beaconNode: bn2, validators: validators} = await createBNAndVC({ + const {beaconNode: bn2, validators} = await createBNAndVC({ genesisTime: bn.chain.getHeadState().genesisTime, }); @@ -202,7 +201,7 @@ describe.skip("doppelganger / doppelganger test", function () { doppelgangerProtection, }); - const {beaconNode: bn2, validators: validators} = await createBNAndVC({ + const {beaconNode: bn2, validators} = await createBNAndVC({ genesisTime: bn.chain.getHeadState().genesisTime, doppelgangerProtection: false, }); diff --git a/packages/beacon-node/test/e2e/eth1/eth1ForBlockProduction.test.ts b/packages/beacon-node/test/e2e/eth1/eth1ForBlockProduction.test.ts index 17692cfcca3a..837a765d1710 100644 --- a/packages/beacon-node/test/e2e/eth1/eth1ForBlockProduction.test.ts +++ b/packages/beacon-node/test/e2e/eth1/eth1ForBlockProduction.test.ts @@ -68,7 +68,6 @@ describe.skip("eth1 / Eth1Provider", function () { // Resolves when Eth1ForBlockProduction has fetched both blocks and deposits const {eth1Datas, deposits} = await (async function resolveWithEth1DataAndDeposits() { - // eslint-disable-next-line no-constant-condition while (true) { const eth1Datas = await db.eth1Data.entries(); const deposits = await db.depositEvent.values(); diff --git a/packages/beacon-node/test/e2e/eth1/eth1MergeBlockTracker.test.ts b/packages/beacon-node/test/e2e/eth1/eth1MergeBlockTracker.test.ts index ae3e0c707542..034493482c21 100644 --- a/packages/beacon-node/test/e2e/eth1/eth1MergeBlockTracker.test.ts +++ b/packages/beacon-node/test/e2e/eth1/eth1MergeBlockTracker.test.ts @@ -10,8 +10,6 @@ import {quantityToBigint} from "../../../src/eth1/provider/utils.js"; import {ZERO_HASH} from "../../../src/constants/index.js"; import {getGoerliRpcUrl} from "../../testParams.js"; -/* eslint-disable @typescript-eslint/naming-convention */ - // This test is constantly failing. We must unblock PR so this issue is a TODO to debug it and re-enable latter. // It's OKAY to disable temporarily since this functionality is tested indirectly by the sim merge tests. // See https://github.com/ChainSafe/lodestar/issues/4197 diff --git a/packages/beacon-node/test/e2e/eth1/jsonRpcHttpClient.test.ts b/packages/beacon-node/test/e2e/eth1/jsonRpcHttpClient.test.ts index 4e290c6d6318..fac0e3810b6d 100644 --- a/packages/beacon-node/test/e2e/eth1/jsonRpcHttpClient.test.ts +++ b/packages/beacon-node/test/e2e/eth1/jsonRpcHttpClient.test.ts @@ -174,7 +174,6 @@ describe("eth1 / jsonRpcHttpClient - with retries", function () { const afterHook = afterHooks.pop(); if (afterHook) await afterHook().catch((e: Error) => { - // eslint-disable-next-line no-console console.error("Error in afterEach hook", e); }); } diff --git a/packages/beacon-node/test/e2e/interop/genesisState.test.ts b/packages/beacon-node/test/e2e/interop/genesisState.test.ts index 2287c6a1deb8..739319a4257c 100644 --- a/packages/beacon-node/test/e2e/interop/genesisState.test.ts +++ b/packages/beacon-node/test/e2e/interop/genesisState.test.ts @@ -9,7 +9,6 @@ describe("interop / initDevState", () => { it("Create interop deposits", () => { const deposits = interopDeposits(config, ssz.phase0.DepositDataRootList.defaultViewDU(), 1); - /* eslint-disable @typescript-eslint/naming-convention */ expect(deposits.map((deposit) => ssz.phase0.Deposit.toJson(deposit))).toEqual([ { proof: [ diff --git a/packages/beacon-node/test/e2e/network/gossipsub.test.ts b/packages/beacon-node/test/e2e/network/gossipsub.test.ts index c19f3c7c4388..3d8b1e07bbd7 100644 --- a/packages/beacon-node/test/e2e/network/gossipsub.test.ts +++ b/packages/beacon-node/test/e2e/network/gossipsub.test.ts @@ -35,7 +35,6 @@ function runTests({useWorker}: {useWorker: boolean}): void { }); // Schedule all forks at ALTAIR_FORK_EPOCH to avoid generating the pubkeys cache - /* eslint-disable @typescript-eslint/naming-convention */ const config = createChainForkConfig({ ...defaultChainConfig, ALTAIR_FORK_EPOCH: 1, @@ -44,7 +43,6 @@ function runTests({useWorker}: {useWorker: boolean}): void { }); const START_SLOT = computeStartSlotAtEpoch(config.ALTAIR_FORK_EPOCH); - // eslint-disable-next-line @typescript-eslint/explicit-function-return-type async function mockModules(gossipHandlersPartial?: Partial) { const [netA, closeA] = await getNetworkForTest(`gossipsub-${useWorker ? "worker" : "main"}-A`, config, { opts: {useWorker}, @@ -65,7 +63,9 @@ function runTests({useWorker}: {useWorker: boolean}): void { it("Publish and receive a voluntaryExit", async function () { let onVoluntaryExit: (ve: Uint8Array) => void; - const onVoluntaryExitPromise = new Promise((resolve) => (onVoluntaryExit = resolve)); + const onVoluntaryExitPromise = new Promise((resolve) => { + onVoluntaryExit = resolve; + }); const {netA, netB} = await mockModules({ [GossipType.voluntary_exit]: async ({gossipData}: GossipHandlerParamGeneric) => { @@ -100,7 +100,9 @@ function runTests({useWorker}: {useWorker: boolean}): void { it("Publish and receive a blsToExecutionChange", async function () { let onBlsToExecutionChange: (blsToExec: Uint8Array) => void; - const onBlsToExecutionChangePromise = new Promise((resolve) => (onBlsToExecutionChange = resolve)); + const onBlsToExecutionChangePromise = new Promise((resolve) => { + onBlsToExecutionChange = resolve; + }); const {netA, netB} = await mockModules({ [GossipType.bls_to_execution_change]: async ({ @@ -136,7 +138,9 @@ function runTests({useWorker}: {useWorker: boolean}): void { it("Publish and receive an attesterSlashing", async function () { let onAttesterSlashingChange: (payload: Uint8Array) => void; - const onAttesterSlashingChangePromise = new Promise((resolve) => (onAttesterSlashingChange = resolve)); + const onAttesterSlashingChangePromise = new Promise((resolve) => { + onAttesterSlashingChange = resolve; + }); const {netA, netB} = await mockModules({ [GossipType.attester_slashing]: async ({gossipData}: GossipHandlerParamGeneric) => { @@ -168,7 +172,9 @@ function runTests({useWorker}: {useWorker: boolean}): void { it("Publish and receive a proposerSlashing", async function () { let onProposerSlashingChange: (payload: Uint8Array) => void; - const onProposerSlashingChangePromise = new Promise((resolve) => (onProposerSlashingChange = resolve)); + const onProposerSlashingChangePromise = new Promise((resolve) => { + onProposerSlashingChange = resolve; + }); const {netA, netB} = await mockModules({ [GossipType.proposer_slashing]: async ({gossipData}: GossipHandlerParamGeneric) => { @@ -200,9 +206,9 @@ function runTests({useWorker}: {useWorker: boolean}): void { it("Publish and receive a LightClientOptimisticUpdate", async function () { let onLightClientOptimisticUpdate: (ou: Uint8Array) => void; - const onLightClientOptimisticUpdatePromise = new Promise( - (resolve) => (onLightClientOptimisticUpdate = resolve) - ); + const onLightClientOptimisticUpdatePromise = new Promise((resolve) => { + onLightClientOptimisticUpdate = resolve; + }); const {netA, netB} = await mockModules({ [GossipType.light_client_optimistic_update]: async ({ @@ -239,9 +245,9 @@ function runTests({useWorker}: {useWorker: boolean}): void { it("Publish and receive a LightClientFinalityUpdate", async function () { let onLightClientFinalityUpdate: (fu: Uint8Array) => void; - const onLightClientFinalityUpdatePromise = new Promise( - (resolve) => (onLightClientFinalityUpdate = resolve) - ); + const onLightClientFinalityUpdatePromise = new Promise((resolve) => { + onLightClientFinalityUpdate = resolve; + }); const {netA, netB} = await mockModules({ [GossipType.light_client_finality_update]: async ({ diff --git a/packages/beacon-node/test/e2e/network/mdns.test.ts b/packages/beacon-node/test/e2e/network/mdns.test.ts index d8e148e191fe..4c49ca319a42 100644 --- a/packages/beacon-node/test/e2e/network/mdns.test.ts +++ b/packages/beacon-node/test/e2e/network/mdns.test.ts @@ -68,7 +68,6 @@ describe.skip("mdns", function () { return {block, state, config: beaconConfig}; }); - // eslint-disable-next-line @typescript-eslint/explicit-function-return-type async function createTestNode(nodeName: string) { const {config} = getStaticData(); const chain = getMockedBeaconChain(); @@ -111,7 +110,6 @@ describe.skip("mdns", function () { return {network, chain}; } - // eslint-disable-next-line @typescript-eslint/explicit-function-return-type async function createTestNodesAB() { return Promise.all([createTestNode("mdns-A"), createTestNode("mdns-B")]); } diff --git a/packages/beacon-node/test/e2e/network/network.test.ts b/packages/beacon-node/test/e2e/network/network.test.ts index 094a75280e8b..a1c1546ef4fc 100644 --- a/packages/beacon-node/test/e2e/network/network.test.ts +++ b/packages/beacon-node/test/e2e/network/network.test.ts @@ -38,7 +38,6 @@ function runTests({useWorker}: {useWorker: boolean}): void { }); afterEach(() => controller.abort()); - // eslint-disable-next-line @typescript-eslint/explicit-function-return-type async function createTestNode(nodeName: string) { const [network, closeAll] = await getNetworkForTest(nodeName, config, {opts: {useWorker}}); diff --git a/packages/beacon-node/test/e2e/network/peers/peerManager.test.ts b/packages/beacon-node/test/e2e/network/peers/peerManager.test.ts index 795a4bf67ecc..b690b9ab4988 100644 --- a/packages/beacon-node/test/e2e/network/peers/peerManager.test.ts +++ b/packages/beacon-node/test/e2e/network/peers/peerManager.test.ts @@ -33,7 +33,6 @@ describe("network / peers / PeerManager", function () { } }); - // eslint-disable-next-line @typescript-eslint/explicit-function-return-type async function mockModules() { // Setup fake chain const block = ssz.phase0.SignedBeaconBlock.defaultValue(); diff --git a/packages/beacon-node/test/e2e/network/reqrespEncode.test.ts b/packages/beacon-node/test/e2e/network/reqrespEncode.test.ts index d96f405eae7c..d8d02c203dd9 100644 --- a/packages/beacon-node/test/e2e/network/reqrespEncode.test.ts +++ b/packages/beacon-node/test/e2e/network/reqrespEncode.test.ts @@ -35,7 +35,6 @@ describe("reqresp encoder", () => { } }); - // eslint-disable-next-line @typescript-eslint/explicit-function-return-type async function getLibp2p() { const listen = `/ip4/127.0.0.1/tcp/${port++}`; const libp2p = await createLibp2p({ @@ -50,7 +49,6 @@ describe("reqresp encoder", () => { return {libp2p, multiaddr: multiaddr(`${listen}/p2p/${libp2p.peerId.toString()}`)}; } - // eslint-disable-next-line @typescript-eslint/explicit-function-return-type async function getReqResp(getHandler?: GetReqRespHandlerFn) { const {libp2p, multiaddr} = await getLibp2p(); @@ -76,7 +74,6 @@ describe("reqresp encoder", () => { return {libp2p, multiaddr, reqresp: new ReqRespBeaconNode(modules)}; } - // eslint-disable-next-line @typescript-eslint/explicit-function-return-type async function dialProtocol({ dialer, toMultiaddr, diff --git a/packages/beacon-node/test/e2e/sync/finalizedSync.test.ts b/packages/beacon-node/test/e2e/sync/finalizedSync.test.ts index 01293285d756..ed19617f0822 100644 --- a/packages/beacon-node/test/e2e/sync/finalizedSync.test.ts +++ b/packages/beacon-node/test/e2e/sync/finalizedSync.test.ts @@ -20,7 +20,6 @@ describe("sync / finalized sync", function () { const validatorCount = 8; const testParams: Pick = { - // eslint-disable-next-line @typescript-eslint/naming-convention SECONDS_PER_SLOT: 2, }; @@ -114,7 +113,7 @@ describe("sync / finalized sync", function () { try { await waitForSynced; loggerNodeB.info("Node B synced to Node A, received head block", {slot: head.message.slot}); - } catch (e) { + } catch (_e) { assert.fail("Failed to sync to other node in time"); } }); diff --git a/packages/beacon-node/test/e2e/sync/unknownBlockSync.test.ts b/packages/beacon-node/test/e2e/sync/unknownBlockSync.test.ts index 31f640269db7..7d31d25a07d3 100644 --- a/packages/beacon-node/test/e2e/sync/unknownBlockSync.test.ts +++ b/packages/beacon-node/test/e2e/sync/unknownBlockSync.test.ts @@ -22,7 +22,6 @@ describe("sync / unknown block sync", function () { const validatorCount = 8; const testParams: Pick = { - // eslint-disable-next-line @typescript-eslint/naming-convention SECONDS_PER_SLOT: 2, }; diff --git a/packages/beacon-node/test/globalSetup.ts b/packages/beacon-node/test/globalSetup.ts index 8194c76662df..f41a7f249b9b 100644 --- a/packages/beacon-node/test/globalSetup.ts +++ b/packages/beacon-node/test/globalSetup.ts @@ -11,7 +11,6 @@ export async function setup(): Promise { // Override FIELD_ELEMENTS_PER_BLOB if its a dev run, mostly to distinguish from // spec runs if (process.env.LODESTAR_PRESET === "minimal" && process.env.DEV_RUN) { - // eslint-disable-next-line @typescript-eslint/naming-convention setActivePreset(PresetName.minimal, {FIELD_ELEMENTS_PER_BLOB: 4096}); } } diff --git a/packages/beacon-node/test/memory/bytesHex.ts b/packages/beacon-node/test/memory/bytesHex.ts index 44115d345b2c..c7429869dac7 100644 --- a/packages/beacon-node/test/memory/bytesHex.ts +++ b/packages/beacon-node/test/memory/bytesHex.ts @@ -45,7 +45,6 @@ function testRunnerMemoryBpi(testCases: {getInstance: (bytes: number) => unknown convergeFactor: 0.2 / 100, }); - // eslint-disable-next-line no-console console.log(`${id.padEnd(longestId)} - ${bpi.toFixed(1)} bytes / instance`); } } diff --git a/packages/beacon-node/test/memory/pubkeysToIndex.ts b/packages/beacon-node/test/memory/pubkeysToIndex.ts index b647d153dba2..32cdf6e82296 100644 --- a/packages/beacon-node/test/memory/pubkeysToIndex.ts +++ b/packages/beacon-node/test/memory/pubkeysToIndex.ts @@ -52,7 +52,6 @@ function testRunnerMemoryBpi(testCases: {getInstance: (bytes: number) => unknown sampleEvery: 5, }); - // eslint-disable-next-line no-console console.log(`${id.padEnd(longestId)} - ${bpi.toFixed(1)} bytes / instance`); } } diff --git a/packages/beacon-node/test/memory/seenAttestationData.ts b/packages/beacon-node/test/memory/seenAttestationData.ts index c6735bd861e9..44a82dcd5841 100644 --- a/packages/beacon-node/test/memory/seenAttestationData.ts +++ b/packages/beacon-node/test/memory/seenAttestationData.ts @@ -53,7 +53,6 @@ function testRunnerMemoryBpi(testCases: {getInstance: (bytes: number) => unknown sampleEvery: 5, }); - // eslint-disable-next-line no-console console.log(`${id.padEnd(longestId)} - ${bpi.toFixed(1)} bytes / instance`); } } diff --git a/packages/beacon-node/test/memory/testRunnerMemory.ts b/packages/beacon-node/test/memory/testRunnerMemory.ts index a5c4df9e5794..05e7c8afab01 100644 --- a/packages/beacon-node/test/memory/testRunnerMemory.ts +++ b/packages/beacon-node/test/memory/testRunnerMemory.ts @@ -57,7 +57,6 @@ export async function testRunnerMemoryGc(opts: TestRunnerMemoryOpts): Prom usedMemoryArr.push(totalUsedMemoryDiff); const usedMemoryReg = linearRegression(xs, usedMemoryArr); - // eslint-disable-next-line no-console console.log("totalUsedMemoryDiff", totalUsedMemoryDiff, usedMemoryReg); } } @@ -137,7 +136,6 @@ export function testRunnerMemory(opts: TestRunnerMemoryOpts): number { } if (logEachSample) { - // eslint-disable-next-line no-console console.log(i, memoryUsage.rss / maxRssBytes, {m}); } diff --git a/packages/beacon-node/test/memory/unfinalizedPubkey2Index.ts b/packages/beacon-node/test/memory/unfinalizedPubkey2Index.ts index b37967d16ca4..247f8a4ea95a 100644 --- a/packages/beacon-node/test/memory/unfinalizedPubkey2Index.ts +++ b/packages/beacon-node/test/memory/unfinalizedPubkey2Index.ts @@ -48,7 +48,6 @@ function testRunnerMemoryBpi(testCases: {getInstance: (bytes: number) => unknown sampleEvery: 5, }); - // eslint-disable-next-line no-console console.log(`${id.padEnd(longestId)} - ${bpi.toFixed(1)} bytes / instance`); } } diff --git a/packages/beacon-node/test/mocks/beaconSyncMock.ts b/packages/beacon-node/test/mocks/beaconSyncMock.ts index 00ef193fdf6e..4d9f11ba90fd 100644 --- a/packages/beacon-node/test/mocks/beaconSyncMock.ts +++ b/packages/beacon-node/test/mocks/beaconSyncMock.ts @@ -1,4 +1,3 @@ -/* eslint-disable @typescript-eslint/naming-convention */ import {Mocked, vi} from "vitest"; import {BeaconSync} from "../../src/sync/index.js"; diff --git a/packages/beacon-node/test/mocks/mockedBeaconChain.ts b/packages/beacon-node/test/mocks/mockedBeaconChain.ts index addeacf26a89..1d597bf4424d 100644 --- a/packages/beacon-node/test/mocks/mockedBeaconChain.ts +++ b/packages/beacon-node/test/mocks/mockedBeaconChain.ts @@ -1,4 +1,3 @@ -/* eslint-disable @typescript-eslint/naming-convention */ import {vi, Mocked, Mock} from "vitest"; import {config as defaultConfig} from "@lodestar/config/default"; import {ChainForkConfig} from "@lodestar/config"; @@ -120,12 +119,10 @@ vi.mock("../../src/chain/chain.js", async (importActual) => { getClientVersion: vi.fn(), }, executionBuilder: {}, - // eslint-disable-next-line @typescript-eslint/ban-ts-comment // @ts-expect-error eth1: new Eth1ForBlockProduction(), opPool: new OpPool(), aggregatedAttestationPool: new AggregatedAttestationPool(config), - // eslint-disable-next-line @typescript-eslint/ban-ts-comment // @ts-expect-error beaconProposerCache: new BeaconProposerCache(), shufflingCache: new ShufflingCache(), @@ -169,7 +166,6 @@ export type MockedBeaconChainOptions = { export function getMockedBeaconChain(opts?: Partial): MockedBeaconChain { const {clock, genesisTime, config} = opts ?? {}; - // eslint-disable-next-line @typescript-eslint/ban-ts-comment // @ts-expect-error return new BeaconChain({ clock: clock ?? "fake", diff --git a/packages/beacon-node/test/mocks/mockedBeaconDb.ts b/packages/beacon-node/test/mocks/mockedBeaconDb.ts index 8b99c85d2345..eb209c9b44fb 100644 --- a/packages/beacon-node/test/mocks/mockedBeaconDb.ts +++ b/packages/beacon-node/test/mocks/mockedBeaconDb.ts @@ -62,7 +62,6 @@ vi.mock("../../src/db/index.js", async (importActual) => { return { ...mod, - // eslint-disable-next-line @typescript-eslint/naming-convention BeaconDb: mockedBeaconDb, }; }); diff --git a/packages/beacon-node/test/mocks/mockedNetwork.ts b/packages/beacon-node/test/mocks/mockedNetwork.ts index ddf70aa1b5aa..9258acc9bc1b 100644 --- a/packages/beacon-node/test/mocks/mockedNetwork.ts +++ b/packages/beacon-node/test/mocks/mockedNetwork.ts @@ -1,4 +1,3 @@ -/* eslint-disable @typescript-eslint/naming-convention */ import {vi, Mocked} from "vitest"; import {Network, INetwork} from "../../src/network/index.js"; diff --git a/packages/beacon-node/test/perf/api/impl/validator/attester.test.ts b/packages/beacon-node/test/perf/api/impl/validator/attester.test.ts index 803d6c84c408..807e29c55b52 100644 --- a/packages/beacon-node/test/perf/api/impl/validator/attester.test.ts +++ b/packages/beacon-node/test/perf/api/impl/validator/attester.test.ts @@ -1,5 +1,4 @@ import {itBench} from "@dapplion/benchmark"; -// eslint-disable-next-line import/no-relative-packages import {generatePerfTestCachedStatePhase0, numValidators} from "../../../../../../state-transition/test/perf/util.js"; import {getPubkeysForIndices} from "../../../../../src/api/impl/validator/utils.js"; import {linspace} from "../../../../../src/util/numpy.js"; diff --git a/packages/beacon-node/test/perf/chain/opPools/aggregatedAttestationPool.test.ts b/packages/beacon-node/test/perf/chain/opPools/aggregatedAttestationPool.test.ts index 45fc07281c3b..89bd76f34eb3 100644 --- a/packages/beacon-node/test/perf/chain/opPools/aggregatedAttestationPool.test.ts +++ b/packages/beacon-node/test/perf/chain/opPools/aggregatedAttestationPool.test.ts @@ -13,7 +13,6 @@ import {ExecutionStatus, ForkChoice, IForkChoiceStore, ProtoArray, DataAvailabil import {ssz} from "@lodestar/types"; import {createChainForkConfig, defaultChainConfig} from "@lodestar/config"; -// eslint-disable-next-line import/no-relative-packages import {generatePerfTestCachedStateAltair} from "../../../../../state-transition/test/perf/util.js"; import {AggregatedAttestationPool} from "../../../../src/chain/opPools/aggregatedAttestationPool.js"; diff --git a/packages/beacon-node/test/perf/chain/opPools/opPool.test.ts b/packages/beacon-node/test/perf/chain/opPools/opPool.test.ts index 6e420f0e1011..9d518c03eec9 100644 --- a/packages/beacon-node/test/perf/chain/opPools/opPool.test.ts +++ b/packages/beacon-node/test/perf/chain/opPools/opPool.test.ts @@ -7,7 +7,6 @@ import { } from "@lodestar/params"; import {CachedBeaconStateAltair} from "@lodestar/state-transition"; import {ssz} from "@lodestar/types"; -// eslint-disable-next-line import/no-relative-packages import {generatePerfTestCachedStateAltair} from "../../../../../state-transition/test/perf/util.js"; import {OpPool} from "../../../../src/chain/opPools/opPool.js"; import {generateBlsToExecutionChanges} from "../../../fixtures/capella.js"; diff --git a/packages/beacon-node/test/perf/chain/produceBlock/produceBlockBody.test.ts b/packages/beacon-node/test/perf/chain/produceBlock/produceBlockBody.test.ts index 7bf8c2f7252f..fdd6f60f5a47 100644 --- a/packages/beacon-node/test/perf/chain/produceBlock/produceBlockBody.test.ts +++ b/packages/beacon-node/test/perf/chain/produceBlock/produceBlockBody.test.ts @@ -5,7 +5,6 @@ import {LevelDbController} from "@lodestar/db"; import {SAFE_SLOTS_TO_IMPORT_OPTIMISTICALLY} from "@lodestar/params"; import {defaultOptions as defaultValidatorOptions} from "@lodestar/validator"; import {CachedBeaconStateAltair} from "@lodestar/state-transition"; -// eslint-disable-next-line import/no-relative-packages import {generatePerfTestCachedStateAltair} from "../../../../../state-transition/test/perf/util.js"; import {BeaconChain} from "../../../../src/chain/index.js"; import {BlockType, produceBlockBody} from "../../../../src/chain/produceBlock/produceBlockBody.js"; diff --git a/packages/beacon-node/test/perf/chain/validation/aggregateAndProof.test.ts b/packages/beacon-node/test/perf/chain/validation/aggregateAndProof.test.ts index 3fc7efe9d675..5e28a7c3b898 100644 --- a/packages/beacon-node/test/perf/chain/validation/aggregateAndProof.test.ts +++ b/packages/beacon-node/test/perf/chain/validation/aggregateAndProof.test.ts @@ -1,6 +1,5 @@ import {itBench} from "@dapplion/benchmark"; import {ssz} from "@lodestar/types"; -// eslint-disable-next-line import/no-relative-packages import {generateTestCachedBeaconStateOnlyValidators} from "../../../../../state-transition/test/perf/util.js"; import {validateApiAggregateAndProof, validateGossipAggregateAndProof} from "../../../../src/chain/validation/index.js"; import {getAggregateAndProofValidData} from "../../../utils/validationData/aggregateAndProof.js"; diff --git a/packages/beacon-node/test/perf/chain/validation/attestation.test.ts b/packages/beacon-node/test/perf/chain/validation/attestation.test.ts index e942e1ea17d0..696b6bdb1871 100644 --- a/packages/beacon-node/test/perf/chain/validation/attestation.test.ts +++ b/packages/beacon-node/test/perf/chain/validation/attestation.test.ts @@ -1,7 +1,6 @@ import {itBench, setBenchOpts} from "@dapplion/benchmark"; import {expect} from "chai"; import {ssz} from "@lodestar/types"; -// eslint-disable-next-line import/no-relative-packages import {generateTestCachedBeaconStateOnlyValidators} from "../../../../../state-transition/test/perf/util.js"; import {validateGossipAttestationsSameAttData} from "../../../../src/chain/validation/index.js"; import {getAttestationValidData} from "../../../utils/validationData/attestation.js"; diff --git a/packages/beacon-node/test/perf/chain/verifyImportBlocks.test.ts b/packages/beacon-node/test/perf/chain/verifyImportBlocks.test.ts index a21c28adaec0..6ae7112f5e3d 100644 --- a/packages/beacon-node/test/perf/chain/verifyImportBlocks.test.ts +++ b/packages/beacon-node/test/perf/chain/verifyImportBlocks.test.ts @@ -4,17 +4,9 @@ import {SAFE_SLOTS_TO_IMPORT_OPTIMISTICALLY, SLOTS_PER_EPOCH} from "@lodestar/pa import {LevelDbController} from "@lodestar/db"; import {sleep} from "@lodestar/utils"; import {defaultOptions as defaultValidatorOptions} from "@lodestar/validator"; -// eslint-disable-next-line import/no-relative-packages import {rangeSyncTest} from "../../../../state-transition/test/perf/params.js"; -import { - getNetworkCachedState, - getNetworkCachedBlock, - // eslint-disable-next-line import/no-relative-packages -} from "../../../../state-transition/test/utils/testFileCache.js"; -import { - beforeValue, - // eslint-disable-next-line import/no-relative-packages -} from "../../../../state-transition/test/utils/beforeValueMocha.js"; +import {getNetworkCachedState, getNetworkCachedBlock} from "../../../../state-transition/test/utils/testFileCache.js"; +import {beforeValue} from "../../../../state-transition/test/utils/beforeValueMocha.js"; import {BeaconChain} from "../../../src/chain/index.js"; import {ExecutionEngineDisabled} from "../../../src/execution/engine/index.js"; import {Eth1ForBlockProductionDisabled} from "../../../src/eth1/index.js"; diff --git a/packages/beacon-node/test/scripts/blsPubkeyBytesFrequency.ts b/packages/beacon-node/test/scripts/blsPubkeyBytesFrequency.ts index 1889cacf1496..aaf882a86bff 100644 --- a/packages/beacon-node/test/scripts/blsPubkeyBytesFrequency.ts +++ b/packages/beacon-node/test/scripts/blsPubkeyBytesFrequency.ts @@ -58,7 +58,6 @@ function analyzeBytesFrequencies(pubkeys: string[]): void { byte0Freq[byte0] = 1 + (byte0Freq[byte0] ?? 0); } - // eslint-disable-next-line no-console console.log( `Byte[${i}] frequency distribution`, JSON.stringify( @@ -95,7 +94,6 @@ function analyzeBytesCollisions(pubkeys: string[]): void { } } - // eslint-disable-next-line no-console console.log(`bytes ${i}, collision rate ${collisions.size / 256 ** i}`); } } @@ -120,7 +118,6 @@ async function writePubkeys(): Promise { } run().catch((e) => { - // eslint-disable-next-line no-console console.error(e); process.exit(1); }); diff --git a/packages/beacon-node/test/setupPreset.ts b/packages/beacon-node/test/setupPreset.ts index b25c1d87835e..968c6e12c668 100644 --- a/packages/beacon-node/test/setupPreset.ts +++ b/packages/beacon-node/test/setupPreset.ts @@ -7,6 +7,5 @@ if (process.env.LODESTAR_PRESET === undefined) { // Override FIELD_ELEMENTS_PER_BLOB if its a dev run, mostly to distinguish from // spec runs if (process.env.LODESTAR_PRESET === "minimal" && process.env.DEV_RUN) { - // eslint-disable-next-line @typescript-eslint/naming-convention setActivePreset(PresetName.minimal, {FIELD_ELEMENTS_PER_BLOB: 4096}); } diff --git a/packages/beacon-node/test/spec/bls/bls.ts b/packages/beacon-node/test/spec/bls/bls.ts index 5af15bcb8eb2..76c511215b61 100644 --- a/packages/beacon-node/test/spec/bls/bls.ts +++ b/packages/beacon-node/test/spec/bls/bls.ts @@ -10,8 +10,6 @@ import { } from "@chainsafe/blst"; import {fromHexString} from "@chainsafe/ssz"; -/* eslint-disable @typescript-eslint/naming-convention */ - export const testFnByType: Record any)> = { aggregate_verify, aggregate, @@ -44,7 +42,7 @@ function aggregate_verify(input: {pubkeys: string[]; messages: string[]; signatu pubkeys.map((pk) => PublicKey.fromHex(pk)), Signature.fromHex(signature) ); - } catch (e) { + } catch (_e) { return false; } } @@ -78,7 +76,7 @@ function fast_aggregate_verify(input: {pubkeys: string[]; message: string; signa pubkeys.map((hex) => PublicKey.fromHex(hex, true)), Signature.fromHex(signature, true) ); - } catch (e) { + } catch (_e) { return false; } } @@ -103,7 +101,7 @@ function batch_verify(input: {pubkeys: string[]; messages: string[]; signatures: sig: Signature.fromHex(signatures[i], true), })) ); - } catch (e) { + } catch (_e) { return false; } } @@ -137,7 +135,7 @@ function verify(input: {pubkey: string; message: string; signature: string}): bo const {pubkey, message, signature} = input; try { return _verify(fromHexString(message), PublicKey.fromHex(pubkey), Signature.fromHex(signature)); - } catch (e) { + } catch (_e) { return false; } } @@ -153,7 +151,7 @@ function deserialization_G1(input: {pubkey: string}): boolean { try { PublicKey.fromHex(input.pubkey, true); return true; - } catch (e) { + } catch (_e) { return false; } } @@ -169,7 +167,7 @@ function deserialization_G2(input: {signature: string}): boolean { try { Signature.fromHex(input.signature, true); return true; - } catch (e) { + } catch (_e) { return false; } } diff --git a/packages/beacon-node/test/spec/general/bls.ts b/packages/beacon-node/test/spec/general/bls.ts index 010a5b9be53d..fca8529e4e3b 100644 --- a/packages/beacon-node/test/spec/general/bls.ts +++ b/packages/beacon-node/test/spec/general/bls.ts @@ -12,8 +12,6 @@ import { import {InputType} from "@lodestar/spec-test-util"; import {TestRunnerFn} from "../utils/types.js"; -/* eslint-disable @typescript-eslint/naming-convention */ - const testFnByType: Record any> = { aggregate, aggregate_verify, @@ -29,7 +27,7 @@ const G2_POINT_AT_INFINITY = const G1_POINT_AT_INFINITY = "0xc00000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000"; -export const blsTestRunner: TestRunnerFn = (fork, testName) => { +export const blsTestRunner: TestRunnerFn = (_fork, testName) => { return { testFunction: ({data}) => { const testFn = testFnByType[testName]; @@ -75,7 +73,7 @@ function aggregate(input: string[]): string | null { const pks = input.map((pkHex) => Signature.fromHex(pkHex)); const agg = aggregateSignatures(pks); return agg.toHex(); - } catch (e) { + } catch (_e) { return null; } } @@ -97,7 +95,7 @@ function aggregate_verify(input: {pubkeys: string[]; messages: string[]; signatu pubkeys.map((pk) => PublicKey.fromHex(pk)), Signature.fromHex(signature) ); - } catch (e) { + } catch (_e) { return false; } } @@ -116,7 +114,7 @@ function eth_aggregate_pubkeys(input: string[]): string | null { try { return aggregateSerializedPublicKeys(input.map((hex) => fromHexString(hex))).toHex(); - } catch (e) { + } catch (_e) { return null; } } @@ -148,7 +146,7 @@ function eth_fast_aggregate_verify(input: {pubkeys: string[]; message: string; s pubkeys.map((hex) => PublicKey.fromHex(hex)), Signature.fromHex(signature) ); - } catch (e) { + } catch (_e) { return false; } } @@ -170,7 +168,7 @@ function fast_aggregate_verify(input: {pubkeys: string[]; message: string; signa pubkeys.map((hex) => PublicKey.fromHex(hex, true)), Signature.fromHex(signature, true) ); - } catch (e) { + } catch (_e) { return false; } } @@ -185,7 +183,7 @@ function sign(input: {privkey: string; message: string}): string | null { const {privkey, message} = input; try { return SecretKey.fromHex(privkey).sign(fromHexString(message)).toHex(); - } catch (e) { + } catch (_e) { return null; } } @@ -201,7 +199,7 @@ function verify(input: {pubkey: string; message: string; signature: string}): bo const {pubkey, message, signature} = input; try { return _verify(fromHexString(message), PublicKey.fromHex(pubkey), Signature.fromHex(signature)); - } catch (e) { + } catch (_e) { return false; } } diff --git a/packages/beacon-node/test/spec/general/index.test.ts b/packages/beacon-node/test/spec/general/index.test.ts index f6bfb0b7b2a1..063f128c3142 100644 --- a/packages/beacon-node/test/spec/general/index.test.ts +++ b/packages/beacon-node/test/spec/general/index.test.ts @@ -5,8 +5,6 @@ import {ethereumConsensusSpecsTests} from "../specTestVersioning.js"; import {blsTestRunner} from "./bls.js"; import {sszGeneric} from "./ssz_generic.js"; -/* eslint-disable @typescript-eslint/naming-convention */ - // NOTE: You MUST always provide a detailed reason of why a spec test is skipped plus link // to an issue marking it as pending to re-enable and an aproximate timeline of when it will // be fixed. diff --git a/packages/beacon-node/test/spec/general/ssz_generic.ts b/packages/beacon-node/test/spec/general/ssz_generic.ts index e791ca62eefe..64e6b4455941 100644 --- a/packages/beacon-node/test/spec/general/ssz_generic.ts +++ b/packages/beacon-node/test/spec/general/ssz_generic.ts @@ -15,7 +15,7 @@ import {getTestType} from "./ssz_generic_types.js"; export const sszGeneric = (skippedTypes: string[]): TestRunnerCustom => - (fork, typeName, testSuite, testSuiteDirpath) => { + (_fork, typeName, testSuite, testSuiteDirpath) => { if (testSuite === "invalid") { for (const testCase of fs.readdirSync(testSuiteDirpath)) { it(testCase, () => { diff --git a/packages/beacon-node/test/spec/general/ssz_generic_types.ts b/packages/beacon-node/test/spec/general/ssz_generic_types.ts index cd95a5dec79e..aa231c962ae3 100644 --- a/packages/beacon-node/test/spec/general/ssz_generic_types.ts +++ b/packages/beacon-node/test/spec/general/ssz_generic_types.ts @@ -20,8 +20,6 @@ const uint64 = new UintBigintType(8); const uint128 = new UintBigintType(16); const uint256 = new UintBigintType(32); -/* eslint-disable @typescript-eslint/naming-convention */ - // class SingleFieldTestStruct(Container): // A: byte const SingleFieldTestStruct = new ContainerType({ diff --git a/packages/beacon-node/test/spec/presets/epoch_processing.test.ts b/packages/beacon-node/test/spec/presets/epoch_processing.test.ts index 604243400aa0..17347269c6f6 100644 --- a/packages/beacon-node/test/spec/presets/epoch_processing.test.ts +++ b/packages/beacon-node/test/spec/presets/epoch_processing.test.ts @@ -20,8 +20,6 @@ import {specTestIterator} from "../utils/specTestIterator.js"; export type EpochTransitionFn = (state: CachedBeaconStateAllForks, epochTransitionCache: EpochTransitionCache) => void; -/* eslint-disable @typescript-eslint/naming-convention */ - const epochTransitionFns: Record = { effective_balance_updates: (state, epochTransitionCache) => { const fork = state.config.getForkSeq(state.slot); @@ -99,7 +97,7 @@ const epochProcessing = post: ssz[fork].BeaconState, }, getExpected: (testCase) => testCase.post, - expectFunc: (testCase, expected, actual) => { + expectFunc: (_testCase, expected, actual) => { expectEqualBeaconState(fork, expected, actual); }, // Do not manually skip tests here, do it in packages/beacon-node/test/spec/presets/index.test.ts diff --git a/packages/beacon-node/test/spec/presets/finality.test.ts b/packages/beacon-node/test/spec/presets/finality.test.ts index 0ec4017064f4..1dce91e360e5 100644 --- a/packages/beacon-node/test/spec/presets/finality.test.ts +++ b/packages/beacon-node/test/spec/presets/finality.test.ts @@ -15,8 +15,6 @@ import {assertCorrectProgressiveBalances} from "../config.js"; import {ethereumConsensusSpecsTests} from "../specTestVersioning.js"; import {specTestIterator} from "../utils/specTestIterator.js"; -/* eslint-disable @typescript-eslint/naming-convention */ - const finality: TestRunnerFn = (fork) => { return { testFunction: (testcase) => { @@ -49,7 +47,7 @@ const finality: TestRunnerFn = (fork) => shouldError: (testCase) => !testCase.post, timeout: 10000, getExpected: (testCase) => testCase.post, - expectFunc: (testCase, expected, actual) => { + expectFunc: (_testCase, expected, actual) => { expectEqualBeaconState(fork, expected, actual); }, // Do not manually skip tests here, do it in packages/beacon-node/test/spec/presets/index.test.ts diff --git a/packages/beacon-node/test/spec/presets/fork.test.ts b/packages/beacon-node/test/spec/presets/fork.test.ts index c121e651fcea..626d6477bcb1 100644 --- a/packages/beacon-node/test/spec/presets/fork.test.ts +++ b/packages/beacon-node/test/spec/presets/fork.test.ts @@ -50,7 +50,7 @@ const fork: TestRunnerFn = (forkNext) => { timeout: 10000, shouldError: (testCase) => testCase.post === undefined, getExpected: (testCase) => testCase.post, - expectFunc: (testCase, expected, actual) => { + expectFunc: (_testCase, expected, actual) => { expectEqualBeaconState(forkNext, expected, actual); }, // Do not manually skip tests here, do it in packages/beacon-node/test/spec/presets/index.test.ts diff --git a/packages/beacon-node/test/spec/presets/fork_choice.test.ts b/packages/beacon-node/test/spec/presets/fork_choice.test.ts index 7cb6e3c3d692..72515e703582 100644 --- a/packages/beacon-node/test/spec/presets/fork_choice.test.ts +++ b/packages/beacon-node/test/spec/presets/fork_choice.test.ts @@ -46,8 +46,6 @@ import {initCKZG, loadEthereumTrustedSetup} from "../../../src/util/kzg.js"; import {ethereumConsensusSpecsTests} from "../specTestVersioning.js"; import {specTestIterator} from "../utils/specTestIterator.js"; -/* eslint-disable @typescript-eslint/naming-convention */ - const ANCHOR_STATE_FILE_NAME = "anchor_state"; const ANCHOR_BLOCK_FILE_NAME = "anchor_block"; const BLOCK_FILE_NAME = "^(block)_([0-9a-zA-Z]+)$"; diff --git a/packages/beacon-node/test/spec/presets/genesis.test.ts b/packages/beacon-node/test/spec/presets/genesis.test.ts index 773debe3bb19..140fa3686e67 100644 --- a/packages/beacon-node/test/spec/presets/genesis.test.ts +++ b/packages/beacon-node/test/spec/presets/genesis.test.ts @@ -22,8 +22,6 @@ import {ethereumConsensusSpecsTests} from "../specTestVersioning.js"; // The aim of the genesis tests is to provide a baseline to test genesis-state initialization and test if the // proposed genesis-validity conditions are working. -/* eslint-disable @typescript-eslint/naming-convention */ - const genesis: TestRunnerFn = (fork, testName, testSuite) => { const testFn = genesisTestFns[testName]; if (testFn === undefined) { @@ -86,7 +84,7 @@ const genesisInitialization: TestRunnerFn testCase.state, - expectFunc: (testCase, expected, actual) => { + expectFunc: (_testCase, expected, actual) => { expectEqualBeaconState(fork, expected, actual); }, // Do not manually skip tests here, do it in packages/beacon-node/test/spec/presets/index.test.ts @@ -108,7 +106,7 @@ const genesisValidity: TestRunnerFn = (fork) = genesis: ssz[fork].BeaconState, }, getExpected: (testCase) => testCase.is_valid, - expectFunc: (testCase, expected, actual) => { + expectFunc: (_testCase, expected, actual) => { expect(actual).toEqualWithMessage(expected, "isValidGenesisState is not" + expected); }, }, diff --git a/packages/beacon-node/test/spec/presets/light_client/index.test.ts b/packages/beacon-node/test/spec/presets/light_client/index.test.ts index 0a44772cab4b..a8cc12238675 100644 --- a/packages/beacon-node/test/spec/presets/light_client/index.test.ts +++ b/packages/beacon-node/test/spec/presets/light_client/index.test.ts @@ -7,8 +7,6 @@ import {singleMerkleProof} from "./single_merkle_proof.js"; import {sync} from "./sync.js"; import {updateRanking} from "./update_ranking.js"; -/* eslint-disable @typescript-eslint/naming-convention */ - const lightClient: TestRunnerFn = (fork, testName, testSuite) => { const testFn = lightclientTestFns[testName]; if (testFn === undefined) { diff --git a/packages/beacon-node/test/spec/presets/light_client/single_merkle_proof.ts b/packages/beacon-node/test/spec/presets/light_client/single_merkle_proof.ts index d230bc926b0d..08dcd0ab8acf 100644 --- a/packages/beacon-node/test/spec/presets/light_client/single_merkle_proof.ts +++ b/packages/beacon-node/test/spec/presets/light_client/single_merkle_proof.ts @@ -7,8 +7,6 @@ import {ForkName} from "@lodestar/params"; import {toHex} from "@lodestar/utils"; import {TestRunnerFn} from "../../utils/types.js"; -/* eslint-disable @typescript-eslint/naming-convention */ - // https://github.com/ethereum/consensus-specs/blob/da3f5af919be4abb5a6db5a80b235deb8b4b5cba/tests/formats/light_client/single_merkle_proof.md type SingleMerkleProofTestCase = { meta?: any; @@ -23,7 +21,11 @@ type SingleMerkleProofTestCase = { }; }; -export const singleMerkleProof: TestRunnerFn = (fork, testHandler, testSuite) => { +export const singleMerkleProof: TestRunnerFn = ( + fork, + _testHandler, + testSuite +) => { return { testFunction: (testcase) => { // Assert correct proof generation @@ -39,7 +41,7 @@ export const singleMerkleProof: TestRunnerFn testCase.proof.branch, - expectFunc: (testCase, expected, actual) => { + expectFunc: (_testCase, expected, actual) => { expect(actual).deep.equals(expected); }, // Do not manually skip tests here, do it in packages/beacon-node/test/spec/presets/index.test.ts diff --git a/packages/beacon-node/test/spec/presets/light_client/sync.ts b/packages/beacon-node/test/spec/presets/light_client/sync.ts index bfd3d0d0bb3d..d931a5f310a8 100644 --- a/packages/beacon-node/test/spec/presets/light_client/sync.ts +++ b/packages/beacon-node/test/spec/presets/light_client/sync.ts @@ -9,8 +9,6 @@ import {computeSyncPeriodAtSlot} from "@lodestar/state-transition"; import {TestRunnerFn} from "../../utils/types.js"; import {testLogger} from "../../../utils/logger.js"; -/* eslint-disable @typescript-eslint/naming-convention */ - // https://github.com/ethereum/consensus-specs/blob/da3f5af919be4abb5a6db5a80b235deb8b4b5cba/tests/formats/light_client/single_merkle_proof.md type SyncTestCase = { meta: { diff --git a/packages/beacon-node/test/spec/presets/light_client/update_ranking.ts b/packages/beacon-node/test/spec/presets/light_client/update_ranking.ts index a2e60c1cc84a..b51219dd4e54 100644 --- a/packages/beacon-node/test/spec/presets/light_client/update_ranking.ts +++ b/packages/beacon-node/test/spec/presets/light_client/update_ranking.ts @@ -5,8 +5,6 @@ import {InputType} from "@lodestar/spec-test-util"; import {isBetterUpdate, LightClientUpdateSummary, toLightClientUpdateSummary} from "@lodestar/light-client/spec"; import {TestRunnerFn} from "../../utils/types.js"; -/* eslint-disable @typescript-eslint/naming-convention */ - // https://github.com/ethereum/consensus-specs/blob/da3f5af919be4abb5a6db5a80b235deb8b4b5cba/tests/formats/light_client/update_ranking.md type UpdateRankingTestCase = { meta: { diff --git a/packages/beacon-node/test/spec/presets/merkle.test.ts b/packages/beacon-node/test/spec/presets/merkle.test.ts index d3f6890527e9..71cebdbd0b5b 100644 --- a/packages/beacon-node/test/spec/presets/merkle.test.ts +++ b/packages/beacon-node/test/spec/presets/merkle.test.ts @@ -11,8 +11,6 @@ import {RunnerType, TestRunnerFn} from "../utils/types.js"; import {ethereumConsensusSpecsTests} from "../specTestVersioning.js"; import {specTestIterator} from "../utils/specTestIterator.js"; -/* eslint-disable @typescript-eslint/naming-convention */ - const merkle: TestRunnerFn = (fork) => { return { testFunction: (testcase) => { @@ -47,7 +45,7 @@ const merkle: TestRunnerFn = (fork) => { }), timeout: 10000, getExpected: (testCase) => testCase.proof, - expectFunc: (testCase, expected, actual) => { + expectFunc: (_testCase, expected, actual) => { expect(actual).toEqualWithMessage(expected, "incorrect proof"); }, // Do not manually skip tests here, do it in packages/beacon-node/test/spec/presets/index.test.ts diff --git a/packages/beacon-node/test/spec/presets/operations.test.ts b/packages/beacon-node/test/spec/presets/operations.test.ts index 7e2e9c1e9c5d..1ab8c19da5ef 100644 --- a/packages/beacon-node/test/spec/presets/operations.test.ts +++ b/packages/beacon-node/test/spec/presets/operations.test.ts @@ -20,8 +20,6 @@ import {BaseSpecTest, RunnerType, shouldVerify, TestRunnerFn} from "../utils/typ import {ethereumConsensusSpecsTests} from "../specTestVersioning.js"; import {specTestIterator} from "../utils/specTestIterator.js"; -/* eslint-disable @typescript-eslint/naming-convention */ - // Define above to re-use in sync_aggregate and sync_aggregate_random const sync_aggregate: BlockProcessFn = ( state, @@ -156,7 +154,7 @@ const operations: TestRunnerFn = (fork, }, shouldError: (testCase) => testCase.post === undefined, getExpected: (testCase) => testCase.post, - expectFunc: (testCase, expected, actual) => { + expectFunc: (_testCase, expected, actual) => { expectEqualBeaconState(fork, expected, actual); }, // Do not manually skip tests here, do it in packages/beacon-node/test/spec/presets/index.test.ts diff --git a/packages/beacon-node/test/spec/presets/rewards.test.ts b/packages/beacon-node/test/spec/presets/rewards.test.ts index 426245242d84..df43c8ca612e 100644 --- a/packages/beacon-node/test/spec/presets/rewards.test.ts +++ b/packages/beacon-node/test/spec/presets/rewards.test.ts @@ -13,8 +13,6 @@ import {assertCorrectProgressiveBalances} from "../config.js"; import {ethereumConsensusSpecsTests} from "../specTestVersioning.js"; import {specTestIterator} from "../utils/specTestIterator.js"; -/* eslint-disable @typescript-eslint/naming-convention */ - const deltasType = new VectorCompositeType(ssz.phase0.Balances, 2); const rewards: TestRunnerFn = (fork) => { @@ -57,7 +55,7 @@ const rewards: TestRunnerFn = (fork) => { ...(testCase.inclusion_delay_deltas ? [testCase.inclusion_delay_deltas] : []), testCase.inactivity_penalty_deltas, ]), - expectFunc: (testCase, expected, actual) => { + expectFunc: (_testCase, expected, actual) => { expect(actual).toEqual(expected); }, // Do not manually skip tests here, do it in packages/beacon-node/test/spec/presets/index.test.ts diff --git a/packages/beacon-node/test/spec/presets/sanity.test.ts b/packages/beacon-node/test/spec/presets/sanity.test.ts index 3ec1efb84fde..cd266483c7f8 100644 --- a/packages/beacon-node/test/spec/presets/sanity.test.ts +++ b/packages/beacon-node/test/spec/presets/sanity.test.ts @@ -18,8 +18,6 @@ import {assertCorrectProgressiveBalances} from "../config.js"; import {ethereumConsensusSpecsTests} from "../specTestVersioning.js"; import {specTestIterator} from "../utils/specTestIterator.js"; -/* eslint-disable @typescript-eslint/naming-convention */ - const sanity: TestRunnerFn = (fork, testName, testSuite) => { switch (testName) { case "slots": @@ -50,7 +48,7 @@ const sanitySlots: TestRunnerFn = (for shouldError: (testCase) => !testCase.post, timeout: 10000, getExpected: (testCase) => testCase.post, - expectFunc: (testCase, expected, actual) => { + expectFunc: (_testCase, expected, actual) => { expectEqualBeaconState(fork, expected, actual); }, // Do not manually skip tests here, do it in packages/beacon-node/test/spec/presets/index.test.ts @@ -88,7 +86,7 @@ const sanityBlocks: TestRunnerFn = (f shouldError: (testCase) => testCase.post === undefined, timeout: 10000, getExpected: (testCase) => testCase.post, - expectFunc: (testCase, expected, actual) => { + expectFunc: (_testCase, expected, actual) => { expectEqualBeaconState(fork, expected, actual); }, // Do not manually skip tests here, do it in packages/beacon-node/test/spec/presets/index.test.ts diff --git a/packages/beacon-node/test/spec/presets/ssz_static.test.ts b/packages/beacon-node/test/spec/presets/ssz_static.test.ts index 6e43d851ef66..06c7aa1fd98d 100644 --- a/packages/beacon-node/test/spec/presets/ssz_static.test.ts +++ b/packages/beacon-node/test/spec/presets/ssz_static.test.ts @@ -32,7 +32,7 @@ type Types = Record>; const sszStatic = (skippedFork: string, skippedTypes?: string[]) => - (fork: ForkName, typeName: string, testSuite: string, testSuiteDirpath: string): void => { + (fork: ForkName, typeName: string, _testSuite: string, testSuiteDirpath: string): void => { if (fork === skippedFork) { return; } @@ -78,7 +78,6 @@ const sszStatic = }; specTestIterator(path.join(ethereumConsensusSpecsTests.outputDir, "tests", ACTIVE_PRESET), { - // eslint-disable-next-line @typescript-eslint/naming-convention ssz_static: { type: RunnerType.custom, // starting from v1.4.0-beta.6, there is "whisk" fork in ssz_static tests but we ignore them diff --git a/packages/beacon-node/test/spec/presets/transition.test.ts b/packages/beacon-node/test/spec/presets/transition.test.ts index cae7c667b590..df818f701c5d 100644 --- a/packages/beacon-node/test/spec/presets/transition.test.ts +++ b/packages/beacon-node/test/spec/presets/transition.test.ts @@ -78,7 +78,7 @@ const transition = shouldError: (testCase) => testCase.post === undefined, timeout: 10000, getExpected: (testCase) => testCase.post, - expectFunc: (testCase, expected, actual) => { + expectFunc: (_testCase, expected, actual) => { expectEqualBeaconState(forkNext, expected, actual); }, // Do not manually skip tests here, do it in packages/beacon-node/test/spec/presets/index.test.ts @@ -88,8 +88,6 @@ const transition = }; }; -/* eslint-disable @typescript-eslint/naming-convention */ - function getTransitionConfig(fork: ForkName, forkEpoch: number): Partial { switch (fork) { case ForkName.phase0: diff --git a/packages/beacon-node/test/spec/specTestVersioning.ts b/packages/beacon-node/test/spec/specTestVersioning.ts index d4bc192f6cad..5e15b696e4a1 100644 --- a/packages/beacon-node/test/spec/specTestVersioning.ts +++ b/packages/beacon-node/test/spec/specTestVersioning.ts @@ -11,7 +11,6 @@ import {DownloadTestsOptions} from "@lodestar/spec-test-util/downloadTests"; // Global variable __dirname no longer available in ES6 modules. // Solutions: https://stackoverflow.com/questions/46745014/alternative-for-dirname-in-node-js-when-using-es6-modules -// eslint-disable-next-line @typescript-eslint/naming-convention const __dirname = path.dirname(fileURLToPath(import.meta.url)); export const ethereumConsensusSpecsTests: DownloadTestsOptions = { diff --git a/packages/beacon-node/test/spec/utils/runValidSszTest.ts b/packages/beacon-node/test/spec/utils/runValidSszTest.ts index e5f249ab5257..7ca02cec2d1e 100644 --- a/packages/beacon-node/test/spec/utils/runValidSszTest.ts +++ b/packages/beacon-node/test/spec/utils/runValidSszTest.ts @@ -21,7 +21,7 @@ export function runValidSszTest(type: Type, testData: ValidTestCaseData console.log( JSON.stringify( testData.jsonValue, - (key, value: unknown) => (typeof value === "bigint" ? value.toString() : value), + (_key, value: unknown) => (typeof value === "bigint" ? value.toString() : value), 2 ) ); diff --git a/packages/beacon-node/test/spec/utils/types.ts b/packages/beacon-node/test/spec/utils/types.ts index 94ad7b73de3f..00bebffd7d7e 100644 --- a/packages/beacon-node/test/spec/utils/types.ts +++ b/packages/beacon-node/test/spec/utils/types.ts @@ -26,8 +26,6 @@ export type TestRunner = | {type: RunnerType.default; fn: TestRunnerFn} | {type: RunnerType.custom; fn: TestRunnerCustom}; -/* eslint-disable @typescript-eslint/naming-convention */ - export type BaseSpecTest = { meta?: { bls_setting?: bigint; diff --git a/packages/beacon-node/test/tsconfig.json b/packages/beacon-node/test/tsconfig.json index 7e6bad81b22f..f4241fc1fbcd 100644 --- a/packages/beacon-node/test/tsconfig.json +++ b/packages/beacon-node/test/tsconfig.json @@ -3,4 +3,4 @@ "compilerOptions": { "noEmit": false } -} \ No newline at end of file +} diff --git a/packages/beacon-node/test/unit/api/impl/events/events.test.ts b/packages/beacon-node/test/unit/api/impl/events/events.test.ts index e031c3ac9958..a5dd21d14fd3 100644 --- a/packages/beacon-node/test/unit/api/impl/events/events.test.ts +++ b/packages/beacon-node/test/unit/api/impl/events/events.test.ts @@ -11,7 +11,6 @@ vi.mock("../../../../../src/chain/index.js", async (importActual) => { return { ...mod, - // eslint-disable-next-line @typescript-eslint/naming-convention BeaconChain: vi.spyOn(mod, "BeaconChain").mockImplementation(() => { return { emitter: new ChainEventEmitter(), diff --git a/packages/beacon-node/test/unit/api/impl/validator/produceBlockV3.test.ts b/packages/beacon-node/test/unit/api/impl/validator/produceBlockV3.test.ts index a7299aa3b956..d8f1b9a317b9 100644 --- a/packages/beacon-node/test/unit/api/impl/validator/produceBlockV3.test.ts +++ b/packages/beacon-node/test/unit/api/impl/validator/produceBlockV3.test.ts @@ -12,7 +12,6 @@ import {CommonBlockBody} from "../../../../../src/chain/interface.js"; import {zeroProtoBlock} from "../../../../utils/state.js"; import {defaultApiOptions} from "../../../../../src/api/options.js"; -/* eslint-disable @typescript-eslint/naming-convention */ describe("api/validator - produceBlockV3", function () { let modules: ApiTestModules; let api: ReturnType; @@ -143,7 +142,7 @@ describe("api/validator - produceBlockV3", function () { }); const expectedBlock = finalSelection === "builder" ? blindedBlock : fullBlock; - const expectedExecution = finalSelection === "builder" ? true : false; + const expectedExecution = finalSelection === "builder"; expect(block).toEqual(expectedBlock); expect(meta.executionPayloadBlinded).toEqual(expectedExecution); diff --git a/packages/beacon-node/test/unit/chain/beaconProposerCache.ts b/packages/beacon-node/test/unit/chain/beaconProposerCache.ts index 4545ef0c94b2..538fe8518458 100644 --- a/packages/beacon-node/test/unit/chain/beaconProposerCache.ts +++ b/packages/beacon-node/test/unit/chain/beaconProposerCache.ts @@ -1,4 +1,4 @@ -import {expect} from "vitest"; +import {expect, describe, it, beforeEach} from "vitest"; import {BeaconProposerCache} from "../../../src/chain/beaconProposerCache.js"; const suggestedFeeRecipient = "0xaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa"; diff --git a/packages/beacon-node/test/unit/chain/genesis/genesis.test.ts b/packages/beacon-node/test/unit/chain/genesis/genesis.test.ts index f836e3621cc9..5b48ca9fd953 100644 --- a/packages/beacon-node/test/unit/chain/genesis/genesis.test.ts +++ b/packages/beacon-node/test/unit/chain/genesis/genesis.test.ts @@ -1,4 +1,3 @@ -/* eslint-disable @typescript-eslint/naming-convention */ import {toHexString} from "@chainsafe/ssz"; import {describe, it, expect} from "vitest"; import {PublicKey, SecretKey} from "@chainsafe/blst"; diff --git a/packages/beacon-node/test/unit/chain/lightclient/upgradeLightClientHeader.test.ts b/packages/beacon-node/test/unit/chain/lightclient/upgradeLightClientHeader.test.ts index 6da728be46e9..ab8f166076b9 100644 --- a/packages/beacon-node/test/unit/chain/lightclient/upgradeLightClientHeader.test.ts +++ b/packages/beacon-node/test/unit/chain/lightclient/upgradeLightClientHeader.test.ts @@ -8,7 +8,6 @@ describe("UpgradeLightClientHeader", function () { let lcHeaderByFork: Record; let testSlots: Record; - /* eslint-disable @typescript-eslint/naming-convention */ const chainConfig = createChainForkConfig({ ...defaultChainConfig, ALTAIR_FORK_EPOCH: 1, diff --git a/packages/beacon-node/test/unit/chain/opPools/attestationPool.test.ts b/packages/beacon-node/test/unit/chain/opPools/attestationPool.test.ts index 68efd0751585..eba01888fa7c 100644 --- a/packages/beacon-node/test/unit/chain/opPools/attestationPool.test.ts +++ b/packages/beacon-node/test/unit/chain/opPools/attestationPool.test.ts @@ -13,7 +13,6 @@ export const validSignature = fromHexString( ); describe("AttestationPool", function () { - /* eslint-disable @typescript-eslint/naming-convention */ const config = createChainForkConfig({ ...defaultChainConfig, ELECTRA_FORK_EPOCH: 5, diff --git a/packages/beacon-node/test/unit/chain/rewards/blockRewards.test.ts b/packages/beacon-node/test/unit/chain/rewards/blockRewards.test.ts index f0d85ce3220f..d417d83e2da9 100644 --- a/packages/beacon-node/test/unit/chain/rewards/blockRewards.test.ts +++ b/packages/beacon-node/test/unit/chain/rewards/blockRewards.test.ts @@ -10,9 +10,7 @@ import { import { generatePerfTestCachedStateAltair, cachedStateAltairPopulateCaches, - // eslint-disable-next-line import/no-relative-packages } from "../../../../../state-transition/test/perf/util.js"; -// eslint-disable-next-line import/no-relative-packages import {BlockAltairOpts, getBlockAltair} from "../../../../../state-transition/test/perf/block/util.js"; import {computeBlockRewards} from "../../../../src/chain/rewards/blockRewards.js"; diff --git a/packages/beacon-node/test/unit/chain/seenCache/seenGossipBlockInput.test.ts b/packages/beacon-node/test/unit/chain/seenCache/seenGossipBlockInput.test.ts index 2a3275536f22..27b5eadecf11 100644 --- a/packages/beacon-node/test/unit/chain/seenCache/seenGossipBlockInput.test.ts +++ b/packages/beacon-node/test/unit/chain/seenCache/seenGossipBlockInput.test.ts @@ -5,7 +5,6 @@ import {ssz} from "@lodestar/types"; import {SeenGossipBlockInput} from "../../../../src/chain/seenCache/seenGossipBlockInput.js"; import {BlockInputType, GossipedInputType, BlockInput} from "../../../../src/chain/blocks/types.js"; -/* eslint-disable @typescript-eslint/naming-convention */ describe("SeenGossipBlockInput", () => { const chainConfig = createChainForkConfig({ ...defaultChainConfig, diff --git a/packages/beacon-node/test/unit/chain/shufflingCache.test.ts b/packages/beacon-node/test/unit/chain/shufflingCache.test.ts index 62b02cbf2b12..3c1824b8c01d 100644 --- a/packages/beacon-node/test/unit/chain/shufflingCache.test.ts +++ b/packages/beacon-node/test/unit/chain/shufflingCache.test.ts @@ -1,5 +1,4 @@ import {describe, it, expect, beforeEach} from "vitest"; -// eslint-disable-next-line import/no-relative-packages import {generateTestCachedBeaconStateOnlyValidators} from "../../../../state-transition/test/perf/util.js"; import {ShufflingCache} from "../../../src/chain/shufflingCache.js"; diff --git a/packages/beacon-node/test/unit/chain/validation/aggregateAndProof.test.ts b/packages/beacon-node/test/unit/chain/validation/aggregateAndProof.test.ts index f2c20fd5cbe4..e2bc392b4ea2 100644 --- a/packages/beacon-node/test/unit/chain/validation/aggregateAndProof.test.ts +++ b/packages/beacon-node/test/unit/chain/validation/aggregateAndProof.test.ts @@ -2,7 +2,6 @@ import {BitArray, toHexString} from "@chainsafe/ssz"; import {describe, it} from "vitest"; import {SLOTS_PER_EPOCH} from "@lodestar/params"; import {phase0, ssz} from "@lodestar/types"; -// eslint-disable-next-line import/no-relative-packages import {generateTestCachedBeaconStateOnlyValidators} from "../../../../../state-transition/test/perf/util.js"; import {IBeaconChain} from "../../../../src/chain/index.js"; import {AttestationErrorCode} from "../../../../src/chain/errors/index.js"; @@ -24,7 +23,6 @@ describe("chain / validation / aggregateAndProof", () => { const getState = memoOnce(() => generateTestCachedBeaconStateOnlyValidators({vc, slot: stateSlot})); - // eslint-disable-next-line @typescript-eslint/explicit-function-return-type function getValidData(opts?: Partial) { return getAggregateAndProofValidData({ currentSlot: stateSlot, diff --git a/packages/beacon-node/test/unit/chain/validation/attestation/getShufflingForAttestationVerification.test.ts b/packages/beacon-node/test/unit/chain/validation/attestation/getShufflingForAttestationVerification.test.ts index a0eb147db8e8..9aa7c29c7825 100644 --- a/packages/beacon-node/test/unit/chain/validation/attestation/getShufflingForAttestationVerification.test.ts +++ b/packages/beacon-node/test/unit/chain/validation/attestation/getShufflingForAttestationVerification.test.ts @@ -1,6 +1,5 @@ import {afterEach, beforeEach, describe, expect, it, vi} from "vitest"; // We need to import the mock before the packages -// eslint-disable-next-line import/order import {MockedBeaconChain, getMockedBeaconChain} from "../../../../mocks/mockedBeaconChain.js"; import {EpochShuffling, computeStartSlotAtEpoch} from "@lodestar/state-transition"; import {EpochDifference, ProtoBlock} from "@lodestar/fork-choice"; diff --git a/packages/beacon-node/test/unit/chain/validation/attestation/validateAttestation.test.ts b/packages/beacon-node/test/unit/chain/validation/attestation/validateAttestation.test.ts index 90d37a74289d..be9fd3587b7c 100644 --- a/packages/beacon-node/test/unit/chain/validation/attestation/validateAttestation.test.ts +++ b/packages/beacon-node/test/unit/chain/validation/attestation/validateAttestation.test.ts @@ -3,7 +3,6 @@ import {describe, expect, it} from "vitest"; import {ForkName, SLOTS_PER_EPOCH} from "@lodestar/params"; import {ssz} from "@lodestar/types"; import {LodestarError} from "@lodestar/utils"; -// eslint-disable-next-line import/no-relative-packages import {generateTestCachedBeaconStateOnlyValidators} from "../../../../../../state-transition/test/perf/util.js"; import {AttestationErrorCode, GossipErrorCode} from "../../../../../src/chain/errors/index.js"; import {IBeaconChain} from "../../../../../src/chain/index.js"; @@ -31,7 +30,6 @@ describe("validateAttestation", () => { const getState = memoOnce(() => generateTestCachedBeaconStateOnlyValidators({vc, slot: stateSlot})); - // eslint-disable-next-line @typescript-eslint/explicit-function-return-type function getValidData(opts?: Partial) { return getAttestationValidData({ currentSlot: stateSlot, diff --git a/packages/beacon-node/test/unit/chain/validation/block.test.ts b/packages/beacon-node/test/unit/chain/validation/block.test.ts index d90ca4a54d24..28375f1625e1 100644 --- a/packages/beacon-node/test/unit/chain/validation/block.test.ts +++ b/packages/beacon-node/test/unit/chain/validation/block.test.ts @@ -33,7 +33,6 @@ describe("gossip block validation", function () { chain.forkChoice = forkChoice; regen = chain.regen; - // eslint-disable-next-line @typescript-eslint/no-unsafe-member-access (chain as any).opts = {maxSkipSlots}; verifySignature = chain.bls.verifySignatureSets; diff --git a/packages/beacon-node/test/unit/chain/validation/lightClientFinalityUpdate.test.ts b/packages/beacon-node/test/unit/chain/validation/lightClientFinalityUpdate.test.ts index ef4364abc366..76eb18fc38eb 100644 --- a/packages/beacon-node/test/unit/chain/validation/lightClientFinalityUpdate.test.ts +++ b/packages/beacon-node/test/unit/chain/validation/lightClientFinalityUpdate.test.ts @@ -12,7 +12,6 @@ describe("Light Client Finality Update validation", function () { const afterEachCallbacks: (() => Promise | void)[] = []; const config = createChainForkConfig({ ...defaultChainConfig, - /* eslint-disable @typescript-eslint/naming-convention */ ALTAIR_FORK_EPOCH: 1, BELLATRIX_FORK_EPOCH: 3, CAPELLA_FORK_EPOCH: Infinity, diff --git a/packages/beacon-node/test/unit/chain/validation/lightClientOptimisticUpdate.test.ts b/packages/beacon-node/test/unit/chain/validation/lightClientOptimisticUpdate.test.ts index b63a08757380..7e35f1272ad6 100644 --- a/packages/beacon-node/test/unit/chain/validation/lightClientOptimisticUpdate.test.ts +++ b/packages/beacon-node/test/unit/chain/validation/lightClientOptimisticUpdate.test.ts @@ -12,7 +12,6 @@ describe("Light Client Optimistic Update validation", function () { const afterEachCallbacks: (() => Promise | void)[] = []; const config = createChainForkConfig({ ...defaultChainConfig, - /* eslint-disable @typescript-eslint/naming-convention */ ALTAIR_FORK_EPOCH: 1, BELLATRIX_FORK_EPOCH: 3, CAPELLA_FORK_EPOCH: Infinity, diff --git a/packages/beacon-node/test/unit/chain/validation/syncCommittee.test.ts b/packages/beacon-node/test/unit/chain/validation/syncCommittee.test.ts index b498333ae738..26571ab19a77 100644 --- a/packages/beacon-node/test/unit/chain/validation/syncCommittee.test.ts +++ b/packages/beacon-node/test/unit/chain/validation/syncCommittee.test.ts @@ -20,7 +20,6 @@ describe("Sync Committee Signature validation", function () { let altairForkEpochBk: Epoch; const altairForkEpoch = 2020; const currentSlot = SLOTS_PER_EPOCH * (altairForkEpoch + 1); - // eslint-disable-next-line @typescript-eslint/naming-convention const config = createChainForkConfig(Object.assign({}, defaultChainConfig, {ALTAIR_FORK_EPOCH: altairForkEpoch})); // all validators have same pubkey const validatorIndexInSyncCommittee = 15; diff --git a/packages/beacon-node/test/unit/db/api/repository.test.ts b/packages/beacon-node/test/unit/db/api/repository.test.ts index 07c199632125..28065c84c7ea 100644 --- a/packages/beacon-node/test/unit/db/api/repository.test.ts +++ b/packages/beacon-node/test/unit/db/api/repository.test.ts @@ -11,7 +11,6 @@ vi.mock("@lodestar/db", async (importOriginal) => { return { ...mod, - // eslint-disable-next-line @typescript-eslint/naming-convention LevelDbController: vi.spyOn(mod, "LevelDbController").mockImplementation(() => { return { get: vi.fn(), @@ -31,7 +30,6 @@ interface TestType { bytes: Bytes32; } -// eslint-disable-next-line @typescript-eslint/naming-convention const TestSSZType = new ContainerType({ bool: ssz.Boolean, bytes: ssz.Bytes32, diff --git a/packages/beacon-node/test/unit/eth1/eth1MergeBlockTracker.test.ts b/packages/beacon-node/test/unit/eth1/eth1MergeBlockTracker.test.ts index 151f3931cfde..edf571b905b3 100644 --- a/packages/beacon-node/test/unit/eth1/eth1MergeBlockTracker.test.ts +++ b/packages/beacon-node/test/unit/eth1/eth1MergeBlockTracker.test.ts @@ -8,8 +8,6 @@ import {Eth1MergeBlockTracker, StatusCode, toPowBlock} from "../../../src/eth1/e import {Eth1ProviderState, EthJsonRpcBlockRaw} from "../../../src/eth1/interface.js"; import {testLogger} from "../../utils/logger.js"; -/* eslint-disable @typescript-eslint/naming-convention */ - describe("eth1 / Eth1MergeBlockTracker", () => { const logger = testLogger(); diff --git a/packages/beacon-node/test/unit/eth1/utils/deposits.test.ts b/packages/beacon-node/test/unit/eth1/utils/deposits.test.ts index 316f75efc5ce..88d2796a12de 100644 --- a/packages/beacon-node/test/unit/eth1/utils/deposits.test.ts +++ b/packages/beacon-node/test/unit/eth1/utils/deposits.test.ts @@ -99,7 +99,6 @@ describe("eth1 / util / deposits", function () { }, ]; - /* eslint-disable @typescript-eslint/naming-convention */ const postElectraConfig = createChainForkConfig({ ALTAIR_FORK_EPOCH: 1, BELLATRIX_FORK_EPOCH: 2, diff --git a/packages/beacon-node/test/unit/eth1/utils/optimizeNextBlockDiffForGenesis.test.ts b/packages/beacon-node/test/unit/eth1/utils/optimizeNextBlockDiffForGenesis.test.ts index cacfd7dc685f..0521823d1283 100644 --- a/packages/beacon-node/test/unit/eth1/utils/optimizeNextBlockDiffForGenesis.test.ts +++ b/packages/beacon-node/test/unit/eth1/utils/optimizeNextBlockDiffForGenesis.test.ts @@ -5,11 +5,8 @@ import {Eth1Block} from "../../../../src/eth1/interface.js"; describe("eth1 / utils / optimizeNextBlockDiffForGenesis", function () { it("should return optimized block diff to find genesis time", () => { const params = { - // eslint-disable-next-line @typescript-eslint/naming-convention MIN_GENESIS_TIME: 1578009600, - // eslint-disable-next-line @typescript-eslint/naming-convention GENESIS_DELAY: 172800, - // eslint-disable-next-line @typescript-eslint/naming-convention SECONDS_PER_ETH1_BLOCK: 14, }; const initialTimeDiff = params.GENESIS_DELAY * 2; diff --git a/packages/beacon-node/test/unit/monitoring/remoteService.ts b/packages/beacon-node/test/unit/monitoring/remoteService.ts index c5ce0e9ef0b3..bea50eee3bdd 100644 --- a/packages/beacon-node/test/unit/monitoring/remoteService.ts +++ b/packages/beacon-node/test/unit/monitoring/remoteService.ts @@ -77,7 +77,7 @@ function validateClientStats(data: ReceivedData, schema: ClientStatsSchema): voi schema.forEach((s) => { try { expect(data[s.key]).toBeInstanceOf(s.type); - } catch { + } catch (_e) { throw new Error( `Validation of property "${s.key}" failed. Expected type "${s.type}" but received "${typeof data[s.key]}".` ); diff --git a/packages/beacon-node/test/unit/monitoring/service.test.ts b/packages/beacon-node/test/unit/monitoring/service.test.ts index 43936ff1756d..0795a165538e 100644 --- a/packages/beacon-node/test/unit/monitoring/service.test.ts +++ b/packages/beacon-node/test/unit/monitoring/service.test.ts @@ -108,7 +108,6 @@ describe("monitoring / service", () => { expect(logger.info).toHaveBeenCalledWith( "Started monitoring service", // TODO: Debug why `expect.any` causing type error - // eslint-disable-next-line @typescript-eslint/no-unsafe-assignment expect.objectContaining({interval: expect.any(Number), machine: null, remote: expect.any(String)}) ); }); diff --git a/packages/beacon-node/test/unit/network/beaconBlocksMaybeBlobsByRange.test.ts b/packages/beacon-node/test/unit/network/beaconBlocksMaybeBlobsByRange.test.ts index d1dc7ba57fa9..dda4959c7b3e 100644 --- a/packages/beacon-node/test/unit/network/beaconBlocksMaybeBlobsByRange.test.ts +++ b/packages/beacon-node/test/unit/network/beaconBlocksMaybeBlobsByRange.test.ts @@ -17,7 +17,6 @@ describe("beaconBlocksMaybeBlobsByRange", () => { const peerId = "Qma9T5YraSnpRDZqRR4krcSJabThc8nwZuJV3LercPHufi"; - /* eslint-disable @typescript-eslint/naming-convention */ const chainConfig = createChainForkConfig({ ...defaultChainConfig, ALTAIR_FORK_EPOCH: 0, diff --git a/packages/beacon-node/test/unit/network/peers/priorization.test.ts b/packages/beacon-node/test/unit/network/peers/priorization.test.ts index 3ec770051275..cc9ef9b7d711 100644 --- a/packages/beacon-node/test/unit/network/peers/priorization.test.ts +++ b/packages/beacon-node/test/unit/network/peers/priorization.test.ts @@ -14,7 +14,6 @@ import {RequestedSubnet} from "../../../../src/network/peers/utils/index.js"; type Result = ReturnType; -// eslint-disable-next-line vitest/valid-describe-callback describe("network / peers / priorization", async () => { const peers: PeerId[] = []; for (let i = 0; i < 8; i++) { @@ -264,7 +263,6 @@ describe("network / peers / priorization", async () => { } }); -// eslint-disable-next-line vitest/valid-describe-callback describe("sortPeersToPrune", async function () { const peers: PeerId[] = []; for (let i = 0; i < 8; i++) { diff --git a/packages/beacon-node/test/unit/network/peers/score.test.ts b/packages/beacon-node/test/unit/network/peers/score.test.ts index df842f9a1310..54cb721a4c21 100644 --- a/packages/beacon-node/test/unit/network/peers/score.test.ts +++ b/packages/beacon-node/test/unit/network/peers/score.test.ts @@ -24,7 +24,6 @@ describe("simple block provider score tracking", function () { const MIN_SCORE = -100; const actionName = "test-action"; - // eslint-disable-next-line @typescript-eslint/explicit-function-return-type function mockStore() { const scoreStore = new PeerRpcScoreStore(); const peerScores = scoreStore["scores"] as MapDef; diff --git a/packages/beacon-node/test/unit/network/subnets/attnetsService.test.ts b/packages/beacon-node/test/unit/network/subnets/attnetsService.test.ts index 0c7b3df98268..cf9345172083 100644 --- a/packages/beacon-node/test/unit/network/subnets/attnetsService.test.ts +++ b/packages/beacon-node/test/unit/network/subnets/attnetsService.test.ts @@ -26,7 +26,6 @@ describe("AttnetsService", () => { "be" ); const ALTAIR_FORK_EPOCH = 100; - // eslint-disable-next-line @typescript-eslint/naming-convention const config = createBeaconConfig({ALTAIR_FORK_EPOCH}, ZERO_HASH); // const {SECONDS_PER_SLOT} = config; let service: AttnetsService; diff --git a/packages/beacon-node/test/unit/sync/backfill/verify.test.ts b/packages/beacon-node/test/unit/sync/backfill/verify.test.ts index 08ffdc4c3b02..3d1a2cd7e7e5 100644 --- a/packages/beacon-node/test/unit/sync/backfill/verify.test.ts +++ b/packages/beacon-node/test/unit/sync/backfill/verify.test.ts @@ -12,7 +12,6 @@ import {BackfillSyncErrorCode, BackfillSyncError} from "./../../../../src/sync/b // Global variable __dirname no longer available in ES6 modules. // Solutions: https://stackoverflow.com/questions/46745014/alternative-for-dirname-in-node-js-when-using-es6-modules -// eslint-disable-next-line @typescript-eslint/naming-convention const __dirname = path.dirname(fileURLToPath(import.meta.url)); describe("backfill sync - verify block sequence", function () { @@ -43,7 +42,9 @@ describe("backfill sync - verify block sequence", function () { const {error} = verifyBlockSequence( beaconConfig, // remove middle block - blocks.filter((b) => b.data.message.slot !== 2).slice(0, blocks.length - 2), + blocks + .filter((b) => b.data.message.slot !== 2) + .slice(0, blocks.length - 2), blocks[blocks.length - 1].data.message.parentRoot ); if (error != null) throw new BackfillSyncError({code: error}); diff --git a/packages/beacon-node/test/unit/sync/range/chain.test.ts b/packages/beacon-node/test/unit/sync/range/chain.test.ts index 44d5cc7c173a..658f950b2c18 100644 --- a/packages/beacon-node/test/unit/sync/range/chain.test.ts +++ b/packages/beacon-node/test/unit/sync/range/chain.test.ts @@ -72,7 +72,7 @@ describe("sync / range / chain", () => { } }; - const downloadBeaconBlocksByRange: SyncChainFns["downloadBeaconBlocksByRange"] = async (peerId, request) => { + const downloadBeaconBlocksByRange: SyncChainFns["downloadBeaconBlocksByRange"] = async (_peerId, request) => { const blocks: BlockInput[] = []; for (let i = request.startSlot; i < request.startSlot + request.count; i += request.step) { if (skippedSlots?.has(i)) { @@ -124,7 +124,7 @@ describe("sync / range / chain", () => { const peers = [peer]; const processChainSegment: SyncChainFns["processChainSegment"] = async () => {}; - const downloadBeaconBlocksByRange: SyncChainFns["downloadBeaconBlocksByRange"] = async (peer, request) => { + const downloadBeaconBlocksByRange: SyncChainFns["downloadBeaconBlocksByRange"] = async (_peer, request) => { const blocks: BlockInput[] = []; for (let i = request.startSlot; i < request.startSlot + request.count; i += request.step) { blocks.push( diff --git a/packages/beacon-node/test/unit/sync/unknownBlock.test.ts b/packages/beacon-node/test/unit/sync/unknownBlock.test.ts index f6791fc29e9c..4805bd123898 100644 --- a/packages/beacon-node/test/unit/sync/unknownBlock.test.ts +++ b/packages/beacon-node/test/unit/sync/unknownBlock.test.ts @@ -22,7 +22,6 @@ import {ZERO_HASH} from "../../../src/constants/constants.js"; describe("sync by UnknownBlockSync", () => { const logger = testLogger(); const slotSec = 0.3; - // eslint-disable-next-line @typescript-eslint/naming-convention const config = createChainForkConfig({...minimalConfig, SECONDS_PER_SLOT: slotSec}); beforeEach(() => { @@ -119,11 +118,13 @@ describe("sync by UnknownBlockSync", () => { ]); let reportPeerResolveFn: (value: Parameters) => void; - const reportPeerPromise = new Promise>((r) => (reportPeerResolveFn = r)); + const reportPeerPromise = new Promise>((r) => { + reportPeerResolveFn = r; + }); let sendBeaconBlocksByRootResolveFn: (value: Parameters) => void; - const sendBeaconBlocksByRootPromise = new Promise>( - (r) => (sendBeaconBlocksByRootResolveFn = r) - ); + const sendBeaconBlocksByRootPromise = new Promise>((r) => { + sendBeaconBlocksByRootResolveFn = r; + }); const network: Partial = { events: new NetworkEventBus(), @@ -157,8 +158,12 @@ describe("sync by UnknownBlockSync", () => { let blockAResolver: () => void; let blockCResolver: () => void; - const blockAProcessed = new Promise((resolve) => (blockAResolver = resolve)); - const blockCProcessed = new Promise((resolve) => (blockCResolver = resolve)); + const blockAProcessed = new Promise((resolve) => { + blockAResolver = resolve; + }); + const blockCProcessed = new Promise((resolve) => { + blockCResolver = resolve; + }); const chain: Partial = { clock: new ClockStopped(0), diff --git a/packages/beacon-node/test/unit/util/kzg.test.ts b/packages/beacon-node/test/unit/util/kzg.test.ts index e170aed1a2de..13cea96d87a6 100644 --- a/packages/beacon-node/test/unit/util/kzg.test.ts +++ b/packages/beacon-node/test/unit/util/kzg.test.ts @@ -31,7 +31,6 @@ describe("C-KZG", () => { expect(ckzg.verifyBlobKzgProofBatch(blobs, commitments, proofs)).toBe(true); }); - /* eslint-disable @typescript-eslint/naming-convention */ it("BlobSidecars", async () => { const chainConfig = createChainForkConfig({ ...defaultChainConfig, @@ -67,7 +66,7 @@ describe("C-KZG", () => { blobSidecars.forEach(async (blobSidecar) => { try { await validateGossipBlobSidecar(chain, blobSidecar, blobSidecar.index); - } catch (error) { + } catch (_e) { // We expect some error from here // console.log(error); } diff --git a/packages/beacon-node/test/utils/clock.ts b/packages/beacon-node/test/utils/clock.ts index ea14c866c1b0..390d7dd095dd 100644 --- a/packages/beacon-node/test/utils/clock.ts +++ b/packages/beacon-node/test/utils/clock.ts @@ -4,11 +4,14 @@ import {Slot, Epoch} from "@lodestar/types"; import {IClock} from "../../src/util/clock.js"; export class ClockStatic extends EventEmitter implements IClock { + genesisTime: number; + constructor( readonly currentSlot: Slot, - public genesisTime = 0 + genesisTime = 0 ) { super(); + this.genesisTime = genesisTime; } get currentEpoch(): Epoch { diff --git a/packages/beacon-node/test/utils/config.ts b/packages/beacon-node/test/utils/config.ts index 2aad1c14c03e..f5d566560b65 100644 --- a/packages/beacon-node/test/utils/config.ts +++ b/packages/beacon-node/test/utils/config.ts @@ -6,7 +6,6 @@ import {ZERO_HASH} from "../../src/constants/index.js"; /** default config with ZERO_HASH as genesisValidatorsRoot */ export const config = createBeaconConfig(chainConfig, ZERO_HASH); -/* eslint-disable @typescript-eslint/naming-convention */ export function getConfig(fork: ForkName, forkEpoch = 0): ChainForkConfig { switch (fork) { case ForkName.phase0: diff --git a/packages/beacon-node/test/utils/node/simTest.ts b/packages/beacon-node/test/utils/node/simTest.ts index e94c32cefb10..7b771b8534ed 100644 --- a/packages/beacon-node/test/utils/node/simTest.ts +++ b/packages/beacon-node/test/utils/node/simTest.ts @@ -112,7 +112,7 @@ function avg(arr: number[]): number { /** * Print a table grid of (Y) epoch / (X) slot_per_epoch */ -function printEpochSlotGrid(map: Map, config: BeaconConfig, title: string): void { +function printEpochSlotGrid(map: Map, _config: BeaconConfig, title: string): void { const lastSlot = Array.from(map.keys())[map.size - 1]; const lastEpoch = computeEpochAtSlot(lastSlot); const rowsByEpochBySlot = linspace(0, lastEpoch).map((epoch) => { @@ -132,7 +132,7 @@ function printEpochGrid(maps: Record>, title: string) return epoch > max ? epoch : max; }, 0); const epochGrid = linspace(0, lastEpoch).map((epoch) => - mapValues(maps, (val, key) => formatValue(maps[key].get(epoch))) + mapValues(maps, (_val, key) => formatValue(maps[key].get(epoch))) ); console.log(renderTitle(title)); console.table(epochGrid); diff --git a/packages/beacon-node/test/utils/runEl.ts b/packages/beacon-node/test/utils/runEl.ts index 9adf1a83c151..f7a2b2f52e58 100644 --- a/packages/beacon-node/test/utils/runEl.ts +++ b/packages/beacon-node/test/utils/runEl.ts @@ -7,7 +7,6 @@ import {Eth1Provider} from "../../src/index.js"; import {ZERO_HASH} from "../../src/constants/index.js"; import {shell} from "../sim/shell.js"; -/* eslint-disable @typescript-eslint/naming-convention */ /* eslint-disable no-console */ let txRpcId = 1; @@ -84,7 +83,7 @@ async function waitForELOnline(url: string, signal: AbortSignal): Promise console.log("Waiting for few seconds for EL to fully setup, for e.g. unlock the account..."); await sleep(5000, signal); return; // Done - } catch (e) { + } catch (_e) { await sleep(1000, signal); } } diff --git a/packages/beacon-node/test/utils/validationData/aggregateAndProof.ts b/packages/beacon-node/test/utils/validationData/aggregateAndProof.ts index 45adfec433e4..462502719134 100644 --- a/packages/beacon-node/test/utils/validationData/aggregateAndProof.ts +++ b/packages/beacon-node/test/utils/validationData/aggregateAndProof.ts @@ -1,7 +1,6 @@ import {computeSigningRoot} from "@lodestar/state-transition"; import {DOMAIN_AGGREGATE_AND_PROOF, DOMAIN_SELECTION_PROOF} from "@lodestar/params"; import {phase0, ssz} from "@lodestar/types"; -// eslint-disable-next-line import/no-relative-packages import {getSecretKeyFromIndexCached} from "../../../../state-transition/test/perf/util.js"; import {IBeaconChain} from "../../../src/chain/index.js"; import {SeenAggregators} from "../../../src/chain/seenCache/index.js"; diff --git a/packages/beacon-node/test/utils/validationData/attestation.ts b/packages/beacon-node/test/utils/validationData/attestation.ts index 22f551cbb663..6715512ac667 100644 --- a/packages/beacon-node/test/utils/validationData/attestation.ts +++ b/packages/beacon-node/test/utils/validationData/attestation.ts @@ -6,7 +6,6 @@ import {phase0, Slot, ssz} from "@lodestar/types"; import { generateTestCachedBeaconStateOnlyValidators, getSecretKeyFromIndexCached, - // eslint-disable-next-line import/no-relative-packages } from "../../../../state-transition/test/perf/util.js"; import {IBeaconChain} from "../../../src/chain/index.js"; import {IStateRegenerator} from "../../../src/chain/regen/index.js"; diff --git a/packages/cli/docsgen/markdown.ts b/packages/cli/docsgen/markdown.ts index 5c3033e9c0df..9c7a4d0ca279 100644 --- a/packages/cli/docsgen/markdown.ts +++ b/packages/cli/docsgen/markdown.ts @@ -117,7 +117,6 @@ function renderOption(optionName: string, option: CliOptionDefinition): string | defaultValue = `"${defaultValue}"`; } if (option.type === "array") { - // eslint-disable-next-line quotes if (!defaultValue.includes(`"`)) { defaultValue = `"${defaultValue}"`; } diff --git a/packages/cli/package.json b/packages/cli/package.json index a5527a8eee87..b4fc206e5a44 100644 --- a/packages/cli/package.json +++ b/packages/cli/package.json @@ -28,8 +28,8 @@ "check-build": "node -e \"(async function() { await import('./lib/index.js') })()\" lodestar --help", "check-types": "tsc", "docs:build": "node --loader ts-node/esm ./docsgen/index.ts", - "lint": "eslint --color --ext .ts src/ test/", - "lint:fix": "yarn run lint --fix", + "lint": "biome check src/ test/", + "lint:fix": "yarn run lint --write", "test:unit": "vitest --run --dir test/unit/", "test:e2e": "vitest --run --config vitest.e2e.config.ts --dir test/e2e/", "test:sim:multifork": "LODESTAR_PRESET=minimal DOTENV_CONFIG_PATH=../../.env.test node -r dotenv/config --loader ts-node/esm test/sim/multiFork.test.ts", diff --git a/packages/cli/src/applyPreset.ts b/packages/cli/src/applyPreset.ts index 25f78b7d32ac..e40ac98841c0 100644 --- a/packages/cli/src/applyPreset.ts +++ b/packages/cli/src/applyPreset.ts @@ -1,8 +1,6 @@ // MUST import this file first before anything and not import any Lodestar code. -// eslint-disable-next-line no-restricted-imports import {hasher} from "@chainsafe/persistent-merkle-tree/lib/hasher/as-sha256.js"; -// eslint-disable-next-line no-restricted-imports import {setHasher} from "@chainsafe/persistent-merkle-tree/lib/hasher/index.js"; // without setting this first, persistent-merkle-tree will use noble instead @@ -45,7 +43,6 @@ else if (network) { if (network === "dev") { process.env.LODESTAR_PRESET = "minimal"; // "c-kzg" has hardcoded the mainnet value, do not use presets - // eslint-disable-next-line @typescript-eslint/naming-convention setActivePreset(PresetName.minimal, {FIELD_ELEMENTS_PER_BLOB: 4096}); } else if (network === "gnosis" || network === "chiado") { process.env.LODESTAR_PRESET = "gnosis"; @@ -57,7 +54,6 @@ else if (process.argv[2] === "dev") { process.env.LODESTAR_PRESET = "minimal"; process.env.LODESTAR_NETWORK = "dev"; // "c-kzg" has hardcoded the mainnet value, do not use presets - // eslint-disable-next-line @typescript-eslint/naming-convention setActivePreset(PresetName.minimal, {FIELD_ELEMENTS_PER_BLOB: 4096}); } diff --git a/packages/cli/src/cmds/beacon/handler.ts b/packages/cli/src/cmds/beacon/handler.ts index 81536d7c7b41..ea424e04824a 100644 --- a/packages/cli/src/cmds/beacon/handler.ts +++ b/packages/cli/src/cmds/beacon/handler.ts @@ -158,7 +158,6 @@ export async function beaconHandler(args: BeaconArgs & GlobalArgs): Promise = { string: true, coerce: (urls: string[]): string[] => // Parse ["url1,url2"] to ["url1", "url2"] - urls.map((item) => item.split(",")).flat(1), + urls + .map((item) => item.split(",")) + .flat(1), alias: ["server"], // for backwards compatibility }, diff --git a/packages/cli/src/cmds/validator/voluntaryExit.ts b/packages/cli/src/cmds/validator/voluntaryExit.ts index 02f1591b59ed..c3982d8d45ee 100644 --- a/packages/cli/src/cmds/validator/voluntaryExit.ts +++ b/packages/cli/src/cmds/validator/voluntaryExit.ts @@ -203,7 +203,6 @@ function selectSignersToExit(args: VoluntaryExitArgs, signers: Signer[]): Signer } } -// eslint-disable-next-line @typescript-eslint/explicit-function-return-type async function resolveValidatorIndexes(client: ApiClient, signersToExit: SignerPubkey[]) { const pubkeys = signersToExit.map(({pubkey}) => pubkey); diff --git a/packages/cli/src/index.ts b/packages/cli/src/index.ts index 5cdccbacfeec..0d509af17ab0 100644 --- a/packages/cli/src/index.ts +++ b/packages/cli/src/index.ts @@ -14,7 +14,6 @@ void lodestar // Show command help message when no command is provided if (msg.includes("Not enough non-option arguments")) { yarg.showHelp(); - // eslint-disable-next-line no-console console.log("\n"); } } @@ -22,7 +21,6 @@ void lodestar const errorMessage = err !== undefined ? (err instanceof YargsError ? err.message : err.stack) : msg || "Unknown error"; - // eslint-disable-next-line no-console console.error(` ✖ ${errorMessage}\n`); process.exit(1); }) diff --git a/packages/cli/src/networks/index.ts b/packages/cli/src/networks/index.ts index 0831b78cd2f6..ba42cf4c7798 100644 --- a/packages/cli/src/networks/index.ts +++ b/packages/cli/src/networks/index.ts @@ -109,7 +109,6 @@ export async function getNetworkBootnodes(network: NetworkName): Promise persistInvalidSszObjectsDir: undefined as any, proposerBoost: args["chain.proposerBoost"], proposerBoostReorg: args["chain.proposerBoostReorg"], diff --git a/packages/cli/src/options/beaconNodeOptions/eth1.ts b/packages/cli/src/options/beaconNodeOptions/eth1.ts index 46654cca6b2e..c558bda61b4e 100644 --- a/packages/cli/src/options/beaconNodeOptions/eth1.ts +++ b/packages/cli/src/options/beaconNodeOptions/eth1.ts @@ -59,7 +59,9 @@ export const options: CliCommandOptions = { string: true, coerce: (urls: string[]): string[] => // Parse ["url1,url2"] to ["url1", "url2"] - urls.map((item) => item.split(",")).flat(1), + urls + .map((item) => item.split(",")) + .flat(1), group: "eth1", }, diff --git a/packages/cli/src/options/beaconNodeOptions/execution.ts b/packages/cli/src/options/beaconNodeOptions/execution.ts index 85b81a5e708b..d60a621d1cdb 100644 --- a/packages/cli/src/options/beaconNodeOptions/execution.ts +++ b/packages/cli/src/options/beaconNodeOptions/execution.ts @@ -45,7 +45,9 @@ export const options: CliCommandOptions = { string: true, coerce: (urls: string[]): string[] => // Parse ["url1,url2"] to ["url1", "url2"] - urls.map((item) => item.split(",")).flat(1), + urls + .map((item) => item.split(",")) + .flat(1), group: "execution", }, diff --git a/packages/cli/src/options/beaconNodeOptions/network.ts b/packages/cli/src/options/beaconNodeOptions/network.ts index bfe9c7710e86..fc13f3293c29 100644 --- a/packages/cli/src/options/beaconNodeOptions/network.ts +++ b/packages/cli/src/options/beaconNodeOptions/network.ts @@ -57,18 +57,17 @@ function validateMultiaddrArg>(args } } -// eslint-disable-next-line @typescript-eslint/explicit-function-return-type export function parseListenArgs(args: NetworkArgs) { // If listenAddress is explicitly set, use it // If listenAddress6 is not set, use defaultListenAddress const listenAddress = args.listenAddress ?? (args.listenAddress6 ? undefined : defaultListenAddress); - const port = listenAddress ? args.port ?? defaultP2pPort : undefined; - const discoveryPort = listenAddress ? args.discoveryPort ?? args.port ?? defaultP2pPort : undefined; + const port = listenAddress ? (args.port ?? defaultP2pPort) : undefined; + const discoveryPort = listenAddress ? (args.discoveryPort ?? args.port ?? defaultP2pPort) : undefined; // Only use listenAddress6 if it is explicitly set const listenAddress6 = args.listenAddress6; - const port6 = listenAddress6 ? args.port6 ?? defaultP2pPort6 : undefined; - const discoveryPort6 = listenAddress6 ? args.discoveryPort6 ?? args.port6 ?? defaultP2pPort6 : undefined; + const port6 = listenAddress6 ? (args.port6 ?? defaultP2pPort6) : undefined; + const discoveryPort6 = listenAddress6 ? (args.discoveryPort6 ?? args.port6 ?? defaultP2pPort6) : undefined; return {listenAddress, port, discoveryPort, listenAddress6, port6, discoveryPort6}; } @@ -115,7 +114,7 @@ export function parseArgs(args: NetworkArgs): IBeaconNodeOptions["network"] { for (const enrStr of bootEnrs) { try { ENR.decodeTxt(enrStr); - } catch (e) { + } catch (_e) { throw new YargsError(`Provided ENR in bootnodes is invalid:\n ${enrStr}`); } } @@ -129,7 +128,7 @@ export function parseArgs(args: NetworkArgs): IBeaconNodeOptions["network"] { ip6: bindMu6, }, bootEnrs, - // eslint-disable-next-line @typescript-eslint/no-unsafe-assignment, @typescript-eslint/no-explicit-any + // biome-ignore lint/suspicious/noExplicitAny: enr: undefined as any, } : null, diff --git a/packages/cli/src/util/file.ts b/packages/cli/src/util/file.ts index 99e93a96dc59..5415cf2affa6 100644 --- a/packages/cli/src/util/file.ts +++ b/packages/cli/src/util/file.ts @@ -13,7 +13,6 @@ export const yamlSchema = FAILSAFE_SCHEMA.extend({ new Type("tag:yaml.org,2002:str", { kind: "scalar", construct: function construct(data) { - // eslint-disable-next-line @typescript-eslint/no-unsafe-return return data !== null ? data : ""; }, }), diff --git a/packages/cli/src/util/gitData/gitDataPath.ts b/packages/cli/src/util/gitData/gitDataPath.ts index e243ca433f2d..1ad3104aafc6 100644 --- a/packages/cli/src/util/gitData/gitDataPath.ts +++ b/packages/cli/src/util/gitData/gitDataPath.ts @@ -4,7 +4,6 @@ import {fileURLToPath} from "node:url"; // Global variable __dirname no longer available in ES6 modules. // Solutions: https://stackoverflow.com/questions/46745014/alternative-for-dirname-in-node-js-when-using-es6-modules -// eslint-disable-next-line @typescript-eslint/naming-convention const __dirname = path.dirname(fileURLToPath(import.meta.url)); // Persist git data and distribute through NPM so CLI consumers can know exactly diff --git a/packages/cli/src/util/gitData/index.ts b/packages/cli/src/util/gitData/index.ts index 96c5e4bbaef2..0720d39d9e30 100644 --- a/packages/cli/src/util/gitData/index.ts +++ b/packages/cli/src/util/gitData/index.ts @@ -11,7 +11,7 @@ export function readAndGetGitData(): GitData { let persistedGitData: Partial; try { persistedGitData = readGitDataFile(); - } catch (e) { + } catch (_e) { persistedGitData = {}; } @@ -23,13 +23,13 @@ export function readAndGetGitData(): GitData { branch: currentGitData.branch && currentGitData.branch.length > 0 ? currentGitData.branch - : persistedGitData.branch ?? "", + : (persistedGitData.branch ?? ""), commit: currentGitData.commit && currentGitData.commit.length > 0 ? currentGitData.commit - : persistedGitData.commit ?? "", + : (persistedGitData.commit ?? ""), }; - } catch (e) { + } catch (_e) { return { branch: "", commit: "", @@ -49,7 +49,7 @@ export function getGitData(): GitData { function getBranch(): string { try { return shellSilent("git rev-parse --abbrev-ref HEAD"); - } catch (e) { + } catch (_e) { return ""; } } @@ -58,7 +58,7 @@ function getBranch(): string { function getCommit(): string { try { return shellSilent("git rev-parse --verify HEAD"); - } catch (e) { + } catch (_e) { return ""; } } diff --git a/packages/cli/src/util/object.ts b/packages/cli/src/util/object.ts index d37f41ea6655..7f2e8a49d6c8 100644 --- a/packages/cli/src/util/object.ts +++ b/packages/cli/src/util/object.ts @@ -3,10 +3,10 @@ import {RecursivePartial} from "@lodestar/utils"; /** * Removes (mutates) all properties with a value === undefined, recursively */ -// eslint-disable-next-line @typescript-eslint/no-explicit-any + +// biome-ignore lint/suspicious/noExplicitAny: export function removeUndefinedRecursive(obj: T): RecursivePartial { for (const key of Object.keys(obj)) { - // eslint-disable-next-line @typescript-eslint/no-unsafe-assignment const value = obj[key]; if (value && typeof value === "object") removeUndefinedRecursive(value); else if (value === undefined) delete obj[key]; diff --git a/packages/cli/src/util/process.ts b/packages/cli/src/util/process.ts index cd040bdffb55..e274d782b8ba 100644 --- a/packages/cli/src/util/process.ts +++ b/packages/cli/src/util/process.ts @@ -8,7 +8,6 @@ const exitSignals = ["SIGTERM", "SIGINT"] as NodeJS.Signals[]; */ export function onGracefulShutdown( cleanUpFunction: () => Promise, - // eslint-disable-next-line no-console logFn: (msg: string) => void = console.log ): void { for (const signal of exitSignals) { diff --git a/packages/cli/src/util/proposerConfig.ts b/packages/cli/src/util/proposerConfig.ts index 509dc8213df1..2c12ce8f8524 100644 --- a/packages/cli/src/util/proposerConfig.ts +++ b/packages/cli/src/util/proposerConfig.ts @@ -1,5 +1,3 @@ -/* eslint-disable @typescript-eslint/naming-convention */ - import fs from "node:fs"; import path from "node:path"; import {ValidatorProposerConfig} from "@lodestar/validator"; diff --git a/packages/cli/src/util/types.ts b/packages/cli/src/util/types.ts index ced3bf34b1f6..bf194170f3e2 100644 --- a/packages/cli/src/util/types.ts +++ b/packages/cli/src/util/types.ts @@ -1,7 +1,8 @@ /** * Typed `Object.keys(o: T)` function, returning `(keyof T)[]` */ -// eslint-disable-next-line @typescript-eslint/no-explicit-any, @typescript-eslint/naming-convention + +// biome-ignore lint/suspicious/noExplicitAny: export function ObjectKeys(o: T): (keyof T)[] { return Object.keys(o); } diff --git a/packages/cli/src/util/version.ts b/packages/cli/src/util/version.ts index 4752856e5b1d..624412107603 100644 --- a/packages/cli/src/util/version.ts +++ b/packages/cli/src/util/version.ts @@ -6,7 +6,6 @@ import {readAndGetGitData} from "./gitData/index.js"; // Global variable __dirname no longer available in ES6 modules. // Solutions: https://stackoverflow.com/questions/46745014/alternative-for-dirname-in-node-js-when-using-es6-modules -// eslint-disable-next-line @typescript-eslint/naming-convention const __dirname = path.dirname(fileURLToPath(import.meta.url)); type VersionJson = { diff --git a/packages/cli/test/e2e/importKeystoresFromApi.test.ts b/packages/cli/test/e2e/importKeystoresFromApi.test.ts index b7abe1e8d293..584ded47bfdd 100644 --- a/packages/cli/test/e2e/importKeystoresFromApi.test.ts +++ b/packages/cli/test/e2e/importKeystoresFromApi.test.ts @@ -30,7 +30,6 @@ describe("import keystores from api", function () { const genesisValidatorsRoot = "0x0000000000000000000000000000000000000000000000000000000000000000"; const slashingProtection: Interchange = { - /* eslint-disable @typescript-eslint/naming-convention */ metadata: { interchange_format_version: "5", genesis_validators_root: genesisValidatorsRoot, diff --git a/packages/cli/test/e2e/propserConfigfromKeymanager.test.ts b/packages/cli/test/e2e/propserConfigfromKeymanager.test.ts index ffeb40460f40..6a6c391b4014 100644 --- a/packages/cli/test/e2e/propserConfigfromKeymanager.test.ts +++ b/packages/cli/test/e2e/propserConfigfromKeymanager.test.ts @@ -39,7 +39,6 @@ describe("import keystores from api, test DefaultProposerConfig", function () { const genesisValidatorsRoot = "0x0000000000000000000000000000000000000000000000000000000000000000"; const slashingProtection: Interchange = { - /* eslint-disable @typescript-eslint/naming-convention */ metadata: { interchange_format_version: "5", genesis_validators_root: genesisValidatorsRoot, diff --git a/packages/cli/test/e2e/voluntaryExit.test.ts b/packages/cli/test/e2e/voluntaryExit.test.ts index 49499e891731..25d4ab345aa7 100644 --- a/packages/cli/test/e2e/voluntaryExit.test.ts +++ b/packages/cli/test/e2e/voluntaryExit.test.ts @@ -79,7 +79,6 @@ describe("voluntaryExit cmd", function () { if (validator.status !== "active_exiting") { throw Error("Validator not exiting"); } else { - // eslint-disable-next-line no-console console.log(`Confirmed validator ${pubkey} = ${validator.status}`); } }, diff --git a/packages/cli/test/e2e/voluntaryExitFromApi.test.ts b/packages/cli/test/e2e/voluntaryExitFromApi.test.ts index 664091d5c520..21a9c0fc6872 100644 --- a/packages/cli/test/e2e/voluntaryExitFromApi.test.ts +++ b/packages/cli/test/e2e/voluntaryExitFromApi.test.ts @@ -86,7 +86,6 @@ describe("voluntary exit from api", function () { if (validator.status !== "active_exiting") { throw Error("Validator not exiting"); } else { - // eslint-disable-next-line no-console console.log(`Confirmed validator ${pubkeyToExit} = ${validator.status}`); } }, diff --git a/packages/cli/test/e2e/voluntaryExitRemoteSigner.test.ts b/packages/cli/test/e2e/voluntaryExitRemoteSigner.test.ts index a9cf2f48a168..8cb5f0d44d95 100644 --- a/packages/cli/test/e2e/voluntaryExitRemoteSigner.test.ts +++ b/packages/cli/test/e2e/voluntaryExitRemoteSigner.test.ts @@ -101,7 +101,6 @@ describe("voluntaryExit using remote signer", function () { if (validator.status !== "active_exiting") { throw Error("Validator not exiting"); } else { - // eslint-disable-next-line no-console console.log(`Confirmed validator ${pubkey} = ${validator.status}`); } }, diff --git a/packages/cli/test/scripts/e2e_test_env.ts b/packages/cli/test/scripts/e2e_test_env.ts index 24d0142827a8..fcecfac5e1c7 100644 --- a/packages/cli/test/scripts/e2e_test_env.ts +++ b/packages/cli/test/scripts/e2e_test_env.ts @@ -1,4 +1,3 @@ -/* eslint-disable @typescript-eslint/naming-convention */ import path from "node:path"; import {BeaconClient, ExecutionClient} from "../utils/crucible/interfaces.js"; import {Simulation} from "../utils/crucible/simulation.js"; diff --git a/packages/cli/test/sim/backupEthProvider.test.ts b/packages/cli/test/sim/backupEthProvider.test.ts index 1310119c9c3e..4ccc131a58bc 100644 --- a/packages/cli/test/sim/backupEthProvider.test.ts +++ b/packages/cli/test/sim/backupEthProvider.test.ts @@ -1,4 +1,3 @@ -/* eslint-disable @typescript-eslint/naming-convention */ import path from "node:path"; import {activePreset} from "@lodestar/params"; import {Simulation} from "../utils/crucible/simulation.js"; diff --git a/packages/cli/test/sim/deneb.test.ts b/packages/cli/test/sim/deneb.test.ts index b9c30a5ff523..865540ae7635 100644 --- a/packages/cli/test/sim/deneb.test.ts +++ b/packages/cli/test/sim/deneb.test.ts @@ -1,4 +1,3 @@ -/* eslint-disable @typescript-eslint/naming-convention */ import path from "node:path"; import {Simulation} from "../utils/crucible/simulation.js"; import {BeaconClient, ExecutionClient, ValidatorClient} from "../utils/crucible/interfaces.js"; diff --git a/packages/cli/test/sim/endpoints.test.ts b/packages/cli/test/sim/endpoints.test.ts index 6a119fc219d7..308ac6a0053c 100644 --- a/packages/cli/test/sim/endpoints.test.ts +++ b/packages/cli/test/sim/endpoints.test.ts @@ -1,4 +1,3 @@ -/* eslint-disable @typescript-eslint/naming-convention */ import path from "node:path"; import assert from "node:assert"; import {toHexString} from "@chainsafe/ssz"; diff --git a/packages/cli/test/sim/mixedClient.test.ts b/packages/cli/test/sim/mixedClient.test.ts index bfb2a5a99b1b..45029a1b26b4 100644 --- a/packages/cli/test/sim/mixedClient.test.ts +++ b/packages/cli/test/sim/mixedClient.test.ts @@ -1,4 +1,3 @@ -/* eslint-disable @typescript-eslint/naming-convention */ import path from "node:path"; import {Simulation} from "../utils/crucible/simulation.js"; import {nodeAssertion} from "../utils/crucible/assertions/nodeAssertion.js"; diff --git a/packages/cli/test/sim/multiFork.test.ts b/packages/cli/test/sim/multiFork.test.ts index 47ad59a165b6..047d9196239d 100644 --- a/packages/cli/test/sim/multiFork.test.ts +++ b/packages/cli/test/sim/multiFork.test.ts @@ -1,4 +1,3 @@ -/* eslint-disable @typescript-eslint/naming-convention */ import path from "node:path"; import {Match, BeaconClient, ExecutionClient, ValidatorClient} from "../utils/crucible/interfaces.js"; import {Simulation} from "../utils/crucible/simulation.js"; diff --git a/packages/cli/test/unit/cmds/beacon.test.ts b/packages/cli/test/unit/cmds/beacon.test.ts index fc1f50ad1251..6e7b7f389a29 100644 --- a/packages/cli/test/unit/cmds/beacon.test.ts +++ b/packages/cli/test/unit/cmds/beacon.test.ts @@ -186,7 +186,6 @@ describe("initPeerIdAndEnr", () => { }); }); -// eslint-disable-next-line @typescript-eslint/explicit-function-return-type async function runBeaconHandlerInit(args: Partial) { return beaconHandlerInit({ logLevel: LogLevel.info, diff --git a/packages/cli/test/unit/config/beaconParams.test.ts b/packages/cli/test/unit/config/beaconParams.test.ts index a7ce463200d0..2a78d498bf89 100644 --- a/packages/cli/test/unit/config/beaconParams.test.ts +++ b/packages/cli/test/unit/config/beaconParams.test.ts @@ -16,7 +16,6 @@ describe("config / beaconParams", () => { const testCases: { id: string; kwargs: Parameters[0]; - // eslint-disable-next-line @typescript-eslint/naming-convention GENESIS_FORK_VERSION: string; }[] = [ { @@ -24,7 +23,6 @@ describe("config / beaconParams", () => { kwargs: { additionalParamsCli: {}, }, - // eslint-disable-next-line @typescript-eslint/naming-convention GENESIS_FORK_VERSION: GENESIS_FORK_VERSION_MAINNET, }, { @@ -33,7 +31,6 @@ describe("config / beaconParams", () => { network: networkName, additionalParamsCli: {}, }, - // eslint-disable-next-line @typescript-eslint/naming-convention GENESIS_FORK_VERSION: GENESIS_FORK_VERSION_HOLESKY, }, { @@ -43,7 +40,6 @@ describe("config / beaconParams", () => { paramsFile: paramsFilepath, additionalParamsCli: {}, }, - // eslint-disable-next-line @typescript-eslint/naming-convention GENESIS_FORK_VERSION: GENESIS_FORK_VERSION_FILE, }, { @@ -51,16 +47,13 @@ describe("config / beaconParams", () => { kwargs: { network: networkName, paramsFile: paramsFilepath, - // eslint-disable-next-line @typescript-eslint/naming-convention additionalParamsCli: {GENESIS_FORK_VERSION: GENESIS_FORK_VERSION_CLI}, }, - // eslint-disable-next-line @typescript-eslint/naming-convention GENESIS_FORK_VERSION: GENESIS_FORK_VERSION_CLI, }, ]; beforeAll(() => { - // eslint-disable-next-line @typescript-eslint/naming-convention fs.writeFileSync(paramsFilepath, yaml.dump({GENESIS_FORK_VERSION: GENESIS_FORK_VERSION_FILE})); }); @@ -68,7 +61,6 @@ describe("config / beaconParams", () => { if (fs.existsSync(paramsFilepath)) fs.unlinkSync(paramsFilepath); }); - // eslint-disable-next-line @typescript-eslint/naming-convention it.each(testCases)("$id", ({kwargs, GENESIS_FORK_VERSION}) => { const params = getBeaconParams(kwargs); expect(toHexString(params.GENESIS_FORK_VERSION)).toBe(GENESIS_FORK_VERSION); diff --git a/packages/cli/test/unit/db.test.ts b/packages/cli/test/unit/db.test.ts index 1e19e514e9e5..b39c9492c9cb 100644 --- a/packages/cli/test/unit/db.test.ts +++ b/packages/cli/test/unit/db.test.ts @@ -1,7 +1,5 @@ import {describe, it} from "vitest"; -// eslint-disable-next-line import/no-relative-packages import {Bucket as BeaconBucket} from "../../../beacon-node/src/db/buckets.js"; -// eslint-disable-next-line import/no-relative-packages import {Bucket as ValidatorBucket} from "../../../validator/src/buckets.js"; describe("no db bucket overlap", () => { diff --git a/packages/cli/test/unit/options/paramsOptions.test.ts b/packages/cli/test/unit/options/paramsOptions.test.ts index a08c70008612..d6563203e652 100644 --- a/packages/cli/test/unit/options/paramsOptions.test.ts +++ b/packages/cli/test/unit/options/paramsOptions.test.ts @@ -11,9 +11,7 @@ describe("options / paramsOptions", () => { }; const expectedBeaconParams: Partial = { - // eslint-disable-next-line @typescript-eslint/naming-convention GENESIS_FORK_VERSION: "0x00000001", - // eslint-disable-next-line @typescript-eslint/naming-convention DEPOSIT_CONTRACT_ADDRESS: "0x1234567890123456789012345678901234567890", }; diff --git a/packages/cli/test/unit/util/format.test.ts b/packages/cli/test/unit/util/format.test.ts index c06259cc1842..194cc1dcbde7 100644 --- a/packages/cli/test/unit/util/format.test.ts +++ b/packages/cli/test/unit/util/format.test.ts @@ -17,8 +17,7 @@ describe("util / format / parseRange", () => { describe("util / format / isValidatePubkeyHex", () => { const testCases: Record = { - "../../malicious_link/0x933ad9491b62059dd065b560d256d8957a8c402cc6e8d8ee7290ae11e8f7329267a8811c397529dac52ae1342ba58c95": - false, + "../../malicious_link/0x933ad9491b62059dd065b560d256d8957a8c402cc6e8d8ee7290ae11e8f7329267a8811c397529dac52ae1342ba58c95": false, "0x933ad9491b62059dd065b560d256d8957a8c402cc6e8d8ee7290ae11e8f7329267a8811c397529dac52ae1342ba58c95": true, "0x933ad9491b62059dd065b560d256d8957a8c402cc6e8d8ee7290ae11e8f7329267a8811c397529dac52ae1342ba58c9": false, "0x933ad9491b62059dd065b560d256d8957a8c402cc6e8d8ee7290ae11e8f7329267a8811c397529dac52ae1342ba58c95f": false, diff --git a/packages/cli/test/unit/util/gitData.test.ts b/packages/cli/test/unit/util/gitData.test.ts index 206dd070b545..12a6b5b18339 100644 --- a/packages/cli/test/unit/util/gitData.test.ts +++ b/packages/cli/test/unit/util/gitData.test.ts @@ -8,7 +8,6 @@ import {getGitData} from "../../../src/util/index.js"; // Global variable __dirname no longer available in ES6 modules. // Solutions: https://stackoverflow.com/questions/46745014/alternative-for-dirname-in-node-js-when-using-es6-modules -// eslint-disable-next-line @typescript-eslint/naming-convention const __dirname = path.dirname(fileURLToPath(import.meta.url)); describe("util / gitData", function () { diff --git a/packages/cli/test/unit/validator/parseProposerConfig.test.ts b/packages/cli/test/unit/validator/parseProposerConfig.test.ts index 66220ca3329a..83c8c63ef877 100644 --- a/packages/cli/test/unit/validator/parseProposerConfig.test.ts +++ b/packages/cli/test/unit/validator/parseProposerConfig.test.ts @@ -1,4 +1,3 @@ -/* eslint-disable @typescript-eslint/naming-convention */ import path from "node:path"; import {fileURLToPath} from "node:url"; import {describe, it, expect} from "vitest"; @@ -27,6 +26,7 @@ const testValue = { builder: { gasLimit: 35000000, selection: routes.validator.BuilderSelection.BuilderAlways, + // biome-ignore lint/correctness/noPrecisionLoss: boostFactor: BigInt(18446744073709551616), }, }, diff --git a/packages/cli/test/utils/crucible/clients/beacon/lighthouse.ts b/packages/cli/test/utils/crucible/clients/beacon/lighthouse.ts index 89802149024a..515418f7e558 100644 --- a/packages/cli/test/utils/crucible/clients/beacon/lighthouse.ts +++ b/packages/cli/test/utils/crucible/clients/beacon/lighthouse.ts @@ -109,7 +109,6 @@ export const generateLighthouseBeaconNode: BeaconNodeGenerator { - // eslint-disable-next-line no-console if (!silent) console.log("Waiting for start of slot", {target: slot, current: this.currentSlot}); const slotTime = this.getSlotTime(slot) * MS_IN_SEC - Date.now(); await sleep(slotTime, this.signal); diff --git a/packages/cli/test/utils/crucible/externalSignerServer.ts b/packages/cli/test/utils/crucible/externalSignerServer.ts index bd8576d214c2..4282f1761db9 100644 --- a/packages/cli/test/utils/crucible/externalSignerServer.ts +++ b/packages/cli/test/utils/crucible/externalSignerServer.ts @@ -29,7 +29,6 @@ export class ExternalSignerServer { return [...this.secretKeyMap.keys()]; }); - /* eslint-disable @typescript-eslint/naming-convention */ this.server.post<{ Params: { /** BLS public key as a hex string. */ diff --git a/packages/cli/test/utils/crucible/interfaces.ts b/packages/cli/test/utils/crucible/interfaces.ts index db4b1f3b8901..84b5043ba983 100644 --- a/packages/cli/test/utils/crucible/interfaces.ts +++ b/packages/cli/test/utils/crucible/interfaces.ts @@ -1,4 +1,3 @@ -/* eslint-disable @typescript-eslint/naming-convention */ import {ChildProcess} from "node:child_process"; import {Web3} from "web3"; import {SecretKey} from "@chainsafe/blst"; diff --git a/packages/cli/test/utils/crucible/runner/dockerRunner.ts b/packages/cli/test/utils/crucible/runner/dockerRunner.ts index cfa52c9b9ebf..bc5b97811cf4 100644 --- a/packages/cli/test/utils/crucible/runner/dockerRunner.ts +++ b/packages/cli/test/utils/crucible/runner/dockerRunner.ts @@ -22,7 +22,7 @@ export class DockerRunner implements RunnerEnv { await execChildProcess(`docker network create --subnet ${dockerNetworkIpRange}.0/24 ${dockerNetworkName}`, { logger: this.logger, }); - } catch { + } catch (_e) { // During multiple sim tests files the network might already exist } } @@ -35,7 +35,7 @@ export class DockerRunner implements RunnerEnv { logger: this.logger, }); return; - } catch { + } catch (_e) { await sleep(5000); } } diff --git a/packages/cli/test/utils/crucible/simulationTracker.ts b/packages/cli/test/utils/crucible/simulationTracker.ts index e374d3b6c328..778a7ad2a771 100644 --- a/packages/cli/test/utils/crucible/simulationTracker.ts +++ b/packages/cli/test/utils/crucible/simulationTracker.ts @@ -68,7 +68,7 @@ async function pathExists(filePath: string): Promise { try { await fs.access(filePath); return true; - } catch { + } catch (_e) { return false; } } diff --git a/packages/cli/test/utils/crucible/utils/index.ts b/packages/cli/test/utils/crucible/utils/index.ts index 0b6ae1bba1e5..0e016778cdce 100644 --- a/packages/cli/test/utils/crucible/utils/index.ts +++ b/packages/cli/test/utils/crucible/utils/index.ts @@ -73,7 +73,6 @@ export function defineSimTestConfig( additionalSlots: opts.additionalSlotsForTTD ?? 2, }); - /* eslint-disable @typescript-eslint/naming-convention */ const forkConfig = createChainForkConfig({ ...opts, GENESIS_DELAY: genesisDelaySeconds, @@ -157,7 +156,7 @@ export const arrayGroupBy = ( ): Record => array.reduce( (acc, value, index, array) => { - (acc[predicate(value, index, array)] ||= []).push(value); + acc[predicate(value, index, array)]?.push(value); return acc; }, {} as {[key: string]: T[]} diff --git a/packages/cli/test/utils/crucible/utils/keys.ts b/packages/cli/test/utils/crucible/utils/keys.ts index 27983c04cd38..8915e85b529e 100644 --- a/packages/cli/test/utils/crucible/utils/keys.ts +++ b/packages/cli/test/utils/crucible/utils/keys.ts @@ -1,4 +1,3 @@ -/* eslint-disable @typescript-eslint/naming-convention */ import {readFile, writeFile} from "node:fs/promises"; import path from "node:path"; import yaml from "js-yaml"; diff --git a/packages/cli/test/utils/crucible/utils/network.ts b/packages/cli/test/utils/crucible/utils/network.ts index e3555fc149b9..7f41b87aff04 100644 --- a/packages/cli/test/utils/crucible/utils/network.ts +++ b/packages/cli/test/utils/crucible/utils/network.ts @@ -74,7 +74,6 @@ export async function waitForNodeSync( } export async function waitForNodeSyncStatus(env: Simulation, node: NodePair): Promise { - // eslint-disable-next-line no-constant-condition while (true) { const result = (await node.beacon.api.node.getSyncingStatus()).value(); if (!result.isSyncing) { diff --git a/packages/cli/test/utils/crucible/utils/syncing.ts b/packages/cli/test/utils/crucible/utils/syncing.ts index 4a8913105335..d31575e74e5d 100644 --- a/packages/cli/test/utils/crucible/utils/syncing.ts +++ b/packages/cli/test/utils/crucible/utils/syncing.ts @@ -148,7 +148,9 @@ export async function assertUnknownBlockSync(env: Simulation): Promise { } catch (error) { if (!(error as Error).message.includes("BLOCK_ERROR_PARENT_UNKNOWN")) { env.tracker.record({ - message: `Publishing unknown block should return "BLOCK_ERROR_PARENT_UNKNOWN" got "${(error as Error).message}"`, + message: `Publishing unknown block should return "BLOCK_ERROR_PARENT_UNKNOWN" got "${ + (error as Error).message + }"`, slot: env.clock.currentSlot, assertionId: "unknownBlockParent", }); @@ -178,7 +180,6 @@ export async function waitForNodeSync( } export async function waitForNodeSyncStatus(env: Simulation, node: NodePair): Promise { - // eslint-disable-next-line no-constant-condition while (true) { const result = (await node.beacon.api.node.getSyncingStatus()).value(); if (!result.isSyncing) { diff --git a/packages/cli/test/utils/mockBeaconApiServer.ts b/packages/cli/test/utils/mockBeaconApiServer.ts index 80ce282e102c..e7e80338686f 100644 --- a/packages/cli/test/utils/mockBeaconApiServer.ts +++ b/packages/cli/test/utils/mockBeaconApiServer.ts @@ -5,7 +5,6 @@ import {ChainForkConfig} from "@lodestar/config"; import {config} from "@lodestar/config/default"; import {ssz} from "@lodestar/types"; import {fromHex, toHex} from "@lodestar/utils"; -// eslint-disable-next-line import/no-relative-packages import {testLogger} from "../../../beacon-node/test/utils/logger.js"; const ZERO_HASH_HEX = toHex(Buffer.alloc(32, 0)); diff --git a/packages/config/package.json b/packages/config/package.json index f257db65cf6e..434000db2a0f 100644 --- a/packages/config/package.json +++ b/packages/config/package.json @@ -47,8 +47,8 @@ "build:watch": "yarn run build --watch", "check-build": "node -e \"(async function() { await import('./lib/index.js') })()\"", "check-types": "tsc", - "lint": "eslint --color --ext .ts src/", - "lint:fix": "yarn run lint --fix", + "lint": "biome check src/", + "lint:fix": "yarn run lint --write", "test": "yarn test:unit", "test:unit": "yarn vitest --run --dir test/unit/", "check-readme": "typescript-docs-verifier" diff --git a/packages/config/src/chainConfig/configs/mainnet.ts b/packages/config/src/chainConfig/configs/mainnet.ts index e5792a87ac70..5da5f8d2acb0 100644 --- a/packages/config/src/chainConfig/configs/mainnet.ts +++ b/packages/config/src/chainConfig/configs/mainnet.ts @@ -1,4 +1,3 @@ -/* eslint-disable @typescript-eslint/naming-convention */ import {fromHex as b} from "@lodestar/utils"; import {PresetName} from "@lodestar/params"; import {ChainConfig} from "../types.js"; diff --git a/packages/config/src/chainConfig/configs/minimal.ts b/packages/config/src/chainConfig/configs/minimal.ts index 53229d283511..f1a52e956f4d 100644 --- a/packages/config/src/chainConfig/configs/minimal.ts +++ b/packages/config/src/chainConfig/configs/minimal.ts @@ -1,4 +1,3 @@ -/* eslint-disable @typescript-eslint/naming-convention */ import {fromHex as b} from "@lodestar/utils"; import {PresetName} from "@lodestar/params"; import {ChainConfig} from "../types.js"; diff --git a/packages/config/src/chainConfig/default.ts b/packages/config/src/chainConfig/default.ts index d778c9b82447..ef2b9743a1d2 100644 --- a/packages/config/src/chainConfig/default.ts +++ b/packages/config/src/chainConfig/default.ts @@ -10,9 +10,10 @@ switch (ACTIVE_PRESET) { defaultChainConfig = minimal; break; case PresetName.mainnet: - default: defaultChainConfig = mainnet; break; + default: + defaultChainConfig = mainnet; } export {defaultChainConfig}; diff --git a/packages/config/src/chainConfig/networks/chiado.ts b/packages/config/src/chainConfig/networks/chiado.ts index d96bd7510c65..096942af672c 100644 --- a/packages/config/src/chainConfig/networks/chiado.ts +++ b/packages/config/src/chainConfig/networks/chiado.ts @@ -1,4 +1,3 @@ -/* eslint-disable @typescript-eslint/naming-convention */ import {fromHex as b} from "@lodestar/utils"; import {ChainConfig} from "../types.js"; import {gnosisChainConfig as gnosis} from "./gnosis.js"; diff --git a/packages/config/src/chainConfig/networks/ephemery.ts b/packages/config/src/chainConfig/networks/ephemery.ts index 6fefc1800bfc..d1c17c36f0ab 100644 --- a/packages/config/src/chainConfig/networks/ephemery.ts +++ b/packages/config/src/chainConfig/networks/ephemery.ts @@ -1,4 +1,3 @@ -/* eslint-disable @typescript-eslint/naming-convention */ import {fromHex as b} from "@lodestar/utils"; import {ChainConfig} from "../types.js"; import {chainConfig as mainnet} from "../configs/mainnet.js"; diff --git a/packages/config/src/chainConfig/networks/gnosis.ts b/packages/config/src/chainConfig/networks/gnosis.ts index 2f58ffd4d045..a25162ae5028 100644 --- a/packages/config/src/chainConfig/networks/gnosis.ts +++ b/packages/config/src/chainConfig/networks/gnosis.ts @@ -1,4 +1,3 @@ -/* eslint-disable @typescript-eslint/naming-convention */ import {fromHex as b} from "@lodestar/utils"; import {PresetName} from "@lodestar/params"; import {ChainConfig} from "../types.js"; diff --git a/packages/config/src/chainConfig/networks/holesky.ts b/packages/config/src/chainConfig/networks/holesky.ts index 16c462a9468e..46c32606931f 100644 --- a/packages/config/src/chainConfig/networks/holesky.ts +++ b/packages/config/src/chainConfig/networks/holesky.ts @@ -1,4 +1,3 @@ -/* eslint-disable @typescript-eslint/naming-convention */ import {fromHex as b} from "@lodestar/utils"; import {ChainConfig} from "../types.js"; import {chainConfig as mainnet} from "../configs/mainnet.js"; diff --git a/packages/config/src/chainConfig/networks/mainnet.ts b/packages/config/src/chainConfig/networks/mainnet.ts index c137c578fc0e..13225b463da9 100644 --- a/packages/config/src/chainConfig/networks/mainnet.ts +++ b/packages/config/src/chainConfig/networks/mainnet.ts @@ -1,4 +1,3 @@ -/* eslint-disable @typescript-eslint/naming-convention */ import {fromHex as b} from "@lodestar/utils"; import {ChainConfig} from "../types.js"; import {chainConfig as mainnet} from "../configs/mainnet.js"; diff --git a/packages/config/src/chainConfig/networks/sepolia.ts b/packages/config/src/chainConfig/networks/sepolia.ts index 39e72a24f3f6..e7e5dc76f691 100644 --- a/packages/config/src/chainConfig/networks/sepolia.ts +++ b/packages/config/src/chainConfig/networks/sepolia.ts @@ -1,4 +1,3 @@ -/* eslint-disable @typescript-eslint/naming-convention */ import {fromHex as b} from "@lodestar/utils"; import {ChainConfig} from "../types.js"; import {chainConfig as mainnet} from "../configs/mainnet.js"; diff --git a/packages/config/src/chainConfig/types.ts b/packages/config/src/chainConfig/types.ts index 05fff02f2eaf..5c06b205c2f6 100644 --- a/packages/config/src/chainConfig/types.ts +++ b/packages/config/src/chainConfig/types.ts @@ -1,7 +1,5 @@ import {PresetName} from "@lodestar/params"; -/* eslint-disable @typescript-eslint/naming-convention */ - /** * Run-time chain configuration */ diff --git a/packages/config/test/unit/index.test.ts b/packages/config/test/unit/index.test.ts index a6fca7ad643a..bde31f6b1477 100644 --- a/packages/config/test/unit/index.test.ts +++ b/packages/config/test/unit/index.test.ts @@ -31,7 +31,6 @@ describe("forks", () => { }); it("correctly handle pre-genesis", () => { - // eslint-disable-next-line @typescript-eslint/naming-convention const postMergeTestnet = createForkConfig({...chainConfig, ALTAIR_FORK_EPOCH: 0, BELLATRIX_FORK_EPOCH: 0}); expect(postMergeTestnet.getForkName(-1)).toBe(ForkName.bellatrix); }); diff --git a/packages/db/package.json b/packages/db/package.json index 0e3a2c847d4b..2a10d36766bf 100644 --- a/packages/db/package.json +++ b/packages/db/package.json @@ -28,8 +28,8 @@ "build:release": "yarn clean && yarn run build", "check-build": "node -e \"(async function() { await import('./lib/index.js') })()\"", "check-types": "tsc", - "lint": "eslint --color --ext .ts src/ test/", - "lint:fix": "yarn run lint --fix", + "lint": "biome check src/ test/", + "lint:fix": "yarn run lint --write", "test": "yarn test:unit", "test:unit": "vitest --run --dir test/unit/", "check-readme": "typescript-docs-verifier" diff --git a/packages/db/src/abstractRepository.ts b/packages/db/src/abstractRepository.ts index e0462d162ddc..5d5b0763ba26 100644 --- a/packages/db/src/abstractRepository.ts +++ b/packages/db/src/abstractRepository.ts @@ -142,7 +142,7 @@ export abstract class Repository { async batchRemove(values: T[]): Promise { // handle single value in batchDelete - await this.batchDelete(Array.from({length: values.length}, (ignored, i) => this.getId(values[i]))); + await this.batchDelete(Array.from({length: values.length}, (_ignored, i) => this.getId(values[i]))); } async keys(opts?: FilterOptions): Promise { diff --git a/packages/db/test/unit/controller/level.test.ts b/packages/db/test/unit/controller/level.test.ts index 11ef0f929fda..16f20e770c93 100644 --- a/packages/db/test/unit/controller/level.test.ts +++ b/packages/db/test/unit/controller/level.test.ts @@ -137,7 +137,7 @@ describe("LevelDB controller", () => { if (res?.startsWith("Usage: gdu ")) { return "gdu"; } - } catch { + } catch (_e) { /* eslint-disable no-console */ console.error("Cannot find gdu command, falling back to du"); } diff --git a/packages/flare/package.json b/packages/flare/package.json index 3a11e9b49ebf..a08e5fe0edc1 100644 --- a/packages/flare/package.json +++ b/packages/flare/package.json @@ -41,8 +41,8 @@ "build:watch": "yarn run build --watch", "check-build": "node -e \"(async function() { await import('./lib/index.js') })()\" flare --help", "check-types": "tsc", - "lint": "eslint --color --ext .ts src/", - "lint:fix": "yarn run lint --fix", + "lint": "biome check src/", + "lint:fix": "yarn run lint --write", "test": "yarn test:unit", "test:unit": "vitest --run --dir test/unit/", "check-readme": "typescript-docs-verifier" diff --git a/packages/flare/src/index.ts b/packages/flare/src/index.ts index bc10fff9181c..5f3b85b459c1 100644 --- a/packages/flare/src/index.ts +++ b/packages/flare/src/index.ts @@ -12,7 +12,6 @@ void flare // Show command help message when no command is provided if (msg.includes("Not enough non-option arguments")) { yarg.showHelp(); - // eslint-disable-next-line no-console console.log("\n"); } } @@ -20,7 +19,6 @@ void flare const errorMessage = err !== undefined ? (err instanceof YargsError ? err.message : err.stack) : msg || "Unknown error"; - // eslint-disable-next-line no-console console.error(` ✖ ${errorMessage}\n`); process.exit(1); }) diff --git a/packages/fork-choice/package.json b/packages/fork-choice/package.json index 728036b365d3..2197ad90a9fd 100644 --- a/packages/fork-choice/package.json +++ b/packages/fork-choice/package.json @@ -29,8 +29,8 @@ "build:release": "yarn clean && yarn run build", "check-build": "node -e \"(async function() { await import('./lib/index.js') })()\"", "check-types": "tsc", - "lint": "eslint --color --ext .ts src/ test/", - "lint:fix": "yarn run lint --fix", + "lint": "biome check src/ test/", + "lint:fix": "yarn run lint --write", "test": "yarn test:unit", "test:unit": "vitest --run --dir test/unit/", "check-readme": "typescript-docs-verifier" diff --git a/packages/fork-choice/src/forkChoice/errors.ts b/packages/fork-choice/src/forkChoice/errors.ts index ea0c6305ba42..43d209106eed 100644 --- a/packages/fork-choice/src/forkChoice/errors.ts +++ b/packages/fork-choice/src/forkChoice/errors.ts @@ -95,8 +95,4 @@ export type ForkChoiceErrorType = | {code: ForkChoiceErrorCode.UNABLE_TO_SET_JUSTIFIED_CHECKPOINT; error: Error} | {code: ForkChoiceErrorCode.AFTER_BLOCK_FAILED; error: Error}; -export class ForkChoiceError extends LodestarError { - constructor(type: ForkChoiceErrorType) { - super(type); - } -} +export class ForkChoiceError extends LodestarError {} diff --git a/packages/fork-choice/src/forkChoice/forkChoice.ts b/packages/fork-choice/src/forkChoice/forkChoice.ts index 6ae3f52e7d3a..828a16725444 100644 --- a/packages/fork-choice/src/forkChoice/forkChoice.ts +++ b/packages/fork-choice/src/forkChoice/forkChoice.ts @@ -198,6 +198,7 @@ export class ForkChoice implements IForkChoice { return {head, isHeadTimely, notReorgedReason}; } case UpdateHeadOpt.GetCanonicialHead: + return {head: canonicialHeadBlock}; default: return {head: canonicialHeadBlock}; } @@ -413,7 +414,8 @@ export class ForkChoice implements IForkChoice { }); } - return (this.head = headNode); + this.head = headNode; + return this.head; } /** diff --git a/packages/fork-choice/src/forkChoice/store.ts b/packages/fork-choice/src/forkChoice/store.ts index d16e021529db..2cd4da512870 100644 --- a/packages/fork-choice/src/forkChoice/store.ts +++ b/packages/fork-choice/src/forkChoice/store.ts @@ -55,18 +55,22 @@ export class ForkChoiceStore implements IForkChoiceStore { private _finalizedCheckpoint: CheckpointWithHex; unrealizedFinalizedCheckpoint: CheckpointWithHex; equivocatingIndices = new Set(); + justifiedBalancesGetter: JustifiedBalancesGetter; + currentSlot: Slot; constructor( - public currentSlot: Slot, + currentSlot: Slot, justifiedCheckpoint: phase0.Checkpoint, finalizedCheckpoint: phase0.Checkpoint, justifiedBalances: EffectiveBalanceIncrements, - public justifiedBalancesGetter: JustifiedBalancesGetter, + justifiedBalancesGetter: JustifiedBalancesGetter, private readonly events?: { onJustified: (cp: CheckpointWithHex) => void; onFinalized: (cp: CheckpointWithHex) => void; } ) { + this.justifiedBalancesGetter = justifiedBalancesGetter; + this.currentSlot = currentSlot; const justified = { checkpoint: toCheckpointWithHex(justifiedCheckpoint), balances: justifiedBalances, diff --git a/packages/fork-choice/src/protoArray/errors.ts b/packages/fork-choice/src/protoArray/errors.ts index 2e044de154e1..650fd1c0b244 100644 --- a/packages/fork-choice/src/protoArray/errors.ts +++ b/packages/fork-choice/src/protoArray/errors.ts @@ -56,8 +56,4 @@ export type ProtoArrayErrorType = | {code: ProtoArrayErrorCode.INVALID_JUSTIFIED_EXECUTION_STATUS; root: RootHex} | ({code: ProtoArrayErrorCode.INVALID_LVH_EXECUTION_RESPONSE} & LVHExecError); -export class ProtoArrayError extends LodestarError { - constructor(type: ProtoArrayErrorType) { - super(type); - } -} +export class ProtoArrayError extends LodestarError {} diff --git a/packages/fork-choice/src/protoArray/protoArray.ts b/packages/fork-choice/src/protoArray/protoArray.ts index 0b793d2be099..b8bb63837e36 100644 --- a/packages/fork-choice/src/protoArray/protoArray.ts +++ b/packages/fork-choice/src/protoArray/protoArray.ts @@ -964,7 +964,6 @@ export class ProtoArray { * Returns a common ancestor for nodeA or nodeB or null if there's none */ getCommonAncestor(nodeA: ProtoNode, nodeB: ProtoNode): ProtoNode | null { - // eslint-disable-next-line no-constant-condition while (true) { // If nodeA is higher than nodeB walk up nodeA tree if (nodeA.slot > nodeB.slot) { diff --git a/packages/fork-choice/test/unit/forkChoice/utils.test.ts b/packages/fork-choice/test/unit/forkChoice/utils.test.ts index 3f315d079842..d8793206f4ba 100644 --- a/packages/fork-choice/test/unit/forkChoice/utils.test.ts +++ b/packages/fork-choice/test/unit/forkChoice/utils.test.ts @@ -4,7 +4,6 @@ import {ssz} from "@lodestar/types"; import {assertValidTerminalPowBlock, ExecutionStatus} from "../../../src/index.js"; describe("assertValidTerminalPowBlock", function () { - // eslint-disable-next-line @typescript-eslint/naming-convention const config = createChainForkConfig({TERMINAL_TOTAL_DIFFICULTY: BigInt(10)}); const block = ssz.bellatrix.BeaconBlock.defaultValue(); const executionStatus = ExecutionStatus.Valid; diff --git a/packages/fork-choice/test/unit/protoArray/getCommonAncestor.test.ts b/packages/fork-choice/test/unit/protoArray/getCommonAncestor.test.ts index fdf1a1f3bae4..9c06682ca351 100644 --- a/packages/fork-choice/test/unit/protoArray/getCommonAncestor.test.ts +++ b/packages/fork-choice/test/unit/protoArray/getCommonAncestor.test.ts @@ -77,7 +77,7 @@ describe("getCommonAncestor", () => { for (const {nodeA, nodeB, ancestor} of testCases) { it(`${nodeA} & ${nodeB} -> ${ancestor}`, () => { - // eslint-disable-next-line @typescript-eslint/no-non-null-assertion + // biome-ignore lint/style/noNonNullAssertion: const ancestorNode = fc.getCommonAncestor(fc.getNode(nodeA)!, fc.getNode(nodeB)!); expect(ancestorNode && ancestorNode.blockRoot).toBe(ancestor); }); diff --git a/packages/light-client/package.json b/packages/light-client/package.json index 2eda3a45d455..a503d6bc510e 100644 --- a/packages/light-client/package.json +++ b/packages/light-client/package.json @@ -62,8 +62,8 @@ "check-bundle": "node -e \"(async function() { await import('./dist/lightclient.min.mjs') })()\"", "build:release": "yarn clean && yarn run build && yarn run build:bundle", "check-types": "tsc", - "lint": "eslint --color --ext .ts src/ test/", - "lint:fix": "yarn run lint --fix", + "lint": "biome check src/ test/", + "lint:fix": "yarn run lint --write", "test": "yarn test:unit", "test:unit": "vitest --run --dir test/unit/", "test:browsers": "yarn test:browsers:chrome && yarn test:browsers:firefox && yarn test:browsers:electron", diff --git a/packages/light-client/src/events.ts b/packages/light-client/src/events.ts index 5b561718e89e..7c01843d8ad0 100644 --- a/packages/light-client/src/events.ts +++ b/packages/light-client/src/events.ts @@ -15,7 +15,7 @@ export type LightclientEmitterEvents = { export type LightclientEmitter = MittEmitter; -// eslint-disable-next-line @typescript-eslint/no-explicit-any +// biome-ignore lint/suspicious/noExplicitAny: export type MittEmitter void>> = { on(type: K, handler: T[K]): void; off(type: K, handler: T[K]): void; diff --git a/packages/light-client/src/index.ts b/packages/light-client/src/index.ts index 5ec0dd73b469..098ea18adc31 100644 --- a/packages/light-client/src/index.ts +++ b/packages/light-client/src/index.ts @@ -224,7 +224,6 @@ export class Lightclient { } private async runLoop(): Promise { - // eslint-disable-next-line no-constant-condition while (true) { const currentPeriod = computeSyncPeriodAtSlot(this.currentSlot); // Check if we have a sync committee for the current clock period diff --git a/packages/light-client/src/spec/utils.ts b/packages/light-client/src/spec/utils.ts index 408412464606..d80b9bb7d9a1 100644 --- a/packages/light-client/src/spec/utils.ts +++ b/packages/light-client/src/spec/utils.ts @@ -106,7 +106,6 @@ export function upgradeLightClientHeader( // Break if no further upgradation is required else fall through if (ForkSeq[targetFork] <= ForkSeq.bellatrix) break; - // eslint-disable-next-line no-fallthrough case ForkName.capella: (upgradedHeader as LightClientHeader).execution = ssz.capella.LightClientHeader.fields.execution.defaultValue(); @@ -116,7 +115,6 @@ export function upgradeLightClientHeader( // Break if no further upgradation is required else fall through if (ForkSeq[targetFork] <= ForkSeq.capella) break; - // eslint-disable-next-line no-fallthrough case ForkName.deneb: (upgradedHeader as LightClientHeader).execution.blobGasUsed = ssz.deneb.LightClientHeader.fields.execution.fields.blobGasUsed.defaultValue(); @@ -126,7 +124,6 @@ export function upgradeLightClientHeader( // Break if no further upgradation is required else fall through if (ForkSeq[targetFork] <= ForkSeq.deneb) break; - // eslint-disable-next-line no-fallthrough case ForkName.electra: // No changes to LightClientHeader in Electra diff --git a/packages/light-client/src/utils/logger.ts b/packages/light-client/src/utils/logger.ts index afdbf7da7d3d..1f13b98bd6c6 100644 --- a/packages/light-client/src/utils/logger.ts +++ b/packages/light-client/src/utils/logger.ts @@ -1,4 +1,4 @@ -// eslint-disable-next-line @typescript-eslint/no-explicit-any +// biome-ignore lint/suspicious/noExplicitAny: export type LogHandler = (message: string, context?: any, error?: Error) => void; export type ILcLogger = { diff --git a/packages/light-client/test/unit/isValidLightClientHeader.test.ts b/packages/light-client/test/unit/isValidLightClientHeader.test.ts index db27a8266103..8181c6a5def4 100644 --- a/packages/light-client/test/unit/isValidLightClientHeader.test.ts +++ b/packages/light-client/test/unit/isValidLightClientHeader.test.ts @@ -5,7 +5,6 @@ import {createBeaconConfig, createChainForkConfig, defaultChainConfig} from "@lo import {isValidLightClientHeader} from "../../src/spec/utils.js"; describe("isValidLightClientHeader", function () { - /* eslint-disable @typescript-eslint/naming-convention */ const chainConfig = createChainForkConfig({ ...defaultChainConfig, ALTAIR_FORK_EPOCH: 0, diff --git a/packages/light-client/test/unit/sync.node.test.ts b/packages/light-client/test/unit/sync.node.test.ts index bcd1d0f25d0b..52afd05760d7 100644 --- a/packages/light-client/test/unit/sync.node.test.ts +++ b/packages/light-client/test/unit/sync.node.test.ts @@ -45,7 +45,6 @@ describe("sync", () => { const targetSlot = firstHeadSlot + slotsIntoPeriod; // Genesis data such that targetSlot is at the current clock slot - // eslint-disable-next-line @typescript-eslint/naming-convention const chainConfig: ChainConfig = {...chainConfigDef, SECONDS_PER_SLOT, ALTAIR_FORK_EPOCH}; const genesisTime = Math.floor(Date.now() / 1000) - chainConfig.SECONDS_PER_SLOT * targetSlot; const genesisValidatorsRoot = Buffer.alloc(32, 0xaa); diff --git a/packages/logger/package.json b/packages/logger/package.json index 196fb306a8b0..3d6ee5a0d874 100644 --- a/packages/logger/package.json +++ b/packages/logger/package.json @@ -53,8 +53,8 @@ "build:release": "yarn clean && yarn build", "check-build": "node -e \"(async function() { await import('./lib/index.js') })()\"", "check-types": "tsc", - "lint": "eslint --color --ext .ts src/ test/", - "lint:fix": "yarn run lint --fix", + "lint": "biome check src/ test/", + "lint:fix": "yarn run lint --write", "test": "yarn test:unit && yarn test:e2e", "test:unit": "vitest --run --dir test/unit/", "test:browsers": "yarn test:browsers:chrome && yarn test:browsers:firefox && yarn test:browsers:electron", diff --git a/packages/logger/src/browser.ts b/packages/logger/src/browser.ts index fc91fcfcd2a3..65a0c2a6a64b 100644 --- a/packages/logger/src/browser.ts +++ b/packages/logger/src/browser.ts @@ -70,9 +70,7 @@ class BrowserConsole extends Transport { const message = info[MESSAGE]; if (val <= this.levels[this.level as LogLevel]) { - // eslint-disable-next-line @typescript-eslint/ban-ts-comment // @ts-expect-error - // eslint-disable-next-line @typescript-eslint/no-unsafe-call, no-console console[mappedMethod](message); } diff --git a/packages/logger/src/interface.ts b/packages/logger/src/interface.ts index 8f270b0dc4ee..e3ba8483a458 100644 --- a/packages/logger/src/interface.ts +++ b/packages/logger/src/interface.ts @@ -1,4 +1,3 @@ -// eslint-disable-next-line import/no-extraneous-dependencies import {LEVEL, MESSAGE} from "triple-beam"; import {LogLevel, Logger, LogHandler, LogData} from "@lodestar/utils"; @@ -15,7 +14,6 @@ export const logLevelNum: {[K in LogLevel]: number} = { [LogLevel.trace]: 5, }; -// eslint-disable-next-line @typescript-eslint/naming-convention export const LogLevels = Object.values(LogLevel); export type LogFormat = "human" | "json"; diff --git a/packages/logger/src/utils/consoleTransport.ts b/packages/logger/src/utils/consoleTransport.ts index 41a1084b4b83..6bfd62b2ecd8 100644 --- a/packages/logger/src/utils/consoleTransport.ts +++ b/packages/logger/src/utils/consoleTransport.ts @@ -26,6 +26,7 @@ export class ConsoleDynamicLevel extends transports.Console { return this.levelByModule.delete(module); } + // biome-ignore lint/correctness/noUndeclaredVariables: BufferEncoding is not been identified by the biomejs _write(info: WinstonLogInfo, enc: BufferEncoding, callback: (error?: Error | null | undefined) => void): void { const moduleLevel = this.levelByModule.get(info.module) ?? this.defaultLevel; diff --git a/packages/logger/src/utils/format.ts b/packages/logger/src/utils/format.ts index 651dc56ce687..4e657c0040af 100644 --- a/packages/logger/src/utils/format.ts +++ b/packages/logger/src/utils/format.ts @@ -21,8 +21,8 @@ export function getFormat(opts: LoggerOptions): Format { switch (opts.format) { case "json": return jsonLogFormat(opts); - case "human": + return humanReadableLogFormat(opts); default: return humanReadableLogFormat(opts); } @@ -49,6 +49,7 @@ function formatTimestamp(opts: LoggerOptions): Format { }; case TimestampFormatCode.DateRegular: + return format.timestamp({format: "MMM-DD HH:mm:ss.SSS"}); default: return format.timestamp({format: "MMM-DD HH:mm:ss.SSS"}); } @@ -70,7 +71,8 @@ function jsonLogFormat(opts: LoggerOptions): Format { /** * Winston template function print a human readable string given a log object */ -// eslint-disable-next-line @typescript-eslint/no-explicit-any + +// biome-ignore lint/suspicious/noExplicitAny: function humanReadableTemplateFn(_info: {[key: string]: any; level: string; message: string}): string { const info = _info as WinstonInfoArg; diff --git a/packages/logger/src/utils/json.ts b/packages/logger/src/utils/json.ts index 7408de582dd1..f1919a38da8b 100644 --- a/packages/logger/src/utils/json.ts +++ b/packages/logger/src/utils/json.ts @@ -127,6 +127,7 @@ export function logCtxToString(arg: unknown, depth = 0, fromError = false): stri case "string": case "undefined": case "boolean": + return String(arg); default: return String(arg); } diff --git a/packages/logger/test/e2e/logger/workerLogger.js b/packages/logger/test/e2e/logger/workerLogger.js index 9608336c433f..83d1c857631f 100644 --- a/packages/logger/test/e2e/logger/workerLogger.js +++ b/packages/logger/test/e2e/logger/workerLogger.js @@ -9,7 +9,6 @@ if (!parentPort) throw Error("parentPort must be defined"); const file = fs.createWriteStream(workerData.logFilepath, {flags: "a"}); parentPort.on("message", (data) => { - // eslint-disable-next-line no-console console.log(data); file.write(data); }); diff --git a/packages/logger/test/e2e/logger/workerLogs.test.ts b/packages/logger/test/e2e/logger/workerLogs.test.ts index 3c81cbf92c57..969cd84bc5ff 100644 --- a/packages/logger/test/e2e/logger/workerLogs.test.ts +++ b/packages/logger/test/e2e/logger/workerLogs.test.ts @@ -7,7 +7,6 @@ import {LoggerWorker, getLoggerWorker} from "./workerLoggerHandler.js"; // Global variable __dirname no longer available in ES6 modules. // Solutions: https://stackoverflow.com/questions/46745014/alternative-for-dirname-in-node-js-when-using-es6-modules -// eslint-disable-next-line @typescript-eslint/naming-convention const __dirname = path.dirname(fileURLToPath(import.meta.url)); describe("worker logs", function () { diff --git a/packages/logger/test/unit/node.node.test.ts b/packages/logger/test/unit/node.node.test.ts index 12782fa49af8..da1245fa37f1 100644 --- a/packages/logger/test/unit/node.node.test.ts +++ b/packages/logger/test/unit/node.node.test.ts @@ -6,7 +6,6 @@ import {formatsTestCases} from "../fixtures/loggerFormats.js"; // Node.js maps `process.stdout` to `console._stdout`. // spy does not work on `process.stdout` directly. -// eslint-disable-next-line @typescript-eslint/naming-convention type TestConsole = typeof console & {_stdout: {write: Mock}}; describe("node logger", () => { diff --git a/packages/logger/test/unit/utils/json.test.ts b/packages/logger/test/unit/utils/json.test.ts index 912f15fa958b..4b91fd1995b5 100644 --- a/packages/logger/test/unit/utils/json.test.ts +++ b/packages/logger/test/unit/utils/json.test.ts @@ -113,7 +113,6 @@ describe("Json helper", () => { // Circular references () => { const circularReference: any = {}; - // eslint-disable-next-line @typescript-eslint/no-unsafe-assignment, @typescript-eslint/no-unsafe-member-access circularReference.myself = circularReference; return { id: "circular reference", @@ -161,7 +160,6 @@ describe("Json helper", () => { // Objects {id: "object of basic types", json: {a: 1, b: "a", c: root}, output: `a=1, b=a, c=${rootHex}`}, - // eslint-disable-next-line quotes {id: "object of objects", json: {a: {b: 1}}, output: `a=[object]`}, { id: "error metadata", @@ -175,7 +173,6 @@ describe("Json helper", () => { // Circular references () => { const circularReference: any = {}; - // eslint-disable-next-line @typescript-eslint/no-unsafe-assignment, @typescript-eslint/no-unsafe-member-access circularReference.myself = circularReference; return { id: "circular reference", diff --git a/packages/logger/test/unit/winston.node.test.ts b/packages/logger/test/unit/winston.node.test.ts index 8ef49da4e02d..6763cc667afd 100644 --- a/packages/logger/test/unit/winston.node.test.ts +++ b/packages/logger/test/unit/winston.node.test.ts @@ -8,7 +8,6 @@ import {readFileWhenExists} from "../utils/files.js"; // Node.js maps `process.stdout` to `console._stdout`. // spy does not work on `process.stdout` directly. -// eslint-disable-next-line @typescript-eslint/naming-convention type TestConsole = typeof console & {_stdout: {write: Mock}}; describe("winston logger", () => { diff --git a/packages/params/package.json b/packages/params/package.json index c281f97a41ec..33b8415170f1 100644 --- a/packages/params/package.json +++ b/packages/params/package.json @@ -50,8 +50,8 @@ "build:watch": "yarn run build --watch", "check-build": "node -e \"(async function() { await import('./lib/index.js') })()\"", "check-types": "tsc", - "lint": "eslint --color --ext .ts src/ test/", - "lint:fix": "yarn run lint --fix", + "lint": "biome check src/ test/", + "lint:fix": "yarn run lint --write", "test": "yarn test:unit", "test:unit": "vitest --run --dir test/unit/", "test:browsers": "yarn test:browsers:chrome && yarn test:browsers:firefox && yarn test:browsers:electron", diff --git a/packages/params/src/presets/gnosis.ts b/packages/params/src/presets/gnosis.ts index 412c38a6eb82..5a4a2eac4113 100644 --- a/packages/params/src/presets/gnosis.ts +++ b/packages/params/src/presets/gnosis.ts @@ -4,7 +4,6 @@ import {mainnetPreset} from "./mainnet.js"; // Gnosis preset // https://github.com/gnosischain/specs/tree/master/consensus/preset/gnosis -/* eslint-disable @typescript-eslint/naming-convention */ export const gnosisPreset: BeaconPreset = { ...mainnetPreset, diff --git a/packages/params/src/presets/mainnet.ts b/packages/params/src/presets/mainnet.ts index ca599e990df4..a7225739037f 100644 --- a/packages/params/src/presets/mainnet.ts +++ b/packages/params/src/presets/mainnet.ts @@ -3,7 +3,6 @@ import {BeaconPreset} from "../types.js"; // Mainnet preset // https://github.com/ethereum/consensus-specs/tree/dev/presets/mainnet -/* eslint-disable @typescript-eslint/naming-convention */ export const mainnetPreset: BeaconPreset = { // Misc // --------------------------------------------------------------- diff --git a/packages/params/src/presets/minimal.ts b/packages/params/src/presets/minimal.ts index 5dc8fc10d803..d7ab2c27f342 100644 --- a/packages/params/src/presets/minimal.ts +++ b/packages/params/src/presets/minimal.ts @@ -3,7 +3,6 @@ import {BeaconPreset} from "../types.js"; // Minimal preset // https://github.com/ethereum/consensus-specs/tree/dev/presets/minimal -/* eslint-disable @typescript-eslint/naming-convention */ export const minimalPreset: BeaconPreset = { // Misc // --------------------------------------------------------------- diff --git a/packages/params/src/types.ts b/packages/params/src/types.ts index e867b4a3cf71..2fd88da9fde3 100644 --- a/packages/params/src/types.ts +++ b/packages/params/src/types.ts @@ -1,5 +1,3 @@ -/* eslint-disable @typescript-eslint/naming-convention */ - /** * Compile-time chain configuration */ diff --git a/packages/params/test/e2e/ensure-config-is-synced.test.ts b/packages/params/test/e2e/ensure-config-is-synced.test.ts index 38168fa02bae..12e4c2a35e55 100644 --- a/packages/params/test/e2e/ensure-config-is-synced.test.ts +++ b/packages/params/test/e2e/ensure-config-is-synced.test.ts @@ -44,7 +44,6 @@ async function downloadRemoteConfig(preset: "mainnet" | "minimal", commit: strin ); // Merge all the fetched yamls for the different forks - // eslint-disable-next-line @typescript-eslint/no-unsafe-assignment const beaconPresetRaw: Record = Object.assign( ...(downloadedParams as unknown as [input: Record]) ); diff --git a/packages/params/test/e2e/overridePreset.test.ts b/packages/params/test/e2e/overridePreset.test.ts index 24995cbaa042..12fa1fb095c6 100644 --- a/packages/params/test/e2e/overridePreset.test.ts +++ b/packages/params/test/e2e/overridePreset.test.ts @@ -13,7 +13,6 @@ const exec = util.promisify(child.exec); // Global variable __dirname no longer available in ES6 modules. // Solutions: https://stackoverflow.com/questions/46745014/alternative-for-dirname-in-node-js-when-using-es6-modules -// eslint-disable-next-line @typescript-eslint/naming-convention const __dirname = path.dirname(fileURLToPath(import.meta.url)); describe("Override preset", function () { diff --git a/packages/params/test/e2e/overridePresetError.ts b/packages/params/test/e2e/overridePresetError.ts index d5a665bece1f..869f521d33b5 100644 --- a/packages/params/test/e2e/overridePresetError.ts +++ b/packages/params/test/e2e/overridePresetError.ts @@ -5,5 +5,4 @@ import "../../lib/index.js"; import {setActivePreset, PresetName} from "../../lib/setPreset.js"; // This line should throw -// eslint-disable-next-line @typescript-eslint/naming-convention setActivePreset(PresetName.minimal, {SLOTS_PER_EPOCH: 2}); diff --git a/packages/params/test/e2e/overridePresetOk.ts b/packages/params/test/e2e/overridePresetOk.ts index 7373ecee7fff..8887155b5400 100644 --- a/packages/params/test/e2e/overridePresetOk.ts +++ b/packages/params/test/e2e/overridePresetOk.ts @@ -6,7 +6,6 @@ import assert from "node:assert"; // 1. Import from @lodestar/params/setPreset only import {setActivePreset, PresetName} from "../../src/setPreset.js"; -// eslint-disable-next-line @typescript-eslint/naming-convention setActivePreset(PresetName.minimal, {SLOTS_PER_EPOCH: 2}); // 2. Import from any other @lodestar/params paths diff --git a/packages/params/test/e2e/setPreset.test.ts b/packages/params/test/e2e/setPreset.test.ts index 844239d56bab..1e236b8f2d85 100644 --- a/packages/params/test/e2e/setPreset.test.ts +++ b/packages/params/test/e2e/setPreset.test.ts @@ -13,7 +13,6 @@ const exec = util.promisify(child.exec); // Global variable __dirname no longer available in ES6 modules. // Solutions: https://stackoverflow.com/questions/46745014/alternative-for-dirname-in-node-js-when-using-es6-modules -// eslint-disable-next-line @typescript-eslint/naming-convention const __dirname = path.dirname(fileURLToPath(import.meta.url)); describe("setPreset", function () { diff --git a/packages/params/test/yaml.ts b/packages/params/test/yaml.ts index 162d48bc4084..d1bc72125923 100644 --- a/packages/params/test/yaml.ts +++ b/packages/params/test/yaml.ts @@ -9,7 +9,6 @@ export const schema = FAILSAFE_SCHEMA.extend({ new Type("tag:yaml.org,2002:str", { kind: "scalar", construct: function (data) { - // eslint-disable-next-line @typescript-eslint/no-unsafe-return return data !== null ? data : ""; }, }), diff --git a/packages/prover/package.json b/packages/prover/package.json index 6a31b5b1baa0..9bfe7f21e480 100644 --- a/packages/prover/package.json +++ b/packages/prover/package.json @@ -48,8 +48,8 @@ "build:release": "yarn clean && yarn run build", "check-build": "node -e \"(async function() { await import('./lib/index.js') })()\"", "check-types": "tsc", - "lint": "eslint --color --ext .ts src/ test/", - "lint:fix": "yarn run lint --fix", + "lint": "biome check src/ test/", + "lint:fix": "yarn run lint --write", "test": "yarn test:unit && yarn test:e2e", "test:unit": "vitest --run --dir test/unit/", "test:browsers": "yarn test:browsers:chrome && yarn test:browsers:firefox && yarn test:browsers:electron", diff --git a/packages/prover/scripts/generate_fixtures.ts b/packages/prover/scripts/generate_fixtures.ts index 70ab31fed5c1..b5d1d18d89f1 100644 --- a/packages/prover/scripts/generate_fixtures.ts +++ b/packages/prover/scripts/generate_fixtures.ts @@ -2,9 +2,7 @@ import {writeFile, mkdir} from "node:fs/promises"; import path from "node:path"; import url from "node:url"; -// eslint-disable-next-line import/no-extraneous-dependencies import axios from "axios"; -// eslint-disable-next-line @typescript-eslint/naming-convention const __dirname = url.fileURLToPath(new URL(".", import.meta.url)); type JSONRequest = {method: string; params: unknown[]}; @@ -95,17 +93,14 @@ async function generateFixture(label: string, generator: Generator, network: NET } const beacon = { - // eslint-disable-next-line @typescript-eslint/no-unsafe-assignment, @typescript-eslint/no-unsafe-member-access, @typescript-eslint/no-explicit-any - executionPayload: ((await rawBeacon(network, `eth/v2/beacon/blocks/${slot}`)) as any).data.message.body + executionPayload: ((await rawBeacon(network, `eth/v2/beacon/blocks/${slot}`)) as any).data.message.body .execution_payload, - // eslint-disable-next-line @typescript-eslint/no-unsafe-assignment, @typescript-eslint/no-unsafe-member-access, @typescript-eslint/no-explicit-any - headers: ((await rawBeacon(network, `eth/v1/beacon/headers/${slot}`)) as any).data, + headers: ((await rawBeacon(network, `eth/v1/beacon/headers/${slot}`)) as any).data, }; const payloadBlock = await getBlockByHash( network, - // eslint-disable-next-line @typescript-eslint/naming-convention - (beacon.executionPayload as {block_hash: string}).block_hash, + (beacon.executionPayload as {block_hash: string}).block_hash, true ); diff --git a/packages/prover/src/cli/applyPreset.ts b/packages/prover/src/cli/applyPreset.ts index 158e05243ec7..4a79a1a4417b 100644 --- a/packages/prover/src/cli/applyPreset.ts +++ b/packages/prover/src/cli/applyPreset.ts @@ -1,8 +1,6 @@ // MUST import this file first before anything and not import any Lodestar code. -// eslint-disable-next-line no-restricted-imports, import/no-extraneous-dependencies import {hasher} from "@chainsafe/persistent-merkle-tree/lib/hasher/as-sha256.js"; -// eslint-disable-next-line no-restricted-imports, import/no-extraneous-dependencies import {setHasher} from "@chainsafe/persistent-merkle-tree/lib/hasher/index.js"; // without setting this first, persistent-merkle-tree will use noble instead @@ -45,7 +43,6 @@ else if (network) { if (network === "dev") { process.env.LODESTAR_PRESET = "minimal"; // "c-kzg" has hardcoded the mainnet value, do not use presets - // eslint-disable-next-line @typescript-eslint/naming-convention setActivePreset(PresetName.minimal, {FIELD_ELEMENTS_PER_BLOB: 4096}); } else if (network === "gnosis" || network === "chiado") { process.env.LODESTAR_PRESET = "gnosis"; diff --git a/packages/prover/src/cli/cmds/start/options.ts b/packages/prover/src/cli/cmds/start/options.ts index f63ee974be44..bdf0670771ef 100644 --- a/packages/prover/src/cli/cmds/start/options.ts +++ b/packages/prover/src/cli/cmds/start/options.ts @@ -57,7 +57,9 @@ export const startOptions: CliCommandOptions = { string: true, coerce: (urls: string[]): string[] => // Parse ["url1,url2"] to ["url1", "url2"] - urls.map((item) => item.split(",")).flat(), + urls + .map((item) => item.split(",")) + .flat(), demandOption: true, group: "beacon", }, diff --git a/packages/prover/src/cli/index.ts b/packages/prover/src/cli/index.ts index 845831b32cb0..5bd071642c96 100644 --- a/packages/prover/src/cli/index.ts +++ b/packages/prover/src/cli/index.ts @@ -14,7 +14,7 @@ void prover // Show command help message when no command is provided if (msg.includes("Not enough non-option arguments")) { yarg.showHelp(); - // eslint-disable-next-line no-console + // biome-ignore lint/suspicious/noConsoleLog: This code will run only in browser so console will be available. console.log("\n"); } } @@ -22,7 +22,6 @@ void prover const errorMessage = err !== undefined ? (err instanceof YargsError ? err.message : err.stack) : msg || "Unknown error"; - // eslint-disable-next-line no-console console.error(` ✖ ${errorMessage}\n`); process.exit(1); }) diff --git a/packages/prover/src/interfaces.ts b/packages/prover/src/interfaces.ts index 36222c1476d3..9a67b47ea3b3 100644 --- a/packages/prover/src/interfaces.ts +++ b/packages/prover/src/interfaces.ts @@ -27,7 +27,7 @@ export type ELRequestHandler = ( payload: JsonRpcRequestOrBatch ) => Promise | undefined>; -// eslint-disable-next-line @typescript-eslint/no-explicit-any +// biome-ignore lint/suspicious/noExplicitAny: export type ELRequestHandlerAny = ELRequestHandler; /** diff --git a/packages/prover/src/types.ts b/packages/prover/src/types.ts index 781ba1f7b207..d404cd96d4d8 100644 --- a/packages/prover/src/types.ts +++ b/packages/prover/src/types.ts @@ -45,17 +45,17 @@ export interface JsonRpcResponseWithErrorPayload { } // Make the very flexible el response type to match different libraries easily -// eslint-disable-next-line @typescript-eslint/no-explicit-any +// biome-ignore lint/suspicious/noExplicitAny: export type JsonRpcResponse = | JsonRpcResponseWithResultPayload | JsonRpcResponseWithErrorPayload; -// eslint-disable-next-line @typescript-eslint/no-explicit-any +// biome-ignore lint/suspicious/noExplicitAny: export type JsonRpcBatchResponse = JsonRpcResponse[]; // Response can be a single response or an array of responses in case of batch request // Make the very flexible el response type to match different libraries easily -// eslint-disable-next-line @typescript-eslint/no-explicit-any +// biome-ignore lint/suspicious/noExplicitAny: export type JsonRpcResponseOrBatch = JsonRpcResponse | JsonRpcBatchResponse; export type HexString = string; @@ -145,7 +145,6 @@ export interface ELAccessListResponse { export type ELStorageProof = Pick; -/* eslint-disable @typescript-eslint/naming-convention */ export type ELApi = { eth_getBalance: (address: string, block?: number | string) => string; eth_createAccessList: (transaction: ELTransaction, block?: ELBlockNumberOrTag) => ELAccessListResponse; diff --git a/packages/prover/src/utils/conversion.ts b/packages/prover/src/utils/conversion.ts index c809de5c4555..77c3141f828a 100644 --- a/packages/prover/src/utils/conversion.ts +++ b/packages/prover/src/utils/conversion.ts @@ -58,7 +58,6 @@ export function headerDataFromELBlock(blockInfo: ELBlock): HeaderData { }; } -// eslint-disable-next-line @typescript-eslint/explicit-function-return-type export function txDataFromELBlock(txInfo: ELTransaction) { return { ...txInfo, diff --git a/packages/prover/src/utils/evm.ts b/packages/prover/src/utils/evm.ts index 19f43d9584c8..40950647b8f3 100644 --- a/packages/prover/src/utils/evm.ts +++ b/packages/prover/src/utils/evm.ts @@ -20,7 +20,7 @@ export async function createVM({proofProvider}: {proofProvider: ProofProvider}): const blockchain = await Blockchain.create({common}); // Connect blockchain object with existing proof provider for block history - // eslint-disable-next-line @typescript-eslint/no-unsafe-member-access, @typescript-eslint/no-explicit-any + // biome-ignore lint/suspicious/noExplicitAny: (blockchain as any).getBlock = async (blockId: number) => { const payload = await proofProvider.getExecutionPayload(blockId); return { diff --git a/packages/prover/src/utils/file.ts b/packages/prover/src/utils/file.ts index d236d2d5dc95..acc62033010f 100644 --- a/packages/prover/src/utils/file.ts +++ b/packages/prover/src/utils/file.ts @@ -15,7 +15,6 @@ const yamlSchema = FAILSAFE_SCHEMA.extend({ new Type("tag:yaml.org,2002:str", { kind: "scalar", construct: function construct(data) { - // eslint-disable-next-line @typescript-eslint/no-unsafe-return return data !== null ? data : ""; }, }), diff --git a/packages/prover/src/utils/gitData/gitDataPath.ts b/packages/prover/src/utils/gitData/gitDataPath.ts index e243ca433f2d..1ad3104aafc6 100644 --- a/packages/prover/src/utils/gitData/gitDataPath.ts +++ b/packages/prover/src/utils/gitData/gitDataPath.ts @@ -4,7 +4,6 @@ import {fileURLToPath} from "node:url"; // Global variable __dirname no longer available in ES6 modules. // Solutions: https://stackoverflow.com/questions/46745014/alternative-for-dirname-in-node-js-when-using-es6-modules -// eslint-disable-next-line @typescript-eslint/naming-convention const __dirname = path.dirname(fileURLToPath(import.meta.url)); // Persist git data and distribute through NPM so CLI consumers can know exactly diff --git a/packages/prover/src/utils/gitData/index.ts b/packages/prover/src/utils/gitData/index.ts index 96c5e4bbaef2..0720d39d9e30 100644 --- a/packages/prover/src/utils/gitData/index.ts +++ b/packages/prover/src/utils/gitData/index.ts @@ -11,7 +11,7 @@ export function readAndGetGitData(): GitData { let persistedGitData: Partial; try { persistedGitData = readGitDataFile(); - } catch (e) { + } catch (_e) { persistedGitData = {}; } @@ -23,13 +23,13 @@ export function readAndGetGitData(): GitData { branch: currentGitData.branch && currentGitData.branch.length > 0 ? currentGitData.branch - : persistedGitData.branch ?? "", + : (persistedGitData.branch ?? ""), commit: currentGitData.commit && currentGitData.commit.length > 0 ? currentGitData.commit - : persistedGitData.commit ?? "", + : (persistedGitData.commit ?? ""), }; - } catch (e) { + } catch (_e) { return { branch: "", commit: "", @@ -49,7 +49,7 @@ export function getGitData(): GitData { function getBranch(): string { try { return shellSilent("git rev-parse --abbrev-ref HEAD"); - } catch (e) { + } catch (_e) { return ""; } } @@ -58,7 +58,7 @@ function getBranch(): string { function getCommit(): string { try { return shellSilent("git rev-parse --verify HEAD"); - } catch (e) { + } catch (_e) { return ""; } } diff --git a/packages/prover/src/utils/process.ts b/packages/prover/src/utils/process.ts index 26768ffce1fb..80748544302c 100644 --- a/packages/prover/src/utils/process.ts +++ b/packages/prover/src/utils/process.ts @@ -13,7 +13,7 @@ import {getResponseForRequest, isBatchRequest, isRequest} from "./json_rpc.js"; import {isNullish} from "./validation.js"; import {ELRpcProvider} from "./rpc_provider.js"; -/* eslint-disable @typescript-eslint/naming-convention, @typescript-eslint/no-explicit-any */ +// biome-ignore lint/suspicious/noExplicitAny: export const verifiableMethodHandlers: Record> = { eth_getBalance: eth_getBalance, eth_getTransactionCount: eth_getTransactionCount, diff --git a/packages/prover/src/utils/version.ts b/packages/prover/src/utils/version.ts index 4752856e5b1d..624412107603 100644 --- a/packages/prover/src/utils/version.ts +++ b/packages/prover/src/utils/version.ts @@ -6,7 +6,6 @@ import {readAndGetGitData} from "./gitData/index.js"; // Global variable __dirname no longer available in ES6 modules. // Solutions: https://stackoverflow.com/questions/46745014/alternative-for-dirname-in-node-js-when-using-es6-modules -// eslint-disable-next-line @typescript-eslint/naming-convention const __dirname = path.dirname(fileURLToPath(import.meta.url)); type VersionJson = { diff --git a/packages/prover/src/verified_requests/eth_call.ts b/packages/prover/src/verified_requests/eth_call.ts index b28bd222c568..eea7ba146c3f 100644 --- a/packages/prover/src/verified_requests/eth_call.ts +++ b/packages/prover/src/verified_requests/eth_call.ts @@ -8,7 +8,6 @@ import { getVerificationFailedMessage, } from "../utils/json_rpc.js"; -// eslint-disable-next-line @typescript-eslint/naming-convention export const eth_call: ELVerifiedRequestHandler = async ({ rpc, payload, diff --git a/packages/prover/src/verified_requests/eth_estimateGas.ts b/packages/prover/src/verified_requests/eth_estimateGas.ts index fee446aadb5b..4ac4c3ccb6bc 100644 --- a/packages/prover/src/verified_requests/eth_estimateGas.ts +++ b/packages/prover/src/verified_requests/eth_estimateGas.ts @@ -8,7 +8,6 @@ import { getVerificationFailedMessage, } from "../utils/json_rpc.js"; -// eslint-disable-next-line @typescript-eslint/naming-convention export const eth_estimateGas: ELVerifiedRequestHandler< ELApiParams["eth_estimateGas"], ELApiReturn["eth_estimateGas"] diff --git a/packages/prover/src/verified_requests/eth_getBalance.ts b/packages/prover/src/verified_requests/eth_getBalance.ts index b5b7e63dcb64..0c03b23be788 100644 --- a/packages/prover/src/verified_requests/eth_getBalance.ts +++ b/packages/prover/src/verified_requests/eth_getBalance.ts @@ -6,7 +6,6 @@ import { getVerificationFailedMessage, } from "../utils/json_rpc.js"; -// eslint-disable-next-line @typescript-eslint/naming-convention export const eth_getBalance: ELVerifiedRequestHandler<[address: string, block?: number | string], string> = async ({ rpc, payload, diff --git a/packages/prover/src/verified_requests/eth_getBlockByHash.ts b/packages/prover/src/verified_requests/eth_getBlockByHash.ts index cb5fa1711c0f..00a110c01e9a 100644 --- a/packages/prover/src/verified_requests/eth_getBlockByHash.ts +++ b/packages/prover/src/verified_requests/eth_getBlockByHash.ts @@ -7,7 +7,6 @@ import { getVerificationFailedMessage, } from "../utils/json_rpc.js"; -// eslint-disable-next-line @typescript-eslint/naming-convention export const eth_getBlockByHash: ELVerifiedRequestHandler<[block: string, hydrated: boolean], ELBlock> = async ({ rpc, payload, diff --git a/packages/prover/src/verified_requests/eth_getBlockByNumber.ts b/packages/prover/src/verified_requests/eth_getBlockByNumber.ts index a08703881cc0..23e0fa2ca863 100644 --- a/packages/prover/src/verified_requests/eth_getBlockByNumber.ts +++ b/packages/prover/src/verified_requests/eth_getBlockByNumber.ts @@ -7,7 +7,6 @@ import { getVerificationFailedMessage, } from "../utils/json_rpc.js"; -// eslint-disable-next-line @typescript-eslint/naming-convention export const eth_getBlockByNumber: ELVerifiedRequestHandler< [block: string | number, hydrated: boolean], ELBlock diff --git a/packages/prover/src/verified_requests/eth_getCode.ts b/packages/prover/src/verified_requests/eth_getCode.ts index 9cb3362c4e50..f94ae8c1c8bd 100644 --- a/packages/prover/src/verified_requests/eth_getCode.ts +++ b/packages/prover/src/verified_requests/eth_getCode.ts @@ -6,7 +6,6 @@ import { getVerificationFailedMessage, } from "../utils/json_rpc.js"; -// eslint-disable-next-line @typescript-eslint/naming-convention export const eth_getCode: ELVerifiedRequestHandler<[address: string, block?: number | string], string> = async ({ rpc, payload, diff --git a/packages/prover/src/verified_requests/eth_getTransactionCount.ts b/packages/prover/src/verified_requests/eth_getTransactionCount.ts index 4cafd9b2b271..aeef67e96e74 100644 --- a/packages/prover/src/verified_requests/eth_getTransactionCount.ts +++ b/packages/prover/src/verified_requests/eth_getTransactionCount.ts @@ -6,7 +6,6 @@ import { getVerificationFailedMessage, } from "../utils/json_rpc.js"; -// eslint-disable-next-line @typescript-eslint/naming-convention export const eth_getTransactionCount: ELVerifiedRequestHandler< [address: string, block?: number | string], string @@ -15,7 +14,6 @@ export const eth_getTransactionCount: ELVerifiedRequestHandler< params: [address, block], } = payload; const result = await verifyAccount({proofProvider, logger, rpc, address, block}); - if (result.valid) { return getResponseForRequest(payload, result.data.nonce); } diff --git a/packages/prover/test/fixtures/mainnet/eth_call.json b/packages/prover/test/fixtures/mainnet/eth_call.json index 92e9ee557bc2..a3fe44880626 100644 --- a/packages/prover/test/fixtures/mainnet/eth_call.json +++ b/packages/prover/test/fixtures/mainnet/eth_call.json @@ -5226,4 +5226,4 @@ ] } ] -} \ No newline at end of file +} diff --git a/packages/prover/test/fixtures/mainnet/eth_estimateGas_contract_call.json b/packages/prover/test/fixtures/mainnet/eth_estimateGas_contract_call.json index eaae6bc7190d..a8be70662e2b 100644 --- a/packages/prover/test/fixtures/mainnet/eth_estimateGas_contract_call.json +++ b/packages/prover/test/fixtures/mainnet/eth_estimateGas_contract_call.json @@ -5226,4 +5226,4 @@ ] } ] -} \ No newline at end of file +} diff --git a/packages/prover/test/fixtures/mainnet/eth_estimateGas_simple_transfer.json b/packages/prover/test/fixtures/mainnet/eth_estimateGas_simple_transfer.json index f9b654b1a6fa..606e520a441c 100644 --- a/packages/prover/test/fixtures/mainnet/eth_estimateGas_simple_transfer.json +++ b/packages/prover/test/fixtures/mainnet/eth_estimateGas_simple_transfer.json @@ -5227,4 +5227,4 @@ ] } ] -} \ No newline at end of file +} diff --git a/packages/prover/test/fixtures/sepolia/eth_getBalance_contract.json b/packages/prover/test/fixtures/sepolia/eth_getBalance_contract.json index f6e2a31b2b87..660889c259d7 100644 --- a/packages/prover/test/fixtures/sepolia/eth_getBalance_contract.json +++ b/packages/prover/test/fixtures/sepolia/eth_getBalance_contract.json @@ -2704,4 +2704,4 @@ } } ] -} \ No newline at end of file +} diff --git a/packages/prover/test/fixtures/sepolia/eth_getBalance_eoa.json b/packages/prover/test/fixtures/sepolia/eth_getBalance_eoa.json index 03627b534159..a2489403db5b 100644 --- a/packages/prover/test/fixtures/sepolia/eth_getBalance_eoa.json +++ b/packages/prover/test/fixtures/sepolia/eth_getBalance_eoa.json @@ -2703,4 +2703,4 @@ } } ] -} \ No newline at end of file +} diff --git a/packages/prover/test/fixtures/sepolia/eth_getBlock_with_contractCreation.json b/packages/prover/test/fixtures/sepolia/eth_getBlock_with_contractCreation.json index 6b0471a182cf..c61d0e58e35e 100644 --- a/packages/prover/test/fixtures/sepolia/eth_getBlock_with_contractCreation.json +++ b/packages/prover/test/fixtures/sepolia/eth_getBlock_with_contractCreation.json @@ -5,10 +5,7 @@ "id": 809166, "jsonrpc": "2.0", "method": "eth_getBlockByHash", - "params": [ - "0x3a0225b38d5927a37cc95fd48254e83c4e9b70115918a103d9fd7e36464030d4", - true - ] + "params": ["0x3a0225b38d5927a37cc95fd48254e83c4e9b70115918a103d9fd7e36464030d4", true] }, "response": { "jsonrpc": "2.0", @@ -571,4 +568,4 @@ } }, "dependentRequests": [] -} \ No newline at end of file +} diff --git a/packages/prover/test/fixtures/sepolia/eth_getBlock_with_no_accessList.json b/packages/prover/test/fixtures/sepolia/eth_getBlock_with_no_accessList.json index 59bb888450d1..c6c1f9c8d675 100644 --- a/packages/prover/test/fixtures/sepolia/eth_getBlock_with_no_accessList.json +++ b/packages/prover/test/fixtures/sepolia/eth_getBlock_with_no_accessList.json @@ -5,10 +5,7 @@ "id": 809162, "jsonrpc": "2.0", "method": "eth_getBlockByHash", - "params": [ - "0x75b10426177f0f4bd8683999e2c7c597007c6e7c4551d6336c0f880b12c6f3bf", - true - ] + "params": ["0x75b10426177f0f4bd8683999e2c7c597007c6e7c4551d6336c0f880b12c6f3bf", true] }, "response": { "jsonrpc": "2.0", @@ -2381,4 +2378,4 @@ } }, "dependentRequests": [] -} \ No newline at end of file +} diff --git a/packages/prover/test/fixtures/sepolia/eth_getCode.json b/packages/prover/test/fixtures/sepolia/eth_getCode.json index 1787e8cfd2ce..a15c15698420 100644 --- a/packages/prover/test/fixtures/sepolia/eth_getCode.json +++ b/packages/prover/test/fixtures/sepolia/eth_getCode.json @@ -2704,4 +2704,4 @@ } } ] -} \ No newline at end of file +} diff --git a/packages/prover/test/fixtures/sepolia/eth_getTransactionCount.json b/packages/prover/test/fixtures/sepolia/eth_getTransactionCount.json index ff45a5e8a776..486c44698c16 100644 --- a/packages/prover/test/fixtures/sepolia/eth_getTransactionCount.json +++ b/packages/prover/test/fixtures/sepolia/eth_getTransactionCount.json @@ -2703,4 +2703,4 @@ } } ] -} \ No newline at end of file +} diff --git a/packages/prover/test/mocks/request_handler.ts b/packages/prover/test/mocks/request_handler.ts index bbe4f24057de..edde1e59a3fe 100644 --- a/packages/prover/test/mocks/request_handler.ts +++ b/packages/prover/test/mocks/request_handler.ts @@ -116,7 +116,6 @@ export function generateReqHandlerOptionsMock( getExecutionPayload: vi.fn().mockResolvedValue(executionPayload), config: { ...config, - // eslint-disable-next-line @typescript-eslint/naming-convention PRESET_BASE: data.network as unknown as PresetName, }, network: data.network, diff --git a/packages/prover/test/tsconfig.json b/packages/prover/test/tsconfig.json index 7e6bad81b22f..f4241fc1fbcd 100644 --- a/packages/prover/test/tsconfig.json +++ b/packages/prover/test/tsconfig.json @@ -3,4 +3,4 @@ "compilerOptions": { "noEmit": false } -} \ No newline at end of file +} diff --git a/packages/prover/test/unit/verified_requests/eth_getBlockByHash.test.ts b/packages/prover/test/unit/verified_requests/eth_getBlockByHash.test.ts index fca484657c01..3175bdd6d60c 100644 --- a/packages/prover/test/unit/verified_requests/eth_getBlockByHash.test.ts +++ b/packages/prover/test/unit/verified_requests/eth_getBlockByHash.test.ts @@ -3,8 +3,12 @@ import {createForkConfig} from "@lodestar/config"; import {NetworkName, networksChainConfig} from "@lodestar/config/networks"; import {VERIFICATION_FAILED_RESPONSE_CODE} from "../../../src/constants.js"; import {eth_getBlockByHash} from "../../../src/verified_requests/eth_getBlockByHash.js"; -import ethGetBlockWithContractCreation from "../../fixtures/sepolia/eth_getBlock_with_contractCreation.json" assert {type: "json"}; -import ethGetBlockWithNoAccessList from "../../fixtures/sepolia/eth_getBlock_with_no_accessList.json" assert {type: "json"}; +import ethGetBlockWithContractCreation from "../../fixtures/sepolia/eth_getBlock_with_contractCreation.json" assert { + type: "json", +}; +import ethGetBlockWithNoAccessList from "../../fixtures/sepolia/eth_getBlock_with_no_accessList.json" assert { + type: "json", +}; import {TestFixture, cloneTestFixture, generateReqHandlerOptionsMock} from "../../mocks/request_handler.js"; import {ELBlock} from "../../../src/types.js"; import {getVerificationFailedMessage} from "../../../src/utils/json_rpc.js"; diff --git a/packages/prover/test/unit/verified_requests/eth_getBlockByNumber.test.ts b/packages/prover/test/unit/verified_requests/eth_getBlockByNumber.test.ts index 81f644a46024..cc1389128ec0 100644 --- a/packages/prover/test/unit/verified_requests/eth_getBlockByNumber.test.ts +++ b/packages/prover/test/unit/verified_requests/eth_getBlockByNumber.test.ts @@ -4,8 +4,12 @@ import {NetworkName, networksChainConfig} from "@lodestar/config/networks"; import {VERIFICATION_FAILED_RESPONSE_CODE} from "../../../src/constants.js"; import {ELBlock} from "../../../src/types.js"; import {eth_getBlockByNumber} from "../../../src/verified_requests/eth_getBlockByNumber.js"; -import ethGetBlockWithContractCreation from "../../fixtures/sepolia/eth_getBlock_with_contractCreation.json" assert {type: "json"}; -import ethGetBlockWithNoAccessList from "../../fixtures/sepolia/eth_getBlock_with_no_accessList.json" assert {type: "json"}; +import ethGetBlockWithContractCreation from "../../fixtures/sepolia/eth_getBlock_with_contractCreation.json" assert { + type: "json", +}; +import ethGetBlockWithNoAccessList from "../../fixtures/sepolia/eth_getBlock_with_no_accessList.json" assert { + type: "json", +}; import {TestFixture, cloneTestFixture, generateReqHandlerOptionsMock} from "../../mocks/request_handler.js"; import {getVerificationFailedMessage} from "../../../src/utils/json_rpc.js"; @@ -88,7 +92,6 @@ describe("verified_requests / eth_getBlockByNumber", () => { // Temper the execution payload const testCase = cloneTestFixture(t, { beacon: { - // eslint-disable-next-line @typescript-eslint/naming-convention executionPayload: {parent_hash: "0xbdbd90ab601a073c3d128111eafb12fa7ece4af239abdc8be60184a08c6d7ef4"}, }, }); diff --git a/packages/prover/test/utils/e2e_env.ts b/packages/prover/test/utils/e2e_env.ts index b63d276daa5f..17af3739569a 100644 --- a/packages/prover/test/utils/e2e_env.ts +++ b/packages/prover/test/utils/e2e_env.ts @@ -1,6 +1,5 @@ import {waitForEndpoint} from "@lodestar/test-utils"; -/* eslint-disable @typescript-eslint/naming-convention */ export const rpcUrl = "http://0.0.0.0:8001"; export const beaconUrl = "http://0.0.0.0:5001"; export const proxyPort = 8888; diff --git a/packages/reqresp/package.json b/packages/reqresp/package.json index 44dcb8048f99..9bd9775ba2c0 100644 --- a/packages/reqresp/package.json +++ b/packages/reqresp/package.json @@ -45,8 +45,8 @@ "build:release": "yarn clean && yarn run build", "check-build": "node -e \"(async function() { await import('./lib/index.js') })()\"", "check-types": "tsc", - "lint": "eslint --color --ext .ts src/ test/", - "lint:fix": "yarn run lint --fix", + "lint": "biome check src/ test/", + "lint:fix": "yarn run lint --write", "test": "yarn test:unit", "test:unit": "vitest --run --dir test/unit/", "check-readme": "typescript-docs-verifier" diff --git a/packages/reqresp/src/encoders/responseDecode.ts b/packages/reqresp/src/encoders/responseDecode.ts index 93ebff674ec6..d55b283df5e6 100644 --- a/packages/reqresp/src/encoders/responseDecode.ts +++ b/packages/reqresp/src/encoders/responseDecode.ts @@ -125,9 +125,8 @@ export async function readErrorMessage(bufferedSource: BufferedSource): Promise< try { return decodeErrorMessage(bytes); - } catch { + } catch (_e) { // Error message is optional and may not be included in the response stream - // eslint-disable-next-line @typescript-eslint/no-unsafe-return, @typescript-eslint/no-unsafe-member-access, @typescript-eslint/no-unsafe-call return Buffer.prototype.toString.call(bytes, "hex"); } } diff --git a/packages/reqresp/src/encodingStrategies/sszSnappy/decode.ts b/packages/reqresp/src/encodingStrategies/sszSnappy/decode.ts index 1bf9fc815e28..9ebe52876cfe 100644 --- a/packages/reqresp/src/encodingStrategies/sszSnappy/decode.ts +++ b/packages/reqresp/src/encodingStrategies/sszSnappy/decode.ts @@ -35,7 +35,7 @@ export async function readSszSnappyHeader(bufferedSource: BufferedSource, type: let sszDataLength: number; try { sszDataLength = varintDecode(buffer.subarray()); - } catch (e) { + } catch (_e) { throw new SszSnappyError({code: SszSnappyErrorCode.INVALID_VARINT_BYTES_COUNT, bytes: Infinity}); } diff --git a/packages/reqresp/src/encodingStrategies/sszSnappy/errors.ts b/packages/reqresp/src/encodingStrategies/sszSnappy/errors.ts index 12113ceb42fb..f9d6c4a8e9b5 100644 --- a/packages/reqresp/src/encodingStrategies/sszSnappy/errors.ts +++ b/packages/reqresp/src/encodingStrategies/sszSnappy/errors.ts @@ -28,8 +28,4 @@ type SszSnappyErrorType = | {code: SszSnappyErrorCode.TOO_MANY_BYTES; sszDataLength: number} | {code: SszSnappyErrorCode.SOURCE_ABORTED}; -export class SszSnappyError extends LodestarError { - constructor(type: SszSnappyErrorType) { - super(type); - } -} +export class SszSnappyError extends LodestarError {} diff --git a/packages/reqresp/src/encodingStrategies/sszSnappy/snappyFrames/uncompress.ts b/packages/reqresp/src/encodingStrategies/sszSnappy/snappyFrames/uncompress.ts index e97260989082..69d9ea44d834 100644 --- a/packages/reqresp/src/encodingStrategies/sszSnappy/snappyFrames/uncompress.ts +++ b/packages/reqresp/src/encodingStrategies/sszSnappy/snappyFrames/uncompress.ts @@ -35,7 +35,6 @@ export class SnappyFramesUncompress { } if (type === ChunkType.IDENTIFIER) { - // eslint-disable-next-line @typescript-eslint/no-unsafe-member-access, @typescript-eslint/no-unsafe-call if (!Buffer.prototype.equals.call(data, IDENTIFIER)) { throw "malformed input: bad identifier"; } diff --git a/packages/reqresp/src/metrics.ts b/packages/reqresp/src/metrics.ts index 4af18a782322..faf4b7cf65ae 100644 --- a/packages/reqresp/src/metrics.ts +++ b/packages/reqresp/src/metrics.ts @@ -5,7 +5,6 @@ export type Metrics = ReturnType; /** * A collection of metrics used throughout the Gossipsub behaviour. */ -// eslint-disable-next-line @typescript-eslint/explicit-function-return-type export function getMetrics(register: MetricsRegister) { // Using function style instead of class to prevent having to re-declare all MetricsPrometheus types. diff --git a/packages/reqresp/src/request/index.ts b/packages/reqresp/src/request/index.ts index 4920a32eb221..b79df24e2adf 100644 --- a/packages/reqresp/src/request/index.ts +++ b/packages/reqresp/src/request/index.ts @@ -98,7 +98,6 @@ export async function* sendRequest( async (timeoutAndParentSignal) => { const protocolIds = Array.from(protocolsMap.keys()); const conn = await libp2p.dialProtocol(peerId, protocolIds, {signal: timeoutAndParentSignal}); - // eslint-disable-next-line @typescript-eslint/strict-boolean-expressions if (!conn) throw Error("dialProtocol timeout"); return conn; }, diff --git a/packages/reqresp/src/response/index.ts b/packages/reqresp/src/response/index.ts index 27758caa3f24..ad13ba8b9359 100644 --- a/packages/reqresp/src/response/index.ts +++ b/packages/reqresp/src/response/index.ts @@ -76,7 +76,7 @@ export async function handleRequest({ signal ).catch((e: unknown) => { if (e instanceof TimeoutError) { - throw e; // Let outter catch {} re-type the error as SERVER_ERROR + throw e; // Let outter catch (_e) {} re-type the error as SERVER_ERROR } else { throw new ResponseError(RespStatus.INVALID_REQUEST, (e as Error).message); } diff --git a/packages/reqresp/src/utils/bufferedSource.ts b/packages/reqresp/src/utils/bufferedSource.ts index ac31a62ba29c..569cc217ea23 100644 --- a/packages/reqresp/src/utils/bufferedSource.ts +++ b/packages/reqresp/src/utils/bufferedSource.ts @@ -18,7 +18,6 @@ export class BufferedSource { } [Symbol.asyncIterator](): AsyncIterator { - // eslint-disable-next-line @typescript-eslint/no-this-alias const that = this; let firstNext = true; @@ -32,7 +31,6 @@ export class BufferedSource { return {done: false, value: that.buffer}; } - // eslint-disable-next-line @typescript-eslint/no-unsafe-assignment const {done, value: chunk} = await that.source.next(); if (done === true) { that.isDone = true; diff --git a/packages/reqresp/test/fixtures/encodingStrategies.ts b/packages/reqresp/test/fixtures/encodingStrategies.ts index c7705bb9493b..7bf183d8714c 100644 --- a/packages/reqresp/test/fixtures/encodingStrategies.ts +++ b/packages/reqresp/test/fixtures/encodingStrategies.ts @@ -15,7 +15,6 @@ import { // Global variable __dirname no longer available in ES6 modules. // Solutions: https://stackoverflow.com/questions/46745014/alternative-for-dirname-in-node-js-when-using-es6-modules -// eslint-disable-next-line @typescript-eslint/naming-convention const __dirname = path.dirname(fileURLToPath(import.meta.url)); type SszSnappyTestBlockData = { diff --git a/packages/reqresp/test/fixtures/messages.ts b/packages/reqresp/test/fixtures/messages.ts index 5558e7c3e13a..a243a05b221b 100644 --- a/packages/reqresp/test/fixtures/messages.ts +++ b/packages/reqresp/test/fixtures/messages.ts @@ -14,7 +14,6 @@ type MessageFixture = { }; const phase0Metadata = ssz.phase0.Metadata.fromJson({ - // eslint-disable-next-line @typescript-eslint/naming-convention seq_number: "9", attnets: "0x0000000000000000", }); @@ -37,7 +36,6 @@ export const sszSnappyPhase0Metadata: MessageFixture = { }; const altairMetadata = ssz.altair.Metadata.fromJson({ - // eslint-disable-next-line @typescript-eslint/naming-convention seq_number: "8", attnets: "0x0000000000000000", syncnets: "0x00", @@ -178,7 +176,6 @@ if (slotBlockAltair - slotBlockPhase0 < SLOTS_PER_EPOCH) { throw Error("phase0 block slot must be an epoch apart from altair block slot"); } const ALTAIR_FORK_EPOCH = Math.floor(slotBlockAltair / SLOTS_PER_EPOCH); -// eslint-disable-next-line @typescript-eslint/naming-convention export const beaconConfig = createBeaconConfig({...chainConfig, ALTAIR_FORK_EPOCH}, ZERO_HASH); export const getEmptyHandler = () => async function* emptyHandler(): AsyncGenerator {}; diff --git a/packages/reqresp/test/fixtures/protocols.ts b/packages/reqresp/test/fixtures/protocols.ts index f20d891781ef..19e8936fc376 100644 --- a/packages/reqresp/test/fixtures/protocols.ts +++ b/packages/reqresp/test/fixtures/protocols.ts @@ -5,7 +5,6 @@ import {ContextBytesType, DialOnlyProtocol, Encoding, ProtocolHandler, Protocol} import {getEmptyHandler} from "./messages.js"; import {beaconConfig} from "./messages.js"; -// eslint-disable-next-line @typescript-eslint/naming-convention const NumToStrReq = new ContainerType( { value: new UintNumberType(4), @@ -15,7 +14,6 @@ const NumToStrReq = new ContainerType( export type NumToStrReqType = ValueOf; -// eslint-disable-next-line @typescript-eslint/naming-convention const NumToStrResp = new ContainerType( { value: new ListBasicType(new UintNumberType(1), 4), diff --git a/packages/spec-test-util/package.json b/packages/spec-test-util/package.json index b4aabf0140e8..501d13024159 100644 --- a/packages/spec-test-util/package.json +++ b/packages/spec-test-util/package.json @@ -44,8 +44,8 @@ "build:watch": "yarn run build --watch", "check-build": "node -e \"(async function() { await import('./lib/downloadTests.js') })()\"", "check-types": "tsc", - "lint": "eslint --color --ext .ts src/ test/", - "lint:fix": "yarn run lint --fix", + "lint": "biome check src/ test/", + "lint:fix": "yarn run lint --write", "test": "yarn test:unit && yarn test:e2e", "test:unit": "vitest --run --passWithNoTests --dir test/unit/", "test:e2e": "vitest --run --config vitest.e2e.config.ts --dir test/e2e/", diff --git a/packages/spec-test-util/src/single.ts b/packages/spec-test-util/src/single.ts index 47bf8d0a0742..af77d45f6242 100644 --- a/packages/spec-test-util/src/single.ts +++ b/packages/spec-test-util/src/single.ts @@ -68,6 +68,7 @@ export interface SpecTestOptions { * Optionally pass function to transform loaded values * (values from input files) */ + inputProcessing?: {[K: string]: (value: any) => any}; shouldError?: (testCase: TestCase) => boolean; @@ -86,7 +87,7 @@ const defaultOptions: SpecTestOptions = { getExpected: (testCase) => testCase, shouldError: () => false, shouldSkip: () => false, - expectFunc: (testCase, expected, actual) => expect(actual).to.be.deep.equal(expected), + expectFunc: (_testCase, expected, actual) => expect(actual).to.be.deep.equal(expected), timeout: 10 * 60 * 1000, }; @@ -101,7 +102,7 @@ export function describeDirectorySpecTest throw new Error(`${testCaseDirectoryPath} is not directory`); } - describe(name, function () { + describe(name, () => { if (options.timeout !== undefined) { vi.setConfig({testTimeout: options.timeout ?? 10 * 60 * 1000}); } @@ -114,7 +115,7 @@ export function describeDirectorySpecTest // Use full path here, not just `testSubDirname` to allow usage of `vitest -t` const testName = `${name}/${testSubDirname}`; - it(testName, async function (context) { + it(testName, async (context) => { // some tests require to load meta.yaml first in order to know respective ssz types. const metaFilePath = path.join(testSubDirPath, "meta.yaml"); const meta: TestCase["meta"] = fs.existsSync(metaFilePath) @@ -131,7 +132,7 @@ export function describeDirectorySpecTest if (options.shouldError?.(testCase)) { try { await testFunction(testCase, name); - } catch (e) { + } catch (_e) { return; } } else { diff --git a/packages/spec-test-util/test/e2e/single/index.test.ts b/packages/spec-test-util/test/e2e/single/index.test.ts index 849b0cead30d..2dbefbb9cd22 100644 --- a/packages/spec-test-util/test/e2e/single/index.test.ts +++ b/packages/spec-test-util/test/e2e/single/index.test.ts @@ -8,11 +8,8 @@ import {describeDirectorySpecTest, InputType, loadYamlFile} from "../../../src/s // Global variable __dirname no longer available in ES6 modules. // Solutions: https://stackoverflow.com/questions/46745014/alternative-for-dirname-in-node-js-when-using-es6-modules -// eslint-disable-next-line @typescript-eslint/naming-convention const __dirname = path.dirname(fileURLToPath(import.meta.url)); -/* eslint-disable @typescript-eslint/naming-convention */ - export type SimpleStruct = { test: boolean; number: number; diff --git a/packages/state-transition/package.json b/packages/state-transition/package.json index 6816e5679cf5..e743ece013d9 100644 --- a/packages/state-transition/package.json +++ b/packages/state-transition/package.json @@ -50,8 +50,8 @@ "build:release": "yarn clean && yarn build", "check-build": "node -e \"(async function() { await import('./lib/index.js') })()\"", "check-types": "tsc", - "lint": "eslint --color --ext .ts src/ test/", - "lint:fix": "yarn run lint --fix", + "lint": "biome check src/ test/", + "lint:fix": "yarn run lint --write", "test": "yarn test:unit", "test:unit": "vitest --run --dir test/unit/", "check-readme": "typescript-docs-verifier" diff --git a/packages/state-transition/src/block/processDeposit.ts b/packages/state-transition/src/block/processDeposit.ts index ee75dff0dfd1..fd671dc5f6f6 100644 --- a/packages/state-transition/src/block/processDeposit.ts +++ b/packages/state-transition/src/block/processDeposit.ts @@ -173,7 +173,7 @@ function isValidDepositSignature( const signature = Signature.fromBytes(depositSignature, true); return verify(signingRoot, publicKey, signature); - } catch (e) { + } catch (_e) { return false; // Catch all BLS errors: failed key validation, failed signature validation, invalid signature } } diff --git a/packages/state-transition/src/util/balance.ts b/packages/state-transition/src/util/balance.ts index e9b7a06e4130..c6b196846ec9 100644 --- a/packages/state-transition/src/util/balance.ts +++ b/packages/state-transition/src/util/balance.ts @@ -2,7 +2,7 @@ import {EFFECTIVE_BALANCE_INCREMENT} from "@lodestar/params"; import {Gwei, ValidatorIndex} from "@lodestar/types"; import {bigIntMax} from "@lodestar/utils"; import {EffectiveBalanceIncrements} from "../cache/effectiveBalanceIncrements.js"; -import {BeaconStateAllForks} from ".."; +import {BeaconStateAllForks} from "../index.js"; import {CachedBeaconStateAllForks} from "../types.js"; /** diff --git a/packages/state-transition/src/util/blindedBlock.ts b/packages/state-transition/src/util/blindedBlock.ts index 2e4e4d590817..ceda91c94bb1 100644 --- a/packages/state-transition/src/util/blindedBlock.ts +++ b/packages/state-transition/src/util/blindedBlock.ts @@ -25,9 +25,13 @@ export function blindedOrFullBlockHashTreeRoot( ): Root { return isBlindedBeaconBlock(blindedOrFull) ? // Blinded - config.getExecutionForkTypes(blindedOrFull.slot).BlindedBeaconBlock.hashTreeRoot(blindedOrFull) + config + .getExecutionForkTypes(blindedOrFull.slot) + .BlindedBeaconBlock.hashTreeRoot(blindedOrFull) : // Full - config.getForkTypes(blindedOrFull.slot).BeaconBlock.hashTreeRoot(blindedOrFull); + config + .getForkTypes(blindedOrFull.slot) + .BeaconBlock.hashTreeRoot(blindedOrFull); } export function blindedOrFullBlockToHeader( @@ -36,9 +40,13 @@ export function blindedOrFullBlockToHeader( ): BeaconBlockHeader { const bodyRoot = isBlindedBeaconBlock(blindedOrFull) ? // Blinded - config.getExecutionForkTypes(blindedOrFull.slot).BlindedBeaconBlockBody.hashTreeRoot(blindedOrFull.body) + config + .getExecutionForkTypes(blindedOrFull.slot) + .BlindedBeaconBlockBody.hashTreeRoot(blindedOrFull.body) : // Full - config.getForkTypes(blindedOrFull.slot).BeaconBlockBody.hashTreeRoot(blindedOrFull.body); + config + .getForkTypes(blindedOrFull.slot) + .BeaconBlockBody.hashTreeRoot(blindedOrFull.body); return { slot: blindedOrFull.slot, diff --git a/packages/state-transition/src/util/seed.ts b/packages/state-transition/src/util/seed.ts index a5a0028d6c17..4131d4d9481f 100644 --- a/packages/state-transition/src/util/seed.ts +++ b/packages/state-transition/src/util/seed.ts @@ -155,7 +155,7 @@ export function computeShuffledIndex(index: number, indexCount: number, seed: By const position = Math.max(permuted, flip); const source = digest(Buffer.concat([_seed, intToBytes(i, 1), intToBytes(Math.floor(position / 256), 4)])); const byte = source[Math.floor((position % 256) / 8)]; - const bit = (byte >> position % 8) % 2; + const bit = (byte >> (position % 8)) % 2; permuted = bit ? flip : permuted; } return permuted; diff --git a/packages/state-transition/src/util/shuffle.ts b/packages/state-transition/src/util/shuffle.ts index 39137bca69d0..a87f22cae43e 100644 --- a/packages/state-transition/src/util/shuffle.ts +++ b/packages/state-transition/src/util/shuffle.ts @@ -108,7 +108,6 @@ function innerShuffleList(input: Shuffleable, seed: Bytes32, dir: boolean): void let source = seed; // just setting it to a Bytes32 let byteV = 0; - // eslint-disable-next-line no-constant-condition while (true) { // spec: pivot = bytes_to_int(hash(seed + int_to_bytes1(round))[0:8]) % list_size // This is the "int_to_bytes1(round)", appended to the seed. diff --git a/packages/state-transition/src/util/weakSubjectivity.ts b/packages/state-transition/src/util/weakSubjectivity.ts index 0e606e66340f..8d7c82842496 100644 --- a/packages/state-transition/src/util/weakSubjectivity.ts +++ b/packages/state-transition/src/util/weakSubjectivity.ts @@ -80,7 +80,6 @@ export function computeWeakSubjectivityPeriodFromConstituents( const t = Math.floor(totalBalanceByIncrement / N); const T = MAX_EFFECTIVE_BALANCE / ETH_TO_GWEI; const delta = churnLimit; - // eslint-disable-next-line @typescript-eslint/naming-convention const Delta = MAX_DEPOSITS * SLOTS_PER_EPOCH; const D = SAFETY_DECAY; diff --git a/packages/state-transition/test/cache.ts b/packages/state-transition/test/cache.ts index 9ca7ea25201c..59ddfe40b7c1 100644 --- a/packages/state-transition/test/cache.ts +++ b/packages/state-transition/test/cache.ts @@ -3,7 +3,6 @@ import {fileURLToPath} from "node:url"; // Global variable __dirname no longer available in ES6 modules. // Solutions: https://stackoverflow.com/questions/46745014/alternative-for-dirname-in-node-js-when-using-es6-modules -// eslint-disable-next-line @typescript-eslint/naming-convention const __dirname = path.dirname(fileURLToPath(import.meta.url)); export const testCachePath = path.join(__dirname, "../test-cache"); diff --git a/packages/state-transition/test/perf/analyzeEpochs.ts b/packages/state-transition/test/perf/analyzeEpochs.ts index deb0861427bf..9fe04bf7c522 100644 --- a/packages/state-transition/test/perf/analyzeEpochs.ts +++ b/packages/state-transition/test/perf/analyzeEpochs.ts @@ -123,7 +123,6 @@ async function analyzeEpochs(network: NetworkName, fromEpoch?: number): Promise< const {previousEpochAttestations, currentEpochAttestations} = state as phase0.BeaconState; - // eslint-disable-next-line no-console console.log(`Processed epoch ${epoch}`); writeToCsv({ epoch, @@ -182,7 +181,6 @@ if (!network) { } analyzeEpochs(network as NetworkName, fromEpoch).catch((e: Error) => { - // eslint-disable-next-line no-console console.error(e); process.exit(1); }); diff --git a/packages/state-transition/test/perf/dataStructures/arrayish.memory.ts b/packages/state-transition/test/perf/dataStructures/arrayish.memory.ts index 7e10f447181f..f37421ce2a89 100644 --- a/packages/state-transition/test/perf/dataStructures/arrayish.memory.ts +++ b/packages/state-transition/test/perf/dataStructures/arrayish.memory.ts @@ -110,7 +110,6 @@ for (let i = 0; i < 1e8; i++) { const heapUsedM = linearRegression(xs, heapUsed).m; const rssM = linearRegression(xs, rss).m; - // eslint-disable-next-line no-console console.log(i, {arrayBuffersM, externalM, heapTotalM, heapUsedM, rssM}); } } diff --git a/packages/state-transition/test/perf/epoch/processRegistryUpdates.test.ts b/packages/state-transition/test/perf/epoch/processRegistryUpdates.test.ts index 2d57de44f8ee..588fe9ec0213 100644 --- a/packages/state-transition/test/perf/epoch/processRegistryUpdates.test.ts +++ b/packages/state-transition/test/perf/epoch/processRegistryUpdates.test.ts @@ -78,7 +78,7 @@ type IndicesLengths = { * Create a state that causes `changeRatio` fraction (0,1) of validators to change their effective balance. */ function getRegistryUpdatesTestData( - vc: number, + _vc: number, lengths: IndicesLengths ): { state: CachedBeaconStateAllForks; diff --git a/packages/state-transition/test/perf/misc/arrayCreation.test.ts b/packages/state-transition/test/perf/misc/arrayCreation.test.ts index 8fd52ff99e27..c6a3cf29ed8e 100644 --- a/packages/state-transition/test/perf/misc/arrayCreation.test.ts +++ b/packages/state-transition/test/perf/misc/arrayCreation.test.ts @@ -36,7 +36,6 @@ describe.skip("array creation", function () { } const to = process.hrtime.bigint(); const diffMs = Number(to - from) / 1e6; - // eslint-disable-next-line no-console console.log(`${id}: ${diffMs / opsRun} ms`); }); } diff --git a/packages/state-transition/test/perf/misc/bitopts.test.ts b/packages/state-transition/test/perf/misc/bitopts.test.ts index 93df681bb3e2..38677002a969 100644 --- a/packages/state-transition/test/perf/misc/bitopts.test.ts +++ b/packages/state-transition/test/perf/misc/bitopts.test.ts @@ -14,7 +14,6 @@ describe.skip("bit opts", function () { } const to = process.hrtime.bigint(); const diffMs = Number(to - from) / 1e6; - // eslint-disable-next-line no-console console.log(`Time spent on OR in getAttestationDeltas: ${diffMs * ((orOptsPerRun * validators) / opsRun)} ms`); }); }); diff --git a/packages/state-transition/test/perf/shuffle/shuffle.test.ts b/packages/state-transition/test/perf/shuffle/shuffle.test.ts index ea1a9d606184..55f7875e69dd 100644 --- a/packages/state-transition/test/perf/shuffle/shuffle.test.ts +++ b/packages/state-transition/test/perf/shuffle/shuffle.test.ts @@ -10,7 +10,8 @@ describe("shuffle list", () => { const seed = new Uint8Array([42, 32]); for (const listSize of [ - 16384, 250000, + 16384, + 250000, // Don't run 4_000_000 since it's very slow and not testnet has gotten there yet // 4e6, ]) { diff --git a/packages/state-transition/test/perf/util.ts b/packages/state-transition/test/perf/util.ts index c764e2d039f9..7a0bfb29efb3 100644 --- a/packages/state-transition/test/perf/util.ts +++ b/packages/state-transition/test/perf/util.ts @@ -61,7 +61,6 @@ const secretKeyByModIndex = new Map(); const epoch = 23638; export const perfStateEpoch = epoch; -// eslint-disable-next-line @typescript-eslint/explicit-function-return-type export function getPubkeys(vc = numValidators) { const pubkeysMod = interopPubkeysCached(keypairsMod); const pubkeysModObj = pubkeysMod.map((pk) => PublicKey.fromBytes(pk)); @@ -85,7 +84,6 @@ export function getSecretKeyFromIndexCached(validatorIndex: number): SecretKey { return sk; } -// eslint-disable-next-line @typescript-eslint/explicit-function-return-type function getPubkeyCaches({pubkeysMod, pubkeysModObj}: ReturnType) { // Manually sync pubkeys to prevent doing BLS opts 110_000 times const pubkey2index = new PubkeyIndexMap(); @@ -223,7 +221,6 @@ export function generatePerfTestCachedStateAltair(opts?: { const {pubkeys, pubkeysMod, pubkeysModObj} = getPubkeys(opts?.vc); const {pubkey2index, index2pubkey} = getPubkeyCaches({pubkeys, pubkeysMod, pubkeysModObj}); - // eslint-disable-next-line @typescript-eslint/naming-convention const altairConfig = createChainForkConfig({ALTAIR_FORK_EPOCH: 0}); const origState = generatePerformanceStateAltair(pubkeys); diff --git a/packages/state-transition/test/unit/cachedBeaconState.test.ts b/packages/state-transition/test/unit/cachedBeaconState.test.ts index 96c026340143..668f22e13a1e 100644 --- a/packages/state-transition/test/unit/cachedBeaconState.test.ts +++ b/packages/state-transition/test/unit/cachedBeaconState.test.ts @@ -52,7 +52,6 @@ describe("CachedBeaconState", () => { expect(state2.epochCtx.getValidatorIndex(pubkey2)).toBe(index2); }); - /* eslint-disable @typescript-eslint/naming-convention */ it("Clone and mutate cache post-Electra", () => { const stateView = ssz.electra.BeaconState.defaultViewDU(); const state1 = createCachedBeaconStateTest( diff --git a/packages/state-transition/test/unit/upgradeState.test.ts b/packages/state-transition/test/unit/upgradeState.test.ts index 301cb105dc98..19a7d5c186f8 100644 --- a/packages/state-transition/test/unit/upgradeState.test.ts +++ b/packages/state-transition/test/unit/upgradeState.test.ts @@ -46,7 +46,6 @@ const ZERO_HASH = Buffer.alloc(32, 0); /** default config with ZERO_HASH as genesisValidatorsRoot */ const config = createBeaconConfig(chainConfig, ZERO_HASH); -/* eslint-disable @typescript-eslint/naming-convention */ function getConfig(fork: ForkName, forkEpoch = 0): ChainForkConfig { switch (fork) { case ForkName.phase0: diff --git a/packages/state-transition/test/unit/util/aggregator.test.ts b/packages/state-transition/test/unit/util/aggregator.test.ts index 07fd3172926c..6a9d0a45a2c7 100644 --- a/packages/state-transition/test/unit/util/aggregator.test.ts +++ b/packages/state-transition/test/unit/util/aggregator.test.ts @@ -8,8 +8,6 @@ import { } from "@lodestar/params"; import {isAggregatorFromCommitteeLength, isSyncCommitteeAggregator} from "../../../src/util/aggregator.js"; -/* eslint-disable @typescript-eslint/naming-convention */ - describe("isAttestationAggregator", function () { const committeeLength = 130; diff --git a/packages/state-transition/test/unit/util/deposit.test.ts b/packages/state-transition/test/unit/util/deposit.test.ts index 3cfa4abb3409..a682b4e993ed 100644 --- a/packages/state-transition/test/unit/util/deposit.test.ts +++ b/packages/state-transition/test/unit/util/deposit.test.ts @@ -29,7 +29,6 @@ describe("getEth1DepositCount", () => { const postElectraState = createCachedBeaconStateTest( stateView, createChainForkConfig({ - /* eslint-disable @typescript-eslint/naming-convention */ ALTAIR_FORK_EPOCH: 0, BELLATRIX_FORK_EPOCH: 0, CAPELLA_FORK_EPOCH: 0, @@ -63,7 +62,6 @@ describe("getEth1DepositCount", () => { const postElectraState = createCachedBeaconStateTest( stateView, createChainForkConfig({ - /* eslint-disable @typescript-eslint/naming-convention */ ALTAIR_FORK_EPOCH: 0, BELLATRIX_FORK_EPOCH: 0, CAPELLA_FORK_EPOCH: 0, diff --git a/packages/state-transition/test/utils/beforeValue.ts b/packages/state-transition/test/utils/beforeValue.ts index f50520372e17..6a2f5ee86945 100644 --- a/packages/state-transition/test/utils/beforeValue.ts +++ b/packages/state-transition/test/utils/beforeValue.ts @@ -21,7 +21,7 @@ export function beforeValue(fn: () => T | Promise, timeout?: number): Lazy return new Proxy<{value: T}>( {value}, { - get: function (target, prop) { + get: function (_target, prop) { if (prop === "value") { if (value === null) { throw Error("beforeValue has not yet run the before() block"); diff --git a/packages/state-transition/test/utils/beforeValueMocha.ts b/packages/state-transition/test/utils/beforeValueMocha.ts index 0d5f8f77d203..d078357bd3b4 100644 --- a/packages/state-transition/test/utils/beforeValueMocha.ts +++ b/packages/state-transition/test/utils/beforeValueMocha.ts @@ -20,7 +20,7 @@ export function beforeValue(fn: () => T | Promise, timeout?: number): Lazy return new Proxy<{value: T}>( {value}, { - get: function (target, prop) { + get: function (_target, prop) { if (prop === "value") { if (value === null) { throw Error("beforeValue has not yet run the before() block"); diff --git a/packages/state-transition/test/utils/rand.ts b/packages/state-transition/test/utils/rand.ts index 11a0efaffe10..988146ac4bf4 100644 --- a/packages/state-transition/test/utils/rand.ts +++ b/packages/state-transition/test/utils/rand.ts @@ -4,7 +4,8 @@ */ export function mulberry32(a: number) { return function () { - let t = (a += 0x6d2b79f5); + a += 0x6d2b79f5; + let t = a; t = Math.imul(t ^ (t >>> 15), t | 1); t ^= t + Math.imul(t ^ (t >>> 7), t | 61); return ((t ^ (t >>> 14)) >>> 0) / 4294967296; diff --git a/packages/state-transition/test/utils/specTestCases.ts b/packages/state-transition/test/utils/specTestCases.ts index 6c038d202d74..ed3776d868d0 100644 --- a/packages/state-transition/test/utils/specTestCases.ts +++ b/packages/state-transition/test/utils/specTestCases.ts @@ -3,7 +3,6 @@ import {fileURLToPath} from "node:url"; // Global variable __dirname no longer available in ES6 modules. // Solutions: https://stackoverflow.com/questions/46745014/alternative-for-dirname-in-node-js-when-using-es6-modules -// eslint-disable-next-line @typescript-eslint/naming-convention const __dirname = path.dirname(fileURLToPath(import.meta.url)); export const SPEC_TEST_LOCATION = path.join(__dirname, "../../../../node_modules/@chainsafe/eth2-spec-tests"); diff --git a/packages/state-transition/test/utils/testFileCache.ts b/packages/state-transition/test/utils/testFileCache.ts index b894674f54f6..28741bf932c5 100644 --- a/packages/state-transition/test/utils/testFileCache.ts +++ b/packages/state-transition/test/utils/testFileCache.ts @@ -96,7 +96,6 @@ export async function getNetworkCachedBlock( async function downloadTestFile(fileId: string): Promise { const fileUrl = `${TEST_FILES_BASE_URL}/${fileId}`; - // eslint-disable-next-line no-console console.log(`Downloading file ${fileUrl}`); const res = await got(fileUrl, {responseType: "buffer"}).catch((e: Error) => { diff --git a/packages/test-utils/package.json b/packages/test-utils/package.json index 5bf61891a9d5..b2a589581055 100644 --- a/packages/test-utils/package.json +++ b/packages/test-utils/package.json @@ -42,8 +42,8 @@ "build:watch": "yarn run build --watch", "check-build": "node -e \"(async function() { await import('./lib/index.js') })()\"", "check-types": "tsc", - "lint": "eslint --color --ext .ts src/", - "lint:fix": "yarn run lint --fix", + "lint": "biome check src/", + "lint:fix": "yarn run lint --write", "check-readme": "typescript-docs-verifier" }, "repository": { diff --git a/packages/test-utils/src/childProcess.ts b/packages/test-utils/src/childProcess.ts index cd6983cca467..d8b86b83ee48 100644 --- a/packages/test-utils/src/childProcess.ts +++ b/packages/test-utils/src/childProcess.ts @@ -86,7 +86,7 @@ export function isPidRunning(pid: number): boolean { // Signal 0 is a special signal that checks if the process exists process.kill(pid, 0); return true; - } catch { + } catch (_e) { return false; } } @@ -304,7 +304,7 @@ export async function spawnChildProcess( }); proc.removeAllListeners("exit"); resolve(proc); - } catch (error) { + } catch (_e) { reject( new Error( `Health check timeout. logPrefix=${logPrefix} pid=${proc.pid} healthTimeout=${prettyMsToTime(healthTimeoutMs ?? 0)}` diff --git a/packages/test-utils/src/cli.ts b/packages/test-utils/src/cli.ts index 8b4a84ec467a..c081a65e03c2 100644 --- a/packages/test-utils/src/cli.ts +++ b/packages/test-utils/src/cli.ts @@ -28,7 +28,6 @@ export async function runCliCommand( opts: CommandRunOptions = {timeoutMs: 1000} ): Promise { return wrapTimeout( - // eslint-disable-next-line no-async-promise-executor new Promise(async (resolve, reject) => { try { await cli diff --git a/packages/test-utils/src/doubles.ts b/packages/test-utils/src/doubles.ts index c61c10ea6099..171c55824996 100644 --- a/packages/test-utils/src/doubles.ts +++ b/packages/test-utils/src/doubles.ts @@ -37,7 +37,6 @@ function wrapLogWriter(...writers: [writer: object, ...keys: string[]][]): { for (const key of keys) { originals[index][key] = writer[key as keyof typeof writer]; - // eslint-disable-next-line @typescript-eslint/ban-ts-comment // @ts-expect-error writer[key as keyof typeof writer] = function mockedWriter(data: string) { // Our fixtures does not include the new line character @@ -51,7 +50,6 @@ function wrapLogWriter(...writers: [writer: object, ...keys: string[]][]): { restore: () => { for (const [index, [writer, ...keys]] of writers.entries()) { for (const key of keys) { - // eslint-disable-next-line @typescript-eslint/ban-ts-comment // @ts-expect-error writer[key as keyof typeof writer] = originals[index][key]; } diff --git a/packages/test-utils/src/externalSigner.ts b/packages/test-utils/src/externalSigner.ts index dbcb6bee1dc5..1e48e6af8d40 100644 --- a/packages/test-utils/src/externalSigner.ts +++ b/packages/test-utils/src/externalSigner.ts @@ -69,7 +69,6 @@ export async function startExternalSigner({ stream .on("data", (line) => process.stdout.write(line)) .on("err", (line) => process.stderr.write(line)) - // eslint-disable-next-line no-console .on("end", () => console.log("Stream closed")); return { diff --git a/packages/test-utils/src/http.ts b/packages/test-utils/src/http.ts index b4dd16390483..85b64c110cab 100644 --- a/packages/test-utils/src/http.ts +++ b/packages/test-utils/src/http.ts @@ -42,7 +42,6 @@ export async function matchReqSuccess(url: string, method: Method = "GET"): Prom * Wait for a given endpoint to return a given status code */ export async function waitForEndpoint(url: string, statusCode = 200): Promise { - // eslint-disable-next-line no-constant-condition while (true) { const status = await getReqStatus(url); diff --git a/packages/types/package.json b/packages/types/package.json index f3e034ec1b35..1c020b409071 100644 --- a/packages/types/package.json +++ b/packages/types/package.json @@ -59,8 +59,8 @@ "build:release": "yarn clean && yarn build", "check-build": "node -e \"(async function() { await import('./lib/index.js') })()\"", "check-types": "tsc", - "lint": "eslint --color --ext .ts src/ test/", - "lint:fix": "yarn run lint --fix", + "lint": "biome check src/ test/", + "lint:fix": "yarn run lint --write", "test": "yarn test:unit", "test:constants:minimal": "LODESTAR_PRESET=minimal vitest --run --dir test/constants/", "test:constants:mainnet": "LODESTAR_PRESET=mainnet vitest --run --dir test/constants/", diff --git a/packages/types/src/sszTypes.ts b/packages/types/src/sszTypes.ts index 4399904a94bc..55218574be76 100644 --- a/packages/types/src/sszTypes.ts +++ b/packages/types/src/sszTypes.ts @@ -26,7 +26,8 @@ const typesByFork = { /** * A type of union of forks must accept as any parameter the UNION of all fork types. */ -// eslint-disable-next-line @typescript-eslint/no-explicit-any + +// biome-ignore lint/suspicious/noExplicitAny: type UnionSSZForksTypeOf> = CompositeType< ValueOf, CompositeView, @@ -41,11 +42,9 @@ type SSZTypesByFork = { export type SSZTypesFor = K extends void ? // It compiles fine, need to debug the error - // eslint-disable-next-line @typescript-eslint/ban-ts-comment // @ts-expect-error {[K2 in keyof SSZTypesByFork[F]]: UnionSSZForksTypeOf} : // It compiles fine, need to debug the error - // eslint-disable-next-line @typescript-eslint/ban-ts-comment // @ts-expect-error UnionSSZForksTypeOf]>; diff --git a/packages/utils/package.json b/packages/utils/package.json index 0723f5f1815c..6c8218741e30 100644 --- a/packages/utils/package.json +++ b/packages/utils/package.json @@ -28,8 +28,8 @@ "build:release": "yarn clean && yarn build", "check-build": "node -e \"(async function() { await import('./lib/index.js') })()\"", "check-types": "tsc && vitest --run --typecheck --dir test/types/", - "lint": "eslint --color --ext .ts src/ test/", - "lint:fix": "yarn run lint --fix", + "lint": "biome check src/ test/", + "lint:fix": "yarn run lint --write", "test:unit": "vitest --run --dir test/unit", "test:browsers": "yarn test:browsers:chrome && yarn test:browsers:firefox && yarn test:browsers:electron", "test:browsers:chrome": "vitest --run --browser chrome --config ./vitest.browser.config.ts --dir test/unit", diff --git a/packages/utils/src/assert.ts b/packages/utils/src/assert.ts index 91612b0e6407..7b6af1f00f97 100644 --- a/packages/utils/src/assert.ts +++ b/packages/utils/src/assert.ts @@ -16,7 +16,6 @@ export const assert = { */ equal(actual: T, expected: T, message?: string): void { if (!(actual === expected)) { - // eslint-disable-next-line @typescript-eslint/restrict-template-expressions throw new AssertionError(`${message || "Expected values to be equal"}: ${actual} === ${expected}`); } }, diff --git a/packages/utils/src/command.ts b/packages/utils/src/command.ts index 89929a6c41ef..2e62ba5a9648 100644 --- a/packages/utils/src/command.ts +++ b/packages/utils/src/command.ts @@ -6,7 +6,7 @@ export interface CliExample { description?: string; } -// eslint-disable-next-line @typescript-eslint/no-explicit-any +// biome-ignore lint/suspicious/noExplicitAny: export interface CliOptionDefinition extends Options { example?: Omit; // Ensure `type` property matches type of `T` @@ -28,7 +28,7 @@ export type CliCommandOptions = Required<{ CliOptionDefinition & (Required> | {demandOption: true}); }>; -// eslint-disable-next-line @typescript-eslint/no-explicit-any +// biome-ignore lint/suspicious/noExplicitAny: export interface CliCommand, ParentArgs = Record, R = any> { command: string; describe: string; @@ -41,7 +41,7 @@ export interface CliCommand, ParentArgs = Record< options?: CliCommandOptions; // 1st arg: any = free own sub command options // 2nd arg: subcommand parent options is = to this command options + parent options - // eslint-disable-next-line @typescript-eslint/no-explicit-any + // biome-ignore lint/suspicious/noExplicitAny: subcommands?: CliCommand[]; handler?: (args: OwnArgs & ParentArgs) => Promise; } @@ -51,7 +51,8 @@ export interface CliCommand, ParentArgs = Record< * @param yargs * @param cliCommand */ -// eslint-disable-next-line @typescript-eslint/no-explicit-any + +// biome-ignore lint/suspicious/noExplicitAny: export function registerCommandToYargs(yargs: Argv, cliCommand: CliCommand): void { yargs.command({ command: cliCommand.command, diff --git a/packages/utils/src/diff.ts b/packages/utils/src/diff.ts index 204989016b46..4aab18e32779 100644 --- a/packages/utils/src/diff.ts +++ b/packages/utils/src/diff.ts @@ -203,10 +203,12 @@ export function getDiffs(val1: Diffable, val2: Diffable, objectPath: string): Di */ export function diff(val1: unknown, val2: unknown, outputValues = false, filename?: string): void { if (!isDiffable(val1)) { + // biome-ignore lint/suspicious/noConsoleLog: console.log("val1 is not Diffable"); return; } if (!isDiffable(val2)) { + // biome-ignore lint/suspicious/noConsoleLog: console.log("val2 is not Diffable"); return; } @@ -226,6 +228,7 @@ export function diff(val1: unknown, val2: unknown, outputValues = false, filenam if (filename) { fs.writeFileSync(filename, output); } else { + // biome-ignore lint/suspicious/noConsoleLog: console.log(output); } } diff --git a/packages/utils/src/err.ts b/packages/utils/src/err.ts index 81f6f92c0044..7c27a0a067a3 100644 --- a/packages/utils/src/err.ts +++ b/packages/utils/src/err.ts @@ -4,7 +4,6 @@ export type Err = {[symErr]: true; error: T}; export type Result = T | Err; -// eslint-disable-next-line @typescript-eslint/naming-convention export function Err(error: T): Err { return {[symErr]: true, error}; } diff --git a/packages/utils/src/logger.ts b/packages/utils/src/logger.ts index 925a357f4b98..e299e730a81a 100644 --- a/packages/utils/src/logger.ts +++ b/packages/utils/src/logger.ts @@ -12,7 +12,6 @@ export enum LogLevel { trace = "trace", } -// eslint-disable-next-line @typescript-eslint/naming-convention export const LogLevels = Object.values(LogLevel); export type LogHandler = (message: string, context?: LogData, error?: Error) => void; diff --git a/packages/utils/src/objects.ts b/packages/utils/src/objects.ts index ad09d36b0ecc..913bc80275b7 100644 --- a/packages/utils/src/objects.ts +++ b/packages/utils/src/objects.ts @@ -63,7 +63,7 @@ export function isEmptyObject(value: unknown): boolean { * * Inspired on lodash.mapValues, see https://lodash.com/docs/4.17.15#mapValues */ -// eslint-disable-next-line @typescript-eslint/no-explicit-any +// biome-ignore lint/suspicious/noExplicitAny: export function mapValues( obj: T, iteratee: (value: T[keyof T], key: keyof T) => R diff --git a/packages/utils/src/promise.ts b/packages/utils/src/promise.ts index 2be7467bfff4..894444d46937 100644 --- a/packages/utils/src/promise.ts +++ b/packages/utils/src/promise.ts @@ -109,7 +109,6 @@ export async function resolveOrRacePromises wrapPromise(p)) as ReturnPromiseWithTuple; // We intentionally want an array of promises here - // eslint-disable-next-line @typescript-eslint/no-floating-promises promises = (promiseResults as PromiseResult[]).map((p) => p.promise) as unknown as T; try { diff --git a/packages/utils/src/yaml/int.ts b/packages/utils/src/yaml/int.ts index 64a2c283dd49..bc68895cfd42 100644 --- a/packages/utils/src/yaml/int.ts +++ b/packages/utils/src/yaml/int.ts @@ -162,25 +162,20 @@ export const intType = new Type("tag:yaml.org,2002:int", { construct: constructYamlInteger, predicate: isInteger, instanceOf: BigInt, - // eslint-disable-next-line @typescript-eslint/ban-ts-comment // @ts-ignore represent: { - // eslint-disable-next-line @typescript-eslint/ban-ts-comment // @ts-ignore binary: function binary(obj: number) { return obj >= 0 ? "0b" + obj.toString(2) : "-0b" + obj.toString(2).slice(1); }, - // eslint-disable-next-line @typescript-eslint/ban-ts-comment // @ts-ignore octal: function octal(obj: number) { return obj >= 0 ? "0" + obj.toString(8) : "-0" + obj.toString(8).slice(1); }, - // eslint-disable-next-line @typescript-eslint/ban-ts-comment // @ts-ignore decimal: function decimal(obj: number) { return obj.toString(10); }, - // eslint-disable-next-line @typescript-eslint/ban-ts-comment // @ts-ignore hexadecimal: function hexadecimal(obj: number) { return obj >= 0 ? "0x" + obj.toString(16).toUpperCase() : "-0x" + obj.toString(16).toUpperCase().slice(1); diff --git a/packages/utils/src/yaml/schema.ts b/packages/utils/src/yaml/schema.ts index b53fc14a3e86..8db0c67cd943 100644 --- a/packages/utils/src/yaml/schema.ts +++ b/packages/utils/src/yaml/schema.ts @@ -3,9 +3,7 @@ import yml, {FAILSAFE_SCHEMA, Type} from "js-yaml"; import {intType} from "./int.js"; export const schema = FAILSAFE_SCHEMA.extend({ - // eslint-disable-next-line @typescript-eslint/ban-ts-comment // @ts-expect-error - // eslint-disable-next-line @typescript-eslint/no-unsafe-member-access implicit: [yml.types.null as Type, yml.types.bool as Type, intType, yml.types.float as Type], explicit: [], }); diff --git a/packages/utils/test/unit/err.test.ts b/packages/utils/test/unit/err.test.ts index 94cebe3ed1a1..7a08ebbc4319 100644 --- a/packages/utils/test/unit/err.test.ts +++ b/packages/utils/test/unit/err.test.ts @@ -60,7 +60,7 @@ describe("Result Err", () => { try { await mapOkResultsAsync([], async () => [0]); throw Error("did not throw"); - } catch (e) { + } catch (_e) { // Ok } }); diff --git a/packages/utils/test/unit/objects.test.ts b/packages/utils/test/unit/objects.test.ts index 4699a8c6f405..a94ed9213390 100644 --- a/packages/utils/test/unit/objects.test.ts +++ b/packages/utils/test/unit/objects.test.ts @@ -17,8 +17,6 @@ describe("Objects helper", () => { }); }); -/* eslint-disable @typescript-eslint/naming-convention */ - describe("objectToExpectedCase", () => { const testCases: { id: string; diff --git a/packages/validator/package.json b/packages/validator/package.json index 65ed656f010d..932eedac1dba 100644 --- a/packages/validator/package.json +++ b/packages/validator/package.json @@ -25,8 +25,8 @@ "build:watch": "yarn run build --watch", "check-build": "node -e \"(async function() { await import('./lib/index.js') })()\"", "check-types": "tsc", - "lint": "eslint --color --ext .ts src/ test/", - "lint:fix": "yarn run lint --fix", + "lint": "biome check src/ test/", + "lint:fix": "yarn run lint --write", "test:unit": "vitest --run --dir test/unit/", "test": "yarn test:unit && yarn test:e2e", "test:spec": "vitest --run --config vitest.spec.config.ts --dir test/spec/", diff --git a/packages/validator/src/genesis.ts b/packages/validator/src/genesis.ts index 3156acee689f..7fc3e20673bc 100644 --- a/packages/validator/src/genesis.ts +++ b/packages/validator/src/genesis.ts @@ -6,7 +6,6 @@ import {ApiClient} from "@lodestar/api"; const WAITING_FOR_GENESIS_POLL_MS = 12 * 1000; export async function waitForGenesis(api: ApiClient, logger: Logger, signal?: AbortSignal): Promise { - // eslint-disable-next-line no-constant-condition while (true) { try { return (await api.beacon.getGenesis()).value(); diff --git a/packages/validator/src/metrics.ts b/packages/validator/src/metrics.ts index a437328e8d5f..ca693056fc54 100644 --- a/packages/validator/src/metrics.ts +++ b/packages/validator/src/metrics.ts @@ -25,7 +25,6 @@ export type LodestarGitData = { /** * A collection of metrics used by the validator client */ -// eslint-disable-next-line @typescript-eslint/explicit-function-return-type export function getMetrics(register: MetricsRegisterExtra, gitData: LodestarGitData) { // Using function style instead of class to prevent having to re-declare all MetricsPrometheus types. diff --git a/packages/validator/src/services/emitter.ts b/packages/validator/src/services/emitter.ts index 19f9ac1de54a..2072acba6219 100644 --- a/packages/validator/src/services/emitter.ts +++ b/packages/validator/src/services/emitter.ts @@ -1,4 +1,4 @@ -import {EventEmitter} from "events"; +import {EventEmitter} from "node:events"; import {StrictEventEmitter} from "strict-event-emitter-types"; import {Slot} from "@lodestar/types"; import {HeadEventData} from "./chainHeaderTracker.js"; diff --git a/packages/validator/src/slashingProtection/attestation/errors.ts b/packages/validator/src/slashingProtection/attestation/errors.ts index 7d4b0978d097..34e11c190c8a 100644 --- a/packages/validator/src/slashingProtection/attestation/errors.ts +++ b/packages/validator/src/slashingProtection/attestation/errors.ts @@ -63,8 +63,4 @@ type InvalidAttestationErrorType = minTargetEpoch: Epoch; }; -export class InvalidAttestationError extends LodestarError { - constructor(type: InvalidAttestationErrorType) { - super(type); - } -} +export class InvalidAttestationError extends LodestarError {} diff --git a/packages/validator/src/slashingProtection/block/errors.ts b/packages/validator/src/slashingProtection/block/errors.ts index be3696bba700..e7868881627b 100644 --- a/packages/validator/src/slashingProtection/block/errors.ts +++ b/packages/validator/src/slashingProtection/block/errors.ts @@ -25,8 +25,4 @@ type InvalidBlockErrorType = minSlot: Slot; }; -export class InvalidBlockError extends LodestarError { - constructor(type: InvalidBlockErrorType) { - super(type); - } -} +export class InvalidBlockError extends LodestarError {} diff --git a/packages/validator/src/slashingProtection/interchange/errors.ts b/packages/validator/src/slashingProtection/interchange/errors.ts index 63771df357c2..d03215f0d930 100644 --- a/packages/validator/src/slashingProtection/interchange/errors.ts +++ b/packages/validator/src/slashingProtection/interchange/errors.ts @@ -12,8 +12,4 @@ type InterchangeErrorErrorType = | {code: InterchangeErrorErrorCode.UNSUPPORTED_VERSION; version: string} | {code: InterchangeErrorErrorCode.GENESIS_VALIDATOR_MISMATCH; root: Root; expectedRoot: Root}; -export class InterchangeError extends LodestarError { - constructor(type: InterchangeErrorErrorType) { - super(type); - } -} +export class InterchangeError extends LodestarError {} diff --git a/packages/validator/src/slashingProtection/interchange/formats/completeV4.ts b/packages/validator/src/slashingProtection/interchange/formats/completeV4.ts index b43ced6c80d3..26210390a272 100644 --- a/packages/validator/src/slashingProtection/interchange/formats/completeV4.ts +++ b/packages/validator/src/slashingProtection/interchange/formats/completeV4.ts @@ -1,4 +1,3 @@ -/* eslint-disable @typescript-eslint/naming-convention */ import {fromHex, toPubkeyHex, toRootHex} from "@lodestar/utils"; import {InterchangeLodestar} from "../types.js"; import {fromOptionalHexString, numToString, toOptionalHexString} from "../../utils.js"; diff --git a/packages/validator/src/slashingProtection/interchange/formats/v5.ts b/packages/validator/src/slashingProtection/interchange/formats/v5.ts index 838ba76c1a57..88e2ce70fe07 100644 --- a/packages/validator/src/slashingProtection/interchange/formats/v5.ts +++ b/packages/validator/src/slashingProtection/interchange/formats/v5.ts @@ -1,4 +1,3 @@ -/* eslint-disable @typescript-eslint/naming-convention */ import {fromHex, toPubkeyHex, toRootHex} from "@lodestar/utils"; import {InterchangeLodestar} from "../types.js"; import {fromOptionalHexString, numToString, toOptionalHexString} from "../../utils.js"; diff --git a/packages/validator/src/slashingProtection/minMaxSurround/errors.ts b/packages/validator/src/slashingProtection/minMaxSurround/errors.ts index fd094df54db3..b6cd31187f57 100644 --- a/packages/validator/src/slashingProtection/minMaxSurround/errors.ts +++ b/packages/validator/src/slashingProtection/minMaxSurround/errors.ts @@ -24,8 +24,4 @@ type SurroundAttestationErrorType = attestation2Target: number; }; -export class SurroundAttestationError extends LodestarError { - constructor(type: SurroundAttestationErrorType) { - super(type); - } -} +export class SurroundAttestationError extends LodestarError {} diff --git a/packages/validator/src/util/externalSignerClient.ts b/packages/validator/src/util/externalSignerClient.ts index 1d9778375b88..64d595452296 100644 --- a/packages/validator/src/util/externalSignerClient.ts +++ b/packages/validator/src/util/externalSignerClient.ts @@ -21,8 +21,6 @@ import {computeEpochAtSlot, blindedOrFullBlockToHeader} from "@lodestar/state-tr import {toHex, toRootHex} from "@lodestar/utils"; import {PubkeyHex} from "../types.js"; -/* eslint-disable @typescript-eslint/naming-convention */ - export enum SignableMessageType { AGGREGATION_SLOT = "AGGREGATION_SLOT", AGGREGATE_AND_PROOF = "AGGREGATE_AND_PROOF", diff --git a/packages/validator/src/util/params.ts b/packages/validator/src/util/params.ts index 6d6705f512df..f83aa9828633 100644 --- a/packages/validator/src/util/params.ts +++ b/packages/validator/src/util/params.ts @@ -5,8 +5,6 @@ export class NotEqualParamsError extends Error {} type ConfigWithPreset = ChainConfig & BeaconPreset; -/* eslint-disable @typescript-eslint/naming-convention */ - /** * Assert localConfig values match externalSpecJson. externalSpecJson may contain more values than localConfig. * diff --git a/packages/validator/test/spec/params.ts b/packages/validator/test/spec/params.ts index c51a881bfeb3..0f5c707ff1c5 100644 --- a/packages/validator/test/spec/params.ts +++ b/packages/validator/test/spec/params.ts @@ -3,7 +3,6 @@ import {fileURLToPath} from "node:url"; // Global variable __dirname no longer available in ES6 modules. // Solutions: https://stackoverflow.com/questions/46745014/alternative-for-dirname-in-node-js-when-using-es6-modules -// eslint-disable-next-line @typescript-eslint/naming-convention const __dirname = path.dirname(fileURLToPath(import.meta.url)); // Full link: https://github.com/eth2-clients/slashing-protection-interchange-tests/releases/download/v5.1.0/eip-3076-tests-v5.1.0.tar.gz diff --git a/packages/validator/test/unit/services/attestation.test.ts b/packages/validator/test/unit/services/attestation.test.ts index 66b722273102..b225ab09cdd2 100644 --- a/packages/validator/test/unit/services/attestation.test.ts +++ b/packages/validator/test/unit/services/attestation.test.ts @@ -52,7 +52,6 @@ describe("AttestationService", function () { vi.resetAllMocks(); }); - // eslint-disable-next-line @typescript-eslint/naming-convention const electraConfig: Partial = {ELECTRA_FORK_EPOCH: 0}; const testContexts: [string, AttestationServiceOpts, Partial][] = [ diff --git a/packages/validator/test/unit/services/doppelganger.test.ts b/packages/validator/test/unit/services/doppelganger.test.ts index 9b669b3c9396..943f0c08a9d3 100644 --- a/packages/validator/test/unit/services/doppelganger.test.ts +++ b/packages/validator/test/unit/services/doppelganger.test.ts @@ -213,8 +213,10 @@ function getMockBeaconApi(livenessMap: LivenessMap): ApiClient { } class ClockMockMsToSlot extends ClockMock { - constructor(public currentEpoch: Epoch) { + currentEpoch: Epoch; + constructor(currentEpoch: Epoch) { super(); + this.currentEpoch = currentEpoch; } async tickEpoch(epoch: Epoch, signal: AbortSignal): Promise { diff --git a/packages/validator/test/unit/services/syncCommitteDuties.test.ts b/packages/validator/test/unit/services/syncCommitteDuties.test.ts index dc43502d5b57..87d052b14ae5 100644 --- a/packages/validator/test/unit/services/syncCommitteDuties.test.ts +++ b/packages/validator/test/unit/services/syncCommitteDuties.test.ts @@ -20,8 +20,6 @@ import {ClockMock} from "../../utils/clock.js"; import {initValidatorStore} from "../../utils/validatorStore.js"; import {syncCommitteeIndicesToSubnets} from "../../../src/services/utils.js"; -/* eslint-disable @typescript-eslint/naming-convention */ - describe("SyncCommitteeDutiesService", function () { const api = getApiClientStub(); @@ -210,7 +208,6 @@ describe("SyncCommitteeDutiesService", function () { validatorSyncCommitteeIndices: [7], }; when(api.validator.getSyncCommitteeDuties) - // eslint-disable-next-line @typescript-eslint/no-unsafe-assignment .calledWith({epoch: expect.any(Number), indices}) .thenResolve(mockApiResponse({data: [duty1, duty2], meta: {executionOptimistic: false}})); diff --git a/packages/validator/test/unit/services/syncCommittee.test.ts b/packages/validator/test/unit/services/syncCommittee.test.ts index 449f826c3806..201bbdc83632 100644 --- a/packages/validator/test/unit/services/syncCommittee.test.ts +++ b/packages/validator/test/unit/services/syncCommittee.test.ts @@ -21,8 +21,6 @@ vi.mock("../../../src/services/emitter.js"); vi.mock("../../../src/services/chainHeaderTracker.js"); vi.mock("../../../src/services/syncingStatusTracker.js"); -/* eslint-disable @typescript-eslint/naming-convention */ - describe("SyncCommitteeService", function () { const api = getApiClientStub(); // @ts-expect-error - Mocked class don't need parameters diff --git a/packages/validator/test/unit/slashingProtection/interchange/index.test.ts b/packages/validator/test/unit/slashingProtection/interchange/index.test.ts index af2694458368..4038c6d1d4c5 100644 --- a/packages/validator/test/unit/slashingProtection/interchange/index.test.ts +++ b/packages/validator/test/unit/slashingProtection/interchange/index.test.ts @@ -1,4 +1,3 @@ -/* eslint-disable @typescript-eslint/naming-convention */ import {describe, it, expect} from "vitest"; import {toHexString} from "@chainsafe/ssz"; import {Root, ssz} from "@lodestar/types"; diff --git a/packages/validator/test/unit/slashingProtection/minMaxSurround/utils.ts b/packages/validator/test/unit/slashingProtection/minMaxSurround/utils.ts index e57af53d6837..6d9e4e0f559d 100644 --- a/packages/validator/test/unit/slashingProtection/minMaxSurround/utils.ts +++ b/packages/validator/test/unit/slashingProtection/minMaxSurround/utils.ts @@ -8,11 +8,11 @@ export class DistanceMapStore { this.map = new Map(); } - async get(pubkey: BLSPubkey, epoch: number): Promise { + async get(_pubkey: BLSPubkey, epoch: number): Promise { return this.map.get(epoch) ?? null; } - async setBatch(pubkey: BLSPubkey, values: DistanceEntry[]): Promise { + async setBatch(_pubkey: BLSPubkey, values: DistanceEntry[]): Promise { for (const {source, distance} of values) { this.map.set(source, distance); } diff --git a/packages/validator/test/unit/utils/clock.test.ts b/packages/validator/test/unit/utils/clock.test.ts index d668d753014a..f1c12e2cf66d 100644 --- a/packages/validator/test/unit/utils/clock.test.ts +++ b/packages/validator/test/unit/utils/clock.test.ts @@ -81,7 +81,6 @@ describe("util / Clock", function () { }); describe("getCurrentSlot", function () { - // eslint-disable-next-line @typescript-eslint/naming-convention const testConfig = {SECONDS_PER_SLOT: 12} as BeaconConfig; const genesisTime = Math.floor(new Date("2021-01-01").getTime() / 1000); diff --git a/packages/validator/test/unit/utils/interopConfigs.ts b/packages/validator/test/unit/utils/interopConfigs.ts index d263fa8c1d8f..36fff9051ce8 100644 --- a/packages/validator/test/unit/utils/interopConfigs.ts +++ b/packages/validator/test/unit/utils/interopConfigs.ts @@ -1,5 +1,3 @@ -/* eslint-disable @typescript-eslint/naming-convention */ - export const lighthouseHoleskyConfig = { CONFIG_NAME: "holesky", PRESET_BASE: "mainnet", diff --git a/packages/validator/test/unit/utils/params.test.ts b/packages/validator/test/unit/utils/params.test.ts index 79701e1f7a6e..13bab507cf13 100644 --- a/packages/validator/test/unit/utils/params.test.ts +++ b/packages/validator/test/unit/utils/params.test.ts @@ -12,8 +12,6 @@ const testCases: {name: string; items: [ChainConfig, Record]}[] {name: "nimbus", items: [networksChainConfig.holesky, nimbusHoleskyConfig]}, ]; -/* eslint-disable @typescript-eslint/naming-convention */ - describe("utils / params / assertEqualParams", () => { it("default == default", () => { const chainConfigJson = chainConfigToJson(chainConfig); diff --git a/packages/validator/test/utils/spec.ts b/packages/validator/test/utils/spec.ts index 91d6a75d1a52..ae0be94b4bfa 100644 --- a/packages/validator/test/utils/spec.ts +++ b/packages/validator/test/utils/spec.ts @@ -1,7 +1,6 @@ import fs from "node:fs"; import path from "node:path"; -/* eslint-disable @typescript-eslint/naming-convention */ export type SlashingProtectionInterchangeTest = { name: string; genesis_validators_root: string; diff --git a/scripts/assert_eslintrc_sorted.mjs b/scripts/assert_eslintrc_sorted.mjs deleted file mode 100755 index 0b298b627340..000000000000 --- a/scripts/assert_eslintrc_sorted.mjs +++ /dev/null @@ -1,22 +0,0 @@ -#!/usr/bin/env node - -import assert from "node:assert"; -import eslintrc from "../.eslintrc.js"; - -assertSorted(eslintrc.extends, ".extends"); -assertSorted(Object.keys(eslintrc.rules), ".rules"); -for (const overrides of eslintrc.overrides) { - assertSorted(Object.keys(overrides.rules), `.overrides ${overrides.files.join(",")}`); -} - -/** @param {string[]} keys @param {string} id */ -// eslint-disable-next-line @typescript-eslint/explicit-function-return-type -function assertSorted(keys, id) { - try { - assert.deepStrictEqual(keys, [...keys].sort()); - } catch (e) { - // eslint-disable-next-line no-console - console.log(`Lint error in ${id}\n\n`, e.message); - process.exit(1); - } -} diff --git a/scripts/release/utils.mjs b/scripts/release/utils.mjs index ee02015f0577..19ae6f3d306b 100644 --- a/scripts/release/utils.mjs +++ b/scripts/release/utils.mjs @@ -50,7 +50,7 @@ export function parseCmdArgs() { // optional arg, defaults to HEAD try { commit = shell(`git log -n 1 --pretty='%h' ${commitArg ?? "HEAD"}`); - } catch (e) { + } catch (_e) { throw Error(`Invalid commit ${commitArg}`); } @@ -62,7 +62,7 @@ export function parseCmdArgs() { try { if (versionObj.includePrerelease) throw Error("Includes pre-release"); if (semver.clean(versionArg) !== versionMMP) throw Error("No clean major.minor.path version"); - } catch (e) { + } catch (_e) { throw Error(`Bad argv[2] semver version '${versionArg}': ${e.message}`); } @@ -82,7 +82,7 @@ export function assertCommitExistsInBranch(commit, branch) { try { // Also, ensure the branch exists first headCommit = shell(`git rev-parse refs/heads/${branch}`); - } catch (e) { + } catch (_e) { throw Error(`Branch ${branch} does not exist: ${e.message}`); } @@ -95,7 +95,7 @@ export function assertCommitExistsInBranch(commit, branch) { try { shell(`git merge-base --is-ancestor ${commit} ${headCommit}`); - } catch (e) { + } catch (_e) { throw Error(`Commit ${commit} does not belong to branch ${branch}`); } } @@ -129,7 +129,7 @@ export async function confirm(message) { export function checkBranchExistsLocal(branch) { try { return shell(`git show-ref refs/heads/${branch}`); - } catch (e) { + } catch (_e) { return null; } } @@ -156,7 +156,7 @@ export function checkBranchExistsRemote(branch) { // Return the first part of the first line return out.split(/\s+/)[0]; - } catch (e) { + } catch (_e) { return null; } } @@ -169,7 +169,7 @@ export function checkBranchExistsRemote(branch) { export function checkTagExistsLocal(tag) { try { return shell(`git show-ref refs/tags/${tag}`); - } catch (e) { + } catch (_e) { return null; } } @@ -195,7 +195,7 @@ export function checkTagExistsRemote(tag) { // Return the first part of the first line return out.split(/\s+/)[0]; - } catch (e) { + } catch (_e) { return null; } } @@ -224,7 +224,7 @@ export function readMainPackageJson() { let jsonStr; try { jsonStr = fs.readFileSync(packageJsonPath, "utf8"); - } catch (e) { + } catch (_e) { if (e.code === "ENOENT") { throw Error(`Must run script from repo root dir, package.json not found at ${packageJsonPath}`); } else { diff --git a/scripts/vitest/setupFiles/dotenv.ts b/scripts/vitest/setupFiles/dotenv.ts index 71364c7426bc..511cefd8eed4 100644 --- a/scripts/vitest/setupFiles/dotenv.ts +++ b/scripts/vitest/setupFiles/dotenv.ts @@ -1,8 +1,6 @@ import path from "node:path"; // It's a dev dependency -// eslint-disable-next-line import/no-extraneous-dependencies import {config} from "dotenv"; -// eslint-disable-next-line @typescript-eslint/naming-convention const __dirname = new URL(".", import.meta.url).pathname; config({path: path.join(__dirname, "../../../.env.test")}); diff --git a/types/vitest/index.d.ts b/types/vitest/index.d.ts index 387edcfa5279..297ed11e1904 100644 --- a/types/vitest/index.d.ts +++ b/types/vitest/index.d.ts @@ -1,4 +1,3 @@ -// eslint-disable-next-line import/no-extraneous-dependencies, @typescript-eslint/no-unused-vars import * as vitest from "vitest"; interface CustomMatchers { @@ -42,7 +41,6 @@ interface CustomAsymmetricMatchers extends CustomMatchers { } declare module "vitest" { - // eslint-disable-next-line @typescript-eslint/no-explicit-any - interface Assertion extends CustomMatchers {} + interface Assertion extends CustomMatchers {} interface AsymmetricMatchersContaining extends CustomAsymmetricMatchers {} } diff --git a/yarn.lock b/yarn.lock index 6d080025630a..9808fee96b84 100644 --- a/yarn.lock +++ b/yarn.lock @@ -2,11 +2,6 @@ # yarn lockfile v1 -"@aashutoshrathi/word-wrap@^1.2.3": - version "1.2.6" - resolved "https://registry.yarnpkg.com/@aashutoshrathi/word-wrap/-/word-wrap-1.2.6.tgz#bd9154aec9983f77b3a034ecaa015c2e4201f6cf" - integrity sha512-1Yjs2SvM8TflER/OD3cOjhWWOZb58A2t7wpE2S9XfBYTiIl+XFhQG2bjy4Pu1I+EAlCNUzRDYDdFwFYUKvXcIA== - "@actions/cache@^1.0.7": version "1.0.7" resolved "https://registry.npmjs.org/@actions/cache/-/cache-1.0.7.tgz" @@ -289,6 +284,60 @@ resolved "https://registry.yarnpkg.com/@bcoe/v8-coverage/-/v8-coverage-0.2.3.tgz#75a2e8b51cb758a7553d6804a5932d7aace75c39" integrity sha512-0hYQ8SB4Db5zvZB4axdMHGwEaQjkZzFjQiN9LVYvIFB2nSUHW9tYpxWriPrWDASIxiaXax83REcLxuSdnGPZtw== +"@biomejs/biome@^1.9.3": + version "1.9.3" + resolved "https://registry.yarnpkg.com/@biomejs/biome/-/biome-1.9.3.tgz#5362fc390ac00c82e3698824490e3801d012c1b0" + integrity sha512-POjAPz0APAmX33WOQFGQrwLvlu7WLV4CFJMlB12b6ZSg+2q6fYu9kZwLCOA+x83zXfcPd1RpuWOKJW0GbBwLIQ== + optionalDependencies: + "@biomejs/cli-darwin-arm64" "1.9.3" + "@biomejs/cli-darwin-x64" "1.9.3" + "@biomejs/cli-linux-arm64" "1.9.3" + "@biomejs/cli-linux-arm64-musl" "1.9.3" + "@biomejs/cli-linux-x64" "1.9.3" + "@biomejs/cli-linux-x64-musl" "1.9.3" + "@biomejs/cli-win32-arm64" "1.9.3" + "@biomejs/cli-win32-x64" "1.9.3" + +"@biomejs/cli-darwin-arm64@1.9.3": + version "1.9.3" + resolved "https://registry.yarnpkg.com/@biomejs/cli-darwin-arm64/-/cli-darwin-arm64-1.9.3.tgz#3a981835a7a891589b356bbdb4e50157e494aa7d" + integrity sha512-QZzD2XrjJDUyIZK+aR2i5DDxCJfdwiYbUKu9GzkCUJpL78uSelAHAPy7m0GuPMVtF/Uo+OKv97W3P9nuWZangQ== + +"@biomejs/cli-darwin-x64@1.9.3": + version "1.9.3" + resolved "https://registry.yarnpkg.com/@biomejs/cli-darwin-x64/-/cli-darwin-x64-1.9.3.tgz#0e33284e5def9cbc17705b6a9acbc22b161accb1" + integrity sha512-vSCoIBJE0BN3SWDFuAY/tRavpUtNoqiceJ5PrU3xDfsLcm/U6N93JSM0M9OAiC/X7mPPfejtr6Yc9vSgWlEgVw== + +"@biomejs/cli-linux-arm64-musl@1.9.3": + version "1.9.3" + resolved "https://registry.yarnpkg.com/@biomejs/cli-linux-arm64-musl/-/cli-linux-arm64-musl-1.9.3.tgz#b68e2fe56381cbf71770b6c785215448c47595fd" + integrity sha512-VBzyhaqqqwP3bAkkBrhVq50i3Uj9+RWuj+pYmXrMDgjS5+SKYGE56BwNw4l8hR3SmYbLSbEo15GcV043CDSk+Q== + +"@biomejs/cli-linux-arm64@1.9.3": + version "1.9.3" + resolved "https://registry.yarnpkg.com/@biomejs/cli-linux-arm64/-/cli-linux-arm64-1.9.3.tgz#bb8186f000bd7366c3a1822a4a505e374905c462" + integrity sha512-vJkAimD2+sVviNTbaWOGqEBy31cW0ZB52KtpVIbkuma7PlfII3tsLhFa+cwbRAcRBkobBBhqZ06hXoZAN8NODQ== + +"@biomejs/cli-linux-x64-musl@1.9.3": + version "1.9.3" + resolved "https://registry.yarnpkg.com/@biomejs/cli-linux-x64-musl/-/cli-linux-x64-musl-1.9.3.tgz#01ccee0db2ca2ec9fb51fa69b2fc9e96434b5b32" + integrity sha512-TJmnOG2+NOGM72mlczEsNki9UT+XAsMFAOo8J0me/N47EJ/vkLXxf481evfHLlxMejTY6IN8SdRSiPVLv6AHlA== + +"@biomejs/cli-linux-x64@1.9.3": + version "1.9.3" + resolved "https://registry.yarnpkg.com/@biomejs/cli-linux-x64/-/cli-linux-x64-1.9.3.tgz#82d6fb824dd2c76142ab8625e202eb63a34e14f1" + integrity sha512-x220V4c+romd26Mu1ptU+EudMXVS4xmzKxPVb9mgnfYlN4Yx9vD5NZraSx/onJnd3Gh/y8iPUdU5CDZJKg9COA== + +"@biomejs/cli-win32-arm64@1.9.3": + version "1.9.3" + resolved "https://registry.yarnpkg.com/@biomejs/cli-win32-arm64/-/cli-win32-arm64-1.9.3.tgz#7fac607ade8e204eecae09e127713f000da0ccf2" + integrity sha512-lg/yZis2HdQGsycUvHWSzo9kOvnGgvtrYRgoCEwPBwwAL8/6crOp3+f47tPwI/LI1dZrhSji7PNsGKGHbwyAhw== + +"@biomejs/cli-win32-x64@1.9.3": + version "1.9.3" + resolved "https://registry.yarnpkg.com/@biomejs/cli-win32-x64/-/cli-win32-x64-1.9.3.tgz#1cbc269dcd5f29b034cb7f5982353c1cc3629318" + integrity sha512-cQMy2zanBkVLpmmxXdK6YePzmZx0s5Z7KEnwmrW54rcXK3myCNbQa09SwGZ8i/8sLw0H9F3X7K4rxVNGU8/D4Q== + "@bundled-es-modules/cookie@^2.0.0": version "2.0.0" resolved "https://registry.yarnpkg.com/@bundled-es-modules/cookie/-/cookie-2.0.0.tgz#c3b82703969a61cf6a46e959a012b2c257f6b164" @@ -438,19 +487,6 @@ uint8-varint "^2.0.2" uint8arrays "^5.0.1" -"@chainsafe/eslint-plugin-node@^11.2.3": - version "11.2.3" - resolved "https://registry.npmjs.org/@chainsafe/eslint-plugin-node/-/eslint-plugin-node-11.2.3.tgz" - integrity sha512-2iQv5JEaPcJuKP4pdawGd6iOVoUEDwx/PhsLqevwQXXz0WYwazW+p1fTF1bAcQNvZzLz4/wEBPtcVpQKNwY+jw== - dependencies: - eslint-plugin-es "^4.1.0" - eslint-utils "^2.0.0" - ignore "^5.1.1" - is-core-module "^2.3.0" - minimatch "^3.0.4" - resolve "^1.10.1" - semver "^6.1.0" - "@chainsafe/fast-crc32c@^4.1.1": version "4.1.1" resolved "https://registry.yarnpkg.com/@chainsafe/fast-crc32c/-/fast-crc32c-4.1.1.tgz#f551284ecf8325f676a1e26b938bcca51b9c8d93" @@ -814,38 +850,6 @@ resolved "https://registry.yarnpkg.com/@esbuild/win32-x64/-/win32-x64-0.21.5.tgz#acad351d582d157bb145535db2a6ff53dd514b5c" integrity sha512-tQd/1efJuzPC6rCFwEvLtci/xNFcTZknmXs98FYDfGE4wP9ClFV98nyKrzJKVPMhdDnjzLhdUyMX4PsQAPjwIw== -"@eslint-community/eslint-utils@^4.2.0", "@eslint-community/eslint-utils@^4.4.0": - version "4.4.0" - resolved "https://registry.yarnpkg.com/@eslint-community/eslint-utils/-/eslint-utils-4.4.0.tgz#a23514e8fb9af1269d5f7788aa556798d61c6b59" - integrity sha512-1/sA4dwrzBAyeUoQ6oxahHKmrZvsnLCg4RfxW3ZFGGmQkSNQPFNLV9CUEFQP1x9EYXHTo5p6xdhZM1Ne9p/AfA== - dependencies: - eslint-visitor-keys "^3.3.0" - -"@eslint-community/regexpp@^4.5.1", "@eslint-community/regexpp@^4.6.1": - version "4.8.1" - resolved "https://registry.yarnpkg.com/@eslint-community/regexpp/-/regexpp-4.8.1.tgz#8c4bb756cc2aa7eaf13cfa5e69c83afb3260c20c" - integrity sha512-PWiOzLIUAjN/w5K17PoF4n6sKBw0gqLHPhywmYHP4t1VFQQVYeb1yWsJwnMVEMl3tUHME7X/SJPZLmtG7XBDxQ== - -"@eslint/eslintrc@^2.1.4": - version "2.1.4" - resolved "https://registry.yarnpkg.com/@eslint/eslintrc/-/eslintrc-2.1.4.tgz#388a269f0f25c1b6adc317b5a2c55714894c70ad" - integrity sha512-269Z39MS6wVJtsoUl10L60WdkhJVdPG24Q4eZTH3nnF6lpvSShEK3wQjDX9JRWAUPvPh7COouPpU9IrqaZFvtQ== - dependencies: - ajv "^6.12.4" - debug "^4.3.2" - espree "^9.6.0" - globals "^13.19.0" - ignore "^5.2.0" - import-fresh "^3.2.1" - js-yaml "^4.1.0" - minimatch "^3.1.2" - strip-json-comments "^3.1.1" - -"@eslint/js@8.57.0": - version "8.57.0" - resolved "https://registry.yarnpkg.com/@eslint/js/-/js-8.57.0.tgz#a5417ae8427873f1dd08b70b3574b453e67b5f7f" - integrity sha512-Ys+3g2TaW7gADOJzPt83SJtCDhMjndcDMFVQ/Tj9iA1BfJzFKD9mAUXT3OenpuPHbI6P/myECxRJrofUsDx/5g== - "@ethereumjs/block@^4.2.2": version "4.2.2" resolved "https://registry.yarnpkg.com/@ethereumjs/block/-/block-4.2.2.tgz#fddecd34ed559f84ab8eb13098a6dee51a1360ae" @@ -1425,25 +1429,6 @@ resolved "https://registry.npmjs.org/@gar/promisify/-/promisify-1.1.3.tgz" integrity sha512-k2Ty1JcVojjJFwrg/ThKi2ujJ7XNLYaFGNB/bWT9wGR+oSMJHMa5w+CUq6p/pVrKeNNgA7pCqEcjSnHVoqJQFw== -"@humanwhocodes/config-array@^0.11.14": - version "0.11.14" - resolved "https://registry.yarnpkg.com/@humanwhocodes/config-array/-/config-array-0.11.14.tgz#d78e481a039f7566ecc9660b4ea7fe6b1fec442b" - integrity sha512-3T8LkOmg45BV5FICb15QQMsyUSWrQ8AygVfC7ZG32zOalnqrilm018ZVCw0eapXux8FtA33q8PSRSstjee3jSg== - dependencies: - "@humanwhocodes/object-schema" "^2.0.2" - debug "^4.3.1" - minimatch "^3.0.5" - -"@humanwhocodes/module-importer@^1.0.1": - version "1.0.1" - resolved "https://registry.yarnpkg.com/@humanwhocodes/module-importer/-/module-importer-1.0.1.tgz#af5b2691a22b44be847b0ca81641c5fb6ad0172c" - integrity sha512-bxveV4V8v5Yb4ncFTT3rPSgZBOpCkjfK0y4oVVVJwIuDVBRMDXrPyXRL988i5ap9m9bnyEEjWfm5WkBmtffLfA== - -"@humanwhocodes/object-schema@^2.0.2": - version "2.0.2" - resolved "https://registry.yarnpkg.com/@humanwhocodes/object-schema/-/object-schema-2.0.2.tgz#d9fae00a2d5cb40f92cfe64b47ad749fbc38f917" - integrity sha512-6EwiSjwWYP7pTckG6I5eyFANjPhmPjUX9JRLUSfNPC7FX7zK9gyZAfUEaECL6ALTpGX5AjnBq3C9XmVWPitNpw== - "@hutson/parse-repository-url@^3.0.0": version "3.0.2" resolved "https://registry.yarnpkg.com/@hutson/parse-repository-url/-/parse-repository-url-3.0.2.tgz#98c23c950a3d9b6c8f0daed06da6c3af06981340" @@ -2202,7 +2187,7 @@ resolved "https://registry.yarnpkg.com/@nodelib/fs.stat/-/fs.stat-2.0.5.tgz#5bd262af94e9d25bd1e71b05deed44876a222e8b" integrity sha512-RkhPPp2zrqDAQA/2jNhnztcPAlv64XdhIp7a7454A5ovI7Bukxgt7MX7udwAu3zg1DcpPU0rz3VV1SeaqvY4+A== -"@nodelib/fs.walk@^1.2.3", "@nodelib/fs.walk@^1.2.8": +"@nodelib/fs.walk@^1.2.3": version "1.2.8" resolved "https://registry.yarnpkg.com/@nodelib/fs.walk/-/fs.walk-1.2.8.tgz#e95737e8bb6746ddedf69c556953494f196fe69a" integrity sha512-oGB+UxlgWcgQkgwo8GcEGwemoTFt3FIO9ababBmaGwXIoBKZ+GTy0pP185beGg7Llih/NSHSV2XAs1lnznocSg== @@ -2657,11 +2642,6 @@ resolved "https://registry.yarnpkg.com/@pkgjs/parseargs/-/parseargs-0.11.0.tgz#a77ea742fab25775145434eb1d2328cf5013ac33" integrity sha512-+1VkjdD0QBLPodGrJUeqarH8VAIvQODIbwh9XpP5Syisf7YoQgsJKPNFoqqLQlu+VQ/tVSshMR6loPMn8U+dPg== -"@pkgr/core@^0.1.0": - version "0.1.1" - resolved "https://registry.yarnpkg.com/@pkgr/core/-/core-0.1.1.tgz#1ec17e2edbec25c8306d424ecfbf13c7de1aaa31" - integrity sha512-cq8o4cWH0ibXh9VGi5P20Tu9XF/0fFXl9EUinr9QfTM7a7p0oTA4iJRCQWppXR1Pg8dSM0UCItCkPwsk9qWWYA== - "@polka/url@^1.0.0-next.24": version "1.0.0-next.24" resolved "https://registry.yarnpkg.com/@polka/url/-/url-1.0.0-next.24.tgz#58601079e11784d20f82d0585865bb42305c4df3" @@ -3179,21 +3159,6 @@ resolved "https://registry.yarnpkg.com/@types/js-yaml/-/js-yaml-4.0.5.tgz#738dd390a6ecc5442f35e7f03fa1431353f7e138" integrity sha512-FhpRzf927MNQdRZP0J5DLIdTXhjLYzeUTmLAu69mnVksLH9CJY3IuSeEgbKUki7GQZm0WqDkGzyxju2EZGD2wA== -"@types/json-schema@^7.0.12": - version "7.0.13" - resolved "https://registry.yarnpkg.com/@types/json-schema/-/json-schema-7.0.13.tgz#02c24f4363176d2d18fc8b70b9f3c54aba178a85" - integrity sha512-RbSSoHliUbnXj3ny0CNFOoxrIDV6SUGyStHsvDqosw6CkdPV8TtWGlfecuK4ToyMEAql6pzNxgCFKanovUzlgQ== - -"@types/json-schema@^7.0.15": - version "7.0.15" - resolved "https://registry.yarnpkg.com/@types/json-schema/-/json-schema-7.0.15.tgz#596a1747233694d50f6ad8a7869fcb6f56cf5841" - integrity sha512-5+fP8P8MFNC+AyZCDxrB2pkZFPGzqQWUzpSeuuVLvm8VMcorNYavBqoFcxK8bQz4Qsbn4oUEEem4wDLfcysGHA== - -"@types/json5@^0.0.29": - version "0.0.29" - resolved "https://registry.npmjs.org/@types/json5/-/json5-0.0.29.tgz" - integrity sha1-7ihweulOEdK4J7y+UnC86n8+ce4= - "@types/keyv@^3.1.4": version "3.1.4" resolved "https://registry.yarnpkg.com/@types/keyv/-/keyv-3.1.4.tgz#3ccdb1c6751b0c7e52300bcdacd5bcbf8faa75b6" @@ -3267,11 +3232,11 @@ undici-types "~5.26.4" "@types/node@^20.12.8": - version "20.12.8" - resolved "https://registry.yarnpkg.com/@types/node/-/node-20.12.8.tgz#35897bf2bfe3469847ab04634636de09552e8256" - integrity sha512-NU0rJLJnshZWdE/097cdCBbyW1h4hEg0xpovcoAQYHl8dnEyp/NAOiE45pvc+Bd1Dt+2r94v2eGFpQJ4R7g+2w== + version "20.16.7" + resolved "https://registry.yarnpkg.com/@types/node/-/node-20.16.7.tgz#0a245bf5805add998a22b8b5adac612ee70190bc" + integrity sha512-QkDQjAY3gkvJNcZOWwzy3BN34RweT0OQ9zJyvLCU0kSK22dO2QYh/NHGfbEAYylPYzRB1/iXcojS79wOg5gFSw== dependencies: - undici-types "~5.26.4" + undici-types "~6.19.2" "@types/node@^20.14.11": version "20.14.11" @@ -3317,16 +3282,6 @@ resolved "https://registry.npmjs.org/@types/retry/-/retry-0.12.1.tgz" integrity sha512-xoDlM2S4ortawSWORYqsdU+2rxdh4LRW9ytc3zmT37RIKQh6IHyKwwtKhKis9ah8ol07DCkZxPt8BBvPjC6v4g== -"@types/semver@^7.5.0": - version "7.5.2" - resolved "https://registry.yarnpkg.com/@types/semver/-/semver-7.5.2.tgz#31f6eec1ed7ec23f4f05608d3a2d381df041f564" - integrity sha512-7aqorHYgdNO4DM36stTiGO3DvKoex9TQRwsJU6vMaFGyqpBA1MNZkz+PG3gaNUPpTAOYhT1WR7M1JyA3fbS9Cw== - -"@types/semver@^7.5.8": - version "7.5.8" - resolved "https://registry.yarnpkg.com/@types/semver/-/semver-7.5.8.tgz#8268a8c57a3e4abd25c165ecd36237db7948a55e" - integrity sha512-I8EUhyrgfLrcTkzV3TSsGyl1tSuPrEDzr0yd5m90UgNxQkyDXULk3b6MlQqTCpZpNtWe1K0hzclnZkTcLBe2UQ== - "@types/sinon@^17.0.3": version "17.0.3" resolved "https://registry.yarnpkg.com/@types/sinon/-/sinon-17.0.3.tgz#9aa7e62f0a323b9ead177ed23a36ea757141a5fa" @@ -3442,145 +3397,6 @@ dependencies: "@types/node" "*" -"@typescript-eslint/eslint-plugin@^7.2.0": - version "7.2.0" - resolved "https://registry.yarnpkg.com/@typescript-eslint/eslint-plugin/-/eslint-plugin-7.2.0.tgz#5a5fcad1a7baed85c10080d71ad901f98c38d5b7" - integrity sha512-mdekAHOqS9UjlmyF/LSs6AIEvfceV749GFxoBAjwAv0nkevfKHWQFDMcBZWUiIC5ft6ePWivXoS36aKQ0Cy3sw== - dependencies: - "@eslint-community/regexpp" "^4.5.1" - "@typescript-eslint/scope-manager" "7.2.0" - "@typescript-eslint/type-utils" "7.2.0" - "@typescript-eslint/utils" "7.2.0" - "@typescript-eslint/visitor-keys" "7.2.0" - debug "^4.3.4" - graphemer "^1.4.0" - ignore "^5.2.4" - natural-compare "^1.4.0" - semver "^7.5.4" - ts-api-utils "^1.0.1" - -"@typescript-eslint/parser@^7.2.0": - version "7.2.0" - resolved "https://registry.yarnpkg.com/@typescript-eslint/parser/-/parser-7.2.0.tgz#44356312aea8852a3a82deebdacd52ba614ec07a" - integrity sha512-5FKsVcHTk6TafQKQbuIVkXq58Fnbkd2wDL4LB7AURN7RUOu1utVP+G8+6u3ZhEroW3DF6hyo3ZEXxgKgp4KeCg== - dependencies: - "@typescript-eslint/scope-manager" "7.2.0" - "@typescript-eslint/types" "7.2.0" - "@typescript-eslint/typescript-estree" "7.2.0" - "@typescript-eslint/visitor-keys" "7.2.0" - debug "^4.3.4" - -"@typescript-eslint/scope-manager@7.2.0": - version "7.2.0" - resolved "https://registry.yarnpkg.com/@typescript-eslint/scope-manager/-/scope-manager-7.2.0.tgz#cfb437b09a84f95a0930a76b066e89e35d94e3da" - integrity sha512-Qh976RbQM/fYtjx9hs4XkayYujB/aPwglw2choHmf3zBjB4qOywWSdt9+KLRdHubGcoSwBnXUH2sR3hkyaERRg== - dependencies: - "@typescript-eslint/types" "7.2.0" - "@typescript-eslint/visitor-keys" "7.2.0" - -"@typescript-eslint/scope-manager@7.7.0": - version "7.7.0" - resolved "https://registry.yarnpkg.com/@typescript-eslint/scope-manager/-/scope-manager-7.7.0.tgz#3f0db079b275bb8b0cb5be7613fb3130cfb5de77" - integrity sha512-/8INDn0YLInbe9Wt7dK4cXLDYp0fNHP5xKLHvZl3mOT5X17rK/YShXaiNmorl+/U4VKCVIjJnx4Ri5b0y+HClw== - dependencies: - "@typescript-eslint/types" "7.7.0" - "@typescript-eslint/visitor-keys" "7.7.0" - -"@typescript-eslint/type-utils@7.2.0": - version "7.2.0" - resolved "https://registry.yarnpkg.com/@typescript-eslint/type-utils/-/type-utils-7.2.0.tgz#7be5c30e9b4d49971b79095a1181324ef6089a19" - integrity sha512-xHi51adBHo9O9330J8GQYQwrKBqbIPJGZZVQTHHmy200hvkLZFWJIFtAG/7IYTWUyun6DE6w5InDReePJYJlJA== - dependencies: - "@typescript-eslint/typescript-estree" "7.2.0" - "@typescript-eslint/utils" "7.2.0" - debug "^4.3.4" - ts-api-utils "^1.0.1" - -"@typescript-eslint/types@7.2.0": - version "7.2.0" - resolved "https://registry.yarnpkg.com/@typescript-eslint/types/-/types-7.2.0.tgz#0feb685f16de320e8520f13cca30779c8b7c403f" - integrity sha512-XFtUHPI/abFhm4cbCDc5Ykc8npOKBSJePY3a3s+lwumt7XWJuzP5cZcfZ610MIPHjQjNsOLlYK8ASPaNG8UiyA== - -"@typescript-eslint/types@7.7.0": - version "7.7.0" - resolved "https://registry.yarnpkg.com/@typescript-eslint/types/-/types-7.7.0.tgz#23af4d24bf9ce15d8d301236e3e3014143604f27" - integrity sha512-G01YPZ1Bd2hn+KPpIbrAhEWOn5lQBrjxkzHkWvP6NucMXFtfXoevK82hzQdpfuQYuhkvFDeQYbzXCjR1z9Z03w== - -"@typescript-eslint/typescript-estree@7.2.0": - version "7.2.0" - resolved "https://registry.yarnpkg.com/@typescript-eslint/typescript-estree/-/typescript-estree-7.2.0.tgz#5beda2876c4137f8440c5a84b4f0370828682556" - integrity sha512-cyxS5WQQCoBwSakpMrvMXuMDEbhOo9bNHHrNcEWis6XHx6KF518tkF1wBvKIn/tpq5ZpUYK7Bdklu8qY0MsFIA== - dependencies: - "@typescript-eslint/types" "7.2.0" - "@typescript-eslint/visitor-keys" "7.2.0" - debug "^4.3.4" - globby "^11.1.0" - is-glob "^4.0.3" - minimatch "9.0.3" - semver "^7.5.4" - ts-api-utils "^1.0.1" - -"@typescript-eslint/typescript-estree@7.7.0": - version "7.7.0" - resolved "https://registry.yarnpkg.com/@typescript-eslint/typescript-estree/-/typescript-estree-7.7.0.tgz#b5dd6383b4c6a852d7b256a37af971e8982be97f" - integrity sha512-8p71HQPE6CbxIBy2kWHqM1KGrC07pk6RJn40n0DSc6bMOBBREZxSDJ+BmRzc8B5OdaMh1ty3mkuWRg4sCFiDQQ== - dependencies: - "@typescript-eslint/types" "7.7.0" - "@typescript-eslint/visitor-keys" "7.7.0" - debug "^4.3.4" - globby "^11.1.0" - is-glob "^4.0.3" - minimatch "^9.0.4" - semver "^7.6.0" - ts-api-utils "^1.3.0" - -"@typescript-eslint/utils@7.2.0": - version "7.2.0" - resolved "https://registry.yarnpkg.com/@typescript-eslint/utils/-/utils-7.2.0.tgz#fc8164be2f2a7068debb4556881acddbf0b7ce2a" - integrity sha512-YfHpnMAGb1Eekpm3XRK8hcMwGLGsnT6L+7b2XyRv6ouDuJU1tZir1GS2i0+VXRatMwSI1/UfcyPe53ADkU+IuA== - dependencies: - "@eslint-community/eslint-utils" "^4.4.0" - "@types/json-schema" "^7.0.12" - "@types/semver" "^7.5.0" - "@typescript-eslint/scope-manager" "7.2.0" - "@typescript-eslint/types" "7.2.0" - "@typescript-eslint/typescript-estree" "7.2.0" - semver "^7.5.4" - -"@typescript-eslint/utils@^7.1.1": - version "7.7.0" - resolved "https://registry.yarnpkg.com/@typescript-eslint/utils/-/utils-7.7.0.tgz#3d2b6606a60ac34f3c625facfb3b3ab7e126f58d" - integrity sha512-LKGAXMPQs8U/zMRFXDZOzmMKgFv3COlxUQ+2NMPhbqgVm6R1w+nU1i4836Pmxu9jZAuIeyySNrN/6Rc657ggig== - dependencies: - "@eslint-community/eslint-utils" "^4.4.0" - "@types/json-schema" "^7.0.15" - "@types/semver" "^7.5.8" - "@typescript-eslint/scope-manager" "7.7.0" - "@typescript-eslint/types" "7.7.0" - "@typescript-eslint/typescript-estree" "7.7.0" - semver "^7.6.0" - -"@typescript-eslint/visitor-keys@7.2.0": - version "7.2.0" - resolved "https://registry.yarnpkg.com/@typescript-eslint/visitor-keys/-/visitor-keys-7.2.0.tgz#5035f177752538a5750cca1af6044b633610bf9e" - integrity sha512-c6EIQRHhcpl6+tO8EMR+kjkkV+ugUNXOmeASA1rlzkd8EPIriavpWoiEz1HR/VLhbVIdhqnV6E7JZm00cBDx2A== - dependencies: - "@typescript-eslint/types" "7.2.0" - eslint-visitor-keys "^3.4.1" - -"@typescript-eslint/visitor-keys@7.7.0": - version "7.7.0" - resolved "https://registry.yarnpkg.com/@typescript-eslint/visitor-keys/-/visitor-keys-7.7.0.tgz#950148cf1ac11562a2d903fdf7acf76714a2dc9e" - integrity sha512-h0WHOj8MhdhY8YWkzIF30R379y0NqyOHExI9N9KCzvmu05EgG4FumeYa3ccfKUSphyWkWQE1ybVrgz/Pbam6YA== - dependencies: - "@typescript-eslint/types" "7.7.0" - eslint-visitor-keys "^3.4.3" - -"@ungap/structured-clone@^1.2.0": - version "1.2.0" - resolved "https://registry.yarnpkg.com/@ungap/structured-clone/-/structured-clone-1.2.0.tgz#756641adb587851b5ccb3e095daf27ae581c8406" - integrity sha512-zuVdFrMJiuCDQUMCzQaD6KL28MjnqqN8XnAqiEq9PNm/hCPTSGfrXCOfwj1ow4LFb/tNymJPwsNbVePc1xFqrQ== - "@vitest/browser@^2.0.4": version "2.0.4" resolved "https://registry.yarnpkg.com/@vitest/browser/-/browser-2.0.4.tgz#6569258b4a8085f348007acd5ecf61db4eec4340" @@ -3853,11 +3669,6 @@ abstract-logging@^2.0.1: resolved "https://registry.yarnpkg.com/abstract-logging/-/abstract-logging-2.0.1.tgz#6b0c371df212db7129b57d2e7fcf282b8bf1c839" integrity sha512-2BjRTZxTPvheOvGbBslFSYOUkr+SjPtOnrLP33f+VIWLzezQpZcqVg7ja3L4dBXmzzgwT+a029jRx5PCi3JuiA== -acorn-jsx@^5.3.2: - version "5.3.2" - resolved "https://registry.yarnpkg.com/acorn-jsx/-/acorn-jsx-5.3.2.tgz#7ed5bb55908b3b2f1bc55c6af1653bada7f07937" - integrity sha512-rq9s+JNhf0IChjtDXxllJ7g41oZk5SlXtp0LHwyA5cejwn7vKmKp4pPri6YEePv2PU65sAsegbXtIinmDFDXgQ== - acorn-walk@^8.1.1: version "8.2.0" resolved "https://registry.npmjs.org/acorn-walk/-/acorn-walk-8.2.0.tgz" @@ -3868,11 +3679,6 @@ acorn@^8.4.1: resolved "https://registry.yarnpkg.com/acorn/-/acorn-8.7.1.tgz#0197122c843d1bf6d0a5e83220a788f278f63c30" integrity sha512-Xx54uLJQZ19lKygFXOWsscKUbsBZW0CPykPhVQdhIeIwrbPmJzqeASDInc8nKBnp/JT6igTs82qPXz069H8I/A== -acorn@^8.9.0: - version "8.10.0" - resolved "https://registry.yarnpkg.com/acorn/-/acorn-8.10.0.tgz#8be5b3907a67221a81ab23c7889c4c5526b62ec5" - integrity sha512-F0SAmZ8iUtS//m8DmCTA0jlh6TDKkHQyK6xc6V4KDTyZKA9dnvX9/3sRTVQrWm79glUAZbnmmNcdYwUIHWVybw== - add-stream@^1.0.0: version "1.0.0" resolved "https://registry.yarnpkg.com/add-stream/-/add-stream-1.0.0.tgz#6a7990437ca736d5e1288db92bd3266d5f5cb2aa" @@ -3926,16 +3732,6 @@ ajv-formats@^3.0.1: dependencies: ajv "^8.0.0" -ajv@^6.12.4, ajv@~6.12.6: - version "6.12.6" - resolved "https://registry.npmjs.org/ajv/-/ajv-6.12.6.tgz" - integrity sha512-j3fVLgvTo527anyYyJOGTYJbG+vnnQYvE0m5mmkc1TK+nxAppkCLMIL0aZ4dblVCNoGShhm+kzE4ZUykBoMg4g== - dependencies: - fast-deep-equal "^3.1.1" - fast-json-stable-stringify "^2.0.0" - json-schema-traverse "^0.4.1" - uri-js "^4.2.2" - ajv@^8.0.0, ajv@^8.12.0: version "8.12.0" resolved "https://registry.yarnpkg.com/ajv/-/ajv-8.12.0.tgz#d1a0527323e22f53562c567c00991577dfbe19d1" @@ -3956,6 +3752,16 @@ ajv@^8.6.0: require-from-string "^2.0.2" uri-js "^4.2.2" +ajv@~6.12.6: + version "6.12.6" + resolved "https://registry.npmjs.org/ajv/-/ajv-6.12.6.tgz" + integrity sha512-j3fVLgvTo527anyYyJOGTYJbG+vnnQYvE0m5mmkc1TK+nxAppkCLMIL0aZ4dblVCNoGShhm+kzE4ZUykBoMg4g== + dependencies: + fast-deep-equal "^3.1.1" + fast-json-stable-stringify "^2.0.0" + json-schema-traverse "^0.4.1" + uri-js "^4.2.2" + ansi-colors@4.1.1: version "4.1.1" resolved "https://registry.npmjs.org/ansi-colors/-/ansi-colors-4.1.1.tgz" @@ -4142,64 +3948,11 @@ array-ify@^1.0.0: resolved "https://registry.yarnpkg.com/array-ify/-/array-ify-1.0.0.tgz#9e528762b4a9066ad163a6962a364418e9626ece" integrity sha512-c5AMf34bKdvPhQ7tBGhqkgKNUzMr4WUs+WDtC2ZUGOUncbxKMTvqxYctiseW3+L4bA8ec+GcZ6/A/FW4m8ukng== -array-includes@^3.1.7: - version "3.1.7" - resolved "https://registry.yarnpkg.com/array-includes/-/array-includes-3.1.7.tgz#8cd2e01b26f7a3086cbc87271593fe921c62abda" - integrity sha512-dlcsNBIiWhPkHdOEEKnehA+RNUWDc4UqFtnIXU4uuYDPtA4LDkr7qip2p0VvFAEXNDr0yWZ9PJyIRiGjRLQzwQ== - dependencies: - call-bind "^1.0.2" - define-properties "^1.2.0" - es-abstract "^1.22.1" - get-intrinsic "^1.2.1" - is-string "^1.0.7" - array-union@^2.1.0: version "2.1.0" resolved "https://registry.yarnpkg.com/array-union/-/array-union-2.1.0.tgz#b798420adbeb1de828d84acd8a2e23d3efe85e8d" integrity sha512-HGyxoOTYUyCM6stUe6EJgnd4EoewAI7zMdfqO+kGjnlZmBDz/cR5pf8r/cR4Wq60sL/p0IkcjUEEPwS3GFrIyw== -array.prototype.filter@^1.0.3: - version "1.0.3" - resolved "https://registry.yarnpkg.com/array.prototype.filter/-/array.prototype.filter-1.0.3.tgz#423771edeb417ff5914111fff4277ea0624c0d0e" - integrity sha512-VizNcj/RGJiUyQBgzwxzE5oHdeuXY5hSbbmKMlphj1cy1Vl7Pn2asCGbSrru6hSQjmCzqTBPVWAF/whmEOVHbw== - dependencies: - call-bind "^1.0.2" - define-properties "^1.2.0" - es-abstract "^1.22.1" - es-array-method-boxes-properly "^1.0.0" - is-string "^1.0.7" - -array.prototype.findlastindex@^1.2.3: - version "1.2.4" - resolved "https://registry.yarnpkg.com/array.prototype.findlastindex/-/array.prototype.findlastindex-1.2.4.tgz#d1c50f0b3a9da191981ff8942a0aedd82794404f" - integrity sha512-hzvSHUshSpCflDR1QMUBLHGHP1VIEBegT4pix9H/Z92Xw3ySoy6c2qh7lJWTJnRJ8JCZ9bJNCgTyYaJGcJu6xQ== - dependencies: - call-bind "^1.0.5" - define-properties "^1.2.1" - es-abstract "^1.22.3" - es-errors "^1.3.0" - es-shim-unscopables "^1.0.2" - -array.prototype.flat@^1.3.2: - version "1.3.2" - resolved "https://registry.yarnpkg.com/array.prototype.flat/-/array.prototype.flat-1.3.2.tgz#1476217df8cff17d72ee8f3ba06738db5b387d18" - integrity sha512-djYB+Zx2vLewY8RWlNCUdHjDXs2XOgm602S9E7P/UpHgfeHL00cRiIF+IN/G/aUJ7kGPb6yO/ErDI5V2s8iycA== - dependencies: - call-bind "^1.0.2" - define-properties "^1.2.0" - es-abstract "^1.22.1" - es-shim-unscopables "^1.0.0" - -array.prototype.flatmap@^1.3.2: - version "1.3.2" - resolved "https://registry.yarnpkg.com/array.prototype.flatmap/-/array.prototype.flatmap-1.3.2.tgz#c9a7c6831db8e719d6ce639190146c24bbd3e527" - integrity sha512-Ewyx0c9PmpcsByhSW4r+9zDU7sGjFc86qf/kKtuSCRdhfbk0SNLLkaT5qvcHnRGgc5NP/ly/y+qkXkqONX54CQ== - dependencies: - call-bind "^1.0.2" - define-properties "^1.2.0" - es-abstract "^1.22.1" - es-shim-unscopables "^1.0.0" - arraybuffer.prototype.slice@^1.0.2: version "1.0.2" resolved "https://registry.yarnpkg.com/arraybuffer.prototype.slice/-/arraybuffer.prototype.slice-1.0.2.tgz#98bd561953e3e74bb34938e77647179dfe6e9f12" @@ -5466,7 +5219,7 @@ cross-spawn@^6.0.5: shebang-command "^1.2.0" which "^1.2.9" -cross-spawn@^7.0.0, cross-spawn@^7.0.2, cross-spawn@^7.0.3: +cross-spawn@^7.0.0, cross-spawn@^7.0.3: version "7.0.3" resolved "https://registry.npmjs.org/cross-spawn/-/cross-spawn-7.0.3.tgz" integrity sha512-iRDPJKUPVEND7dHPO8rkbOnPpyDygcDFtWjpeWNCgy8WP2rXcxXL8TskReQl6OrB2G7+UJrags1q15Fudc7G6w== @@ -5583,20 +5336,13 @@ de-indent@^1.0.2: resolved "https://registry.yarnpkg.com/de-indent/-/de-indent-1.0.2.tgz#b2038e846dc33baa5796128d0804b455b8c1e21d" integrity sha512-e/1zu3xH5MQryN2zdVaF0OrdNLUbvWxzMbi+iNA6Bky7l1RoP8a2fIbRocyHclXt/arDrrR6lL3TqFD9pMQTsg== -debug@4, debug@4.3.4, debug@^4.1.0, debug@^4.1.1, debug@^4.2.0, debug@^4.3.1, debug@^4.3.2, debug@^4.3.3, debug@^4.3.4: +debug@4, debug@4.3.4, debug@^4.1.0, debug@^4.1.1, debug@^4.2.0, debug@^4.3.1, debug@^4.3.3, debug@^4.3.4: version "4.3.4" resolved "https://registry.yarnpkg.com/debug/-/debug-4.3.4.tgz#1319f6579357f2338d3337d2cdd4914bb5dcc865" integrity sha512-PRWFHuSU3eDtQJPvnNY7Jcket1j0t5OuOsFzPPzsekD52Zl8qUfFIPEiswXqIvHWGVHOgX+7G/vCNNhehwxfkQ== dependencies: ms "2.1.2" -debug@^3.2.7: - version "3.2.7" - resolved "https://registry.npmjs.org/debug/-/debug-3.2.7.tgz" - integrity sha512-CFjzYYAi4ThfiQvizrFQevTTXHtnCqWfe7x1AhgEscTz6ZbLbfoLRLPugTQyBth6f8ZERVUSyWHFD/7Wu4t1XQ== - dependencies: - ms "^2.1.1" - debug@^4.3.5: version "4.3.5" resolved "https://registry.yarnpkg.com/debug/-/debug-4.3.5.tgz#e83444eceb9fedd4a1da56d671ae2446a01a6e1e" @@ -5649,11 +5395,6 @@ deep-eql@^5.0.1: resolved "https://registry.yarnpkg.com/deep-eql/-/deep-eql-5.0.2.tgz#4b756d8d770a9257300825d52a2c2cff99c3a341" integrity sha512-h5k/5U50IJJFpzfL6nO9jaaumfjO/f2NjK/oYB2Djzm4p9L+3T9qWpZqZ2hAbLPuuYq9wrU08WQyBTL5GbPk5Q== -deep-is@^0.1.3: - version "0.1.3" - resolved "https://registry.npmjs.org/deep-is/-/deep-is-0.1.3.tgz" - integrity sha1-s2nW+128E+7PUk+RsHD+7cNXzzQ= - deepmerge-ts@^5.0.0, deepmerge-ts@^5.1.0: version "5.1.0" resolved "https://registry.yarnpkg.com/deepmerge-ts/-/deepmerge-ts-5.1.0.tgz#c55206cc4c7be2ded89b9c816cf3608884525d7a" @@ -5690,7 +5431,7 @@ define-lazy-prop@^2.0.0: resolved "https://registry.yarnpkg.com/define-lazy-prop/-/define-lazy-prop-2.0.0.tgz#3f7ae421129bcaaac9bc74905c98a0009ec9ee7f" integrity sha512-Ds09qNh8yw3khSjiJjiUInaGX9xlqZDY7JVryGxdxV7NPeuqQfplOpQ66yJFZut3jLa5zOwkXw1g9EI2uKh4Og== -define-properties@^1.1.3, define-properties@^1.1.4, define-properties@^1.2.0, define-properties@^1.2.1: +define-properties@^1.1.3, define-properties@^1.1.4, define-properties@^1.2.0: version "1.2.1" resolved "https://registry.yarnpkg.com/define-properties/-/define-properties-1.2.1.tgz#10781cc616eb951a80a034bafcaa7377f6af2b6c" integrity sha512-8QmQKqEASLd5nx0U1B1okLElbUuuttJ/AnYmRXbbbGDWh6uS208EjD4Xqq/I9wK7u0v6O08XhTWnt5XtEbR6Dg== @@ -5865,20 +5606,6 @@ dockerode@^3.3.5: docker-modem "^3.0.0" tar-fs "~2.0.1" -doctrine@^2.1.0: - version "2.1.0" - resolved "https://registry.npmjs.org/doctrine/-/doctrine-2.1.0.tgz" - integrity sha512-35mSku4ZXK0vfCuHEDAwt55dg2jNajHZ1odvF+8SSr82EsZY4QmXfuWso8oEd8zRhVObSN18aM0CjSdoBX7zIw== - dependencies: - esutils "^2.0.2" - -doctrine@^3.0.0: - version "3.0.0" - resolved "https://registry.npmjs.org/doctrine/-/doctrine-3.0.0.tgz" - integrity sha512-yS+Q5i3hBf7GBkd4KG8a7eBNNWNGLTaEwwYWUijIYM7zrlYDM0BFXHjjPWlWZ1Rg7UaddZeIDmi9jF3HmqiQ2w== - dependencies: - esutils "^2.0.2" - dom-accessibility-api@^0.5.9: version "0.5.16" resolved "https://registry.yarnpkg.com/dom-accessibility-api/-/dom-accessibility-api-0.5.16.tgz#5a7429e6066eb3664d911e33fb0e45de8eb08453" @@ -6011,14 +5738,6 @@ end-of-stream@^1.1.0, end-of-stream@^1.4.1: dependencies: once "^1.4.0" -enhanced-resolve@^5.12.0: - version "5.15.0" - resolved "https://registry.yarnpkg.com/enhanced-resolve/-/enhanced-resolve-5.15.0.tgz#1af946c7d93603eb88e9896cee4904dc012e9c35" - integrity sha512-LXYT42KJ7lpIKECr2mAXIaMldcNCh/7E0KBKOu4KSfkHmP+mZmSs+8V5gBAqisWBy0OO4W5Oyys0GO1Y8KtdKg== - dependencies: - graceful-fs "^4.2.4" - tapable "^2.2.0" - enquirer@~2.3.6: version "2.3.6" resolved "https://registry.yarnpkg.com/enquirer/-/enquirer-2.3.6.tgz#2a7fe5dd634a1e4125a975ec994ff5456dc3734d" @@ -6058,7 +5777,7 @@ error-ex@^1.3.1: dependencies: is-arrayish "^0.2.1" -es-abstract@^1.18.0-next.2, es-abstract@^1.22.1, es-abstract@^1.22.3: +es-abstract@^1.18.0-next.2, es-abstract@^1.22.1: version "1.22.3" resolved "https://registry.yarnpkg.com/es-abstract/-/es-abstract-1.22.3.tgz#48e79f5573198de6dee3589195727f4f74bc4f32" integrity sha512-eiiY8HQeYfYH2Con2berK+To6GrK2RxbPawDkGq4UiCQQfZHb6wX9qQqkbpPqaxQFcl8d9QzZqo0tGE0VcrdwA== @@ -6103,16 +5822,6 @@ es-abstract@^1.18.0-next.2, es-abstract@^1.22.1, es-abstract@^1.22.3: unbox-primitive "^1.0.2" which-typed-array "^1.1.13" -es-array-method-boxes-properly@^1.0.0: - version "1.0.0" - resolved "https://registry.yarnpkg.com/es-array-method-boxes-properly/-/es-array-method-boxes-properly-1.0.0.tgz#873f3e84418de4ee19c5be752990b2e44718d09e" - integrity sha512-wd6JXUmyHmt8T5a2xreUwKcGPq6f1f+WwIJkijUqiGcJz1qqnZgP6XIK+QyIWU5lT7imeNxUll48bziG+TSYcA== - -es-errors@^1.0.0, es-errors@^1.3.0: - version "1.3.0" - resolved "https://registry.yarnpkg.com/es-errors/-/es-errors-1.3.0.tgz#05f75a25dab98e4fb1dcd5e1472c0546d5057c8f" - integrity sha512-Zf5H2Kxt2xjTvbJvP2ZWLEICxA6j+hAmMzIlypy4xcBg1vKVnx89Wy0GbS+kf5cwCVFFzdCFh2XSCFNULS6csw== - es-set-tostringtag@^2.0.1: version "2.0.1" resolved "https://registry.yarnpkg.com/es-set-tostringtag/-/es-set-tostringtag-2.0.1.tgz#338d502f6f674301d710b80c8592de8a15f09cd8" @@ -6122,20 +5831,6 @@ es-set-tostringtag@^2.0.1: has "^1.0.3" has-tostringtag "^1.0.0" -es-shim-unscopables@^1.0.0: - version "1.0.0" - resolved "https://registry.yarnpkg.com/es-shim-unscopables/-/es-shim-unscopables-1.0.0.tgz#702e632193201e3edf8713635d083d378e510241" - integrity sha512-Jm6GPcCdC30eMLbZ2x8z2WuRwAws3zTBBKuusffYVUrNj/GVSUAZ+xKMaUpfNDR5IbyNA5LJbaecoUVbmUcB1w== - dependencies: - has "^1.0.3" - -es-shim-unscopables@^1.0.2: - version "1.0.2" - resolved "https://registry.yarnpkg.com/es-shim-unscopables/-/es-shim-unscopables-1.0.2.tgz#1f6942e71ecc7835ed1c8a83006d8771a63a3763" - integrity sha512-J3yBRXCzDu4ULnQwxyToo/OjdMx6akgVC7K6few0a7F/0wLtmKKN7I73AH5T2836UuXRqN7Qg+IIUw/+YJksRw== - dependencies: - hasown "^2.0.0" - es-to-primitive@^1.2.1: version "1.2.1" resolved "https://registry.yarnpkg.com/es-to-primitive/-/es-to-primitive-1.2.1.tgz#e55cd4c9cdc188bcefb03b366c736323fc5c898a" @@ -6220,191 +5915,17 @@ escodegen@^2.1.0: optionalDependencies: source-map "~0.6.1" -eslint-import-resolver-node@^0.3.9: - version "0.3.9" - resolved "https://registry.yarnpkg.com/eslint-import-resolver-node/-/eslint-import-resolver-node-0.3.9.tgz#d4eaac52b8a2e7c3cd1903eb00f7e053356118ac" - integrity sha512-WFj2isz22JahUv+B788TlO3N6zL3nNJGU8CcZbPZvVEkBPaJdCV4vy5wyghty5ROFbCRnm132v8BScu5/1BQ8g== - dependencies: - debug "^3.2.7" - is-core-module "^2.13.0" - resolve "^1.22.4" - -eslint-import-resolver-typescript@^3.6.1: - version "3.6.1" - resolved "https://registry.yarnpkg.com/eslint-import-resolver-typescript/-/eslint-import-resolver-typescript-3.6.1.tgz#7b983680edd3f1c5bce1a5829ae0bc2d57fe9efa" - integrity sha512-xgdptdoi5W3niYeuQxKmzVDTATvLYqhpwmykwsh7f6HIOStGWEIL9iqZgQDF9u9OEzrRwR8no5q2VT+bjAujTg== - dependencies: - debug "^4.3.4" - enhanced-resolve "^5.12.0" - eslint-module-utils "^2.7.4" - fast-glob "^3.3.1" - get-tsconfig "^4.5.0" - is-core-module "^2.11.0" - is-glob "^4.0.3" - -eslint-module-utils@^2.7.4: - version "2.7.4" - resolved "https://registry.yarnpkg.com/eslint-module-utils/-/eslint-module-utils-2.7.4.tgz#4f3e41116aaf13a20792261e61d3a2e7e0583974" - integrity sha512-j4GT+rqzCoRKHwURX7pddtIPGySnX9Si/cgMI5ztrcqOPtk5dDEeZ34CQVPphnqkJytlc97Vuk05Um2mJ3gEQA== - dependencies: - debug "^3.2.7" - -eslint-module-utils@^2.8.0: - version "2.8.0" - resolved "https://registry.yarnpkg.com/eslint-module-utils/-/eslint-module-utils-2.8.0.tgz#e439fee65fc33f6bba630ff621efc38ec0375c49" - integrity sha512-aWajIYfsqCKRDgUfjEXNN/JlrzauMuSEy5sbd7WXbtW3EH6A6MpwEh42c7qD+MqQo9QMJ6fWLAeIJynx0g6OAw== - dependencies: - debug "^3.2.7" - -eslint-plugin-es@^4.1.0: - version "4.1.0" - resolved "https://registry.npmjs.org/eslint-plugin-es/-/eslint-plugin-es-4.1.0.tgz" - integrity sha512-GILhQTnjYE2WorX5Jyi5i4dz5ALWxBIdQECVQavL6s7cI76IZTDWleTHkxz/QT3kvcs2QlGHvKLYsSlPOlPXnQ== - dependencies: - eslint-utils "^2.0.0" - regexpp "^3.0.0" - -eslint-plugin-import@^2.29.1: - version "2.29.1" - resolved "https://registry.yarnpkg.com/eslint-plugin-import/-/eslint-plugin-import-2.29.1.tgz#d45b37b5ef5901d639c15270d74d46d161150643" - integrity sha512-BbPC0cuExzhiMo4Ff1BTVwHpjjv28C5R+btTOGaCRC7UEz801up0JadwkeSk5Ued6TG34uaczuVuH6qyy5YUxw== - dependencies: - array-includes "^3.1.7" - array.prototype.findlastindex "^1.2.3" - array.prototype.flat "^1.3.2" - array.prototype.flatmap "^1.3.2" - debug "^3.2.7" - doctrine "^2.1.0" - eslint-import-resolver-node "^0.3.9" - eslint-module-utils "^2.8.0" - hasown "^2.0.0" - is-core-module "^2.13.1" - is-glob "^4.0.3" - minimatch "^3.1.2" - object.fromentries "^2.0.7" - object.groupby "^1.0.1" - object.values "^1.1.7" - semver "^6.3.1" - tsconfig-paths "^3.15.0" - -eslint-plugin-prettier@^5.1.3: - version "5.1.3" - resolved "https://registry.yarnpkg.com/eslint-plugin-prettier/-/eslint-plugin-prettier-5.1.3.tgz#17cfade9e732cef32b5f5be53bd4e07afd8e67e1" - integrity sha512-C9GCVAs4Eq7ZC/XFQHITLiHJxQngdtraXaM+LoUFoFp/lHNl2Zn8f3WQbe9HvTBBQ9YnKFB0/2Ajdqwo5D1EAw== - dependencies: - prettier-linter-helpers "^1.0.0" - synckit "^0.8.6" - -eslint-plugin-vitest@^0.3.26: - version "0.3.26" - resolved "https://registry.yarnpkg.com/eslint-plugin-vitest/-/eslint-plugin-vitest-0.3.26.tgz#0906893c1f8f7094614fc6ff255c0a369cfbf427" - integrity sha512-oxe5JSPgRjco8caVLTh7Ti8PxpwJdhSV0hTQAmkFcNcmy/9DnqLB/oNVRA11RmVRP//2+jIIT6JuBEcpW3obYg== - dependencies: - "@typescript-eslint/utils" "^7.1.1" - -eslint-scope@^7.2.2: - version "7.2.2" - resolved "https://registry.yarnpkg.com/eslint-scope/-/eslint-scope-7.2.2.tgz#deb4f92563390f32006894af62a22dba1c46423f" - integrity sha512-dOt21O7lTMhDM+X9mB4GX+DZrZtCUJPL/wlcTqxyrx5IvO0IYtILdtrQGQp+8n5S0gwSVmOf9NQrjMOgfQZlIg== - dependencies: - esrecurse "^4.3.0" - estraverse "^5.2.0" - -eslint-utils@^2.0.0: - version "2.1.0" - resolved "https://registry.npmjs.org/eslint-utils/-/eslint-utils-2.1.0.tgz" - integrity sha512-w94dQYoauyvlDc43XnGB8lU3Zt713vNChgt4EWwhXAP2XkBvndfxF0AgIqKOOasjPIPzj9JqgwkwbCYD0/V3Zg== - dependencies: - eslint-visitor-keys "^1.1.0" - -eslint-visitor-keys@^1.1.0: - version "1.3.0" - resolved "https://registry.npmjs.org/eslint-visitor-keys/-/eslint-visitor-keys-1.3.0.tgz" - integrity sha512-6J72N8UNa462wa/KFODt/PJ3IU60SDpC3QXC1Hjc1BXXpfL2C9R5+AU7jhe0F6GREqVMh4Juu+NY7xn+6dipUQ== - -eslint-visitor-keys@^3.3.0, eslint-visitor-keys@^3.4.1, eslint-visitor-keys@^3.4.3: - version "3.4.3" - resolved "https://registry.yarnpkg.com/eslint-visitor-keys/-/eslint-visitor-keys-3.4.3.tgz#0cd72fe8550e3c2eae156a96a4dddcd1c8ac5800" - integrity sha512-wpc+LXeiyiisxPlEkUzU6svyS1frIO3Mgxj1fdy7Pm8Ygzguax2N3Fa/D/ag1WqbOprdI+uY6wMUl8/a2G+iag== - -eslint@^8.57.0: - version "8.57.0" - resolved "https://registry.yarnpkg.com/eslint/-/eslint-8.57.0.tgz#c786a6fd0e0b68941aaf624596fb987089195668" - integrity sha512-dZ6+mexnaTIbSBZWgou51U6OmzIhYM2VcNdtiTtI7qPNZm35Akpr0f6vtw3w1Kmn5PYo+tZVfh13WrhpS6oLqQ== - dependencies: - "@eslint-community/eslint-utils" "^4.2.0" - "@eslint-community/regexpp" "^4.6.1" - "@eslint/eslintrc" "^2.1.4" - "@eslint/js" "8.57.0" - "@humanwhocodes/config-array" "^0.11.14" - "@humanwhocodes/module-importer" "^1.0.1" - "@nodelib/fs.walk" "^1.2.8" - "@ungap/structured-clone" "^1.2.0" - ajv "^6.12.4" - chalk "^4.0.0" - cross-spawn "^7.0.2" - debug "^4.3.2" - doctrine "^3.0.0" - escape-string-regexp "^4.0.0" - eslint-scope "^7.2.2" - eslint-visitor-keys "^3.4.3" - espree "^9.6.1" - esquery "^1.4.2" - esutils "^2.0.2" - fast-deep-equal "^3.1.3" - file-entry-cache "^6.0.1" - find-up "^5.0.0" - glob-parent "^6.0.2" - globals "^13.19.0" - graphemer "^1.4.0" - ignore "^5.2.0" - imurmurhash "^0.1.4" - is-glob "^4.0.0" - is-path-inside "^3.0.3" - js-yaml "^4.1.0" - json-stable-stringify-without-jsonify "^1.0.1" - levn "^0.4.1" - lodash.merge "^4.6.2" - minimatch "^3.1.2" - natural-compare "^1.4.0" - optionator "^0.9.3" - strip-ansi "^6.0.1" - text-table "^0.2.0" - esm@^3.2.25: version "3.2.25" resolved "https://registry.npmjs.org/esm/-/esm-3.2.25.tgz" integrity sha512-U1suiZ2oDVWv4zPO56S0NcR5QriEahGtdN2OR6FiOG4WJvcjBVFB0qI4+eKoWFH483PKGuLuu6V8Z4T5g63UVA== -espree@^9.6.0, espree@^9.6.1: - version "9.6.1" - resolved "https://registry.yarnpkg.com/espree/-/espree-9.6.1.tgz#a2a17b8e434690a5432f2f8018ce71d331a48c6f" - integrity sha512-oruZaFkjorTpF32kDSI5/75ViwGeZginGGy2NoOSg3Q9bnwlnmDm4HLnkl0RE3n+njDXR037aY1+x58Z/zFdwQ== - dependencies: - acorn "^8.9.0" - acorn-jsx "^5.3.2" - eslint-visitor-keys "^3.4.1" - esprima@^4.0.0, esprima@^4.0.1: version "4.0.1" resolved "https://registry.npmjs.org/esprima/-/esprima-4.0.1.tgz" integrity sha512-eGuFFw7Upda+g4p+QHvnW0RyTX/SVeJBDM/gCtMARO0cLuT2HcEKnTPvhjV6aGeqrCB/sbNop0Kszm0jsaWU4A== -esquery@^1.4.2: - version "1.5.0" - resolved "https://registry.yarnpkg.com/esquery/-/esquery-1.5.0.tgz#6ce17738de8577694edd7361c57182ac8cb0db0b" - integrity sha512-YQLXUplAwJgCydQ78IMJywZCceoqk1oH01OERdSAJc/7U2AylwjhSCLDEtqwg811idIS/9fIU5GjG73IgjKMVg== - dependencies: - estraverse "^5.1.0" - -esrecurse@^4.3.0: - version "4.3.0" - resolved "https://registry.npmjs.org/esrecurse/-/esrecurse-4.3.0.tgz" - integrity sha512-KmfKL3b6G+RXvP8N1vr3Tq1kL/oCFgn2NYXEtqP8/L3pKapUA4G8cFVaoF3SU323CD4XypR/ffioHmkti6/Tag== - dependencies: - estraverse "^5.2.0" - -estraverse@^5.1.0, estraverse@^5.2.0: +estraverse@^5.2.0: version "5.2.0" resolved "https://registry.npmjs.org/estraverse/-/estraverse-5.2.0.tgz" integrity sha512-BxbNGGNm0RyRYvUdHpIwv9IWzeM9XClbOxwoATuFdOE7ZE6wHL+HQ5T8hoPM+zHvmKzzsEqhgy0GrQ5X13afiQ== @@ -6608,17 +6129,12 @@ fast-deep-equal@^3.1.1, fast-deep-equal@^3.1.3: resolved "https://registry.yarnpkg.com/fast-deep-equal/-/fast-deep-equal-3.1.3.tgz#3a7d56b559d6cbc3eb512325244e619a65c6c525" integrity sha512-f3qQ9oQy9j2AhBe/H9VC91wLmKBCCU/gDOnKNAYG5hswO7BLKj09Hc5HYNz9cGI++xlpDCIgDaitVs03ATR84Q== -fast-diff@^1.1.2: - version "1.2.0" - resolved "https://registry.npmjs.org/fast-diff/-/fast-diff-1.2.0.tgz" - integrity sha512-xJuoT5+L99XlZ8twedaRf6Ax2TgQVxvgZOYoPKqZufmJib0tL2tegPBOZb1pVNgIhlqDlA0eO0c3wBvQcmzx4w== - fast-fifo@^1.1.0, fast-fifo@^1.2.0: version "1.3.2" resolved "https://registry.yarnpkg.com/fast-fifo/-/fast-fifo-1.3.2.tgz#286e31de96eb96d38a97899815740ba2a4f3640c" integrity sha512-/d9sfos4yxzpwkDkuN7k2SqFKtYNmCTzgfEpz82x34IM9/zc8KGxQoXg1liNC/izpRM/MBdt44Nmx41ZWqk+FQ== -fast-glob@^3.2.9, fast-glob@^3.3.1: +fast-glob@^3.2.9: version "3.3.2" resolved "https://registry.yarnpkg.com/fast-glob/-/fast-glob-3.3.2.tgz#a904501e57cfdd2ffcded45e99a54fef55e46129" integrity sha512-oX2ruAFQwf/Orj8m737Y5adxDQO0LAB7/S5MnxCdTNDd4p6BsyIVsv9JQsATbTSq8KHRpLwIHbVlUNatxd+1Ow== @@ -6647,11 +6163,6 @@ fast-json-stringify@^6.0.0: json-schema-ref-resolver "^1.0.1" rfdc "^1.2.0" -fast-levenshtein@^2.0.6: - version "2.0.6" - resolved "https://registry.npmjs.org/fast-levenshtein/-/fast-levenshtein-2.0.6.tgz" - integrity sha1-PYpcZog6FqMMqGQ+hR8Zuqd5eRc= - fast-querystring@^1.0.0: version "1.1.1" resolved "https://registry.yarnpkg.com/fast-querystring/-/fast-querystring-1.1.1.tgz#f4c56ef56b1a954880cfd8c01b83f9e1a3d3fda2" @@ -6754,13 +6265,6 @@ figures@^5.0.0: escape-string-regexp "^5.0.0" is-unicode-supported "^1.2.0" -file-entry-cache@^6.0.1: - version "6.0.1" - resolved "https://registry.yarnpkg.com/file-entry-cache/-/file-entry-cache-6.0.1.tgz#211b2dd9659cb0394b073e7323ac3c933d522027" - integrity sha512-7Gps/XWymbLk2QLYK4NzpMOrYjMhdIxXuIvy2QBsLE6ljuodKvdkWs/cpyJJ3CVIVpH0Oi1Hvg1ovbMzLdFBBg== - dependencies: - flat-cache "^3.0.4" - file-stream-rotator@^0.6.1: version "0.6.1" resolved "https://registry.yarnpkg.com/file-stream-rotator/-/file-stream-rotator-0.6.1.tgz#007019e735b262bb6c6f0197e58e5c87cb96cec3" @@ -6834,24 +6338,11 @@ find-up@^6.3.0: locate-path "^7.1.0" path-exists "^5.0.0" -flat-cache@^3.0.4: - version "3.0.4" - resolved "https://registry.yarnpkg.com/flat-cache/-/flat-cache-3.0.4.tgz#61b0338302b2fe9f957dcc32fc2a87f1c3048b11" - integrity sha512-dm9s5Pw7Jc0GvMYbshN6zchCA9RgQlzzEZX3vylR9IqFfS8XciblUXOKfW6SiuJ0e13eDYZoZV5wdrev7P3Nwg== - dependencies: - flatted "^3.1.0" - rimraf "^3.0.2" - flat@^5.0.2: version "5.0.2" resolved "https://registry.npmjs.org/flat/-/flat-5.0.2.tgz" integrity sha512-b6suED+5/3rTpUBdG1gupIl8MPFCAMA0QXwmljLhvCUKcUvdE4gWky9zpuGCcXHOsz4J9wPGNWq6OKpmIzz3hQ== -flatted@^3.1.0: - version "3.2.5" - resolved "https://registry.yarnpkg.com/flatted/-/flatted-3.2.5.tgz#76c8584f4fc843db64702a6bd04ab7a8bd666da3" - integrity sha512-WIWGi2L3DyTUvUrwRKgGi9TwxQMUEqPOPQBVi71R96jZXJdFskXEmf54BoZaS1kknGODoIGASGEzBUYdyMCBJg== - fn.name@1.x.x: version "1.1.0" resolved "https://registry.npmjs.org/fn.name/-/fn.name-1.1.0.tgz" @@ -7153,13 +6644,6 @@ get-symbol-description@^1.0.0: call-bind "^1.0.2" get-intrinsic "^1.1.1" -get-tsconfig@^4.5.0: - version "4.6.2" - resolved "https://registry.yarnpkg.com/get-tsconfig/-/get-tsconfig-4.6.2.tgz#831879a5e6c2aa24fe79b60340e2233a1e0f472e" - integrity sha512-E5XrT4CbbXcXWy+1jChlZmrmCwd5KGx502kDCXJJ7y898TtWW9FwoG5HfOLVRKmlmDGkWN2HM9Ho+/Y8F0sJDg== - dependencies: - resolve-pkg-maps "^1.0.0" - get-uri@^6.0.1: version "6.0.2" resolved "https://registry.yarnpkg.com/get-uri/-/get-uri-6.0.2.tgz#e019521646f4a8ff6d291fbaea2c46da204bb75b" @@ -7224,13 +6708,6 @@ glob-parent@5.1.2, glob-parent@^5.1.2, glob-parent@~5.1.2: dependencies: is-glob "^4.0.1" -glob-parent@^6.0.2: - version "6.0.2" - resolved "https://registry.yarnpkg.com/glob-parent/-/glob-parent-6.0.2.tgz#6d237d99083950c79290f24c7642a3de9a28f9e3" - integrity sha512-XxwI8EOhVQgWp6iDL+3b0r86f4d6AX6zSU55HfB4ydCEuXLXc5FcYeOu+nnGftS4TEju/11rt4KJPTMgbfmv4A== - dependencies: - is-glob "^4.0.3" - glob@7.1.4: version "7.1.4" resolved "https://registry.yarnpkg.com/glob/-/glob-7.1.4.tgz#aa608a2f6c577ad357e1ae5a5c26d9a8d1969255" @@ -7346,13 +6823,6 @@ global-agent@^3.0.0: semver "^7.3.2" serialize-error "^7.0.1" -globals@^13.19.0: - version "13.20.0" - resolved "https://registry.yarnpkg.com/globals/-/globals-13.20.0.tgz#ea276a1e508ffd4f1612888f9d1bad1e2717bf82" - integrity sha512-Qg5QtVkCy/kv3FUSlu4ukeZDVf9ee0iXLAUYX13gbR17bnejFTzr4iS9bY7kwCf1NztRNm1t91fjOiyx4CSwPQ== - dependencies: - type-fest "^0.20.2" - globalthis@^1.0.1, globalthis@^1.0.3: version "1.0.3" resolved "https://registry.yarnpkg.com/globalthis/-/globalthis-1.0.3.tgz#5852882a52b80dc301b0660273e1ed082f0b6ccf" @@ -7360,7 +6830,7 @@ globalthis@^1.0.1, globalthis@^1.0.3: dependencies: define-properties "^1.1.3" -globby@11.1.0, globby@^11.1.0: +globby@11.1.0: version "11.1.0" resolved "https://registry.yarnpkg.com/globby/-/globby-11.1.0.tgz#bd4be98bb042f83d796f7e3811991fbe82a0d34b" integrity sha512-jhIXaOzy1sb8IyocaruWSn1TjmnBVs8Ayhcy83rmxNJ8q2uWKCAj3CnJY+KpGSXCueAPc0i05kVvVKtP1t9S3g== @@ -7423,11 +6893,6 @@ grapheme-splitter@^1.0.2: resolved "https://registry.yarnpkg.com/grapheme-splitter/-/grapheme-splitter-1.0.4.tgz#9cf3a665c6247479896834af35cf1dbb4400767e" integrity sha512-bzh50DW9kTPM00T8y4o8vQg89Di9oLJVLW/KaOGIXJWP/iqCN6WKYkbNOF04vFLJhwcpYUh9ydh/+5vpOqV4YQ== -graphemer@^1.4.0: - version "1.4.0" - resolved "https://registry.yarnpkg.com/graphemer/-/graphemer-1.4.0.tgz#fb2f1d55e0e3a1849aeffc90c4fa0dd53a0e66c6" - integrity sha512-EtKwoO6kxCL9WO5xipiHTZlSzBm7WLT627TqC/uVRd0HKmq8NXyebnNYxDoBi7wt8eTWrUrKXCOVaFq9x1kgag== - graphql@^16.8.1: version "16.9.0" resolved "https://registry.yarnpkg.com/graphql/-/graphql-16.9.0.tgz#1c310e63f16a49ce1fbb230bd0a000e99f6f115f" @@ -7743,7 +7208,7 @@ ignore-walk@^6.0.0: dependencies: minimatch "^7.4.2" -ignore@^5.0.4, ignore@^5.1.1, ignore@^5.2.0, ignore@^5.2.4: +ignore@^5.0.4, ignore@^5.2.0: version "5.3.0" resolved "https://registry.yarnpkg.com/ignore/-/ignore-5.3.0.tgz#67418ae40d34d6999c95ff56016759c718c82f78" integrity sha512-g7dmpshy+gD7mh88OC9NwSGTKoc3kyLAZQRU1mt53Aw/vnvfXnbC+F/7F7QoYVKbV+KNvJx8wArewKy1vXMtlg== @@ -7753,7 +7218,7 @@ immutable@^4.3.2: resolved "https://registry.yarnpkg.com/immutable/-/immutable-4.3.5.tgz#f8b436e66d59f99760dc577f5c99a4fd2a5cc5a0" integrity sha512-8eabxkth9gZatlwl5TBuJnCsoTADlL6ftEr7A4qgdaTsPyreilDSnUk57SO+jfKcNtxPa22U5KK6DSeAYhpBJw== -import-fresh@^3.2.1, import-fresh@^3.3.0: +import-fresh@^3.3.0: version "3.3.0" resolved "https://registry.npmjs.org/import-fresh/-/import-fresh-3.3.0.tgz" integrity sha512-veYYhQa+D1QBKznvhUHxb8faxlrwUnxseDAbAp457E0wLNio2bOSKnjYDhMj+YiAq61xrMGhQk9iXVk5FzgQMw== @@ -7979,7 +7444,7 @@ is-ci@3.0.1: dependencies: ci-info "^3.2.0" -is-core-module@^2.1.0, is-core-module@^2.11.0, is-core-module@^2.13.0, is-core-module@^2.13.1, is-core-module@^2.3.0, is-core-module@^2.5.0, is-core-module@^2.8.1: +is-core-module@^2.1.0, is-core-module@^2.13.0, is-core-module@^2.5.0, is-core-module@^2.8.1: version "2.13.1" resolved "https://registry.yarnpkg.com/is-core-module/-/is-core-module-2.13.1.tgz#ad0d7532c6fea9da1ebdc82742d74525c6273384" integrity sha512-hHrIjvZsftOsvKSn2TRYl63zvxsgE0K+0mYMoH6gD4omR5IWB2KynivBQczo3+wF1cCkjzvptnI9Q0sPU66ilw== @@ -8018,7 +7483,7 @@ is-generator-function@^1.0.7: resolved "https://registry.npmjs.org/is-generator-function/-/is-generator-function-1.0.8.tgz" integrity sha512-2Omr/twNtufVZFr1GhxjOMFPAj2sjc/dKaIqBhvo4qciXfJmITGH6ZGd8eZYNHza8t1y0e01AuqRhJwfWp26WQ== -is-glob@^4.0.0, is-glob@^4.0.1, is-glob@^4.0.3, is-glob@~4.0.1: +is-glob@^4.0.1, is-glob@~4.0.1: version "4.0.3" resolved "https://registry.yarnpkg.com/is-glob/-/is-glob-4.0.3.tgz#64f61e42cbbb2eec2071a9dac0b28ba1e65d5084" integrity sha512-xelSayHH36ZgE7ZWhli7pW34hNbNl8Ojv5KVmkJD4hBdD3th8Tfk9vYasLM+mXWOZhFkgZfxhLSnrwRr4elSSg== @@ -8101,11 +7566,6 @@ is-observable@^2.1.0: resolved "https://registry.npmjs.org/is-observable/-/is-observable-2.1.0.tgz" integrity sha512-DailKdLb0WU+xX8K5w7VsJhapwHLZ9jjmazqCJq4X12CTgqq73TKnbRcnSLuXYPOoLQgV5IrD7ePiX/h1vnkBw== -is-path-inside@^3.0.3: - version "3.0.3" - resolved "https://registry.yarnpkg.com/is-path-inside/-/is-path-inside-3.0.3.tgz#d231362e53a07ff2b0e0ea7fed049161ffd16283" - integrity sha512-Fd4gABb+ycGAmKou8eMftCupSir5lRxqf4aD/vd0cD2qc4HL07OjCeuHMr8Ro4CoMaeCKDB0/ECBOVWjTwUvPQ== - is-plain-obj@^1.0.0, is-plain-obj@^1.1.0: version "1.1.0" resolved "https://registry.yarnpkg.com/is-plain-obj/-/is-plain-obj-1.1.0.tgz#71a50c8429dfca773c92a390a4a03b39fcd51d3e" @@ -8611,23 +8071,11 @@ json-schema-traverse@^1.0.0: resolved "https://registry.npmjs.org/json-schema-traverse/-/json-schema-traverse-1.0.0.tgz" integrity sha512-NM8/P9n3XjXhIZn1lLhkFaACTOURQXjWhV4BA/RnOv8xvgqtqpAX9IO4mRQxSx1Rlo4tqzeqb0sOlruaOy3dug== -json-stable-stringify-without-jsonify@^1.0.1: - version "1.0.1" - resolved "https://registry.npmjs.org/json-stable-stringify-without-jsonify/-/json-stable-stringify-without-jsonify-1.0.1.tgz" - integrity sha1-nbe1lJatPzz+8wp1FC0tkwrXJlE= - json-stringify-safe@^5.0.1: version "5.0.1" resolved "https://registry.yarnpkg.com/json-stringify-safe/-/json-stringify-safe-5.0.1.tgz#1296a2d58fd45f19a0f6ce01d65701e2c735b6eb" integrity sha512-ZClg6AaYvamvYEE82d3Iyd3vSSIjQ+odgjaTzRuO3s7toCdFKczob2i0zCh7JE8kWn17yvAWhUVxvqGwUalsRA== -json5@^1.0.2: - version "1.0.2" - resolved "https://registry.yarnpkg.com/json5/-/json5-1.0.2.tgz#63d98d60f21b313b77c4d6da18bfa69d80e1d593" - integrity sha512-g1MWMLBiz8FKi1e4w0UyVL3w+iJceWAFBAaBnnGKOpNa5f8TLktkbre1+s6oICydWAm+HRUGTmI+//xv2hvXYA== - dependencies: - minimist "^1.2.0" - json5@^2.2.2: version "2.2.3" resolved "https://registry.yarnpkg.com/json5/-/json5-2.2.3.tgz#78cd6f1a19bdc12b73db5ad0c61efd66c1e29283" @@ -8805,14 +8253,6 @@ level@^8.0.0: browser-level "^1.0.1" classic-level "^1.2.0" -levn@^0.4.1: - version "0.4.1" - resolved "https://registry.npmjs.org/levn/-/levn-0.4.1.tgz" - integrity sha512-+bT2uH4E5LGE7h/n3evcS/sQlJXCpIp6ym8OWJ5eV6+67Dsql/LaaT7qJBAt2rzfoa/5QBGBhxDix1dMt2kQKQ== - dependencies: - prelude-ls "^1.2.1" - type-check "~0.4.0" - libnpmaccess@7.0.2: version "7.0.2" resolved "https://registry.yarnpkg.com/libnpmaccess/-/libnpmaccess-7.0.2.tgz#7f056c8c933dd9c8ba771fa6493556b53c5aac52" @@ -8994,11 +8434,6 @@ lodash.isplainobject@^4.0.6: resolved "https://registry.yarnpkg.com/lodash.isplainobject/-/lodash.isplainobject-4.0.6.tgz#7c526a52d89b45c45cc690b88163be0497f550cb" integrity sha512-oSXzaWypCMHkPC3NvBEaPHf0KsA5mvPrOPgQWDsbg8n7orZ290M0BmC/jgRZ4vcJ6DTAhjrsSYgdsW/F+MFOBA== -lodash.merge@^4.6.2: - version "4.6.2" - resolved "https://registry.yarnpkg.com/lodash.merge/-/lodash.merge-4.6.2.tgz#558aa53b43b661e1925a0afdfa36a9a1085fe57a" - integrity sha512-0KpjqXRVvrYyCsX1swR/XTK0va6VQkQM6MNo7PqW77ByjAhoARA8EfrP1N4+KlKj8YS0ZUCtRT/YUuhyYDujIQ== - lodash.some@^4.6.0: version "4.6.0" resolved "https://registry.npmjs.org/lodash.some/-/lodash.some-4.6.0.tgz" @@ -9417,13 +8852,6 @@ minimatch@5.0.1: dependencies: brace-expansion "^2.0.1" -minimatch@9.0.3, minimatch@^9.0.0, minimatch@^9.0.1: - version "9.0.3" - resolved "https://registry.yarnpkg.com/minimatch/-/minimatch-9.0.3.tgz#a6e00c3de44c3a542bfaae70abfc22420a6da825" - integrity sha512-RHiac9mvaRw0x3AYRgDC1CxAP7HTcNrrECeA8YYJeWnpo+2Q5CegtZjaotWTWxDG3UeGA1coE05iH1mPjT/2mg== - dependencies: - brace-expansion "^2.0.1" - minimatch@^10.0.0: version "10.0.1" resolved "https://registry.yarnpkg.com/minimatch/-/minimatch-10.0.1.tgz#ce0521856b453c86e25f2c4c0d03e6ff7ddc440b" @@ -9431,7 +8859,7 @@ minimatch@^10.0.0: dependencies: brace-expansion "^2.0.1" -minimatch@^3.0.4, minimatch@^3.0.5, minimatch@^3.1.1, minimatch@^3.1.2: +minimatch@^3.0.4, minimatch@^3.1.1: version "3.1.2" resolved "https://registry.yarnpkg.com/minimatch/-/minimatch-3.1.2.tgz#19cd194bfd3e428f049a70817c038d89ab4be35b" integrity sha512-J7p63hRiAjw1NDEww1W7i37+ByIrOWO5XQQAzZ3VOcL0PNybwpfmV/N05zFAzwQ9USyEcX6t3UO+K5aqBQOIHw== @@ -9459,13 +8887,27 @@ minimatch@^8.0.2: dependencies: brace-expansion "^2.0.1" -minimatch@^9.0.3, minimatch@^9.0.4: +minimatch@^9.0.0, minimatch@^9.0.1: + version "9.0.3" + resolved "https://registry.yarnpkg.com/minimatch/-/minimatch-9.0.3.tgz#a6e00c3de44c3a542bfaae70abfc22420a6da825" + integrity sha512-RHiac9mvaRw0x3AYRgDC1CxAP7HTcNrrECeA8YYJeWnpo+2Q5CegtZjaotWTWxDG3UeGA1coE05iH1mPjT/2mg== + dependencies: + brace-expansion "^2.0.1" + +minimatch@^9.0.3: version "9.0.4" resolved "https://registry.yarnpkg.com/minimatch/-/minimatch-9.0.4.tgz#8e49c731d1749cbec05050ee5145147b32496a51" integrity sha512-KqWh+VchfxcMNRAJjj2tnsSJdNbHsVgnkBhTNrW7AjVo6OvLtxw8zfT9oLw1JSohlFzJ8jCoTgaoXvJ+kHt6fw== dependencies: brace-expansion "^2.0.1" +minimatch@^9.0.4: + version "9.0.5" + resolved "https://registry.yarnpkg.com/minimatch/-/minimatch-9.0.5.tgz#d74f9dd6b57d83d8e98cfb82133b03978bc929e5" + integrity sha512-G6T0ZX48xgozx7587koeX9Ys2NYy6Gmv//P89sEte9V9whIapMNF4idKxnW2QtCcLiTWlb/wfCabAtAFWhhBow== + dependencies: + brace-expansion "^2.0.1" + minimatch@~3.0.3: version "3.0.8" resolved "https://registry.yarnpkg.com/minimatch/-/minimatch-3.0.8.tgz#5e6a59bd11e2ab0de1cfb843eb2d82e546c321c1" @@ -9783,11 +9225,6 @@ native-fetch@^4.0.2: resolved "https://registry.yarnpkg.com/native-fetch/-/native-fetch-4.0.2.tgz#75c8a44c5f3bb021713e5e24f2846750883e49af" integrity sha512-4QcVlKFtv2EYVS5MBgsGX5+NWKtbDbIECdUXDBGDMAZXq3Jkv9zf+y8iS7Ub8fEdga3GpYeazp9gauNqXHJOCg== -natural-compare@^1.4.0: - version "1.4.0" - resolved "https://registry.npmjs.org/natural-compare/-/natural-compare-1.4.0.tgz" - integrity sha1-Sr6/7tdUHywnrPspvbvRXI1bpPc= - negotiator@^0.6.2, negotiator@^0.6.3: version "0.6.3" resolved "https://registry.npmjs.org/negotiator/-/negotiator-0.6.3.tgz" @@ -10235,35 +9672,6 @@ object.assign@^4.1.4: has-symbols "^1.0.3" object-keys "^1.1.1" -object.fromentries@^2.0.7: - version "2.0.7" - resolved "https://registry.yarnpkg.com/object.fromentries/-/object.fromentries-2.0.7.tgz#71e95f441e9a0ea6baf682ecaaf37fa2a8d7e616" - integrity sha512-UPbPHML6sL8PI/mOqPwsH4G6iyXcCGzLin8KvEPenOZN5lpCNBZZQ+V62vdjB1mQHrmqGQt5/OJzemUA+KJmEA== - dependencies: - call-bind "^1.0.2" - define-properties "^1.2.0" - es-abstract "^1.22.1" - -object.groupby@^1.0.1: - version "1.0.2" - resolved "https://registry.yarnpkg.com/object.groupby/-/object.groupby-1.0.2.tgz#494800ff5bab78fd0eff2835ec859066e00192ec" - integrity sha512-bzBq58S+x+uo0VjurFT0UktpKHOZmv4/xePiOA1nbB9pMqpGK7rUPNgf+1YC+7mE+0HzhTMqNUuCqvKhj6FnBw== - dependencies: - array.prototype.filter "^1.0.3" - call-bind "^1.0.5" - define-properties "^1.2.1" - es-abstract "^1.22.3" - es-errors "^1.0.0" - -object.values@^1.1.7: - version "1.1.7" - resolved "https://registry.yarnpkg.com/object.values/-/object.values-1.1.7.tgz#617ed13272e7e1071b43973aa1655d9291b8442a" - integrity sha512-aU6xnDFYT3x17e/f0IiiwlGPTy2jzMySGfUB4fq6z7CV8l85CWHDk5ErhyhpfDHhrOMwGFhSQkhMGHaIotA6Ng== - dependencies: - call-bind "^1.0.2" - define-properties "^1.2.0" - es-abstract "^1.22.1" - obliterator@^2.0.1: version "2.0.4" resolved "https://registry.yarnpkg.com/obliterator/-/obliterator-2.0.4.tgz#fa650e019b2d075d745e44f1effeb13a2adbe816" @@ -10326,18 +9734,6 @@ openapi-types@^12.1.3: resolved "https://registry.yarnpkg.com/openapi-types/-/openapi-types-12.1.3.tgz#471995eb26c4b97b7bd356aacf7b91b73e777dd3" integrity sha512-N4YtSYJqghVu4iek2ZUvcN/0aqH1kRDuNqzcycDxhOUpg7GdvLa2F3DgS6yBNhInhv2r/6I0Flkn7CqL8+nIcw== -optionator@^0.9.3: - version "0.9.3" - resolved "https://registry.yarnpkg.com/optionator/-/optionator-0.9.3.tgz#007397d44ed1872fdc6ed31360190f81814e2c64" - integrity sha512-JjCoypp+jKn1ttEFExxhetCKeJt9zhAgAve5FXHixTvFDW/5aEktX9bufBKLRRMdU7bNtpLfcGu94B3cdEJgjg== - dependencies: - "@aashutoshrathi/word-wrap" "^1.2.3" - deep-is "^0.1.3" - fast-levenshtein "^2.0.6" - levn "^0.4.1" - prelude-ls "^1.2.1" - type-check "^0.4.0" - ora@^5.4.1: version "5.4.1" resolved "https://registry.npmjs.org/ora/-/ora-5.4.1.tgz" @@ -10849,18 +10245,6 @@ postcss@^8.4.39: picocolors "^1.0.1" source-map-js "^1.2.0" -prelude-ls@^1.2.1: - version "1.2.1" - resolved "https://registry.npmjs.org/prelude-ls/-/prelude-ls-1.2.1.tgz" - integrity sha512-vkcDPrRZo1QZLbn5RLGPpg/WmIQ65qoWWhcGKf/b5eplkkarX0m9z8ppCat4mlOqUsWpyNuYgO3VRyrYHSzX5g== - -prettier-linter-helpers@^1.0.0: - version "1.0.0" - resolved "https://registry.npmjs.org/prettier-linter-helpers/-/prettier-linter-helpers-1.0.0.tgz" - integrity sha512-GbK2cP9nraSSUF9N2XwUwqfzlAFlMNYYl+ShE/V+H8a9uNl/oUqB1w2EL54Jh0OlyRSd8RfWYJ3coVS4TROP2w== - dependencies: - fast-diff "^1.1.2" - prettier@^3.2.5: version "3.2.5" resolved "https://registry.yarnpkg.com/prettier/-/prettier-3.2.5.tgz#e52bc3090586e824964a8813b09aba6233b28368" @@ -11315,11 +10699,6 @@ regexp.prototype.flags@^1.5.1: define-properties "^1.2.0" set-function-name "^2.0.0" -regexpp@^3.0.0: - version "3.1.0" - resolved "https://registry.npmjs.org/regexpp/-/regexpp-3.1.0.tgz" - integrity sha512-ZOIzd8yVsQQA7j8GCSlPGXwg5PfmA1mrq0JP4nGhh54LaKN3xdai/vHUDu74pKwV8OxseMS65u2NImosQcSD0Q== - require-directory@^2.1.1: version "2.1.1" resolved "https://registry.yarnpkg.com/require-directory/-/require-directory-2.1.1.tgz#8c64ad5fd30dab1c976e2344ffe7f792a6a6df42" @@ -11357,12 +10736,7 @@ resolve-from@^4.0.0: resolved "https://registry.yarnpkg.com/resolve-from/-/resolve-from-4.0.0.tgz#4abcd852ad32dd7baabfe9b40e00a36db5f392e6" integrity sha512-pb/MYmXstAkysRFx8piNI1tGFNQIFA3vkE3Gq4EuA1dF6gHp/+vgZqsCGJapvy8N3Q+4o7FwvquPJcnZ7RYy4g== -resolve-pkg-maps@^1.0.0: - version "1.0.0" - resolved "https://registry.yarnpkg.com/resolve-pkg-maps/-/resolve-pkg-maps-1.0.0.tgz#616b3dc2c57056b5588c31cdf4b3d64db133720f" - integrity sha512-seS2Tj26TBVOC2NIc2rOe2y2ZO7efxITtLZcGSOnHHNOQ7CkiUBfw0Iw2ck6xkIhPwLhKNLS8BO+hEpngQlqzw== - -resolve@^1.10.0, resolve@^1.10.1, resolve@^1.17.0, resolve@^1.22.4, resolve@~1.22.1: +resolve@^1.10.0, resolve@^1.17.0, resolve@~1.22.1: version "1.22.8" resolved "https://registry.yarnpkg.com/resolve/-/resolve-1.22.8.tgz#b6c87a9f2aa06dfab52e3d70ac8cde321fa5a48d" integrity sha512-oKWePCxqpd6FlLvGV1VU0x7bkPmmCNolxzjMf4NczoDnQcIWrAF+cPtZn5i6n+RfD2d9i0tzpKnG6Yk168yIyw== @@ -11669,7 +11043,7 @@ semver@7.5.3: dependencies: lru-cache "^6.0.0" -semver@^6.1.0, semver@^6.2.0, semver@^6.3.1: +semver@^6.1.0, semver@^6.2.0: version "6.3.1" resolved "https://registry.yarnpkg.com/semver/-/semver-6.3.1.tgz#556d2ef8689146e46dcea4bfdd095f3434dffcb4" integrity sha512-BR7VvDCVHO+q2xBEWskxS6DJE1qRnb7DxzUrogb71CWoSficBxYsiAGd+Kl0mmq/MprG9yArRkyrQxTO6XjMzA== @@ -12277,7 +11651,7 @@ strip-indent@^3.0.0: dependencies: min-indent "^1.0.0" -strip-json-comments@3.1.1, strip-json-comments@^3.1.1, strip-json-comments@~3.1.1: +strip-json-comments@3.1.1, strip-json-comments@~3.1.1: version "3.1.1" resolved "https://registry.npmjs.org/strip-json-comments/-/strip-json-comments-3.1.1.tgz" integrity sha512-6fPc+R4ihwqP6N/aIv2f1gMH8lOVtWQHoqC4yK6oSDVVocumAsfCqjkXnqiYMhmMwS/mEHLp7Vehlt3ql6lEig== @@ -12358,25 +11732,12 @@ symbol-tree@^3.2.4: resolved "https://registry.yarnpkg.com/symbol-tree/-/symbol-tree-3.2.4.tgz#430637d248ba77e078883951fb9aa0eed7c63fa2" integrity sha512-9QNk5KwDF+Bvz+PyObkmSYjI5ksVUYtjW7AU22r2NKcfLJcXp96hkDWU3+XndOsUb+AQ9QhfzfCT2O+CNWT5Tw== -synckit@^0.8.6: - version "0.8.8" - resolved "https://registry.yarnpkg.com/synckit/-/synckit-0.8.8.tgz#fe7fe446518e3d3d49f5e429f443cf08b6edfcd7" - integrity sha512-HwOKAP7Wc5aRGYdKH+dw0PRRpbO841v2DENBtjnR5HFWoiNByAl7vrx3p0G/rCyYXQsrxqtX48TImFtPcIHSpQ== - dependencies: - "@pkgr/core" "^0.1.0" - tslib "^2.6.2" - systeminformation@^5.22.9: version "5.22.9" resolved "https://registry.yarnpkg.com/systeminformation/-/systeminformation-5.22.9.tgz#68700a895a48cbf96e2cd6a34c5027d1fe58f053" integrity sha512-qUWJhQ9JSBhdjzNUQywpvc0icxUAjMY3sZqUoS0GOtaJV9Ijq8s9zEP8Gaqmymn1dOefcICyPXK1L3kgKxlUpg== -tapable@^2.2.0: - version "2.2.1" - resolved "https://registry.yarnpkg.com/tapable/-/tapable-2.2.1.tgz#1967a73ef4060a82f12ab96af86d52fdb76eeca0" - integrity sha512-GNzQvQTOIP6RyTfE2Qxb8ZVlNmw0n88vp1szwWRimP02mnTsx3Wtn5qRdqY9w2XduFNUgvOwhNnQsjwCp+kqaQ== - -tar-fs@^3.0.4, tar-fs@^3.0.5, tar-fs@^3.0.6: +tar-fs@^3.0.4, tar-fs@^3.0.6: version "3.0.6" resolved "https://registry.yarnpkg.com/tar-fs/-/tar-fs-3.0.6.tgz#eaccd3a67d5672f09ca8e8f9c3d2b89fa173f217" integrity sha512-iokBDQQkUyeXhgPYaZxmczGPhnhXZ0CmrqI+MOb/WFGS9DW5wnfrLgtjUJBvz50vQ3qfRwJ62QVoCFu8mPVu5w== @@ -12387,6 +11748,17 @@ tar-fs@^3.0.4, tar-fs@^3.0.5, tar-fs@^3.0.6: bare-fs "^2.1.1" bare-path "^2.1.0" +tar-fs@^3.0.5: + version "3.0.5" + resolved "https://registry.yarnpkg.com/tar-fs/-/tar-fs-3.0.5.tgz#f954d77767e4e6edf973384e1eb95f8f81d64ed9" + integrity sha512-JOgGAmZyMgbqpLwct7ZV8VzkEB6pxXFBVErLtb+XCOqzc6w1xiWKI9GVd6bwk68EX7eJ4DWmfXVmq8K2ziZTGg== + dependencies: + pump "^3.0.0" + tar-stream "^3.1.5" + optionalDependencies: + bare-fs "^2.1.1" + bare-path "^2.1.0" + tar-fs@~2.0.1: version "2.0.1" resolved "https://registry.yarnpkg.com/tar-fs/-/tar-fs-2.0.1.tgz#e44086c1c60d31a4f0cf893b1c4e155dabfae9e2" @@ -12492,11 +11864,6 @@ text-hex@1.0.x: resolved "https://registry.npmjs.org/text-hex/-/text-hex-1.0.0.tgz" integrity sha512-uuVGNWzgJ4yhRaNSiubPY7OjISw4sw4E5Uv0wbjp+OzcbmVU/rsT8ujgcXJhn9ypzsgr5vlzpPqP+MBBKcGvbg== -text-table@^0.2.0: - version "0.2.0" - resolved "https://registry.npmjs.org/text-table/-/text-table-0.2.0.tgz" - integrity sha1-f17oI66AUgfACvLfSoTsP8+lcLQ= - thread-stream@^2.6.0: version "2.7.0" resolved "https://registry.yarnpkg.com/thread-stream/-/thread-stream-2.7.0.tgz#d8a8e1b3fd538a6cca8ce69dbe5d3d097b601e11" @@ -12648,16 +12015,6 @@ triple-beam@^1.3.0: resolved "https://registry.npmjs.org/triple-beam/-/triple-beam-1.3.0.tgz" integrity sha512-XrHUvV5HpdLmIj4uVMxHggLbFSZYIn7HEWsqePZcI50pco+MPqJ50wMGY794X7AOOhxOBAjbkqfAbEe/QMp2Lw== -ts-api-utils@^1.0.1: - version "1.0.1" - resolved "https://registry.yarnpkg.com/ts-api-utils/-/ts-api-utils-1.0.1.tgz#8144e811d44c749cd65b2da305a032510774452d" - integrity sha512-lC/RGlPmwdrIBFTX59wwNzqh7aR2otPNPR/5brHZm/XKFYKsfqxihXUe9pU3JI+3vGkl+vyCoNNnPhJn3aLK1A== - -ts-api-utils@^1.3.0: - version "1.3.0" - resolved "https://registry.yarnpkg.com/ts-api-utils/-/ts-api-utils-1.3.0.tgz#4b490e27129f1e8e686b45cc4ab63714dc60eea1" - integrity sha512-UQMIo7pb8WRomKR1/+MFVLTroIvDVtMX3K6OUir8ynLyzB8Jeriont2bTAtmNPa1ekAgN7YPDyf6V+ygrdU+eQ== - ts-node@^10.8.1: version "10.9.1" resolved "https://registry.yarnpkg.com/ts-node/-/ts-node-10.9.1.tgz#e73de9102958af9e1f0b168a6ff320e25adcff4b" @@ -12696,16 +12053,6 @@ ts-node@^10.9.2: v8-compile-cache-lib "^3.0.1" yn "3.1.1" -tsconfig-paths@^3.15.0: - version "3.15.0" - resolved "https://registry.yarnpkg.com/tsconfig-paths/-/tsconfig-paths-3.15.0.tgz#5299ec605e55b1abb23ec939ef15edaf483070d4" - integrity sha512-2Ac2RgzDe/cn48GvOe3M+o82pEFewD3UPbyoUHHdKasHwJKjds4fLXWf/Ux5kATBKN20oaFGu+jbElp1pos0mg== - dependencies: - "@types/json5" "^0.0.29" - json5 "^1.0.2" - minimist "^1.2.6" - strip-bom "^3.0.0" - tsconfig-paths@^4.1.2: version "4.2.0" resolved "https://registry.yarnpkg.com/tsconfig-paths/-/tsconfig-paths-4.2.0.tgz#ef78e19039133446d244beac0fd6a1632e2d107c" @@ -12735,7 +12082,7 @@ tslib@^1.10.0: resolved "https://registry.npmjs.org/tslib/-/tslib-1.14.1.tgz" integrity sha512-Xni35NKzjgMrwevysHTCArtLDpPvye8zV/0E4EyYn43P7/7qvQwPh9BGkHewbMulVntbigmcT7rdX3BNo9wRJg== -tslib@^2.0.0, tslib@^2.0.1, tslib@^2.1.0, tslib@^2.2.0, tslib@^2.3.0, tslib@^2.4.0, tslib@^2.6.1, tslib@^2.6.2: +tslib@^2.0.0, tslib@^2.0.1, tslib@^2.1.0, tslib@^2.2.0, tslib@^2.3.0, tslib@^2.4.0, tslib@^2.6.1: version "2.6.2" resolved "https://registry.yarnpkg.com/tslib/-/tslib-2.6.2.tgz#703ac29425e7b37cd6fd456e92404d46d1f3e4ae" integrity sha512-AEYxH93jGFPn/a2iVAwW87VuUIkR1FVUKB77NwMF7nBTDkDrrT/Hpt/IrCJ0QXhW27jTBDcf5ZY7w6RiqTMw2Q== @@ -12769,13 +12116,6 @@ tweetnacl@^0.14.3: resolved "https://registry.yarnpkg.com/tweetnacl/-/tweetnacl-0.14.5.tgz#5ae68177f192d4456269d108afa93ff8743f4f64" integrity sha512-KXXFFdAbFXY4geFIwoyNK+f5Z1b7swfXABfL7HXCmoIWMKU3dmS26672A4EeQtDzLKy7SXmfBu51JolvEKwtGA== -type-check@^0.4.0, type-check@~0.4.0: - version "0.4.0" - resolved "https://registry.npmjs.org/type-check/-/type-check-0.4.0.tgz" - integrity sha512-XleUoc9uwGXqjWwXaUTZAmzMcFZ5858QA2vvx1Ur5xIcixXIP+8LnFDgRplU30us6teqdlskFfu+ae4K79Ooew== - dependencies: - prelude-ls "^1.2.1" - type-fest@2.13.0: version "2.13.0" resolved "https://registry.yarnpkg.com/type-fest/-/type-fest-2.13.0.tgz#d1ecee38af29eb2e863b22299a3d68ef30d2abfb" @@ -12791,11 +12131,6 @@ type-fest@^0.18.0: resolved "https://registry.yarnpkg.com/type-fest/-/type-fest-0.18.1.tgz#db4bc151a4a2cf4eebf9add5db75508db6cc841f" integrity sha512-OIAYXk8+ISY+qTOwkHtKqzAuxchoMiD9Udx+FSGQDuiRR+PJKJHc2NJAXlbhkGwTt/4/nKZxELY1w3ReWOL8mw== -type-fest@^0.20.2: - version "0.20.2" - resolved "https://registry.yarnpkg.com/type-fest/-/type-fest-0.20.2.tgz#1bf207f4b28f91583666cb5fbd327887301cd5f4" - integrity sha512-Ne+eE4r0/iWnpAxD852z3A+N0Bt5RN//NjJwRd2VFHEmrywxf5vsZlh4R6lixl6B+wz/8d+maTSAkN1FIkI3LQ== - type-fest@^0.21.3: version "0.21.3" resolved "https://registry.yarnpkg.com/type-fest/-/type-fest-0.21.3.tgz#d260a24b0198436e133fa26a524a6d65fa3b2e37" @@ -12948,6 +12283,11 @@ undici-types@~5.26.4: resolved "https://registry.yarnpkg.com/undici-types/-/undici-types-5.26.5.tgz#bcd539893d00b56e964fd2657a4866b221a65617" integrity sha512-JlCMO+ehdEIKqlFxk6IfVoAUVmgz7cU7zD/h9XZ0qzeosSHmUJVOzSQvvYSYWXkFXC+IfLKSIffhv0sVZup6pA== +undici-types@~6.19.2: + version "6.19.8" + resolved "https://registry.yarnpkg.com/undici-types/-/undici-types-6.19.8.tgz#35111c9d1437ab83a7cdc0abae2f26d88eda0a02" + integrity sha512-ve2KP6f/JnbPBFyobGHuerC9g1FYGn/F8n1LWTwNxCEzd6IfqTwUQcNXgEtmmQ6DlRrC1hrSrBnCZPokRrDHjw== + undici@^5.12.0: version "5.28.4" resolved "https://registry.yarnpkg.com/undici/-/undici-5.28.4.tgz#6b280408edb6a1a604a9b20340f45b422e373068" From 38f54abed47128667d1b7917a442ffb934ff9c7d Mon Sep 17 00:00:00 2001 From: vladmarusyk <149159095+vladmarusyk@users.noreply.github.com> Date: Thu, 10 Oct 2024 20:09:54 +0300 Subject: [PATCH 43/52] feat: allow filtering of validators by top-level validator status (#7143) * Fix ValidatorStatus type issue * refactor: use switch-case and typed general validator status mapping * Update packages/beacon-node/src/api/impl/beacon/state/utils.ts Co-authored-by: Nico Flaig * refactor: deleted unrelated code * refactor: deleted unrelated code * Update packages/beacon-node/src/api/impl/beacon/state/utils.ts Co-authored-by: Nico Flaig --------- Co-authored-by: Nico Flaig --- .../src/api/impl/beacon/state/utils.ts | 25 ++++++++++++++++++- 1 file changed, 24 insertions(+), 1 deletion(-) diff --git a/packages/beacon-node/src/api/impl/beacon/state/utils.ts b/packages/beacon-node/src/api/impl/beacon/state/utils.ts index 074fa7928d91..15e8bdf73176 100644 --- a/packages/beacon-node/src/api/impl/beacon/state/utils.ts +++ b/packages/beacon-node/src/api/impl/beacon/state/utils.ts @@ -83,6 +83,28 @@ export async function getStateResponseWithRegen( return res; } +type GeneralValidatorStatus = "active" | "pending" | "exited" | "withdrawal"; + +function mapToGeneralStatus(subStatus: routes.beacon.ValidatorStatus): GeneralValidatorStatus { + switch (subStatus) { + case "active_ongoing": + case "active_exiting": + case "active_slashed": + return "active"; + case "pending_initialized": + case "pending_queued": + return "pending"; + case "exited_slashed": + case "exited_unslashed": + return "exited"; + case "withdrawal_possible": + case "withdrawal_done": + return "withdrawal"; + default: + throw new Error(`Unknown substatus: ${subStatus}`); + } +} + export function toValidatorResponse( index: ValidatorIndex, validator: phase0.Validator, @@ -109,9 +131,10 @@ export function filterStateValidatorsByStatus( for (const validator of validatorsArr) { const validatorStatus = getValidatorStatus(validator, currentEpoch); + const generalStatus = mapToGeneralStatus(validatorStatus); const resp = getStateValidatorIndex(validator.pubkey, state, pubkey2index); - if (resp.valid && statusSet.has(validatorStatus)) { + if (resp.valid && (statusSet.has(validatorStatus) || statusSet.has(generalStatus))) { responses.push( toValidatorResponse(resp.validatorIndex, validator, state.balances.get(resp.validatorIndex), currentEpoch) ); From 0d87c28aedb2e0556b027fc0714349542ff17542 Mon Sep 17 00:00:00 2001 From: Nico Flaig Date: Thu, 10 Oct 2024 19:39:30 +0100 Subject: [PATCH 44/52] chore: remove 'active' from validator status type (#7146) * chore: remove 'active' from validator status type * Clean up usage --- packages/beacon-node/src/api/impl/validator/index.ts | 1 - packages/types/src/utils/validatorStatus.ts | 4 +++- packages/validator/src/services/indices.ts | 1 - .../validator/test/unit/services/attestationDuties.test.ts | 2 +- .../validator/test/unit/services/syncCommitteDuties.test.ts | 2 +- 5 files changed, 5 insertions(+), 5 deletions(-) diff --git a/packages/beacon-node/src/api/impl/validator/index.ts b/packages/beacon-node/src/api/impl/validator/index.ts index f6cbc4e98e98..8629bbb1f47c 100644 --- a/packages/beacon-node/src/api/impl/validator/index.ts +++ b/packages/beacon-node/src/api/impl/validator/index.ts @@ -1363,7 +1363,6 @@ export function getValidatorApi( const validator = headState.validators.getReadonly(validatorIndex); const status = getValidatorStatus(validator, currentEpoch); return ( - status === "active" || status === "active_exiting" || status === "active_ongoing" || status === "active_slashed" || diff --git a/packages/types/src/utils/validatorStatus.ts b/packages/types/src/utils/validatorStatus.ts index e14a4b14c412..aa8171fbbbd2 100644 --- a/packages/types/src/utils/validatorStatus.ts +++ b/packages/types/src/utils/validatorStatus.ts @@ -1,8 +1,10 @@ import {FAR_FUTURE_EPOCH} from "@lodestar/params"; import {Epoch, phase0} from "../types.js"; +/** + * [Validator status specification](https://hackmd.io/ofFJ5gOmQpu1jjHilHbdQQ) + */ export type ValidatorStatus = - | "active" | "pending_initialized" | "pending_queued" | "active_ongoing" diff --git a/packages/validator/src/services/indices.ts b/packages/validator/src/services/indices.ts index c3f511669bf1..ff8d1d46ab26 100644 --- a/packages/validator/src/services/indices.ts +++ b/packages/validator/src/services/indices.ts @@ -20,7 +20,6 @@ type SimpleValidatorStatus = "pending" | "active" | "exited" | "withdrawn"; const statusToSimpleStatusMapping = (status: routes.beacon.ValidatorStatus): SimpleValidatorStatus => { switch (status) { - case "active": case "active_exiting": case "active_slashed": case "active_ongoing": diff --git a/packages/validator/test/unit/services/attestationDuties.test.ts b/packages/validator/test/unit/services/attestationDuties.test.ts index a9d50eaf42c6..f59b00d88c9c 100644 --- a/packages/validator/test/unit/services/attestationDuties.test.ts +++ b/packages/validator/test/unit/services/attestationDuties.test.ts @@ -33,7 +33,7 @@ describe("AttestationDutiesService", function () { const defaultValidator: routes.beacon.ValidatorResponse = { index, balance: 32e9, - status: "active", + status: "active_ongoing", validator: ssz.phase0.Validator.defaultValue(), }; diff --git a/packages/validator/test/unit/services/syncCommitteDuties.test.ts b/packages/validator/test/unit/services/syncCommitteDuties.test.ts index 87d052b14ae5..d94926e9b564 100644 --- a/packages/validator/test/unit/services/syncCommitteDuties.test.ts +++ b/packages/validator/test/unit/services/syncCommitteDuties.test.ts @@ -36,7 +36,7 @@ describe("SyncCommitteeDutiesService", function () { const defaultValidator: routes.beacon.ValidatorResponse = { index: indices[0], balance: 32e9, - status: "active", + status: "active_ongoing", validator: ssz.phase0.Validator.defaultValue(), }; From a570048187f1e729c0be3939239fcfa3aa0a008e Mon Sep 17 00:00:00 2001 From: twoeths Date: Fri, 11 Oct 2024 09:37:29 +0700 Subject: [PATCH 45/52] fix: improve forkchoice (#7142) * fix: reuse deltas in computeDeltas * fix: remodel queuedAttestations * fix: call forkchoice.updateTime() once per clock slot * fix: recomputeForkChoiceHead() at slot boundary * fix: improve computeDeltas() - handle newBalances = oldBalances * fix: do not compute forkchoice head at slot boundary * fix: prepareNextSlot unit test --- .../src/api/impl/validator/index.ts | 12 ----- .../src/chain/blocks/importBlock.ts | 3 +- packages/beacon-node/src/chain/chain.ts | 12 ++--- .../beacon-node/src/chain/forkChoice/index.ts | 5 ++ packages/beacon-node/src/chain/interface.ts | 3 +- .../beacon-node/src/chain/prepareNextSlot.ts | 5 +- .../beacon-node/src/metrics/metrics/beacon.ts | 4 +- .../test/unit/chain/prepareNextSlot.test.ts | 2 +- .../fork-choice/src/forkChoice/forkChoice.ts | 51 ++++++++++++------- .../fork-choice/src/forkChoice/interface.ts | 11 ---- .../src/protoArray/computeDeltas.ts | 11 ++-- 11 files changed, 61 insertions(+), 58 deletions(-) diff --git a/packages/beacon-node/src/api/impl/validator/index.ts b/packages/beacon-node/src/api/impl/validator/index.ts index 8629bbb1f47c..e1ea415443b9 100644 --- a/packages/beacon-node/src/api/impl/validator/index.ts +++ b/packages/beacon-node/src/api/impl/validator/index.ts @@ -389,10 +389,6 @@ export function getValidatorApi( notWhileSyncing(); await waitForSlot(slot); // Must never request for a future slot > currentSlot - // Process the queued attestations in the forkchoice for correct head estimation - // forkChoice.updateTime() might have already been called by the onSlot clock - // handler, in which case this should just return. - chain.forkChoice.updateTime(slot); parentBlockRoot = fromHex(chain.getProposerHead(slot).blockRoot); } else { parentBlockRoot = inParentBlockRoot; @@ -459,10 +455,6 @@ export function getValidatorApi( notWhileSyncing(); await waitForSlot(slot); // Must never request for a future slot > currentSlot - // Process the queued attestations in the forkchoice for correct head estimation - // forkChoice.updateTime() might have already been called by the onSlot clock - // handler, in which case this should just return. - chain.forkChoice.updateTime(slot); parentBlockRoot = fromHex(chain.getProposerHead(slot).blockRoot); } else { parentBlockRoot = inParentBlockRoot; @@ -535,10 +527,6 @@ export function getValidatorApi( notWhileSyncing(); await waitForSlot(slot); // Must never request for a future slot > currentSlot - // Process the queued attestations in the forkchoice for correct head estimation - // forkChoice.updateTime() might have already been called by the onSlot clock - // handler, in which case this should just return. - chain.forkChoice.updateTime(slot); const parentBlockRoot = fromHex(chain.getProposerHead(slot).blockRoot); notOnOutOfRangeData(parentBlockRoot); diff --git a/packages/beacon-node/src/chain/blocks/importBlock.ts b/packages/beacon-node/src/chain/blocks/importBlock.ts index d19d6a60c564..596f01f391a4 100644 --- a/packages/beacon-node/src/chain/blocks/importBlock.ts +++ b/packages/beacon-node/src/chain/blocks/importBlock.ts @@ -19,6 +19,7 @@ import {ChainEvent, ReorgEventData} from "../emitter.js"; import {REPROCESS_MIN_TIME_TO_NEXT_SLOT_SEC} from "../reprocess.js"; import type {BeaconChain} from "../chain.js"; import {callInNextEventLoop} from "../../util/eventLoop.js"; +import {ForkchoiceCaller} from "../forkChoice/index.js"; import {FullyVerifiedBlock, ImportBlockOpts, AttestationImportOpt, BlockInputType} from "./types.js"; import {getCheckpointFromState} from "./utils/checkpoint.js"; import {writeBlockInputToDb} from "./writeBlockInputToDb.js"; @@ -208,7 +209,7 @@ export async function importBlock( // 5. Compute head. If new head, immediately stateCache.setHeadState() const oldHead = this.forkChoice.getHead(); - const newHead = this.recomputeForkChoiceHead(); + const newHead = this.recomputeForkChoiceHead(ForkchoiceCaller.importBlock); const currFinalizedEpoch = this.forkChoice.getFinalizedCheckpoint().epoch; if (newHead.blockRoot !== oldHead.blockRoot) { diff --git a/packages/beacon-node/src/chain/chain.ts b/packages/beacon-node/src/chain/chain.ts index 371f660abe2e..4bd8cd2bea3d 100644 --- a/packages/beacon-node/src/chain/chain.ts +++ b/packages/beacon-node/src/chain/chain.ts @@ -60,7 +60,7 @@ import { } from "./interface.js"; import {IChainOptions} from "./options.js"; import {QueuedStateRegenerator, RegenCaller} from "./regen/index.js"; -import {initializeForkChoice} from "./forkChoice/index.js"; +import {ForkchoiceCaller, initializeForkChoice} from "./forkChoice/index.js"; import {IBlsVerifier, BlsSingleThreadVerifier, BlsMultiThreadWorkerPool} from "./bls/index.js"; import { SeenAttesters, @@ -784,9 +784,9 @@ export class BeaconChain implements IBeaconChain { }; } - recomputeForkChoiceHead(): ProtoBlock { + recomputeForkChoiceHead(caller: ForkchoiceCaller): ProtoBlock { this.metrics?.forkChoice.requests.inc(); - const timer = this.metrics?.forkChoice.findHead.startTimer({entrypoint: FindHeadFnName.recomputeForkChoiceHead}); + const timer = this.metrics?.forkChoice.findHead.startTimer({caller}); try { return this.forkChoice.updateAndGetHead({mode: UpdateHeadOpt.GetCanonicialHead}).head; @@ -800,7 +800,7 @@ export class BeaconChain implements IBeaconChain { predictProposerHead(slot: Slot): ProtoBlock { this.metrics?.forkChoice.requests.inc(); - const timer = this.metrics?.forkChoice.findHead.startTimer({entrypoint: FindHeadFnName.predictProposerHead}); + const timer = this.metrics?.forkChoice.findHead.startTimer({caller: FindHeadFnName.predictProposerHead}); try { return this.forkChoice.updateAndGetHead({mode: UpdateHeadOpt.GetPredictedProposerHead, slot}).head; @@ -814,7 +814,7 @@ export class BeaconChain implements IBeaconChain { getProposerHead(slot: Slot): ProtoBlock { this.metrics?.forkChoice.requests.inc(); - const timer = this.metrics?.forkChoice.findHead.startTimer({entrypoint: FindHeadFnName.getProposerHead}); + const timer = this.metrics?.forkChoice.findHead.startTimer({caller: FindHeadFnName.getProposerHead}); const secFromSlot = this.clock.secFromSlot(slot); try { @@ -1060,8 +1060,8 @@ export class BeaconChain implements IBeaconChain { if (this.forkChoice.irrecoverableError) { this.processShutdownCallback(this.forkChoice.irrecoverableError); } - this.forkChoice.updateTime(slot); + this.forkChoice.updateTime(slot); this.metrics?.clockSlot.set(slot); this.attestationPool.prune(slot); diff --git a/packages/beacon-node/src/chain/forkChoice/index.ts b/packages/beacon-node/src/chain/forkChoice/index.ts index 346a4afe1e7f..839975de4e26 100644 --- a/packages/beacon-node/src/chain/forkChoice/index.ts +++ b/packages/beacon-node/src/chain/forkChoice/index.ts @@ -27,6 +27,11 @@ export type ForkChoiceOpts = RawForkChoiceOpts & { forkchoiceConstructor?: typeof ForkChoice; }; +export enum ForkchoiceCaller { + prepareNextSlot = "prepare_next_slot", + importBlock = "import_block", +} + /** * Fork Choice extended with a ChainEventEmitter */ diff --git a/packages/beacon-node/src/chain/interface.ts b/packages/beacon-node/src/chain/interface.ts index 531f60dc0e63..3b44ffd594ae 100644 --- a/packages/beacon-node/src/chain/interface.ts +++ b/packages/beacon-node/src/chain/interface.ts @@ -58,6 +58,7 @@ import {ShufflingCache} from "./shufflingCache.js"; import {BlockRewards} from "./rewards/blockRewards.js"; import {AttestationsRewards} from "./rewards/attestationsRewards.js"; import {SyncCommitteeRewards} from "./rewards/syncCommitteeRewards.js"; +import {ForkchoiceCaller} from "./forkChoice/index.js"; export {BlockType, type AssembledBlockType}; export {type ProposerPreparationData}; @@ -204,7 +205,7 @@ export interface IBeaconChain { getStatus(): phase0.Status; - recomputeForkChoiceHead(): ProtoBlock; + recomputeForkChoiceHead(caller: ForkchoiceCaller): ProtoBlock; /** When proposerBoostReorg is enabled, this is called at slot n-1 to predict the head block to build on if we are proposing at slot n */ predictProposerHead(slot: Slot): ProtoBlock; diff --git a/packages/beacon-node/src/chain/prepareNextSlot.ts b/packages/beacon-node/src/chain/prepareNextSlot.ts index 48724ab25b0b..bda618758842 100644 --- a/packages/beacon-node/src/chain/prepareNextSlot.ts +++ b/packages/beacon-node/src/chain/prepareNextSlot.ts @@ -18,6 +18,7 @@ import {isQueueErrorAborted} from "../util/queue/index.js"; import {prepareExecutionPayload, getPayloadAttributesForSSE} from "./produceBlock/produceBlockBody.js"; import {IBeaconChain} from "./interface.js"; import {RegenCaller} from "./regen/index.js"; +import {ForkchoiceCaller} from "./forkChoice/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; @@ -77,7 +78,9 @@ export class PrepareNextSlotScheduler { await sleep(slotMs - slotMs / SCHEDULER_LOOKAHEAD_FACTOR, this.signal); // calling updateHead() here before we produce a block to reduce reorg possibility - const {slot: headSlot, blockRoot: headRoot} = this.chain.recomputeForkChoiceHead(); + const {slot: headSlot, blockRoot: headRoot} = this.chain.recomputeForkChoiceHead( + ForkchoiceCaller.prepareNextSlot + ); // PS: previously this was comparing slots, but that gave no leway on the skipped // slots on epoch bounday. Making it more fluid. diff --git a/packages/beacon-node/src/metrics/metrics/beacon.ts b/packages/beacon-node/src/metrics/metrics/beacon.ts index 6e86328ee561..1737a5a2468f 100644 --- a/packages/beacon-node/src/metrics/metrics/beacon.ts +++ b/packages/beacon-node/src/metrics/metrics/beacon.ts @@ -58,11 +58,11 @@ export function createBeaconMetrics(register: RegistryMetricCreator) { // Non-spec'ed forkChoice: { - findHead: register.histogram<{entrypoint: string}>({ + findHead: register.histogram<{caller: string}>({ name: "beacon_fork_choice_find_head_seconds", help: "Time taken to find head in seconds", buckets: [0.1, 1, 10], - labelNames: ["entrypoint"], + labelNames: ["caller"], }), requests: register.gauge({ name: "beacon_fork_choice_requests_total", diff --git a/packages/beacon-node/test/unit/chain/prepareNextSlot.test.ts b/packages/beacon-node/test/unit/chain/prepareNextSlot.test.ts index 9ce121e976d0..c7d0a7801fec 100644 --- a/packages/beacon-node/test/unit/chain/prepareNextSlot.test.ts +++ b/packages/beacon-node/test/unit/chain/prepareNextSlot.test.ts @@ -98,7 +98,7 @@ describe("PrepareNextSlot scheduler", () => { scheduler.prepareForNextSlot(2 * SLOTS_PER_EPOCH - 1), vi.advanceTimersByTimeAsync((config.SECONDS_PER_SLOT * 1000 * 2) / 3), ]); - expect(chainStub.recomputeForkChoiceHead).toHaveBeenCalledWith(); + expect(chainStub.recomputeForkChoiceHead).toHaveBeenCalledOnce(); expect(regenStub.getBlockSlotState).not.toHaveBeenCalled(); }); diff --git a/packages/fork-choice/src/forkChoice/forkChoice.ts b/packages/fork-choice/src/forkChoice/forkChoice.ts index 828a16725444..6ca3fd3a183a 100644 --- a/packages/fork-choice/src/forkChoice/forkChoice.ts +++ b/packages/fork-choice/src/forkChoice/forkChoice.ts @@ -1,4 +1,4 @@ -import {Logger, fromHex, toRootHex} from "@lodestar/utils"; +import {Logger, MapDef, fromHex, toRootHex} from "@lodestar/utils"; import {SLOTS_PER_HISTORICAL_ROOT, SLOTS_PER_EPOCH, INTERVALS_PER_SLOT} from "@lodestar/params"; import {bellatrix, Slot, ValidatorIndex, phase0, ssz, RootHex, Epoch, Root, BeaconBlock} from "@lodestar/types"; import { @@ -34,7 +34,6 @@ import {ForkChoiceError, ForkChoiceErrorCode, InvalidBlockCode, InvalidAttestati import { IForkChoice, LatestMessage, - QueuedAttestation, PowBlockHex, EpochDifference, AncestorResult, @@ -91,7 +90,9 @@ export class ForkChoice implements IForkChoice { * Attestations that arrived at the current slot and must be queued for later processing. * NOT currently tracked in the protoArray */ - private readonly queuedAttestations = new Set(); + private readonly queuedAttestations: MapDef>> = new MapDef( + () => new MapDef(() => new Set()) + ); // Note: as of Jun 2022 Lodestar metrics show that 100% of the times updateHead() is called, synced = false. // Because we are processing attestations from gossip, recomputing scores is always necessary @@ -128,9 +129,13 @@ export class ForkChoice implements IForkChoice { } getMetrics(): ForkChoiceMetrics { + let numAttestations = 0; + for (const indicesByRoot of this.queuedAttestations.values()) { + numAttestations += Array.from(indicesByRoot.values()).reduce((acc, indices) => acc + indices.size, 0); + } return { votes: this.votes.length, - queuedAttestations: this.queuedAttestations.size, + queuedAttestations: numAttestations, validatedAttestationDatas: this.validatedAttestationDatas.size, balancesLength: this.balances.length, nodes: this.protoArray.nodes.length, @@ -716,12 +721,13 @@ export class ForkChoice implements IForkChoice { // Attestations can only affect the fork choice of subsequent slots. // Delay consideration in the fork choice until their slot is in the past. // ``` - this.queuedAttestations.add({ - slot: slot, - attestingIndices: attestation.attestingIndices, - blockRoot: blockRootHex, - targetEpoch, - }); + const byRoot = this.queuedAttestations.getOrDefault(slot); + const validatorIndices = byRoot.getOrDefault(blockRootHex); + for (const validatorIndex of attestation.attestingIndices) { + if (!this.fcStore.equivocatingIndices.has(validatorIndex)) { + validatorIndices.add(validatorIndex); + } + } } } @@ -751,6 +757,11 @@ export class ForkChoice implements IForkChoice { /** * Call `onTick` for all slots between `fcStore.getCurrentSlot()` and the provided `currentSlot`. + * This should only be called once per slot because: + * - calling this multiple times in the same slot does not update `votes` + * - new attestations in the current slot must stay in the queue + * - new attestations in the old slots are applied to the `votes` already + * - also side effect of this function is `validatedAttestationDatas` reseted */ updateTime(currentSlot: Slot): void { if (this.fcStore.currentSlot >= currentSlot) return; @@ -1352,15 +1363,19 @@ export class ForkChoice implements IForkChoice { */ private processAttestationQueue(): void { const currentSlot = this.fcStore.currentSlot; - for (const attestation of this.queuedAttestations.values()) { - // Delay consideration in the fork choice until their slot is in the past. - if (attestation.slot < currentSlot) { - this.queuedAttestations.delete(attestation); - const {blockRoot, targetEpoch} = attestation; - const blockRootHex = blockRoot; - for (const validatorIndex of attestation.attestingIndices) { - this.addLatestMessage(validatorIndex, targetEpoch, blockRootHex); + for (const [slot, byRoot] of this.queuedAttestations.entries()) { + const targetEpoch = computeEpochAtSlot(slot); + if (slot < currentSlot) { + this.queuedAttestations.delete(slot); + for (const [blockRoot, validatorIndices] of byRoot.entries()) { + const blockRootHex = blockRoot; + for (const validatorIndex of validatorIndices) { + // equivocatingIndices was checked in onAttestation + this.addLatestMessage(validatorIndex, targetEpoch, blockRootHex); + } } + } else { + break; } } } diff --git a/packages/fork-choice/src/forkChoice/interface.ts b/packages/fork-choice/src/forkChoice/interface.ts index 0b6d56a88bf2..9ac8cdfac81b 100644 --- a/packages/fork-choice/src/forkChoice/interface.ts +++ b/packages/fork-choice/src/forkChoice/interface.ts @@ -250,14 +250,3 @@ export type LatestMessage = { epoch: Epoch; root: RootHex; }; - -/** - * Used for queuing attestations from the current slot. Only contains the minimum necessary - * information about the attestation. - */ -export type QueuedAttestation = { - slot: Slot; - attestingIndices: ValidatorIndex[]; - blockRoot: RootHex; - targetEpoch: Epoch; -}; diff --git a/packages/fork-choice/src/protoArray/computeDeltas.ts b/packages/fork-choice/src/protoArray/computeDeltas.ts index 8301c1e77a75..2b87deb098da 100644 --- a/packages/fork-choice/src/protoArray/computeDeltas.ts +++ b/packages/fork-choice/src/protoArray/computeDeltas.ts @@ -3,6 +3,9 @@ import {EffectiveBalanceIncrements} from "@lodestar/state-transition"; import {VoteTracker} from "./interface.js"; import {ProtoArrayError, ProtoArrayErrorCode} from "./errors.js"; +// reuse arrays to avoid memory reallocation and gc +const deltas = new Array(); + /** * Returns a list of `deltas`, where there is one delta for each of the indices in `indices` * @@ -19,10 +22,8 @@ export function computeDeltas( newBalances: EffectiveBalanceIncrements, equivocatingIndices: Set ): number[] { - const deltas = new Array(numProtoNodes); - for (let i = 0; i < numProtoNodes; i++) { - deltas[i] = 0; - } + deltas.length = numProtoNodes; + deltas.fill(0); // avoid creating new variables in the loop to potentially reduce GC pressure let oldBalance, newBalance: number; @@ -47,7 +48,7 @@ export function computeDeltas( // It is possible that there was a vote for an unknown validator if we change our justified // state to a new state with a higher epoch that is on a different fork because that fork may have // on-boarded fewer validators than the prior fork. - newBalance = newBalances[vIndex] ?? 0; + newBalance = newBalances === oldBalances ? oldBalance : newBalances[vIndex] ?? 0; if (equivocatingIndices.size > 0 && equivocatingIndices.has(vIndex)) { // this function could be called multiple times but we only want to process slashing validator for 1 time From 4b7d871ab3387e2af99996c4d4ec8268a95cf41b Mon Sep 17 00:00:00 2001 From: Nazar Hussain Date: Fri, 11 Oct 2024 14:34:21 +0200 Subject: [PATCH 46/52] chore: fix lint error (#7152) Fix lint error --- packages/fork-choice/src/protoArray/computeDeltas.ts | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/packages/fork-choice/src/protoArray/computeDeltas.ts b/packages/fork-choice/src/protoArray/computeDeltas.ts index 2b87deb098da..a3366fa738ae 100644 --- a/packages/fork-choice/src/protoArray/computeDeltas.ts +++ b/packages/fork-choice/src/protoArray/computeDeltas.ts @@ -48,7 +48,7 @@ export function computeDeltas( // It is possible that there was a vote for an unknown validator if we change our justified // state to a new state with a higher epoch that is on a different fork because that fork may have // on-boarded fewer validators than the prior fork. - newBalance = newBalances === oldBalances ? oldBalance : newBalances[vIndex] ?? 0; + newBalance = newBalances === oldBalances ? oldBalance : (newBalances[vIndex] ?? 0); if (equivocatingIndices.size > 0 && equivocatingIndices.has(vIndex)) { // this function could be called multiple times but we only want to process slashing validator for 1 time From ac6edd36ee997f8d7a4210337230fbd6a754a8bd Mon Sep 17 00:00:00 2001 From: Nazar Hussain Date: Fri, 11 Oct 2024 15:08:18 +0200 Subject: [PATCH 47/52] chore: add vscode settings to split prettier and biome (#7149) * Add vscode settings to split prettier and biome * Add whitespace * Fix branch name --- .prettierignore | 4 +++- .vscode/extensions.json | 3 ++- lodestar.code-workspace | 12 ++++++++++++ 3 files changed, 17 insertions(+), 2 deletions(-) create mode 100644 lodestar.code-workspace diff --git a/.prettierignore b/.prettierignore index 7871bd5d3ad7..3934e7720067 100644 --- a/.prettierignore +++ b/.prettierignore @@ -2,4 +2,6 @@ **/.nyc_output /packages/*/spec-tests node_modules -**/node_modules \ No newline at end of file +**/node_modules +*.js +*.ts diff --git a/.vscode/extensions.json b/.vscode/extensions.json index de51190cd9f3..d2b074c6eea1 100644 --- a/.vscode/extensions.json +++ b/.vscode/extensions.json @@ -1,5 +1,6 @@ { "recommendations": [ - "biomejs.biome" + "biomejs.biome", + "esbenp.prettier-vscode" ] } diff --git a/lodestar.code-workspace b/lodestar.code-workspace new file mode 100644 index 000000000000..7030ab8d7270 --- /dev/null +++ b/lodestar.code-workspace @@ -0,0 +1,12 @@ +{ + "settings": { + "window.title": "${activeEditorShort}${separator}${rootName}${separator}${profileName}${separator}[${activeRepositoryBranchName}]", + "editor.defaultFormatter": "esbenp.prettier-vscode", + "[javascript]": { + "editor.defaultFormatter": "biomejs.biome" + }, + "[typescript]": { + "editor.defaultFormatter": "biomejs.biome" + }, + } +} From cbc7c9018d7b7de648473c45617f2b6789ebe648 Mon Sep 17 00:00:00 2001 From: Nico Flaig Date: Fri, 11 Oct 2024 16:53:42 +0100 Subject: [PATCH 48/52] feat: support fetching historical proposer duties (#7130) * feat: support fetching historical proposer duties * Clone state before creating cached beacon state * Fix error message * Update test cases * Skip syncing pubkeys and sync committe cache * Update proposers tests epoch * Use switch/case instead of if/else * Add comment to clarify when head state can be used * Use loadState instead of creating a separate ViewDU * Clarify not yet initialized error for prev proposer duties * Assert loaded state epoch matches requested --- .../src/api/impl/validator/index.ts | 74 +++++++++++++---- .../test/mocks/mockedBeaconChain.ts | 4 + .../impl/validator/duties/proposer.test.ts | 79 ++++++++++++++----- .../state-transition/src/cache/epochCache.ts | 4 + 4 files changed, 127 insertions(+), 34 deletions(-) diff --git a/packages/beacon-node/src/api/impl/validator/index.ts b/packages/beacon-node/src/api/impl/validator/index.ts index e1ea415443b9..9c5e6c2987f1 100644 --- a/packages/beacon-node/src/api/impl/validator/index.ts +++ b/packages/beacon-node/src/api/impl/validator/index.ts @@ -1,3 +1,4 @@ +import {PubkeyIndexMap} from "@chainsafe/pubkey-index-map"; import {routes} from "@lodestar/api"; import {ApplicationMethods} from "@lodestar/api/server"; import { @@ -10,6 +11,8 @@ import { computeEpochAtSlot, getCurrentSlot, beaconBlockToBlinded, + createCachedBeaconState, + loadState, } from "@lodestar/state-transition"; import { GENESIS_SLOT, @@ -62,6 +65,7 @@ import {validateSyncCommitteeGossipContributionAndProof} from "../../../chain/va import {CommitteeSubscription} from "../../../network/subnets/index.js"; import {ApiModules} from "../types.js"; import {RegenCaller} from "../../../chain/regen/index.js"; +import {getStateResponseWithRegen} from "../beacon/state/utils.js"; import {validateGossipFnRetryUnknownRoot} from "../../../network/processor/gossipHandlers.js"; import {SCHEDULER_LOOKAHEAD_FACTOR} from "../../../chain/prepareNextSlot.js"; import {ChainEvent, CheckpointHex, CommonBlockBody} from "../../../chain/index.js"; @@ -888,15 +892,16 @@ export function getValidatorApi( async getProposerDuties({epoch}) { notWhileSyncing(); - // Early check that epoch is within [current_epoch, current_epoch + 1], or allow for pre-genesis + // Early check that epoch is no more than current_epoch + 1, or allow for pre-genesis const currentEpoch = currentEpochWithDisparity(); const nextEpoch = currentEpoch + 1; - if (currentEpoch >= 0 && epoch !== currentEpoch && epoch !== nextEpoch) { - throw Error(`Requested epoch ${epoch} must equal current ${currentEpoch} or next epoch ${nextEpoch}`); + if (currentEpoch >= 0 && epoch > nextEpoch) { + throw new ApiError(400, `Requested epoch ${epoch} must not be more than one epoch in the future`); } const head = chain.forkChoice.getHead(); let state: CachedBeaconStateAllForks | undefined = undefined; + const startSlot = computeStartSlotAtEpoch(epoch); const slotMs = config.SECONDS_PER_SLOT * 1000; const prepareNextSlotLookAheadMs = slotMs / SCHEDULER_LOOKAHEAD_FACTOR; const toNextEpochMs = msToNextEpoch(); @@ -914,21 +919,63 @@ export function getValidatorApi( } if (!state) { - state = await chain.getHeadStateAtCurrentEpoch(RegenCaller.getDuties); + if (epoch >= currentEpoch - 1) { + // Cached beacon state stores proposers for previous, current and next epoch. The + // requested epoch is within that range, we can use the head state at current epoch + state = await chain.getHeadStateAtCurrentEpoch(RegenCaller.getDuties); + } else { + const res = await getStateResponseWithRegen(chain, startSlot); + + const stateViewDU = + res.state instanceof Uint8Array + ? loadState(config, chain.getHeadState(), res.state).state + : res.state.clone(); + + state = createCachedBeaconState( + stateViewDU, + { + config: chain.config, + // Not required to compute proposers + pubkey2index: new PubkeyIndexMap(), + index2pubkey: [], + }, + {skipSyncPubkeys: true, skipSyncCommitteeCache: true} + ); + + if (state.epochCtx.epoch !== epoch) { + throw Error(`Loaded state epoch ${state.epochCtx.epoch} does not match requested epoch ${epoch}`); + } + } } const stateEpoch = state.epochCtx.epoch; let indexes: ValidatorIndex[] = []; - if (epoch === stateEpoch) { - indexes = state.epochCtx.getBeaconProposers(); - } else if (epoch === stateEpoch + 1) { - // Requesting duties for next epoch is allow since they can be predicted with high probabilities. - // @see `epochCtx.getBeaconProposersNextEpoch` JSDocs for rationale. - indexes = state.epochCtx.getBeaconProposersNextEpoch(); - } else { - // Should never happen, epoch is checked to be in bounds above - throw Error(`Proposer duties for epoch ${epoch} not supported, current epoch ${stateEpoch}`); + switch (epoch) { + case stateEpoch: + indexes = state.epochCtx.getBeaconProposers(); + break; + + case stateEpoch + 1: + // Requesting duties for next epoch is allowed since they can be predicted with high probabilities. + // @see `epochCtx.getBeaconProposersNextEpoch` JSDocs for rationale. + indexes = state.epochCtx.getBeaconProposersNextEpoch(); + break; + + case stateEpoch - 1: { + const indexesPrevEpoch = state.epochCtx.getBeaconProposersPrevEpoch(); + if (indexesPrevEpoch === null) { + // Should not happen as previous proposer duties should be initialized for head state + // and if we load state from `Uint8Array` it will always be the state of requested epoch + throw Error(`Proposer duties for previous epoch ${epoch} not yet initialized`); + } + indexes = indexesPrevEpoch; + break; + } + + default: + // Should never happen, epoch is checked to be in bounds above + throw Error(`Proposer duties for epoch ${epoch} not supported, current epoch ${stateEpoch}`); } // NOTE: this is the fastest way of getting compressed pubkeys. @@ -937,7 +984,6 @@ export function getValidatorApi( // TODO: Add a flag to just send 0x00 as pubkeys since the Lodestar validator does not need them. const pubkeys = getPubkeysForIndices(state.validators, indexes); - const startSlot = computeStartSlotAtEpoch(epoch); const duties: routes.validator.ProposerDuty[] = []; for (let i = 0; i < SLOTS_PER_EPOCH; i++) { duties.push({slot: startSlot + i, validatorIndex: indexes[i], pubkey: pubkeys[i]}); diff --git a/packages/beacon-node/test/mocks/mockedBeaconChain.ts b/packages/beacon-node/test/mocks/mockedBeaconChain.ts index 1d597bf4424d..a69efc55836c 100644 --- a/packages/beacon-node/test/mocks/mockedBeaconChain.ts +++ b/packages/beacon-node/test/mocks/mockedBeaconChain.ts @@ -1,4 +1,5 @@ import {vi, Mocked, Mock} from "vitest"; +import {PubkeyIndexMap} from "@chainsafe/pubkey-index-map"; import {config as defaultConfig} from "@lodestar/config/default"; import {ChainForkConfig} from "@lodestar/config"; import {ForkChoice, ProtoBlock, EpochDifference} from "@lodestar/fork-choice"; @@ -126,6 +127,8 @@ vi.mock("../../src/chain/chain.js", async (importActual) => { // @ts-expect-error beaconProposerCache: new BeaconProposerCache(), shufflingCache: new ShufflingCache(), + pubkey2index: new PubkeyIndexMap(), + index2pubkey: [], produceCommonBlockBody: vi.fn(), getProposerHead: vi.fn(), produceBlock: vi.fn(), @@ -135,6 +138,7 @@ vi.mock("../../src/chain/chain.js", async (importActual) => { predictProposerHead: vi.fn(), getHeadStateAtCurrentEpoch: vi.fn(), getHeadState: vi.fn(), + getStateBySlot: vi.fn(), updateBuilderStatus: vi.fn(), processBlock: vi.fn(), regenStateForAttestationVerification: vi.fn(), diff --git a/packages/beacon-node/test/unit/api/impl/validator/duties/proposer.test.ts b/packages/beacon-node/test/unit/api/impl/validator/duties/proposer.test.ts index b101382e01a0..49758c9bca58 100644 --- a/packages/beacon-node/test/unit/api/impl/validator/duties/proposer.test.ts +++ b/packages/beacon-node/test/unit/api/impl/validator/duties/proposer.test.ts @@ -3,6 +3,7 @@ import {routes} from "@lodestar/api"; import {config} from "@lodestar/config/default"; import {MAX_EFFECTIVE_BALANCE, SLOTS_PER_EPOCH} from "@lodestar/params"; import {BeaconStateAllForks} from "@lodestar/state-transition"; +import {Slot} from "@lodestar/types"; import {ApiTestModules, getApiTestModules} from "../../../../../utils/api.js"; import {FAR_FUTURE_EPOCH} from "../../../../../../src/constants/index.js"; import {SYNC_TOLERANCE_EPOCHS, getValidatorApi} from "../../../../../../src/api/impl/validator/index.js"; @@ -13,6 +14,9 @@ import {SyncState} from "../../../../../../src/sync/interface.js"; import {defaultApiOptions} from "../../../../../../src/api/options.js"; describe("get proposers api impl", function () { + const currentEpoch = 2; + const currentSlot = SLOTS_PER_EPOCH * currentEpoch; + let api: ReturnType; let modules: ApiTestModules; let state: BeaconStateAllForks; @@ -20,12 +24,24 @@ describe("get proposers api impl", function () { beforeEach(function () { vi.useFakeTimers({now: 0}); + vi.advanceTimersByTime(currentSlot * config.SECONDS_PER_SLOT * 1000); modules = getApiTestModules({clock: "real"}); api = getValidatorApi(defaultApiOptions, modules); + initializeState(currentSlot); + + modules.chain.getHeadStateAtCurrentEpoch.mockResolvedValue(cachedState); + modules.forkChoice.getHead.mockReturnValue(zeroProtoBlock); + modules.forkChoice.getFinalizedBlock.mockReturnValue(zeroProtoBlock); + modules.db.block.get.mockResolvedValue({message: {stateRoot: Buffer.alloc(32)}} as any); + + vi.spyOn(modules.sync, "state", "get").mockReturnValue(SyncState.Synced); + }); + + function initializeState(slot: Slot): void { state = generateState( { - slot: 0, + slot, validators: generateValidators(25, { effectiveBalance: MAX_EFFECTIVE_BALANCE, activationEpoch: 0, @@ -37,14 +53,10 @@ describe("get proposers api impl", function () { ); cachedState = createCachedBeaconStateTest(state, config); - modules.chain.getHeadStateAtCurrentEpoch.mockResolvedValue(cachedState); - modules.forkChoice.getHead.mockReturnValue(zeroProtoBlock); - modules.db.block.get.mockResolvedValue({message: {stateRoot: Buffer.alloc(32)}} as any); - - vi.spyOn(modules.sync, "state", "get").mockReturnValue(SyncState.Synced); vi.spyOn(cachedState.epochCtx, "getBeaconProposersNextEpoch"); vi.spyOn(cachedState.epochCtx, "getBeaconProposers"); - }); + vi.spyOn(cachedState.epochCtx, "getBeaconProposersPrevEpoch"); + } afterEach(() => { vi.useRealTimers(); @@ -54,7 +66,7 @@ describe("get proposers api impl", function () { vi.advanceTimersByTime((SYNC_TOLERANCE_EPOCHS * SLOTS_PER_EPOCH + 1) * config.SECONDS_PER_SLOT * 1000); vi.spyOn(modules.sync, "state", "get").mockReturnValue(SyncState.SyncingHead); - await expect(api.getProposerDuties({epoch: 1})).rejects.toThrow("Node is syncing - headSlot 0 currentSlot 9"); + await expect(api.getProposerDuties({epoch: 1})).rejects.toThrow("Node is syncing - headSlot 0 currentSlot 25"); }); it("should raise error if node stalled", async () => { @@ -65,34 +77,61 @@ describe("get proposers api impl", function () { }); it("should get proposers for current epoch", async () => { - const {data: result} = (await api.getProposerDuties({epoch: 0})) as {data: routes.validator.ProposerDutyList}; + const {data: result} = (await api.getProposerDuties({epoch: currentEpoch})) as { + data: routes.validator.ProposerDutyList; + }; expect(result.length).toBe(SLOTS_PER_EPOCH); expect(cachedState.epochCtx.getBeaconProposers).toHaveBeenCalledOnce(); expect(cachedState.epochCtx.getBeaconProposersNextEpoch).not.toHaveBeenCalled(); - expect(result.map((p) => p.slot)).toEqual(Array.from({length: SLOTS_PER_EPOCH}, (_, i) => i)); + expect(cachedState.epochCtx.getBeaconProposersPrevEpoch).not.toHaveBeenCalled(); + expect(result.map((p) => p.slot)).toEqual( + Array.from({length: SLOTS_PER_EPOCH}, (_, i) => currentEpoch * SLOTS_PER_EPOCH + i) + ); }); it("should get proposers for next epoch", async () => { - const {data: result} = (await api.getProposerDuties({epoch: 1})) as {data: routes.validator.ProposerDutyList}; + const nextEpoch = currentEpoch + 1; + const {data: result} = (await api.getProposerDuties({epoch: nextEpoch})) as { + data: routes.validator.ProposerDutyList; + }; expect(result.length).toBe(SLOTS_PER_EPOCH); expect(cachedState.epochCtx.getBeaconProposers).not.toHaveBeenCalled(); expect(cachedState.epochCtx.getBeaconProposersNextEpoch).toHaveBeenCalledOnce(); - expect(result.map((p) => p.slot)).toEqual(Array.from({length: SLOTS_PER_EPOCH}, (_, i) => SLOTS_PER_EPOCH + i)); + expect(cachedState.epochCtx.getBeaconProposersPrevEpoch).not.toHaveBeenCalled(); + expect(result.map((p) => p.slot)).toEqual( + Array.from({length: SLOTS_PER_EPOCH}, (_, i) => nextEpoch * SLOTS_PER_EPOCH + i) + ); + }); + + it("should get proposers for historical epoch", async () => { + const historicalEpoch = currentEpoch - 2; + initializeState(currentSlot - 2 * SLOTS_PER_EPOCH); + modules.chain.getStateBySlot.mockResolvedValue({state, executionOptimistic: false, finalized: true}); + + const {data: result} = (await api.getProposerDuties({epoch: historicalEpoch})) as { + data: routes.validator.ProposerDutyList; + }; + + expect(result.length).toBe(SLOTS_PER_EPOCH); + // Spy won't be called as `getProposerDuties` will create a new cached beacon state + expect(result.map((p) => p.slot)).toEqual( + Array.from({length: SLOTS_PER_EPOCH}, (_, i) => historicalEpoch * SLOTS_PER_EPOCH + i) + ); }); it("should raise error for more than one epoch in the future", async () => { - await expect(api.getProposerDuties({epoch: 2})).rejects.toThrow( - "Requested epoch 2 must equal current 0 or next epoch 1" + await expect(api.getProposerDuties({epoch: currentEpoch + 2})).rejects.toThrow( + "Requested epoch 4 must not be more than one epoch in the future" ); }); it("should have different proposer validator public keys for current and next epoch", async () => { - const {data: currentProposers} = (await api.getProposerDuties({epoch: 0})) as { + const {data: currentProposers} = (await api.getProposerDuties({epoch: currentEpoch})) as { data: routes.validator.ProposerDutyList; }; - const {data: nextProposers} = (await api.getProposerDuties({epoch: 1})) as { + const {data: nextProposers} = (await api.getProposerDuties({epoch: currentEpoch + 1})) as { data: routes.validator.ProposerDutyList; }; @@ -101,10 +140,10 @@ describe("get proposers api impl", function () { }); it("should have different proposer validator indexes for current and next epoch", async () => { - const {data: currentProposers} = (await api.getProposerDuties({epoch: 0})) as { + const {data: currentProposers} = (await api.getProposerDuties({epoch: currentEpoch})) as { data: routes.validator.ProposerDutyList; }; - const {data: nextProposers} = (await api.getProposerDuties({epoch: 1})) as { + const {data: nextProposers} = (await api.getProposerDuties({epoch: currentEpoch + 1})) as { data: routes.validator.ProposerDutyList; }; @@ -112,10 +151,10 @@ describe("get proposers api impl", function () { }); it("should have different proposer slots for current and next epoch", async () => { - const {data: currentProposers} = (await api.getProposerDuties({epoch: 0})) as { + const {data: currentProposers} = (await api.getProposerDuties({epoch: currentEpoch})) as { data: routes.validator.ProposerDutyList; }; - const {data: nextProposers} = (await api.getProposerDuties({epoch: 1})) as { + const {data: nextProposers} = (await api.getProposerDuties({epoch: currentEpoch + 1})) as { data: routes.validator.ProposerDutyList; }; diff --git a/packages/state-transition/src/cache/epochCache.ts b/packages/state-transition/src/cache/epochCache.ts index 5e901e33d992..4eb16fa49927 100644 --- a/packages/state-transition/src/cache/epochCache.ts +++ b/packages/state-transition/src/cache/epochCache.ts @@ -877,6 +877,10 @@ export class EpochCache { return this.proposers; } + getBeaconProposersPrevEpoch(): ValidatorIndex[] | null { + return this.proposersPrevEpoch; + } + /** * We allow requesting proposal duties 1 epoch in the future as in normal network conditions it's possible to predict * the correct shuffling with high probability. While knowing the proposers in advance is not useful for consensus, From 105a38808f91db1d1a1ecb206496df1c81c49869 Mon Sep 17 00:00:00 2001 From: Nico Flaig Date: Fri, 11 Oct 2024 17:19:13 +0100 Subject: [PATCH 49/52] feat: add ssz support to LC updates by range endpoint (#7119) --- packages/api/src/beacon/routes/lightclient.ts | 62 ++++++++++++++++--- .../api/test/unit/beacon/oapiSpec.test.ts | 2 - .../test/unit/beacon/testData/lightclient.ts | 2 +- 3 files changed, 54 insertions(+), 12 deletions(-) diff --git a/packages/api/src/beacon/routes/lightclient.ts b/packages/api/src/beacon/routes/lightclient.ts index decf8982b654..bac73b43ddb2 100644 --- a/packages/api/src/beacon/routes/lightclient.ts +++ b/packages/api/src/beacon/routes/lightclient.ts @@ -7,10 +7,12 @@ import { ssz, SyncPeriod, } from "@lodestar/types"; -import {ForkName} from "@lodestar/params"; -import {ChainForkConfig} from "@lodestar/config"; +import {fromHex} from "@lodestar/utils"; +import {ForkName, ZERO_HASH} from "@lodestar/params"; +import {BeaconConfig, ChainForkConfig, createBeaconConfig} from "@lodestar/config"; +import {genesisData, NetworkName} from "@lodestar/config/networks"; import {Endpoint, RouteDefinitions, Schema} from "../../utils/index.js"; -import {VersionCodec, VersionMeta} from "../../utils/metadata.js"; +import {MetaHeader, VersionCodec, VersionMeta} from "../../utils/metadata.js"; import {getLightClientForkTypes, toForkName} from "../../utils/fork.js"; import { EmptyArgs, @@ -19,7 +21,6 @@ import { EmptyMetaCodec, EmptyRequest, WithVersion, - JsonOnlyResp, } from "../../utils/codecs.js"; // See /packages/api/src/routes/index.ts for reasoning and instructions to add new routes @@ -90,7 +91,18 @@ export type Endpoints = { >; }; -export function getDefinitions(_config: ChainForkConfig): RouteDefinitions { +export function getDefinitions(config: ChainForkConfig): RouteDefinitions { + // Cache config so fork digests don't need to be recomputed + let beaconConfig: BeaconConfig | undefined; + + const cachedBeaconConfig = (): BeaconConfig => { + if (beaconConfig === undefined) { + const genesisValidatorsRoot = genesisData[config.CONFIG_NAME as NetworkName]?.genesisValidatorsRoot; + beaconConfig = createBeaconConfig(config, genesisValidatorsRoot ? fromHex(genesisValidatorsRoot) : ZERO_HASH); + } + return beaconConfig; + }; + return { getLightClientUpdatesByRange: { url: "/eth/v1/beacon/light_client/updates", @@ -100,7 +112,7 @@ export function getDefinitions(_config: ChainForkConfig): RouteDefinitions ({startPeriod: query.start_period, count: query.count}), schema: {query: {start_period: Schema.UintRequired, count: Schema.UintRequired}}, }, - resp: JsonOnlyResp({ + resp: { data: { toJson: (data, meta) => { const json: unknown[] = []; @@ -118,12 +130,44 @@ export function getDefinitions(_config: ChainForkConfig): RouteDefinitions { + const chunks: Uint8Array[] = []; + for (const [i, update] of data.entries()) { + const version = meta.versions[i]; + const forkDigest = cachedBeaconConfig().forkName2ForkDigest(version); + const serialized = getLightClientForkTypes(version).LightClientUpdate.serialize(update); + const length = ssz.UintNum64.serialize(4 + serialized.length); + chunks.push(length, forkDigest, serialized); + } + return Buffer.concat(chunks); + }, + deserialize: (data) => { + let offset = 0; + const updates: LightClientUpdate[] = []; + while (offset < data.length) { + const length = ssz.UintNum64.deserialize(data.subarray(offset, offset + 8)); + const forkDigest = ssz.ForkDigest.deserialize(data.subarray(offset + 8, offset + 12)); + const version = cachedBeaconConfig().forkDigest2ForkName(forkDigest); + updates.push( + getLightClientForkTypes(version).LightClientUpdate.deserialize( + data.subarray(offset + 12, offset + 8 + length) + ) + ); + offset += 8 + length; + } + return updates; + }, }, meta: { toJson: (meta) => meta, fromJson: (val) => val as {versions: ForkName[]}, - toHeadersObject: () => ({}), - fromHeaders: () => ({versions: []}), + toHeadersObject: (meta) => ({ + [MetaHeader.Version]: meta.versions.join(","), + }), + fromHeaders: (headers) => { + const versions = headers.getOrDefault(MetaHeader.Version, ""); + return {versions: versions === "" ? [] : (versions.split(",") as ForkName[])}; + }, }, transform: { toResponse: (data, meta) => { @@ -147,7 +191,7 @@ export function getDefinitions(_config: ChainForkConfig): RouteDefinitions = { diff --git a/packages/api/test/unit/beacon/testData/lightclient.ts b/packages/api/test/unit/beacon/testData/lightclient.ts index b86e1f338329..f405d514fc5d 100644 --- a/packages/api/test/unit/beacon/testData/lightclient.ts +++ b/packages/api/test/unit/beacon/testData/lightclient.ts @@ -14,7 +14,7 @@ const signatureSlot = ssz.Slot.defaultValue(); export const testData: GenericServerTestCases = { getLightClientUpdatesByRange: { args: {startPeriod: 1, count: 2}, - res: {data: [lightClientUpdate], meta: {versions: [ForkName.bellatrix]}}, + res: {data: [lightClientUpdate, lightClientUpdate], meta: {versions: [ForkName.altair, ForkName.altair]}}, }, getLightClientOptimisticUpdate: { args: undefined, From 911a3f59f6e47ff8264b88d2b881e90a0f4824e7 Mon Sep 17 00:00:00 2001 From: Matthew Keil Date: Sat, 12 Oct 2024 03:26:34 +0700 Subject: [PATCH 50/52] feat: use rust shuffle (#7120) * feat: add temp-deps to test on feat group * feat: add build_temp_deps.sh process * feat: use async for shuffling in epoch transition * feat: use v0.0.1 instead of temp-deps * chore: lint and check-types * fix: log error context * refactor: use toHex * fix: address computeEpochShuffling refactor comments * test: remove perf tests that were moved to swp-or-not-shuffle package * test: add strict equal check for sync/async computeEpochShuffling impls * Revert "refactor: use toHex" This reverts commit 9d64b6735b1358668f8dc6bf4f87d84497206ea5. * fix: EpochShuffling ssz type issue * feat: upgrade swap-or-not to 0.0.2 * refactor: buildCommitteesFromShuffling * docs: add TODO about removing state from shuffling computation * docs: add TODO about removing state from shuffling computation --- .../beacon-node/src/chain/shufflingCache.ts | 21 +- .../test/spec/presets/shuffling.test.ts | 17 +- packages/state-transition/package.json | 1 + .../src/util/epochShuffling.ts | 59 +++-- packages/state-transition/src/util/index.ts | 1 - packages/state-transition/src/util/shuffle.ts | 221 ------------------ .../test/perf/hashing.test.ts | 14 +- .../test/perf/shuffle/numberMath.test.ts | 82 ------- .../test/perf/shuffle/shuffle.test.ts | 29 --- .../test/unit/util/shuffle.test.ts | 29 --- .../test/unit/util/shuffling.test.ts | 32 +++ yarn.lock | 54 +++++ 12 files changed, 161 insertions(+), 399 deletions(-) delete mode 100644 packages/state-transition/src/util/shuffle.ts delete mode 100644 packages/state-transition/test/perf/shuffle/numberMath.test.ts delete mode 100644 packages/state-transition/test/perf/shuffle/shuffle.test.ts delete mode 100644 packages/state-transition/test/unit/util/shuffle.test.ts create mode 100644 packages/state-transition/test/unit/util/shuffling.test.ts diff --git a/packages/beacon-node/src/chain/shufflingCache.ts b/packages/beacon-node/src/chain/shufflingCache.ts index 6c42228b5356..749fea1b82ff 100644 --- a/packages/beacon-node/src/chain/shufflingCache.ts +++ b/packages/beacon-node/src/chain/shufflingCache.ts @@ -4,11 +4,11 @@ import { IShufflingCache, ShufflingBuildProps, computeEpochShuffling, + computeEpochShufflingAsync, } from "@lodestar/state-transition"; import {Epoch, RootHex} from "@lodestar/types"; import {LodestarError, Logger, MapDef, pruneSetToMax} from "@lodestar/utils"; import {Metrics} from "../metrics/metrics.js"; -import {callInNextEventLoop} from "../util/eventLoop.js"; /** * Same value to CheckpointBalancesCache, with the assumption that we don't have to use it for old epochs. In the worse case: @@ -178,14 +178,19 @@ export class ShufflingCache implements IShufflingCache { this.insertPromise(epoch, decisionRoot); /** * TODO: (@matthewkeil) This will get replaced by a proper build queue and a worker to do calculations - * on a NICE thread with a rust implementation + * on a NICE thread */ - callInNextEventLoop(() => { - const timer = this.metrics?.shufflingCache.shufflingCalculationTime.startTimer({source: "build"}); - const shuffling = computeEpochShuffling(state, activeIndices, epoch); - timer?.(); - this.set(shuffling, decisionRoot); - }); + const timer = this.metrics?.shufflingCache.shufflingCalculationTime.startTimer({source: "build"}); + computeEpochShufflingAsync(state, activeIndices, epoch) + .then((shuffling) => { + this.set(shuffling, decisionRoot); + }) + .catch((err) => + this.logger?.error(`error building shuffling for epoch ${epoch} at decisionRoot ${decisionRoot}`, {}, err) + ) + .finally(() => { + timer?.(); + }); } /** diff --git a/packages/beacon-node/test/spec/presets/shuffling.test.ts b/packages/beacon-node/test/spec/presets/shuffling.test.ts index 06e7d4717d06..7b0f38ecf581 100644 --- a/packages/beacon-node/test/spec/presets/shuffling.test.ts +++ b/packages/beacon-node/test/spec/presets/shuffling.test.ts @@ -1,24 +1,27 @@ import path from "node:path"; -import {unshuffleList} from "@lodestar/state-transition"; +import {unshuffleList} from "@chainsafe/swap-or-not-shuffle"; import {InputType} from "@lodestar/spec-test-util"; import {bnToNum, fromHex} from "@lodestar/utils"; -import {ACTIVE_PRESET} from "@lodestar/params"; +import {ACTIVE_PRESET, SHUFFLE_ROUND_COUNT} from "@lodestar/params"; import {RunnerType, TestRunnerFn} from "../utils/types.js"; import {ethereumConsensusSpecsTests} from "../specTestVersioning.js"; import {specTestIterator} from "../utils/specTestIterator.js"; -const shuffling: TestRunnerFn = () => { +const shuffling: TestRunnerFn = () => { return { testFunction: (testcase) => { const seed = fromHex(testcase.mapping.seed); - const output = Array.from({length: bnToNum(testcase.mapping.count)}, (_, i) => i); - unshuffleList(output, seed); - return output; + const output = unshuffleList( + Uint32Array.from(Array.from({length: bnToNum(testcase.mapping.count)}, (_, i) => i)), + seed, + SHUFFLE_ROUND_COUNT + ); + return Buffer.from(output).toString("hex"); }, options: { inputTypes: {mapping: InputType.YAML}, timeout: 10000, - getExpected: (testCase) => testCase.mapping.mapping.map((value) => bnToNum(value)), + getExpected: (testCase) => Buffer.from(testCase.mapping.mapping.map((value) => bnToNum(value))).toString("hex"), // Do not manually skip tests here, do it in packages/beacon-node/test/spec/presets/index.test.ts }, }; diff --git a/packages/state-transition/package.json b/packages/state-transition/package.json index e743ece013d9..a01d835bae95 100644 --- a/packages/state-transition/package.json +++ b/packages/state-transition/package.json @@ -63,6 +63,7 @@ "@chainsafe/persistent-merkle-tree": "^0.8.0", "@chainsafe/persistent-ts": "^0.19.1", "@chainsafe/ssz": "^0.17.1", + "@chainsafe/swap-or-not-shuffle": "^0.0.2", "@lodestar/config": "^1.22.0", "@lodestar/params": "^1.22.0", "@lodestar/types": "^1.22.0", diff --git a/packages/state-transition/src/util/epochShuffling.ts b/packages/state-transition/src/util/epochShuffling.ts index c26c62fd2079..6f63a2f4f5f8 100644 --- a/packages/state-transition/src/util/epochShuffling.ts +++ b/packages/state-transition/src/util/epochShuffling.ts @@ -1,3 +1,4 @@ +import {asyncUnshuffleList, unshuffleList} from "@chainsafe/swap-or-not-shuffle"; import {Epoch, RootHex, ssz, ValidatorIndex} from "@lodestar/types"; import {GaugeExtra, intDiv, Logger, NoLabels, toRootHex} from "@lodestar/utils"; import { @@ -6,11 +7,11 @@ import { MAX_COMMITTEES_PER_SLOT, SLOTS_PER_EPOCH, TARGET_COMMITTEE_SIZE, + SHUFFLE_ROUND_COUNT, } from "@lodestar/params"; import {BeaconConfig} from "@lodestar/config"; import {BeaconStateAllForks} from "../types.js"; import {getSeed} from "./seed.js"; -import {unshuffleList} from "./shuffle.js"; import {computeStartSlotAtEpoch} from "./epoch.js"; import {getBlockRootAtSlot} from "./blockRoot.js"; import {computeAnchorCheckpoint} from "./computeAnchorCheckpoint.js"; @@ -102,24 +103,15 @@ export function computeCommitteeCount(activeValidatorCount: number): number { return Math.max(1, Math.min(MAX_COMMITTEES_PER_SLOT, committeesPerSlot)); } -export function computeEpochShuffling( - state: BeaconStateAllForks, - activeIndices: Uint32Array, - epoch: Epoch -): EpochShuffling { - const activeValidatorCount = activeIndices.length; - - const shuffling = activeIndices.slice(); - const seed = getSeed(state, epoch, DOMAIN_BEACON_ATTESTER); - unshuffleList(shuffling, seed); - +function buildCommitteesFromShuffling(shuffling: Uint32Array): Uint32Array[][] { + const activeValidatorCount = shuffling.length; const committeesPerSlot = computeCommitteeCount(activeValidatorCount); - const committeeCount = committeesPerSlot * SLOTS_PER_EPOCH; - const committees: Uint32Array[][] = []; + const committees = new Array(SLOTS_PER_EPOCH); for (let slot = 0; slot < SLOTS_PER_EPOCH; slot++) { - const slotCommittees: Uint32Array[] = []; + const slotCommittees = new Array(committeesPerSlot); + for (let committeeIndex = 0; committeeIndex < committeesPerSlot; committeeIndex++) { const index = slot * committeesPerSlot + committeeIndex; const startOffset = Math.floor((activeValidatorCount * index) / committeeCount); @@ -127,17 +119,48 @@ export function computeEpochShuffling( if (!(startOffset <= endOffset)) { throw new Error(`Invalid offsets: start ${startOffset} must be less than or equal end ${endOffset}`); } - slotCommittees.push(shuffling.subarray(startOffset, endOffset)); + slotCommittees[committeeIndex] = shuffling.subarray(startOffset, endOffset); } - committees.push(slotCommittees); + + committees[slot] = slotCommittees; } + return committees; +} + +export function computeEpochShuffling( + // TODO: (@matthewkeil) remove state/epoch and pass in seed to clean this up + state: BeaconStateAllForks, + activeIndices: Uint32Array, + epoch: Epoch +): EpochShuffling { + const seed = getSeed(state, epoch, DOMAIN_BEACON_ATTESTER); + const shuffling = unshuffleList(activeIndices, seed, SHUFFLE_ROUND_COUNT); + const committees = buildCommitteesFromShuffling(shuffling); + return { + epoch, + activeIndices, + shuffling, + committees, + committeesPerSlot: committees[0].length, + }; +} + +export async function computeEpochShufflingAsync( + // TODO: (@matthewkeil) remove state/epoch and pass in seed to clean this up + state: BeaconStateAllForks, + activeIndices: Uint32Array, + epoch: Epoch +): Promise { + const seed = getSeed(state, epoch, DOMAIN_BEACON_ATTESTER); + const shuffling = await asyncUnshuffleList(activeIndices, seed, SHUFFLE_ROUND_COUNT); + const committees = buildCommitteesFromShuffling(shuffling); return { epoch, activeIndices, shuffling, committees, - committeesPerSlot, + committeesPerSlot: committees[0].length, }; } diff --git a/packages/state-transition/src/util/index.ts b/packages/state-transition/src/util/index.ts index 5f8d9e5cdcfc..b88a20719b85 100644 --- a/packages/state-transition/src/util/index.ts +++ b/packages/state-transition/src/util/index.ts @@ -17,7 +17,6 @@ export * from "./genesis.js"; export * from "./interop.js"; export * from "./rootCache.js"; export * from "./seed.js"; -export * from "./shuffle.js"; export * from "./shufflingDecisionRoot.js"; export * from "./signatureSets.js"; export * from "./signingRoot.js"; diff --git a/packages/state-transition/src/util/shuffle.ts b/packages/state-transition/src/util/shuffle.ts deleted file mode 100644 index a87f22cae43e..000000000000 --- a/packages/state-transition/src/util/shuffle.ts +++ /dev/null @@ -1,221 +0,0 @@ -import {digest} from "@chainsafe/as-sha256"; -import {SHUFFLE_ROUND_COUNT} from "@lodestar/params"; -import {Bytes32} from "@lodestar/types"; -import {assert, bytesToBigInt} from "@lodestar/utils"; - -// ArrayLike but with settable indices -type Shuffleable = { - readonly length: number; - [index: number]: number; -}; - -// ShuffleList shuffles a list, using the given seed for randomness. Mutates the input list. -export function shuffleList(input: Shuffleable, seed: Bytes32): void { - innerShuffleList(input, seed, true); -} - -// UnshuffleList undoes a list shuffling using the seed of the shuffling. Mutates the input list. -export function unshuffleList(input: Shuffleable, seed: Bytes32): void { - innerShuffleList(input, seed, false); -} - -const _SHUFFLE_H_SEED_SIZE = 32; -const _SHUFFLE_H_ROUND_SIZE = 1; -const _SHUFFLE_H_POSITION_WINDOW_SIZE = 4; -const _SHUFFLE_H_PIVOT_VIEW_SIZE = _SHUFFLE_H_SEED_SIZE + _SHUFFLE_H_ROUND_SIZE; -const _SHUFFLE_H_TOTAL_SIZE = _SHUFFLE_H_SEED_SIZE + _SHUFFLE_H_ROUND_SIZE + _SHUFFLE_H_POSITION_WINDOW_SIZE; - -/* - -def shuffle(list_size, seed): - indices = list(range(list_size)) - for round in range(90): - hash_bytes = b''.join([ - hash(seed + round.to_bytes(1, 'little') + (i).to_bytes(4, 'little')) - for i in range((list_size + 255) // 256) - ]) - pivot = int.from_bytes(hash(seed + round.to_bytes(1, 'little')), 'little') % list_size - - powers_of_two = [1, 2, 4, 8, 16, 32, 64, 128] - - for i, index in enumerate(indices): - flip = (pivot - index) % list_size - hash_pos = index if index > flip else flip - byte = hash_bytes[hash_pos // 8] - if byte & powers_of_two[hash_pos % 8]: - indices[i] = flip - return indices - -Heavily-optimized version of the set-shuffling algorithm proposed by Vitalik to shuffle all items in a list together. - -Original here: - https://github.com/ethereum/consensus-specs/pull/576 - -Main differences, implemented by @protolambda: - - User can supply input slice to shuffle, simple provide [0,1,2,3,4, ...] to get a list of cleanly shuffled indices. - - Input slice is shuffled (hence no return value), no new array is allocated - - Allocations as minimal as possible: only a very minimal buffer for hashing - (this should be allocated on the stack, compiler will find it with escape analysis). - This is not bigger than what's used for shuffling a single index! - As opposed to larger allocations (size O(n) instead of O(1)) made in the original. - - Replaced pseudocode/python workarounds with bit-logic. - - User can provide their own hash-function (as long as it outputs a 32 len byte slice) - -This Typescript version is an adaption of the Python version, in turn an adaption of the original Go version. -Python: https://github.com/protolambda/eth2fastspec/blob/14e04e9db77ef7c8b7788ffdaa7e142d7318dd7e/eth2fastspec.py#L63 -Go: https://github.com/protolambda/eth2-shuffle -All three implemented by @protolambda, but meant for public use, like the original spec version. -*/ - -function setPositionUint32(value: number, buf: Buffer): void { - // Little endian, optimized version - buf[_SHUFFLE_H_PIVOT_VIEW_SIZE] = (value >> 0) & 0xff; - buf[_SHUFFLE_H_PIVOT_VIEW_SIZE + 1] = (value >> 8) & 0xff; - buf[_SHUFFLE_H_PIVOT_VIEW_SIZE + 2] = (value >> 16) & 0xff; - buf[_SHUFFLE_H_PIVOT_VIEW_SIZE + 3] = (value >> 24) & 0xff; -} - -// Shuffles or unshuffles, depending on the `dir` (true for shuffling, false for unshuffling -function innerShuffleList(input: Shuffleable, seed: Bytes32, dir: boolean): void { - if (input.length <= 1) { - // nothing to (un)shuffle - return; - } - if (SHUFFLE_ROUND_COUNT == 0) { - // no shuffling - return; - } - // uint32 is sufficient, and necessary in JS, - // as we do a lot of bit math on it, which cannot be done as fast on more bits. - const listSize = input.length >>> 0; - // check if list size fits in uint32 - assert.equal(listSize, input.length, "input length does not fit uint32"); - // check that the seed is 32 bytes - assert.lte(seed.length, _SHUFFLE_H_SEED_SIZE, `seed length is not lte ${_SHUFFLE_H_SEED_SIZE} bytes`); - - const buf = Buffer.alloc(_SHUFFLE_H_TOTAL_SIZE); - let r = 0; - if (!dir) { - // Start at last round. - // Iterating through the rounds in reverse, un-swaps everything, effectively un-shuffling the list. - r = SHUFFLE_ROUND_COUNT - 1; - } - - // Seed is always the first 32 bytes of the hash input, we never have to change this part of the buffer. - buf.set(seed, 0); - - // initial values here are not used: overwritten first within the inner for loop. - let source = seed; // just setting it to a Bytes32 - let byteV = 0; - - while (true) { - // spec: pivot = bytes_to_int(hash(seed + int_to_bytes1(round))[0:8]) % list_size - // This is the "int_to_bytes1(round)", appended to the seed. - buf[_SHUFFLE_H_SEED_SIZE] = r; - // Seed is already in place, now just hash the correct part of the buffer, and take a uint64 from it, - // and modulo it to get a pivot within range. - const h = digest(buf.subarray(0, _SHUFFLE_H_PIVOT_VIEW_SIZE)); - const pivot = Number(bytesToBigInt(h.subarray(0, 8)) % BigInt(listSize)) >>> 0; - - // Split up the for-loop in two: - // 1. Handle the part from 0 (incl) to pivot (incl). This is mirrored around (pivot / 2) - // 2. Handle the part from pivot (excl) to N (excl). This is mirrored around ((pivot / 2) + (size/2)) - // The pivot defines a split in the array, with each of the splits mirroring their data within the split. - // Print out some example even/odd sized index lists, with some even/odd pivots, - // and you can deduce how the mirroring works exactly. - // Note that the mirror is strict enough to not consider swapping the index @mirror with itself. - let mirror = (pivot + 1) >> 1; - // Since we are iterating through the "positions" in order, we can just repeat the hash every 256th position. - // No need to pre-compute every possible hash for efficiency like in the example code. - // We only need it consecutively (we are going through each in reverse order however, but same thing) - // - // spec: source = hash(seed + int_to_bytes1(round) + int_to_bytes4(position // 256)) - // - seed is still in 0:32 (excl., 32 bytes) - // - round number is still in 32 - // - mix in the position for randomness, except the last byte of it, - // which will be used later to select a bit from the resulting hash. - // We start from the pivot position, and work back to the mirror position (of the part left to the pivot). - // This makes us process each pear exactly once (instead of unnecessarily twice, like in the spec) - setPositionUint32(pivot >> 8, buf); // already using first pivot byte below. - source = digest(buf); - byteV = source[(pivot & 0xff) >> 3]; - - for (let i = 0, j; i < mirror; i++) { - j = pivot - i; - // -- step() fn start - // The pair is i,j. With j being the bigger of the two, hence the "position" identifier of the pair. - // Every 256th bit (aligned to j). - if ((j & 0xff) == 0xff) { - // just overwrite the last part of the buffer, reuse the start (seed, round) - setPositionUint32(j >> 8, buf); - source = digest(buf); - } - - // Same trick with byte retrieval. Only every 8th. - if ((j & 0x7) == 0x7) { - byteV = source[(j & 0xff) >> 3]; - } - - const bitV = (byteV >> (j & 0x7)) & 0x1; - - if (bitV == 1) { - // swap the pair items - const tmp = input[j]; - input[j] = input[i]; - input[i] = tmp; - } - // -- step() fn end - } - - // Now repeat, but for the part after the pivot. - mirror = (pivot + listSize + 1) >> 1; - const end = listSize - 1; - // Again, seed and round input is in place, just update the position. - // We start at the end, and work back to the mirror point. - // This makes us process each pear exactly once (instead of unnecessarily twice, like in the spec) - setPositionUint32(end >> 8, buf); - source = digest(buf); - byteV = source[(end & 0xff) >> 3]; - for (let i = pivot + 1, j; i < mirror; i++) { - j = end - i + pivot + 1; - // -- step() fn start - // The pair is i,j. With j being the bigger of the two, hence the "position" identifier of the pair. - // Every 256th bit (aligned to j). - if ((j & 0xff) == 0xff) { - // just overwrite the last part of the buffer, reuse the start (seed, round) - setPositionUint32(j >> 8, buf); - source = digest(buf); - } - - // Same trick with byte retrieval. Only every 8th. - if ((j & 0x7) == 0x7) { - byteV = source[(j & 0xff) >> 3]; - } - - const bitV = (byteV >> (j & 0x7)) & 0x1; - - if (bitV == 1) { - // swap the pair items - const tmp = input[j]; - input[j] = input[i]; - input[i] = tmp; - } - // -- step() fn end - } - - // go forwards? - if (dir) { - // -> shuffle - r += 1; - if (r == SHUFFLE_ROUND_COUNT) { - break; - } - } else { - if (r == 0) { - break; - } - // -> un-shuffle - r -= 1; - } - } -} diff --git a/packages/state-transition/test/perf/hashing.test.ts b/packages/state-transition/test/perf/hashing.test.ts index b7afc59717bc..26bfd935c08a 100644 --- a/packages/state-transition/test/perf/hashing.test.ts +++ b/packages/state-transition/test/perf/hashing.test.ts @@ -1,13 +1,14 @@ import {itBench} from "@dapplion/benchmark"; +import {unshuffleList} from "@chainsafe/swap-or-not-shuffle"; import {ssz} from "@lodestar/types"; -import {unshuffleList} from "../../src/index.js"; +import {SHUFFLE_ROUND_COUNT} from "@lodestar/params"; import {generatePerfTestCachedStatePhase0, numValidators} from "./util.js"; // Test cost of hashing state after some modifications describe("BeaconState hashTreeRoot", () => { const vc = numValidators; - const indicesShuffled: number[] = []; + let indicesShuffled: Uint32Array; let stateOg: ReturnType; before(function () { @@ -15,8 +16,13 @@ describe("BeaconState hashTreeRoot", () => { stateOg = generatePerfTestCachedStatePhase0(); stateOg.hashTreeRoot(); - for (let i = 0; i < vc; i++) indicesShuffled[i] = i; - unshuffleList(indicesShuffled, new Uint8Array([42, 32])); + const seed = new Uint8Array(32); + seed.set([42, 32], 0); + const preShuffle = new Uint32Array(numValidators); + for (let i = 0; i < vc; i++) { + preShuffle[i] = i; + } + indicesShuffled = unshuffleList(preShuffle, seed, SHUFFLE_ROUND_COUNT); }); const validator = ssz.phase0.Validator.defaultViewDU(); diff --git a/packages/state-transition/test/perf/shuffle/numberMath.test.ts b/packages/state-transition/test/perf/shuffle/numberMath.test.ts deleted file mode 100644 index 08e57b090aa3..000000000000 --- a/packages/state-transition/test/perf/shuffle/numberMath.test.ts +++ /dev/null @@ -1,82 +0,0 @@ -import {itBench} from "@dapplion/benchmark"; - -describe.skip("shuffle number math ops", () => { - const forRuns = 100e5; - const j = forRuns / 2; - - const arrSize = forRuns; - const input: number[] = []; - const inputUint32Array = new Uint32Array(arrSize); - for (let i = 0; i < arrSize; i++) { - input[i] = i; - inputUint32Array[i] = i; - } - - itBench("if(i == 1)", () => { - for (let i = 0; i < forRuns; i++) { - if (i === 1) { - // - } - } - }); - - itBench("if(i)", () => { - for (let i = 0; i < forRuns; i++) { - if (i) { - // - } - } - }); - - itBench("i == j", () => { - for (let i = 0; i < forRuns; i++) { - i == j; - } - }); - - itBench("i === j", () => { - for (let i = 0; i < forRuns; i++) { - i === j; - } - }); - - itBench("bit opts", () => { - for (let i = 0; i < forRuns; i++) { - (j & 0x7) == 0x7; - } - }); - - itBench("modulo", () => { - for (let i = 0; i < forRuns; i++) { - j % 8 == 0; - } - }); - - itBench(">> 3", () => { - for (let i = 0; i < forRuns; i++) { - j >> 3; - } - }); - - itBench("/ 8", () => { - for (let i = 0; i < forRuns; i++) { - j / 8; - } - }); - - itBench("swap item in array", () => { - for (let i = 0; i < forRuns; i++) { - const tmp = input[forRuns - i]; - input[forRuns - i] = input[i]; - input[i] = tmp; - } - }); - - itBench("swap item in Uint32Array", () => { - for (let i = 0; i < forRuns; i++) { - const tmp = inputUint32Array[forRuns - i]; - inputUint32Array[forRuns - i] = inputUint32Array[i]; - inputUint32Array[i] = tmp; - } - }); -}); diff --git a/packages/state-transition/test/perf/shuffle/shuffle.test.ts b/packages/state-transition/test/perf/shuffle/shuffle.test.ts deleted file mode 100644 index 55f7875e69dd..000000000000 --- a/packages/state-transition/test/perf/shuffle/shuffle.test.ts +++ /dev/null @@ -1,29 +0,0 @@ -import {itBench} from "@dapplion/benchmark"; -import {unshuffleList} from "../../../src/index.js"; - -// Lightouse Lodestar -// 512 254.04 us 1.6034 ms (x6) -// 16384 6.2046 ms 18.272 ms (x3) -// 4000000 1.5617 s 4.9690 s (x3) - -describe("shuffle list", () => { - const seed = new Uint8Array([42, 32]); - - for (const listSize of [ - 16384, - 250000, - // Don't run 4_000_000 since it's very slow and not testnet has gotten there yet - // 4e6, - ]) { - itBench({ - id: `shuffle list - ${listSize} els`, - before: () => { - const input: number[] = []; - for (let i = 0; i < listSize; i++) input[i] = i; - return new Uint32Array(input); - }, - beforeEach: (input) => input, - fn: (input) => unshuffleList(input, seed), - }); - } -}); diff --git a/packages/state-transition/test/unit/util/shuffle.test.ts b/packages/state-transition/test/unit/util/shuffle.test.ts deleted file mode 100644 index 9186968674ae..000000000000 --- a/packages/state-transition/test/unit/util/shuffle.test.ts +++ /dev/null @@ -1,29 +0,0 @@ -import {expect, describe, it} from "vitest"; -import {unshuffleList} from "../../../src/index.js"; - -describe("util / shuffle", () => { - const testCases: { - id: string; - input: number[]; - res: number[]; - }[] = [ - // Values from `unshuffleList()` at commit https://github.com/ChainSafe/lodestar/commit/ec065635ca7da7f3788da018bd68c4900f0427d2 - { - id: "8 elements", - input: [0, 1, 2, 3, 4, 5, 6, 7], - res: [6, 3, 4, 0, 1, 5, 7, 2], - }, - { - id: "16 elements", - input: [0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15], - res: [8, 4, 11, 7, 10, 6, 0, 3, 15, 12, 5, 14, 1, 9, 13, 2], - }, - ]; - - const seed = new Uint8Array([42, 32]); - - it.each(testCases)("$id", ({input, res}) => { - unshuffleList(input, seed); - expect(input).toEqual(res); - }); -}); diff --git a/packages/state-transition/test/unit/util/shuffling.test.ts b/packages/state-transition/test/unit/util/shuffling.test.ts new file mode 100644 index 000000000000..f4039b472f5c --- /dev/null +++ b/packages/state-transition/test/unit/util/shuffling.test.ts @@ -0,0 +1,32 @@ +import {describe, it, expect} from "vitest"; +import {ssz} from "@lodestar/types"; +import {generateState} from "../../utils/state.js"; +import {computeEpochShuffling, computeEpochShufflingAsync} from "../../../src/util/epochShuffling.js"; +import {computeEpochAtSlot} from "../../../src/index.js"; + +describe("EpochShuffling", () => { + it("async and sync versions should be identical", async () => { + const numberOfValidators = 1000; + const activeIndices = Uint32Array.from(Array.from({length: numberOfValidators}, (_, i) => i)); + const state = generateState(); + state.slot = 12345; + state.validators = ssz.phase0.Validators.toViewDU( + Array.from({length: numberOfValidators}, () => ({ + activationEligibilityEpoch: 0, + activationEpoch: 0, + exitEpoch: Infinity, + effectiveBalance: 32, + pubkey: Buffer.alloc(48, 0xaa), + slashed: false, + withdrawableEpoch: Infinity, + withdrawalCredentials: Buffer.alloc(8, 0x01), + })) + ); + const epoch = computeEpochAtSlot(state.slot); + + const sync = computeEpochShuffling(state, activeIndices, epoch); + const async = await computeEpochShufflingAsync(state, activeIndices, epoch); + + expect(sync).toStrictEqual(async); + }); +}); diff --git a/yarn.lock b/yarn.lock index 9808fee96b84..3907e9f4e441 100644 --- a/yarn.lock +++ b/yarn.lock @@ -674,6 +674,60 @@ "@chainsafe/as-sha256" "0.5.0" "@chainsafe/persistent-merkle-tree" "0.8.0" +"@chainsafe/swap-or-not-shuffle-darwin-arm64@0.0.2": + version "0.0.2" + resolved "https://registry.yarnpkg.com/@chainsafe/swap-or-not-shuffle-darwin-arm64/-/swap-or-not-shuffle-darwin-arm64-0.0.2.tgz#9c4b02970619b9ec5274f357f3a03ff97e745957" + integrity sha512-e2tmpSgGTHFv1g3oEKP/YElDTmxZwuSwVQ+Cf0gTUA8z4YQsJar61293My6JeA7qC5razWjhvcEk13ZbTCqk0w== + +"@chainsafe/swap-or-not-shuffle-darwin-x64@0.0.2": + version "0.0.2" + resolved "https://registry.yarnpkg.com/@chainsafe/swap-or-not-shuffle-darwin-x64/-/swap-or-not-shuffle-darwin-x64-0.0.2.tgz#d2777b93455a217bf4b5b94b84e76239bc3ce860" + integrity sha512-JrK4psAQz0HzlfnsGRcHnhJSv6OHfjVNkEtERnpAjyeigwCRh09wNBzHEnIk8SOGFk29DabI4FC1wdh2Cs0DAA== + +"@chainsafe/swap-or-not-shuffle-linux-arm64-gnu@0.0.2": + version "0.0.2" + resolved "https://registry.yarnpkg.com/@chainsafe/swap-or-not-shuffle-linux-arm64-gnu/-/swap-or-not-shuffle-linux-arm64-gnu-0.0.2.tgz#a881c6e29704bbbaceb8b75fd9394832087979f3" + integrity sha512-nGTIRUXt1QRNiWQXZnA8IWiHnAw6FNkU7RkngkoDzjD8pEhrtWs8tv/pdOxRKEhw21HBvKi7z8J+a7/MtxDLTg== + +"@chainsafe/swap-or-not-shuffle-linux-arm64-musl@0.0.2": + version "0.0.2" + resolved "https://registry.yarnpkg.com/@chainsafe/swap-or-not-shuffle-linux-arm64-musl/-/swap-or-not-shuffle-linux-arm64-musl-0.0.2.tgz#118f80f7bd7e8f83fb566112a17003f228d86593" + integrity sha512-sumwkxQ0Mky+W66Jf43cHUybgHQ4FENj2iRBRw3jGWiZ79Vv/DZ1dMA6I4/LVWCsvZmFUIvMvKNthGHXefh2DQ== + +"@chainsafe/swap-or-not-shuffle-linux-x64-gnu@0.0.2": + version "0.0.2" + resolved "https://registry.yarnpkg.com/@chainsafe/swap-or-not-shuffle-linux-x64-gnu/-/swap-or-not-shuffle-linux-x64-gnu-0.0.2.tgz#2dca41ba2848f904b5c9bc831cb0428c958261f3" + integrity sha512-do9NH/43eUWxtY+k3fxFltSSfKJpyvAINA/dJ3EHVkqS/oBTwR450CVNV5HFcR5Uvgxuth3/BjVYb4APs8N/MQ== + +"@chainsafe/swap-or-not-shuffle-linux-x64-musl@0.0.2": + version "0.0.2" + resolved "https://registry.yarnpkg.com/@chainsafe/swap-or-not-shuffle-linux-x64-musl/-/swap-or-not-shuffle-linux-x64-musl-0.0.2.tgz#75025eee02e2b34f10852c1de57b8e0050584320" + integrity sha512-ClwDMZd768PIaAUQhbyZpqqip0b6Sgjt8IpP5ACYMJr2AHoiG64POZaiFu+zusT4q3s4/dvqaz86jRQaF4vFkw== + +"@chainsafe/swap-or-not-shuffle-win32-arm64-msvc@0.0.2": + version "0.0.2" + resolved "https://registry.yarnpkg.com/@chainsafe/swap-or-not-shuffle-win32-arm64-msvc/-/swap-or-not-shuffle-win32-arm64-msvc-0.0.2.tgz#f5520df2bf72e823ef225d9f13d317b91b6372e4" + integrity sha512-i9+qj0VSppy2xMChQE38rCmWmmy8SJ0uSaApc0L4KZ+t2aqquYyEUXWGgfdXMZx9MqAUvuigzv34T9qivADFag== + +"@chainsafe/swap-or-not-shuffle-win32-x64-msvc@0.0.2": + version "0.0.2" + resolved "https://registry.yarnpkg.com/@chainsafe/swap-or-not-shuffle-win32-x64-msvc/-/swap-or-not-shuffle-win32-x64-msvc-0.0.2.tgz#7413aa32a4006bf144b66087844aee71bb2a5f42" + integrity sha512-zZ9J0PWzGEgfjjAVMeTvAPdHNs5XCeQqfNQ0E/lQUYhS8Wi84y44R+7M6C/KIcS0GmvCpZXI2sQGeNjqbU5LoA== + +"@chainsafe/swap-or-not-shuffle@^0.0.2": + version "0.0.2" + resolved "https://registry.yarnpkg.com/@chainsafe/swap-or-not-shuffle/-/swap-or-not-shuffle-0.0.2.tgz#59a148b80bb8e8d4f2f38f7bd00562c7a6b99e62" + integrity sha512-Rbk3p86cX71VAq46+nRcBOHOetK2ls4QrAUf1YOWTYLHmmLvx8j9Q6gQndjtu0OeYGd7Eyj1pQCFDlS9kixk+g== + optionalDependencies: + "@chainsafe/swap-or-not-shuffle-darwin-arm64" "0.0.2" + "@chainsafe/swap-or-not-shuffle-darwin-x64" "0.0.2" + "@chainsafe/swap-or-not-shuffle-linux-arm64-gnu" "0.0.2" + "@chainsafe/swap-or-not-shuffle-linux-arm64-musl" "0.0.2" + "@chainsafe/swap-or-not-shuffle-linux-x64-gnu" "0.0.2" + "@chainsafe/swap-or-not-shuffle-linux-x64-musl" "0.0.2" + "@chainsafe/swap-or-not-shuffle-win32-arm64-msvc" "0.0.2" + "@chainsafe/swap-or-not-shuffle-win32-x64-msvc" "0.0.2" + "@chainsafe/threads@^1.11.1": version "1.11.1" resolved "https://registry.yarnpkg.com/@chainsafe/threads/-/threads-1.11.1.tgz#0b3b8c76f5875043ef6d47aeeb681dc80378f205" From d37bdb0eb8a6e8deedd019fd6b7b3413f3fcf6d4 Mon Sep 17 00:00:00 2001 From: Cayman Date: Fri, 11 Oct 2024 17:19:34 -0400 Subject: [PATCH 51/52] chore: upgrade to js-libp2p 2.0 (#7077) * chore: upgrade to js-libp2p 2.0 * chore: bump libp2p versions * chore: fix up yarn lock * chore: fix some tests * chore: fix connection map * feat: gossipsub v1.2 * chore: bump libp2p * chore: tweak idontwantMinDataSize * chore: bump libp2p deps --- package.json | 2 +- packages/beacon-node/package.json | 35 +- .../src/network/core/networkCore.ts | 17 +- .../src/network/core/networkCoreWorker.ts | 8 +- .../network/core/networkCoreWorkerHandler.ts | 10 +- .../beacon-node/src/network/core/types.ts | 2 +- .../beacon-node/src/network/discv5/index.ts | 14 +- .../beacon-node/src/network/discv5/types.ts | 2 +- .../beacon-node/src/network/discv5/worker.ts | 13 +- .../src/network/gossip/gossipsub.ts | 4 + packages/beacon-node/src/network/interface.ts | 4 +- .../beacon-node/src/network/libp2p/index.ts | 21 +- packages/beacon-node/src/network/network.ts | 18 +- .../src/network/peers/datastore.ts | 3 +- .../beacon-node/src/network/peers/discover.ts | 10 +- .../src/network/peers/peerManager.ts | 5 +- .../peers/utils/getConnectedPeerIds.ts | 4 +- packages/beacon-node/src/network/util.ts | 4 +- packages/beacon-node/src/node/nodejs.ts | 8 +- packages/beacon-node/src/util/peerId.ts | 2 +- .../beacon-node/test/e2e/network/mdns.test.ts | 16 +- .../e2e/network/peers/peerManager.test.ts | 12 +- .../test/e2e/network/reqrespEncode.test.ts | 2 +- .../test/perf/network/noise/sendData.test.ts | 17 +- .../peers/util/prioritizePeers.test.ts | 6 +- .../unit/network/peers/priorization.test.ts | 9 +- packages/beacon-node/test/utils/network.ts | 15 +- .../test/utils/networkWithMockDb.ts | 6 +- .../beacon-node/test/utils/node/beacon.ts | 12 +- packages/beacon-node/test/utils/peer.ts | 8 +- packages/cli/package.json | 10 +- packages/cli/src/cmds/beacon/handler.ts | 10 +- .../cli/src/cmds/beacon/initPeerIdAndEnr.ts | 54 +- packages/cli/src/cmds/bootnode/handler.ts | 14 +- packages/cli/src/config/peerId.ts | 67 +- packages/cli/test/unit/cmds/beacon.test.ts | 57 +- .../test/unit/cmds/initPeerIdAndEnr.test.ts | 13 +- packages/cli/test/unit/config/peerId.test.ts | 12 +- packages/reqresp/package.json | 6 +- packages/reqresp/test/utils/peer.ts | 5 +- yarn.lock | 816 ++++++++++-------- 41 files changed, 754 insertions(+), 599 deletions(-) diff --git a/package.json b/package.json index 7399b4ba6c1e..e6de076cf494 100644 --- a/package.json +++ b/package.json @@ -60,7 +60,7 @@ "https-browserify": "^1.0.0", "jsdom": "^23.0.1", "lerna": "^7.3.0", - "libp2p": "1.4.3", + "libp2p": "2.1.7", "mocha": "^10.2.0", "node-gyp": "^9.4.0", "npm-run-all": "^4.1.5", diff --git a/packages/beacon-node/package.json b/packages/beacon-node/package.json index 8b46bc0038c7..e3d095b6f1e0 100644 --- a/packages/beacon-node/package.json +++ b/packages/beacon-node/package.json @@ -96,11 +96,10 @@ "dependencies": { "@chainsafe/as-sha256": "^0.5.0", "@chainsafe/blst": "^2.0.3", - "@chainsafe/discv5": "^9.0.0", - "@chainsafe/enr": "^3.0.0", - "@chainsafe/libp2p-gossipsub": "^13.0.0", - "@chainsafe/libp2p-identify": "^1.0.0", - "@chainsafe/libp2p-noise": "^15.0.0", + "@chainsafe/discv5": "^10.0.1", + "@chainsafe/enr": "^4.0.1", + "@chainsafe/libp2p-gossipsub": "^14.1.0", + "@chainsafe/libp2p-noise": "^16.0.0", "@chainsafe/persistent-merkle-tree": "^0.8.0", "@chainsafe/prometheus-gc-stats": "^1.0.0", "@chainsafe/ssz": "^0.17.1", @@ -111,15 +110,15 @@ "@fastify/cors": "^10.0.1", "@fastify/swagger": "^9.0.0", "@fastify/swagger-ui": "^5.0.1", - "@libp2p/bootstrap": "^10.0.21", - "@libp2p/identify": "^1.0.20", - "@libp2p/interface": "^1.3.0", - "@libp2p/mdns": "^10.0.21", - "@libp2p/mplex": "^10.0.21", - "@libp2p/peer-id": "^4.1.0", - "@libp2p/peer-id-factory": "^4.1.0", - "@libp2p/prometheus-metrics": "^3.0.21", - "@libp2p/tcp": "9.0.23", + "@libp2p/bootstrap": "^11.0.4", + "@libp2p/crypto": "^5.0.4", + "@libp2p/identify": "^3.0.4", + "@libp2p/interface": "^2.1.2", + "@libp2p/mdns": "^11.0.4", + "@libp2p/mplex": "^11.0.4", + "@libp2p/peer-id": "^5.0.4", + "@libp2p/prometheus-metrics": "^4.1.2", + "@libp2p/tcp": "10.0.4", "@lodestar/api": "^1.22.0", "@lodestar/config": "^1.22.0", "@lodestar/db": "^1.22.0", @@ -134,15 +133,15 @@ "@lodestar/validator": "^1.22.0", "@multiformats/multiaddr": "^12.1.3", "c-kzg": "^2.1.2", - "datastore-core": "^9.1.1", - "datastore-level": "^10.1.1", + "datastore-core": "^10.0.0", + "datastore-level": "^11.0.0", "deepmerge": "^4.3.1", "fastify": "^5.0.0", - "interface-datastore": "^8.2.7", + "interface-datastore": "^8.3.0", "it-all": "^3.0.4", "it-pipe": "^3.0.1", "jwt-simple": "0.5.6", - "libp2p": "1.4.3", + "libp2p": "2.1.7", "multiformats": "^11.0.1", "prom-client": "^15.1.0", "qs": "^6.11.1", diff --git a/packages/beacon-node/src/network/core/networkCore.ts b/packages/beacon-node/src/network/core/networkCore.ts index 1a497925e4fd..9d075c730558 100644 --- a/packages/beacon-node/src/network/core/networkCore.ts +++ b/packages/beacon-node/src/network/core/networkCore.ts @@ -1,4 +1,4 @@ -import {Connection, PeerId} from "@libp2p/interface"; +import {Connection, PrivateKey} from "@libp2p/interface"; import {multiaddr} from "@multiformats/multiaddr"; import {PublishOpts} from "@chainsafe/libp2p-gossipsub/types"; import {PeerScoreStatsDump} from "@chainsafe/libp2p-gossipsub/dist/src/score/peer-score.js"; @@ -55,7 +55,7 @@ type Mods = { export type BaseNetworkInit = { opts: NetworkOptions; config: BeaconConfig; - peerId: PeerId; + privateKey: PrivateKey; peerStoreDir: string | undefined; logger: LoggerNode; metricsRegistry: RegistryMetricCreator | null; @@ -126,7 +126,7 @@ export class NetworkCore implements INetworkCore { static async init({ opts, config, - peerId, + privateKey, peerStoreDir, logger, metricsRegistry, @@ -136,7 +136,7 @@ export class NetworkCore implements INetworkCore { activeValidatorCount, initialStatus, }: BaseNetworkInit): Promise { - const libp2p = await createNodeJsLibp2p(peerId, opts, { + const libp2p = await createNodeJsLibp2p(privateKey, opts, { peerStoreDir, metrics: Boolean(metricsRegistry), metricsRegistry: metricsRegistry ?? undefined, @@ -200,8 +200,9 @@ export class NetworkCore implements INetworkCore { const peerManager = await PeerManager.init( { + privateKey, libp2p, - gossip: gossip, + gossip, reqResp, attnetsService, syncnetsService, @@ -359,7 +360,11 @@ export class NetworkCore implements INetworkCore { } getConnectionsByPeer(): Map { - return getConnectionsMap(this.libp2p); + const m = new Map(); + for (const [k, v] of getConnectionsMap(this.libp2p).entries()) { + m.set(k, v.value); + } + return m; } async getConnectedPeers(): Promise { diff --git a/packages/beacon-node/src/network/core/networkCoreWorker.ts b/packages/beacon-node/src/network/core/networkCoreWorker.ts index 5e4b057402d8..07b6de828b6c 100644 --- a/packages/beacon-node/src/network/core/networkCoreWorker.ts +++ b/packages/beacon-node/src/network/core/networkCoreWorker.ts @@ -3,7 +3,8 @@ import path from "node:path"; import worker from "node:worker_threads"; import type {ModuleThread} from "@chainsafe/threads"; import {expose} from "@chainsafe/threads/worker"; -import {createFromProtobuf} from "@libp2p/peer-id-factory"; +import {privateKeyFromProtobuf} from "@libp2p/crypto/keys"; +import {peerIdFromPrivateKey} from "@libp2p/peer-id"; import {chainConfigFromJson, createBeaconConfig} from "@lodestar/config"; import {getNodeLogger} from "@lodestar/logger/node"; import {RegistryMetricCreator, collectNodeJSMetrics} from "../../metrics/index.js"; @@ -32,7 +33,8 @@ if (!workerData) throw Error("workerData must be defined"); if (!parentPort) throw Error("parentPort must be defined"); const config = createBeaconConfig(chainConfigFromJson(workerData.chainConfigJson), workerData.genesisValidatorsRoot); -const peerId = await createFromProtobuf(workerData.peerIdProto); +const privateKey = privateKeyFromProtobuf(workerData.privateKeyProto); +const peerId = peerIdFromPrivateKey(privateKey); // TODO: Pass options from main thread for logging // TODO: Logging won't be visible in file loggers @@ -92,7 +94,7 @@ if (networkCoreWorkerMetrics) { const core = await NetworkCore.init({ opts: workerData.opts, config, - peerId, + privateKey, peerStoreDir: workerData.peerStoreDir, logger, metricsRegistry: metricsRegister, diff --git a/packages/beacon-node/src/network/core/networkCoreWorkerHandler.ts b/packages/beacon-node/src/network/core/networkCoreWorkerHandler.ts index bd66a21e726b..e883476b5e65 100644 --- a/packages/beacon-node/src/network/core/networkCoreWorkerHandler.ts +++ b/packages/beacon-node/src/network/core/networkCoreWorkerHandler.ts @@ -3,8 +3,8 @@ import workerThreads from "node:worker_threads"; import {PeerScoreStatsDump} from "@chainsafe/libp2p-gossipsub/dist/src/score/peer-score.js"; import {PublishOpts} from "@chainsafe/libp2p-gossipsub/types"; import {ModuleThread, Thread, Worker, spawn} from "@chainsafe/threads"; -import {PeerId, Secp256k1PeerId} from "@libp2p/interface"; -import {exportToProtobuf} from "@libp2p/peer-id-factory"; +import {PrivateKey} from "@libp2p/interface"; +import {privateKeyToProtobuf} from "@libp2p/crypto/keys"; import {routes} from "@lodestar/api"; import {BeaconConfig, chainConfigToJson} from "@lodestar/config"; import type {LoggerNode} from "@lodestar/logger/node"; @@ -44,7 +44,7 @@ export type WorkerNetworkCoreInitModules = { opts: WorkerNetworkCoreOpts; config: BeaconConfig; logger: LoggerNode; - peerId: PeerId; + privateKey: PrivateKey; events: NetworkEventBus; metrics: Metrics | null; getReqRespHandler: GetReqRespHandlerFn; @@ -103,14 +103,14 @@ export class WorkerNetworkCore implements INetworkCore { } static async init(modules: WorkerNetworkCoreInitModules): Promise { - const {opts, config, peerId} = modules; + const {opts, config, privateKey} = modules; const {genesisTime, peerStoreDir, activeValidatorCount, localMultiaddrs, metricsEnabled, initialStatus} = opts; const workerData: NetworkWorkerData = { opts, chainConfigJson: chainConfigToJson(config), genesisValidatorsRoot: config.genesisValidatorsRoot, - peerIdProto: exportToProtobuf(peerId as Secp256k1PeerId), + privateKeyProto: privateKeyToProtobuf(privateKey), localMultiaddrs, metricsEnabled, peerStoreDir, diff --git a/packages/beacon-node/src/network/core/types.ts b/packages/beacon-node/src/network/core/types.ts index 4eeaf96e1903..d2f56c8fa2f1 100644 --- a/packages/beacon-node/src/network/core/types.ts +++ b/packages/beacon-node/src/network/core/types.ts @@ -78,7 +78,7 @@ export type NetworkWorkerData = { genesisTime: number; activeValidatorCount: number; initialStatus: phase0.Status; - peerIdProto: Uint8Array; + privateKeyProto: Uint8Array; localMultiaddrs: string[]; metricsEnabled: boolean; peerStoreDir?: string; diff --git a/packages/beacon-node/src/network/discv5/index.ts b/packages/beacon-node/src/network/discv5/index.ts index 745b3171c38d..34990d404c90 100644 --- a/packages/beacon-node/src/network/discv5/index.ts +++ b/packages/beacon-node/src/network/discv5/index.ts @@ -1,8 +1,8 @@ import EventEmitter from "node:events"; -import {PeerId, Secp256k1PeerId} from "@libp2p/interface"; +import {privateKeyToProtobuf} from "@libp2p/crypto/keys"; +import {PrivateKey} from "@libp2p/interface"; import {StrictEventEmitter} from "strict-event-emitter-types"; -import {exportToProtobuf} from "@libp2p/peer-id-factory"; -import {createPrivateKeyFromPeerId, ENR, ENRData, SignableENR} from "@chainsafe/enr"; +import {ENR, ENRData, SignableENR} from "@chainsafe/enr"; import {spawn, Thread, Worker} from "@chainsafe/threads"; import {chainConfigFromJson, chainConfigToJson, BeaconConfig} from "@lodestar/config"; import {LoggerNode} from "@lodestar/logger/node"; @@ -10,7 +10,7 @@ import {NetworkCoreMetrics} from "../core/metrics.js"; import {Discv5WorkerApi, Discv5WorkerData, LodestarDiscv5Opts} from "./types.js"; export type Discv5Opts = { - peerId: PeerId; + privateKey: PrivateKey; discv5: LodestarDiscv5Opts; logger: LoggerNode; config: BeaconConfig; @@ -25,7 +25,6 @@ export type Discv5Events = { * Wrapper class abstracting the details of discv5 worker instantiation and message-passing */ export class Discv5Worker extends (EventEmitter as {new (): StrictEventEmitter}) { - private readonly keypair; private readonly subscription: {unsubscribe: () => void}; private closed = false; @@ -35,14 +34,13 @@ export class Discv5Worker extends (EventEmitter as {new (): StrictEventEmitter this.onDiscovered(enrObj)); } static async init(opts: Discv5Opts): Promise { const workerData: Discv5WorkerData = { enr: opts.discv5.enr, - peerIdProto: exportToProtobuf(opts.peerId as Secp256k1PeerId), + privateKeyProto: privateKeyToProtobuf(opts.privateKey), bindAddrs: opts.discv5.bindAddrs, config: opts.discv5.config ?? {}, bootEnrs: opts.discv5.bootEnrs, @@ -80,7 +78,7 @@ export class Discv5Worker extends (EventEmitter as {new (): StrictEventEmitter { const obj = await this.workerApi.enr(); - return new SignableENR(obj.kvs, obj.seq, this.keypair.privateKey); + return new SignableENR(obj.kvs, obj.seq, this.opts.privateKey.raw); } setEnrValue(key: string, value: Uint8Array): Promise { diff --git a/packages/beacon-node/src/network/discv5/types.ts b/packages/beacon-node/src/network/discv5/types.ts index 63c5cd52b6fe..cbaf2423f87f 100644 --- a/packages/beacon-node/src/network/discv5/types.ts +++ b/packages/beacon-node/src/network/discv5/types.ts @@ -31,7 +31,7 @@ export type LodestarDiscv5Opts = { /** discv5 worker constructor data */ export interface Discv5WorkerData { enr: string; - peerIdProto: Uint8Array; + privateKeyProto: Uint8Array; bindAddrs: BindAddrs; config: Discv5Config; bootEnrs: string[]; diff --git a/packages/beacon-node/src/network/discv5/worker.ts b/packages/beacon-node/src/network/discv5/worker.ts index 8e96751d5fe7..40eb08f7af92 100644 --- a/packages/beacon-node/src/network/discv5/worker.ts +++ b/packages/beacon-node/src/network/discv5/worker.ts @@ -1,12 +1,13 @@ import worker from "node:worker_threads"; import path from "node:path"; import fs from "node:fs"; -import {createFromProtobuf} from "@libp2p/peer-id-factory"; import {Multiaddr, multiaddr} from "@multiformats/multiaddr"; import {expose} from "@chainsafe/threads/worker"; import {Observable, Subject} from "@chainsafe/threads/observable"; import {Discv5} from "@chainsafe/discv5"; -import {createPrivateKeyFromPeerId, ENR, ENRData, SignableENR, SignableENRData} from "@chainsafe/enr"; +import {ENR, ENRData, SignableENR, SignableENRData} from "@chainsafe/enr"; +import {privateKeyFromProtobuf} from "@libp2p/crypto/keys"; +import {peerIdFromPrivateKey} from "@libp2p/peer-id"; import {createBeaconConfig} from "@lodestar/config"; import {getNodeLogger} from "@lodestar/logger/node"; import {Gauge} from "@lodestar/utils"; @@ -42,15 +43,15 @@ if (workerData.metrics) { }); } -const peerId = await createFromProtobuf(workerData.peerIdProto); -const keypair = createPrivateKeyFromPeerId(peerId); +const privateKey = privateKeyFromProtobuf(workerData.privateKeyProto); +const peerId = peerIdFromPrivateKey(privateKey); const config = createBeaconConfig(workerData.chainConfig, workerData.genesisValidatorsRoot); // Initialize discv5 const discv5 = Discv5.create({ - enr: SignableENR.decodeTxt(workerData.enr, keypair.privateKey), - peerId, + enr: SignableENR.decodeTxt(workerData.enr, privateKey.raw), + privateKey, bindAddrs: { ip4: (workerData.bindAddrs.ip4 ? multiaddr(workerData.bindAddrs.ip4) : undefined) as Multiaddr, ip6: workerData.bindAddrs.ip6 ? multiaddr(workerData.bindAddrs.ip6) : undefined, diff --git a/packages/beacon-node/src/network/gossip/gossipsub.ts b/packages/beacon-node/src/network/gossip/gossipsub.ts index 1fc326ba1e58..debcbaf89854 100644 --- a/packages/beacon-node/src/network/gossip/gossipsub.ts +++ b/packages/beacon-node/src/network/gossip/gossipsub.ts @@ -135,6 +135,10 @@ export class Eth2Gossipsub extends GossipSub { // if this is false, only publish to mesh peers. If there is not enough GOSSIP_D mesh peers, // publish to some more topic peers to make sure we always publish to at least GOSSIP_D peers floodPublish: !opts?.disableFloodPublish, + // Only send IDONTWANT messages if the message size is larger than this + // This should be large enough to not send IDONTWANT for "small" messages + // See https://github.com/ChainSafe/lodestar/pull/7077#issuecomment-2383679472 + idontwantMinDataSize: 16829, }); this.scoreParams = scoreParams; this.config = config; diff --git a/packages/beacon-node/src/network/interface.ts b/packages/beacon-node/src/network/interface.ts index 8d73379af221..ccb5ddecb557 100644 --- a/packages/beacon-node/src/network/interface.ts +++ b/packages/beacon-node/src/network/interface.ts @@ -12,10 +12,11 @@ import { PeerRouting, PeerStore, Upgrader, + PrivateKey, } from "@libp2p/interface"; import type {AddressManager, ConnectionManager, Registrar, TransportManager} from "@libp2p/interface-internal"; import type {Datastore} from "interface-datastore"; -import {Identify} from "@chainsafe/libp2p-identify"; +import {Identify} from "@libp2p/identify"; import { LightClientFinalityUpdate, LightClientOptimisticUpdate, @@ -93,6 +94,7 @@ export interface INetwork extends INetworkCorePublic { export type LodestarComponents = { peerId: PeerId; + privateKey: PrivateKey; nodeInfo: NodeInfo; logger: ComponentLogger; events: TypedEventTarget; diff --git a/packages/beacon-node/src/network/libp2p/index.ts b/packages/beacon-node/src/network/libp2p/index.ts index a0d58033cf2f..7697dbcb49a7 100644 --- a/packages/beacon-node/src/network/libp2p/index.ts +++ b/packages/beacon-node/src/network/libp2p/index.ts @@ -1,8 +1,7 @@ -import {PeerId} from "@libp2p/interface"; +import {PrivateKey} from "@libp2p/interface"; import {Registry} from "prom-client"; import {ENR} from "@chainsafe/enr"; -// TODO: We should use this fork until https://github.com/libp2p/js-libp2p/pull/2387 -import {identify} from "@chainsafe/libp2p-identify"; +import {identify} from "@libp2p/identify"; import {bootstrap} from "@libp2p/bootstrap"; import {mdns} from "@libp2p/mdns"; import {createLibp2p} from "libp2p"; @@ -34,7 +33,7 @@ export async function getDiscv5Multiaddrs(bootEnrs: string[]): Promise } export async function createNodeJsLibp2p( - peerId: PeerId, + privateKey: PrivateKey, networkOpts: Partial = {}, nodeJsLibp2pOpts: NodeJsLibp2pOpts = {} ): Promise { @@ -65,12 +64,12 @@ export async function createNodeJsLibp2p( } return createLibp2p({ - peerId, + privateKey, addresses: { listen: localMultiaddrs, announce: [], }, - connectionEncryption: [noise()], + connectionEncrypters: [noise()], // Reject connections when the server's connection count gets high transports: [ tcp({ @@ -99,15 +98,14 @@ export async function createNodeJsLibp2p( maxParallelDials: 100, maxPeerAddrsToDial: 4, dialTimeout: 30_000, - - // Rely entirely on lodestar's peer manager to prune connections - //maxConnections: options.maxConnections, - // DOCS: There is no way to turn off autodial other than setting minConnections to 0 - minConnections: 0, // the maximum number of pending connections libp2p will accept before it starts rejecting incoming connections. // make it the same to backlog option above maxIncomingPendingConnections: 5, }, + // rely on lodestar's peer manager to ping peers + connectionMonitor: { + enabled: false, + }, datastore, services: { identify: identify({ @@ -118,6 +116,7 @@ export async function createNodeJsLibp2p( // and passing it here directly causes problems downstream, not to mention is slowwww components: (components: LodestarComponents) => ({ peerId: components.peerId, + privateKey: components.privateKey, nodeInfo: components.nodeInfo, logger: components.logger, events: components.events, diff --git a/packages/beacon-node/src/network/network.ts b/packages/beacon-node/src/network/network.ts index 1b3ccaaaf75a..73208f497d66 100644 --- a/packages/beacon-node/src/network/network.ts +++ b/packages/beacon-node/src/network/network.ts @@ -1,6 +1,7 @@ -import {PeerId} from "@libp2p/interface"; +import {PeerId, PrivateKey} from "@libp2p/interface"; import {PublishOpts} from "@chainsafe/libp2p-gossipsub/types"; import {PeerScoreStatsDump} from "@chainsafe/libp2p-gossipsub/score"; +import {peerIdFromPrivateKey} from "@libp2p/peer-id"; import {BeaconConfig} from "@lodestar/config"; import {sleep} from "@lodestar/utils"; import {LoggerNode} from "@lodestar/logger/node"; @@ -50,7 +51,7 @@ import {getActiveForks} from "./forks.js"; type NetworkModules = { opts: NetworkOptions; - peerId: PeerId; + privateKey: PrivateKey; config: BeaconConfig; logger: LoggerNode; chain: IBeaconChain; @@ -63,7 +64,7 @@ type NetworkModules = { export type NetworkInitModules = { opts: NetworkOptions; config: BeaconConfig; - peerId: PeerId; + privateKey: PrivateKey; peerStoreDir?: string; logger: LoggerNode; metrics: Metrics | null; @@ -104,7 +105,7 @@ export class Network implements INetwork { private regossipBlsChangesPromise: Promise | null = null; constructor(modules: NetworkModules) { - this.peerId = modules.peerId; + this.peerId = peerIdFromPrivateKey(modules.privateKey); this.config = modules.config; this.logger = modules.logger; this.chain = modules.chain; @@ -134,7 +135,7 @@ export class Network implements INetwork { chain, db, gossipHandlers, - peerId, + privateKey, peerStoreDir, getReqRespHandler, }: NetworkInitModules): Promise { @@ -159,7 +160,7 @@ export class Network implements INetwork { initialStatus, }, config, - peerId, + privateKey, logger, events, metrics, @@ -168,7 +169,7 @@ export class Network implements INetwork { : await NetworkCore.init({ opts, config, - peerId, + privateKey, peerStoreDir, logger, clock: chain.clock, @@ -185,11 +186,12 @@ export class Network implements INetwork { ); const multiaddresses = opts.localMultiaddrs?.join(","); + const peerId = peerIdFromPrivateKey(privateKey); logger.info(`PeerId ${peerIdToString(peerId)}, Multiaddrs ${multiaddresses}`); return new Network({ opts, - peerId, + privateKey, config, logger, chain, diff --git a/packages/beacon-node/src/network/peers/datastore.ts b/packages/beacon-node/src/network/peers/datastore.ts index 88a7a6f5f2d6..e0f2001c26ee 100644 --- a/packages/beacon-node/src/network/peers/datastore.ts +++ b/packages/beacon-node/src/network/peers/datastore.ts @@ -1,3 +1,4 @@ +import {AbortOptions} from "@libp2p/interface"; import {BaseDatastore} from "datastore-core"; import {LevelDatastore} from "datastore-level"; import {Key, KeyQuery, Query, Pair} from "interface-datastore"; @@ -57,7 +58,7 @@ export class Eth2PeerDataStore extends BaseDatastore { return this._dbDatastore.close(); } - async put(key: Key, val: Uint8Array): Promise { + async put(key: Key, val: Uint8Array, _options?: AbortOptions): Promise { return this._put(key, val, false); } diff --git a/packages/beacon-node/src/network/peers/discover.ts b/packages/beacon-node/src/network/peers/discover.ts index 9e06a39b4fb4..d3bfd2d2aab4 100644 --- a/packages/beacon-node/src/network/peers/discover.ts +++ b/packages/beacon-node/src/network/peers/discover.ts @@ -1,5 +1,5 @@ import {Multiaddr} from "@multiformats/multiaddr"; -import type {PeerId, PeerInfo} from "@libp2p/interface"; +import type {PeerId, PeerInfo, PrivateKey} from "@libp2p/interface"; import {ENR} from "@chainsafe/enr"; import {BeaconConfig} from "@lodestar/config"; import {pruneSetToMax, sleep} from "@lodestar/utils"; @@ -27,6 +27,7 @@ export type PeerDiscoveryOpts = { }; export type PeerDiscoveryModules = { + privateKey: PrivateKey; libp2p: Libp2p; peerRpcScores: IPeerRpcScoreStore; metrics: NetworkCoreMetrics | null; @@ -158,7 +159,7 @@ export class PeerDiscovery { static async init(modules: PeerDiscoveryModules, opts: PeerDiscoveryOpts): Promise { const discv5 = await Discv5Worker.init({ discv5: opts.discv5, - peerId: modules.libp2p.peerId, + privateKey: modules.privateKey, metrics: modules.metrics ?? undefined, logger: modules.logger, config: modules.config, @@ -323,8 +324,7 @@ export class PeerDiscovery { if (this.randomNodeQuery.code === QueryStatusCode.Active) { this.randomNodeQuery.count++; } - // async due to some crypto that's no longer necessary - const peerId = await enr.peerId(); + const peerId = enr.peerId; // tcp multiaddr is known to be be present, checked inside the worker const multiaddrTCP = enr.getLocationMultiaddr(ENRKey.tcp); if (!multiaddrTCP) { @@ -473,7 +473,7 @@ export class PeerDiscovery { /** Check if there is 1+ open connection with this peer */ private isPeerConnected(peerIdStr: PeerIdStr): boolean { const connections = getConnectionsMap(this.libp2p).get(peerIdStr); - return Boolean(connections && connections.some((connection) => connection.status === "open")); + return Boolean(connections && connections.value.some((connection) => connection.status === "open")); } } diff --git a/packages/beacon-node/src/network/peers/peerManager.ts b/packages/beacon-node/src/network/peers/peerManager.ts index 3971e2147707..7894b63e0be2 100644 --- a/packages/beacon-node/src/network/peers/peerManager.ts +++ b/packages/beacon-node/src/network/peers/peerManager.ts @@ -1,4 +1,4 @@ -import {Connection, PeerId} from "@libp2p/interface"; +import {Connection, PeerId, PrivateKey} from "@libp2p/interface"; import {BitArray} from "@chainsafe/ssz"; import {SYNC_COMMITTEE_SUBNET_COUNT} from "@lodestar/params"; import {BeaconConfig} from "@lodestar/config"; @@ -94,6 +94,7 @@ export interface IReqRespBeaconNodePeerManager { } export type PeerManagerModules = { + privateKey: PrivateKey; libp2p: Libp2p; logger: LoggerNode; metrics: NetworkCoreMetrics | null; @@ -685,7 +686,7 @@ export class PeerManager { } for (const connections of getConnectionsMap(this.libp2p).values()) { - const openCnx = connections.find((cnx) => cnx.status === "open"); + const openCnx = connections.value.find((cnx) => cnx.status === "open"); if (openCnx) { const direction = openCnx.direction; peersByDirection.set(direction, 1 + (peersByDirection.get(direction) ?? 0)); diff --git a/packages/beacon-node/src/network/peers/utils/getConnectedPeerIds.ts b/packages/beacon-node/src/network/peers/utils/getConnectedPeerIds.ts index 8542df605b06..d001c0d8892a 100644 --- a/packages/beacon-node/src/network/peers/utils/getConnectedPeerIds.ts +++ b/packages/beacon-node/src/network/peers/utils/getConnectedPeerIds.ts @@ -8,7 +8,7 @@ import {getConnectionsMap} from "../../util.js"; export function getConnectedPeerIds(libp2p: Libp2p): PeerId[] { const peerIds: PeerId[] = []; for (const connections of getConnectionsMap(libp2p).values()) { - const openConnection = connections.find(isConnectionOpen); + const openConnection = connections.value.find(isConnectionOpen); if (openConnection) { peerIds.push(openConnection.remotePeer); } @@ -21,7 +21,7 @@ export function getConnectedPeerIds(libp2p: Libp2p): PeerId[] { */ export function hasSomeConnectedPeer(libp2p: Libp2p): boolean { for (const connections of getConnectionsMap(libp2p).values()) { - if (connections.some(isConnectionOpen)) { + if (connections.value.some(isConnectionOpen)) { return true; } } diff --git a/packages/beacon-node/src/network/util.ts b/packages/beacon-node/src/network/util.ts index 835096afbfc8..2be4756fe693 100644 --- a/packages/beacon-node/src/network/util.ts +++ b/packages/beacon-node/src/network/util.ts @@ -14,12 +14,12 @@ export function prettyPrintPeerIdStr(id: PeerIdStr): string { * Get the connections map from a connection manager */ // Compat function for efficiency reasons -export function getConnectionsMap(libp2p: Libp2p): Map { +export function getConnectionsMap(libp2p: Libp2p): Map { return libp2p.services.components.connectionManager.getConnectionsMap()["map"]; } export function getConnection(libp2p: Libp2p, peerIdStr: string): Connection | undefined { - return getConnectionsMap(libp2p).get(peerIdStr)?.[0] ?? undefined; + return getConnectionsMap(libp2p).get(peerIdStr)?.value[0] ?? undefined; } // https://github.com/ChainSafe/js-libp2p-gossipsub/blob/3475242ed254f7647798ab7f36b21909f6cb61da/src/index.ts#L2009 diff --git a/packages/beacon-node/src/node/nodejs.ts b/packages/beacon-node/src/node/nodejs.ts index 088541a6b5d5..7b42f0daceb2 100644 --- a/packages/beacon-node/src/node/nodejs.ts +++ b/packages/beacon-node/src/node/nodejs.ts @@ -1,7 +1,7 @@ import {setMaxListeners} from "node:events"; import {Registry} from "prom-client"; -import {PeerId} from "@libp2p/interface"; +import {PrivateKey} from "@libp2p/interface"; import {BeaconConfig} from "@lodestar/config"; import {phase0} from "@lodestar/types"; import {sleep} from "@lodestar/utils"; @@ -49,7 +49,7 @@ export type BeaconNodeInitModules = { db: IBeaconDb; logger: LoggerNode; processShutdownCallback: ProcessShutdownCallback; - peerId: PeerId; + privateKey: PrivateKey; peerStoreDir?: string; anchorState: BeaconStateAllForks; wsCheckpoint?: phase0.Checkpoint; @@ -146,7 +146,7 @@ export class BeaconNode { db, logger, processShutdownCallback, - peerId, + privateKey, peerStoreDir, anchorState, wsCheckpoint, @@ -243,7 +243,7 @@ export class BeaconNode { metrics, chain, db, - peerId, + privateKey, peerStoreDir, getReqRespHandler: getReqRespHandlers({db, chain}), }); diff --git a/packages/beacon-node/src/util/peerId.ts b/packages/beacon-node/src/util/peerId.ts index 2afb9bed390e..c62f5416cdfe 100644 --- a/packages/beacon-node/src/util/peerId.ts +++ b/packages/beacon-node/src/util/peerId.ts @@ -12,5 +12,5 @@ export type PeerIdStr = string; export {peerIdFromString}; export function peerIdToString(peerId: PeerId): string { - return base58btc.encode(peerId.multihash.bytes).slice(1); + return base58btc.encode(peerId.toMultihash().bytes).slice(1); } diff --git a/packages/beacon-node/test/e2e/network/mdns.test.ts b/packages/beacon-node/test/e2e/network/mdns.test.ts index 4c49ca319a42..5c796df985b9 100644 --- a/packages/beacon-node/test/e2e/network/mdns.test.ts +++ b/packages/beacon-node/test/e2e/network/mdns.test.ts @@ -1,8 +1,8 @@ import {describe, it, afterEach, beforeEach, expect, vi} from "vitest"; -import {PeerId} from "@libp2p/interface"; +import {PrivateKey} from "@libp2p/interface"; import {multiaddr} from "@multiformats/multiaddr"; -import {createSecp256k1PeerId} from "@libp2p/peer-id-factory"; import {SignableENR} from "@chainsafe/enr"; +import {generateKeyPair} from "@libp2p/crypto/keys"; import {createBeaconConfig} from "@lodestar/config"; import {config} from "@lodestar/config/default"; import {ssz} from "@lodestar/types"; @@ -34,9 +34,9 @@ describe.skip("mdns", function () { }); afterEach(() => controller.abort()); - async function getOpts(peerId: PeerId): Promise { + async function getOpts(privateKey: PrivateKey): Promise { const bindAddrUdp = `/ip4/0.0.0.0/udp/${port++}`; - const enr = SignableENR.createFromPeerId(peerId); + const enr = SignableENR.createFromPrivateKey(privateKey); enr.setLocationMultiaddr(multiaddr(bindAddrUdp)); return { @@ -80,12 +80,12 @@ describe.skip("mdns", function () { const db = getMockedBeaconDb(); const gossipHandlers = {} as GossipHandlers; - const peerId = await createSecp256k1PeerId(); + const privateKey = await generateKeyPair("secp256k1"); const logger = testLogger(nodeName); - const opts = await getOpts(peerId); + const opts = await getOpts(privateKey); - const modules: Omit = { + const modules: Omit = { config, chain, db, @@ -96,7 +96,7 @@ describe.skip("mdns", function () { const network = await Network.init({ ...modules, - ...(await createNetworkModules(mu, peerId, {...opts, mdns: true})), + ...(await createNetworkModules(mu, privateKey, {...opts, mdns: true})), logger, }); diff --git a/packages/beacon-node/test/e2e/network/peers/peerManager.test.ts b/packages/beacon-node/test/e2e/network/peers/peerManager.test.ts index b690b9ab4988..e872a3882945 100644 --- a/packages/beacon-node/test/e2e/network/peers/peerManager.test.ts +++ b/packages/beacon-node/test/e2e/network/peers/peerManager.test.ts @@ -1,7 +1,7 @@ import {describe, it, afterEach, expect, vi} from "vitest"; import {Connection} from "@libp2p/interface"; -import {CustomEvent} from "@libp2p/interface"; import {BitArray} from "@chainsafe/ssz"; +import {generateKeyPair} from "@libp2p/crypto/keys"; import {config} from "@lodestar/config/default"; import {altair, phase0, ssz} from "@lodestar/types"; import {sleep} from "@lodestar/utils"; @@ -47,7 +47,8 @@ describe("network / peers / PeerManager", function () { const clock = new Clock({config: beaconConfig, genesisTime: 0, signal: controller.signal}); const status = ssz.phase0.Status.defaultValue(); const statusCache = new LocalStatusCache(status); - const libp2p = await createNode("/ip4/127.0.0.1/tcp/0"); + const privateKey = await generateKeyPair("secp256k1"); + const libp2p = await createNode("/ip4/127.0.0.1/tcp/0", privateKey); afterEachCallbacks.push(async () => { controller.abort(); @@ -68,6 +69,7 @@ describe("network / peers / PeerManager", function () { const peerManager = new PeerManager( { + privateKey, libp2p, reqResp, logger, @@ -158,7 +160,7 @@ describe("network / peers / PeerManager", function () { const {statusCache, libp2p, networkEventBus} = await mockModules(); // Simualate a peer connection, get() should return truthy - getConnectionsMap(libp2p).set(peerId1.toString(), [libp2pConnectionOutboud]); + getConnectionsMap(libp2p).set(peerId1.toString(), {key: peerId1, value: [libp2pConnectionOutboud]}); // Subscribe to `peerConnected` event, which must fire after checking peer relevance const peerConnectedPromise = waitForEvent(networkEventBus, NetworkEvent.peerConnected, 2000); @@ -177,7 +179,7 @@ describe("network / peers / PeerManager", function () { const {statusCache, libp2p, reqResp, peerManager, networkEventBus} = await mockModules(); // Simualate a peer connection, get() should return truthy - getConnectionsMap(libp2p).set(peerId1.toString(), [libp2pConnectionOutboud]); + getConnectionsMap(libp2p).set(peerId1.toString(), {key: peerId1, value: [libp2pConnectionOutboud]}); // Subscribe to `peerConnected` event, which must fire after checking peer relevance const peerConnectedPromise = waitForEvent(networkEventBus, NetworkEvent.peerConnected, 2000); @@ -190,7 +192,7 @@ describe("network / peers / PeerManager", function () { reqResp.sendMetadata.mockResolvedValue(remoteMetadata); // Simualate a peer connection, get() should return truthy - getConnectionsMap(libp2p).set(peerId1.toString(), [libp2pConnectionOutboud]); + getConnectionsMap(libp2p).set(peerId1.toString(), {key: peerId1, value: [libp2pConnectionOutboud]}); libp2p.services.components.events.dispatchEvent( new CustomEvent("connection:open", {detail: libp2pConnectionOutboud}) ); diff --git a/packages/beacon-node/test/e2e/network/reqrespEncode.test.ts b/packages/beacon-node/test/e2e/network/reqrespEncode.test.ts index d8d02c203dd9..123a4da420f0 100644 --- a/packages/beacon-node/test/e2e/network/reqrespEncode.test.ts +++ b/packages/beacon-node/test/e2e/network/reqrespEncode.test.ts @@ -40,7 +40,7 @@ describe("reqresp encoder", () => { const libp2p = await createLibp2p({ transports: [tcp()], streamMuxers: [mplex()], - connectionEncryption: [noise()], + connectionEncrypters: [noise()], addresses: { listen: [listen], }, diff --git a/packages/beacon-node/test/perf/network/noise/sendData.test.ts b/packages/beacon-node/test/perf/network/noise/sendData.test.ts index 35538a417adf..49e37980a598 100644 --- a/packages/beacon-node/test/perf/network/noise/sendData.test.ts +++ b/packages/beacon-node/test/perf/network/noise/sendData.test.ts @@ -1,11 +1,12 @@ import {itBench} from "@dapplion/benchmark"; import {duplexPair} from "it-pair/duplex"; -import {createSecp256k1PeerId} from "@libp2p/peer-id-factory"; import {pipe} from "it-pipe"; import drain from "it-drain"; import {defaultLogger} from "@libp2p/logger"; import {noise} from "@chainsafe/libp2p-noise"; import {Uint8ArrayList} from "uint8arraylist"; +import {generateKeyPair} from "@libp2p/crypto/keys"; +import {peerIdFromPrivateKey} from "@libp2p/peer-id"; describe("network / noise / sendData", () => { const numberOfMessages = 1000; @@ -24,15 +25,17 @@ describe("network / noise / sendData", () => { itBench({ id: `send data - ${numberOfMessages} ${messageLength}B messages`, beforeEach: async () => { - const peerA = await createSecp256k1PeerId(); - const peerB = await createSecp256k1PeerId(); - const noiseA = noise()({logger: defaultLogger()}); - const noiseB = noise()({logger: defaultLogger()}); + const privateKeyA = await generateKeyPair("secp256k1"); + const privateKeyB = await generateKeyPair("secp256k1"); + const peerA = peerIdFromPrivateKey(privateKeyA); + const peerB = peerIdFromPrivateKey(privateKeyB); + const noiseA = noise()({logger: defaultLogger(), privateKey: privateKeyA, peerId: peerA}); + const noiseB = noise()({logger: defaultLogger(), privateKey: privateKeyB, peerId: peerB}); const [inboundConnection, outboundConnection] = duplexPair(); const [outbound, inbound] = await Promise.all([ - noiseA.secureOutbound(peerA, outboundConnection, peerB), - noiseB.secureInbound(peerB, inboundConnection, peerA), + noiseA.secureOutbound(outboundConnection, {remotePeer: peerB}), + noiseB.secureInbound(inboundConnection, {remotePeer: peerA}), ]); return {connA: outbound.conn, connB: inbound.conn, data: new Uint8Array(messageLength)}; diff --git a/packages/beacon-node/test/perf/network/peers/util/prioritizePeers.test.ts b/packages/beacon-node/test/perf/network/peers/util/prioritizePeers.test.ts index a0d648a161ea..ecc30ebacef9 100644 --- a/packages/beacon-node/test/perf/network/peers/util/prioritizePeers.test.ts +++ b/packages/beacon-node/test/perf/network/peers/util/prioritizePeers.test.ts @@ -1,6 +1,7 @@ import {itBench} from "@dapplion/benchmark"; import {PeerId} from "@libp2p/interface"; -import {createSecp256k1PeerId} from "@libp2p/peer-id-factory"; +import {generateKeyPair} from "@libp2p/crypto/keys"; +import {peerIdFromPrivateKey} from "@libp2p/peer-id"; import {ATTESTATION_SUBNET_COUNT, SYNC_COMMITTEE_SUBNET_COUNT} from "@lodestar/params"; import {altair, phase0} from "@lodestar/types"; import {defaultNetworkOptions} from "../../../../../src/network/options.js"; @@ -12,7 +13,8 @@ describe("prioritizePeers", () => { before(async function () { for (let i = 0; i < defaultNetworkOptions.maxPeers; i++) { - const peer = await createSecp256k1PeerId(); + const pk = await generateKeyPair("secp256k1"); + const peer = peerIdFromPrivateKey(pk); peer.toString = () => `peer-${i}`; seedPeers.push({ id: peer, diff --git a/packages/beacon-node/test/unit/network/peers/priorization.test.ts b/packages/beacon-node/test/unit/network/peers/priorization.test.ts index cc9ef9b7d711..5b318a9b007f 100644 --- a/packages/beacon-node/test/unit/network/peers/priorization.test.ts +++ b/packages/beacon-node/test/unit/network/peers/priorization.test.ts @@ -1,7 +1,8 @@ import {PeerId} from "@libp2p/interface"; -import {createSecp256k1PeerId} from "@libp2p/peer-id-factory"; import {BitArray} from "@chainsafe/ssz"; import {describe, it, expect} from "vitest"; +import {generateKeyPair} from "@libp2p/crypto/keys"; +import {peerIdFromPrivateKey} from "@libp2p/peer-id"; import {ATTESTATION_SUBNET_COUNT} from "@lodestar/params"; import { ExcessPeerDisconnectReason, @@ -17,7 +18,8 @@ type Result = ReturnType; describe("network / peers / priorization", async () => { const peers: PeerId[] = []; for (let i = 0; i < 8; i++) { - const peer = await createSecp256k1PeerId(); + const pk = await generateKeyPair("secp256k1"); + const peer = peerIdFromPrivateKey(pk); peer.toString = () => `peer-${i}`; peers.push(peer); } @@ -266,7 +268,8 @@ describe("network / peers / priorization", async () => { describe("sortPeersToPrune", async function () { const peers: PeerId[] = []; for (let i = 0; i < 8; i++) { - const peer = await createSecp256k1PeerId(); + const pk = await generateKeyPair("secp256k1"); + const peer = peerIdFromPrivateKey(pk); peer.toString = () => `peer-${i}`; peers.push(peer); } diff --git a/packages/beacon-node/test/utils/network.ts b/packages/beacon-node/test/utils/network.ts index 56c831b269f5..71bb0bd255da 100644 --- a/packages/beacon-node/test/utils/network.ts +++ b/packages/beacon-node/test/utils/network.ts @@ -1,6 +1,6 @@ import {BitArray} from "@chainsafe/ssz"; -import {PeerId} from "@libp2p/interface"; -import {createSecp256k1PeerId} from "@libp2p/peer-id-factory"; +import {PrivateKey} from "@libp2p/interface"; +import {generateKeyPair} from "@libp2p/crypto/keys"; import {ATTESTATION_SUBNET_COUNT, SYNC_COMMITTEE_SUBNET_COUNT} from "@lodestar/params"; import {INetwork, Network, NetworkEvent} from "../../src/network/index.js"; import {Libp2p} from "../../src/network/interface.js"; @@ -8,18 +8,17 @@ import {createNodeJsLibp2p} from "../../src/network/libp2p/index.js"; import {NetworkOptions, defaultNetworkOptions} from "../../src/network/options.js"; import {PeerIdStr} from "../../src/util/peerId.js"; -export async function createNode(multiaddr: string, inPeerId?: PeerId): Promise { - const peerId = inPeerId || (await createSecp256k1PeerId()); - return createNodeJsLibp2p(peerId, {localMultiaddrs: [multiaddr]}); +export async function createNode(multiaddr: string, privateKey?: PrivateKey): Promise { + return createNodeJsLibp2p(privateKey ?? (await generateKeyPair("secp256k1")), {localMultiaddrs: [multiaddr]}); } export async function createNetworkModules( multiaddr: string, - peerId?: PeerId, + privateKey?: PrivateKey, opts?: Partial -): Promise<{opts: NetworkOptions; peerId: PeerId}> { +): Promise<{opts: NetworkOptions; privateKey: PrivateKey}> { return { - peerId: peerId ?? (await createSecp256k1PeerId()), + privateKey: privateKey ?? (await generateKeyPair("secp256k1")), opts: {...defaultNetworkOptions, ...opts, localMultiaddrs: [multiaddr]}, }; } diff --git a/packages/beacon-node/test/utils/networkWithMockDb.ts b/packages/beacon-node/test/utils/networkWithMockDb.ts index f8a4a6181d2f..b1c4293588d2 100644 --- a/packages/beacon-node/test/utils/networkWithMockDb.ts +++ b/packages/beacon-node/test/utils/networkWithMockDb.ts @@ -1,4 +1,4 @@ -import {createSecp256k1PeerId} from "@libp2p/peer-id-factory"; +import {generateKeyPair} from "@libp2p/crypto/keys"; import {ChainForkConfig, createBeaconConfig} from "@lodestar/config"; import {ssz} from "@lodestar/types"; import {BeaconChain} from "../../src/chain/chain.js"; @@ -70,7 +70,7 @@ export async function getNetworkForTest( } ); - const modules: Omit = { + const modules: Omit = { config: beaconConfig, chain, db, @@ -81,7 +81,7 @@ export async function getNetworkForTest( const network = await Network.init({ ...modules, - peerId: await createSecp256k1PeerId(), + privateKey: await generateKeyPair("secp256k1"), opts: { ...defaultNetworkOptions, maxPeers: 1, diff --git a/packages/beacon-node/test/utils/node/beacon.ts b/packages/beacon-node/test/utils/node/beacon.ts index 0163fa148102..746c2cde5fd4 100644 --- a/packages/beacon-node/test/utils/node/beacon.ts +++ b/packages/beacon-node/test/utils/node/beacon.ts @@ -1,7 +1,7 @@ import deepmerge from "deepmerge"; import tmp from "tmp"; -import {PeerId} from "@libp2p/interface"; -import {createSecp256k1PeerId} from "@libp2p/peer-id-factory"; +import {PrivateKey} from "@libp2p/interface"; +import {generateKeyPair} from "@libp2p/crypto/keys"; import {config as minimalConfig} from "@lodestar/config/default"; import {createBeaconConfig, createChainForkConfig, ChainConfig} from "@lodestar/config"; import {RecursivePartial} from "@lodestar/utils"; @@ -26,16 +26,16 @@ export async function getDevBeaconNode( options?: RecursivePartial; validatorCount?: number; logger?: LoggerNode; - peerId?: PeerId; + privateKey?: PrivateKey; peerStoreDir?: string; anchorState?: BeaconStateAllForks; wsCheckpoint?: phase0.Checkpoint; } & InteropStateOpts ): Promise { const {params, validatorCount = 8, peerStoreDir} = opts; - let {options = {}, logger, peerId} = opts; + let {options = {}, logger, privateKey} = opts; - if (!peerId) peerId = await createSecp256k1PeerId(); + if (!privateKey) privateKey = await generateKeyPair("secp256k1"); const tmpDir = tmp.dirSync({unsafeCleanup: true}); const config = createChainForkConfig({...minimalConfig, ...params}); logger = logger ?? testLogger(); @@ -93,7 +93,7 @@ export async function getDevBeaconNode( db, logger, processShutdownCallback: () => {}, - peerId, + privateKey, peerStoreDir, anchorState, wsCheckpoint: opts.wsCheckpoint, diff --git a/packages/beacon-node/test/utils/peer.ts b/packages/beacon-node/test/utils/peer.ts index 8bd5c6c67be8..aeec92bf994e 100644 --- a/packages/beacon-node/test/utils/peer.ts +++ b/packages/beacon-node/test/utils/peer.ts @@ -1,6 +1,6 @@ import {PeerId} from "@libp2p/interface"; -import {createSecp256k1PeerId} from "@libp2p/peer-id-factory"; -import {peerIdFromBytes} from "@libp2p/peer-id"; +import {peerIdFromPrivateKey, peerIdFromPublicKey} from "@libp2p/peer-id"; +import {generateKeyPair, publicKeyFromProtobuf} from "@libp2p/crypto/keys"; import {peerIdToString} from "../../src/util/peerId.js"; /** @@ -9,11 +9,11 @@ import {peerIdToString} from "../../src/util/peerId.js"; */ export function getValidPeerId(): PeerId { const id = Buffer.from("002508021221039481269fe831799b1a0f1d521c1395b4831514859e4559c44d155eae46f03819", "hex"); - return peerIdFromBytes(id); + return peerIdFromPublicKey(publicKeyFromProtobuf(id)); } export async function getRandPeerIdStr(): Promise { - return peerIdToString(await createSecp256k1PeerId()); + return peerIdToString(peerIdFromPrivateKey(await generateKeyPair("secp256k1"))); } export const validPeerIdStr = peerIdToString(getValidPeerId()); diff --git a/packages/cli/package.json b/packages/cli/package.json index b4fc206e5a44..67d0dfd332cc 100644 --- a/packages/cli/package.json +++ b/packages/cli/package.json @@ -54,14 +54,14 @@ "@chainsafe/bls-keygen": "^0.4.0", "@chainsafe/bls-keystore": "^3.1.0", "@chainsafe/blst": "^2.0.3", - "@chainsafe/discv5": "^9.0.0", - "@chainsafe/enr": "^3.0.0", + "@chainsafe/discv5": "^10.0.1", + "@chainsafe/enr": "^4.0.1", "@chainsafe/persistent-merkle-tree": "^0.8.0", "@chainsafe/ssz": "^0.17.1", "@chainsafe/threads": "^1.11.1", - "@libp2p/crypto": "^4.1.0", - "@libp2p/peer-id": "^4.1.0", - "@libp2p/peer-id-factory": "^4.1.0", + "@libp2p/crypto": "^5.0.4", + "@libp2p/interface": "^2.1.2", + "@libp2p/peer-id": "^5.0.4", "@lodestar/api": "^1.22.0", "@lodestar/beacon-node": "^1.22.0", "@lodestar/config": "^1.22.0", diff --git a/packages/cli/src/cmds/beacon/handler.ts b/packages/cli/src/cmds/beacon/handler.ts index ea424e04824a..2a0238fede20 100644 --- a/packages/cli/src/cmds/beacon/handler.ts +++ b/packages/cli/src/cmds/beacon/handler.ts @@ -24,7 +24,7 @@ import {LogArgs} from "../../options/logOptions.js"; import {BeaconArgs} from "./options.js"; import {getBeaconPaths} from "./paths.js"; import {initBeaconState} from "./initBeaconState.js"; -import {initPeerIdAndEnr} from "./initPeerIdAndEnr.js"; +import {initPrivateKeyAndEnr} from "./initPeerIdAndEnr.js"; const DEFAULT_RETENTION_SSZ_OBJECTS_HOURS = 15 * 24; const HOURS_TO_MS = 3600 * 1000; @@ -34,7 +34,7 @@ const EIGHT_GB = 8 * 1024 * 1024 * 1024; * Runs a beacon node. */ export async function beaconHandler(args: BeaconArgs & GlobalArgs): Promise { - const {config, options, beaconPaths, network, version, commit, peerId, logger} = await beaconHandlerInit(args); + const {config, options, beaconPaths, network, version, commit, privateKey, logger} = await beaconHandlerInit(args); const heapSizeLimit = getHeapStatistics().heap_size_limit; if (heapSizeLimit < EIGHT_GB) { @@ -80,7 +80,7 @@ export async function beaconHandler(args: BeaconArgs & GlobalArgs): Promise { +): Promise<{privateKey: PrivateKey; enr: SignableENR}> { const {persistNetworkIdentity} = args; - const newPeerIdAndENR = async (): Promise<{peerId: PeerId; enr: SignableENR}> => { - const peerId = await createSecp256k1PeerId(); - const enr = SignableENR.createV4(createPrivateKeyFromPeerId(peerId).privateKey); - return {peerId, enr}; + const newPrivateKeyAndENR = async (): Promise<{privateKey: PrivateKey; enr: SignableENR}> => { + const privateKey = await generateKeyPair("secp256k1"); + const enr = SignableENR.createFromPrivateKey(privateKey); + return {privateKey, enr}; }; - const readPersistedPeerIdAndENR = async ( + const readPersistedPrivateKeyAndENR = async ( peerIdFile: string, enrFile: string - ): Promise<{peerId: PeerId; enr: SignableENR; newEnr: boolean}> => { - let peerId: PeerId; + ): Promise<{privateKey: PrivateKey; enr: SignableENR; newEnr: boolean}> => { + let privateKey: PrivateKey; let enr: SignableENR; // attempt to read stored peer id try { - peerId = await readPeerId(peerIdFile); + privateKey = readPrivateKey(peerIdFile); } catch (_e) { logger.warn("Unable to read peerIdFile, creating a new peer id"); - return {...(await newPeerIdAndENR()), newEnr: true}; + return {...(await newPrivateKeyAndENR()), newEnr: true}; } // attempt to read stored enr try { - enr = SignableENR.decodeTxt(fs.readFileSync(enrFile, "utf-8"), createPrivateKeyFromPeerId(peerId).privateKey); + enr = SignableENR.decodeTxt(fs.readFileSync(enrFile, "utf-8"), privateKey.raw); } catch (_e) { logger.warn("Unable to decode stored local ENR, creating a new ENR"); - enr = SignableENR.createV4(createPrivateKeyFromPeerId(peerId).privateKey); - return {peerId, enr, newEnr: true}; + enr = SignableENR.createFromPrivateKey(privateKey); + return {privateKey, enr, newEnr: true}; } // check stored peer id against stored enr - if (!peerId.equals(await enr.peerId())) { + if (!privateKey.equals(enr.peerId)) { logger.warn("Stored local ENR doesn't match peerIdFile, creating a new ENR"); - enr = SignableENR.createV4(createPrivateKeyFromPeerId(peerId).privateKey); - return {peerId, enr, newEnr: true}; + enr = SignableENR.createFromPrivateKey(privateKey); + return {privateKey, enr, newEnr: true}; } - return {peerId, enr, newEnr: false}; + return {privateKey, enr, newEnr: false}; }; if (persistNetworkIdentity) { const enrFile = path.join(beaconDir, "enr"); const peerIdFile = path.join(beaconDir, "peer-id.json"); - const {peerId, enr, newEnr} = await readPersistedPeerIdAndENR(peerIdFile, enrFile); + const {privateKey, enr, newEnr} = await readPersistedPrivateKeyAndENR(peerIdFile, enrFile); overwriteEnrWithCliArgs(enr, args, logger, {newEnr, bootnode}); // Re-persist peer-id and enr - writeFile600Perm(peerIdFile, exportToJSON(peerId)); + writeFile600Perm(peerIdFile, exportToJSON(privateKey)); writeFile600Perm(enrFile, enr.encodeTxt()); - return {peerId, enr}; + return {privateKey, enr}; } else { - const {peerId, enr} = await newPeerIdAndENR(); + const {privateKey, enr} = await newPrivateKeyAndENR(); overwriteEnrWithCliArgs(enr, args, logger, {newEnr: true, bootnode}); - return {peerId, enr}; + return {privateKey, enr}; } } diff --git a/packages/cli/src/cmds/bootnode/handler.ts b/packages/cli/src/cmds/bootnode/handler.ts index 8a262d8f12b7..9c093eed1272 100644 --- a/packages/cli/src/cmds/bootnode/handler.ts +++ b/packages/cli/src/cmds/bootnode/handler.ts @@ -10,7 +10,7 @@ import {getBeaconConfigFromArgs} from "../../config/index.js"; import {getNetworkBootnodes, isKnownNetworkName, readBootnodes} from "../../networks/index.js"; import {onGracefulShutdown, mkdir, writeFile600Perm} from "../../util/index.js"; import {getVersionData} from "../../util/version.js"; -import {initPeerIdAndEnr} from "../beacon/initPeerIdAndEnr.js"; +import {initPrivateKeyAndEnr} from "../beacon/initPeerIdAndEnr.js"; import {parseArgs as parseMetricsArgs} from "../../options/beaconNodeOptions/metrics.js"; import {parseArgs as parseNetworkArgs} from "../../options/beaconNodeOptions/network.js"; import {getBeaconPaths} from "../beacon/paths.js"; @@ -22,7 +22,7 @@ import {BootnodeArgs} from "./options.js"; * Runs a bootnode. */ export async function bootnodeHandler(args: BootnodeArgs & GlobalArgs): Promise { - const {discv5Args, metricsArgs, bootnodeDir, network, version, commit, peerId, enr, logger} = + const {discv5Args, metricsArgs, bootnodeDir, network, version, commit, privateKey, enr, logger} = await bootnodeHandlerInit(args); const abortController = new AbortController(); @@ -34,7 +34,7 @@ export async function bootnodeHandler(args: BootnodeArgs & GlobalArgs): Promise< ip4: enr.getLocationMultiaddr("udp4")?.toString(), ip6: enr.getLocationMultiaddr("udp6")?.toString(), }); - logger.info("Identity", {peerId: peerId.toString(), nodeId: enr.nodeId}); + logger.info("Identity", {peerId: enr.peerId.toString(), nodeId: enr.nodeId}); logger.info("ENR", {enr: enr.encodeTxt()}); // bootnode setup @@ -53,7 +53,7 @@ export async function bootnodeHandler(args: BootnodeArgs & GlobalArgs): Promise< const discv5 = Discv5.create({ enr, - peerId, + privateKey, bindAddrs: { ip4: (bindAddrs.ip4 ? multiaddr(bindAddrs.ip4) : undefined) as Multiaddr, ip6: bindAddrs.ip6 ? multiaddr(bindAddrs.ip6) : undefined, @@ -68,7 +68,7 @@ export async function bootnodeHandler(args: BootnodeArgs & GlobalArgs): Promise< logger.info("Adding bootnode", { ip4: bootEnr.getLocationMultiaddr("udp4")?.toString(), ip6: bootEnr.getLocationMultiaddr("udp6")?.toString(), - peerId: (await bootEnr.peerId()).toString(), + peerId: bootEnr.peerId.toString(), nodeId: enr.nodeId, }); discv5.addEnr(bootEnr); @@ -180,7 +180,7 @@ export async function bootnodeHandlerInit(args: BootnodeArgs & GlobalArgs) { ); const logger = initLogger(args, beaconPaths.dataDir, config, "bootnode.log"); - const {peerId, enr} = await initPeerIdAndEnr(args as unknown as BeaconArgs, bootnodeDir, logger, true); + const {privateKey, enr} = await initPrivateKeyAndEnr(args as unknown as BeaconArgs, bootnodeDir, logger, true); - return {discv5Args, metricsArgs, bootnodeDir, network, version, commit, peerId, enr, logger}; + return {discv5Args, metricsArgs, bootnodeDir, network, version, commit, privateKey, enr, logger}; } diff --git a/packages/cli/src/config/peerId.ts b/packages/cli/src/config/peerId.ts index d4906c716ba7..91390696c2f4 100644 --- a/packages/cli/src/config/peerId.ts +++ b/packages/cli/src/config/peerId.ts @@ -1,7 +1,11 @@ -import type {PeerId} from "@libp2p/interface"; -import {peerIdFromBytes} from "@libp2p/peer-id"; -import {createFromPrivKey, createFromPubKey} from "@libp2p/peer-id-factory"; -import {unmarshalPrivateKey, unmarshalPublicKey} from "@libp2p/crypto/keys"; +import type {PrivateKey} from "@libp2p/interface"; +import {peerIdFromPrivateKey, peerIdFromString} from "@libp2p/peer-id"; +import { + privateKeyFromProtobuf, + privateKeyToProtobuf, + publicKeyFromProtobuf, + publicKeyToProtobuf, +} from "@libp2p/crypto/keys"; import {fromString as uint8ArrayFromString} from "uint8arrays/from-string"; import {toString as uint8ArrayToString} from "uint8arrays/to-string"; import {writeFile600Perm, readFile} from "../util/index.js"; @@ -9,45 +13,38 @@ import {writeFile600Perm, readFile} from "../util/index.js"; // Peer id to / from JSON taken from peer-id-factory // See https://github.com/libp2p/js-libp2p-peer-id/pull/9 for more details -async function createFromParts(multihash: Uint8Array, privKey?: Uint8Array, pubKey?: Uint8Array): Promise { - if (privKey != null) { - const key = await unmarshalPrivateKey(privKey); +// after libp2p 2.0, PeerId no longer contains a private key +// but we retain a semi-backwards-compatible on-disk format +// Note: all properties are required +export type PeerIdJSON = {id: string; pubKey: string; privKey: string}; - return createFromPrivKey(key); - } else if (pubKey != null) { - const key = unmarshalPublicKey(pubKey); - - return createFromPubKey(key); - } - - return peerIdFromBytes(multihash); -} - -export type PeerIdJSON = {id: string; pubKey?: string; privKey?: string}; - -export function exportToJSON(peerId: PeerId, excludePrivateKey?: boolean): PeerIdJSON { +export function exportToJSON(privateKey: PrivateKey): PeerIdJSON { + const publicKey = privateKey.publicKey; + const peerId = peerIdFromPrivateKey(privateKey); return { - id: uint8ArrayToString(peerId.toBytes(), "base58btc"), - pubKey: peerId.publicKey != null ? uint8ArrayToString(peerId.publicKey, "base64pad") : undefined, - privKey: - excludePrivateKey === true || peerId.privateKey == null - ? undefined - : uint8ArrayToString(peerId.privateKey, "base64pad"), + id: peerId.toString(), + pubKey: uint8ArrayToString(publicKeyToProtobuf(publicKey), "base64pad"), + privKey: uint8ArrayToString(privateKeyToProtobuf(privateKey), "base64pad"), }; } -export async function createFromJSON(obj: PeerIdJSON): Promise { - return createFromParts( - uint8ArrayFromString(obj.id, "base58btc"), - obj.privKey != null ? uint8ArrayFromString(obj.privKey, "base64pad") : undefined, - obj.pubKey != null ? uint8ArrayFromString(obj.pubKey, "base64pad") : undefined - ); +export function createFromJSON(obj: PeerIdJSON): PrivateKey { + const privateKey = privateKeyFromProtobuf(uint8ArrayFromString(obj.privKey, "base64pad")); + const publicKey = publicKeyFromProtobuf(uint8ArrayFromString(obj.pubKey, "base64pad")); + const peerId = peerIdFromString(obj.id); + if (!publicKey.equals(privateKey.publicKey)) { + throw new Error("Public key does not match private key"); + } + if (!peerId.equals(peerIdFromPrivateKey(privateKey))) { + throw new Error("Peer ID does not match private key"); + } + return privateKey; } -export function writePeerId(filepath: string, peerId: PeerId): void { - writeFile600Perm(filepath, exportToJSON(peerId)); +export function writePrivateKey(filepath: string, privateKey: PrivateKey): void { + writeFile600Perm(filepath, exportToJSON(privateKey)); } -export async function readPeerId(filepath: string): Promise { +export function readPrivateKey(filepath: string): PrivateKey { return createFromJSON(readFile(filepath)); } diff --git a/packages/cli/test/unit/cmds/beacon.test.ts b/packages/cli/test/unit/cmds/beacon.test.ts index 6e7b7f389a29..74cde026b1ad 100644 --- a/packages/cli/test/unit/cmds/beacon.test.ts +++ b/packages/cli/test/unit/cmds/beacon.test.ts @@ -1,15 +1,16 @@ import path from "node:path"; import fs from "node:fs"; import {describe, it, expect} from "vitest"; -import {createFromJSON, createSecp256k1PeerId} from "@libp2p/peer-id-factory"; import {multiaddr} from "@multiformats/multiaddr"; -import {createPrivateKeyFromPeerId, ENR, SignableENR} from "@chainsafe/enr"; +import {ENR, SignableENR} from "@chainsafe/enr"; +import {generateKeyPair} from "@libp2p/crypto/keys"; +import {peerIdFromPrivateKey} from "@libp2p/peer-id"; import {chainConfig} from "@lodestar/config/default"; import {chainConfigToJson} from "@lodestar/config"; import {LogLevel} from "@lodestar/utils"; -import {exportToJSON} from "../../../src/config/peerId.js"; +import {createFromJSON, exportToJSON} from "../../../src/config/peerId.js"; import {beaconHandlerInit} from "../../../src/cmds/beacon/handler.js"; -import {initPeerIdAndEnr, isLocalMultiAddr} from "../../../src/cmds/beacon/initPeerIdAndEnr.js"; +import {initPrivateKeyAndEnr, isLocalMultiAddr} from "../../../src/cmds/beacon/initPeerIdAndEnr.js"; import {BeaconArgs} from "../../../src/cmds/beacon/options.js"; import {GlobalArgs} from "../../../src/options/globalOptions.js"; import {testFilesDir, testLogger} from "../../utils.js"; @@ -55,26 +56,26 @@ describe("cmds / beacon / args handler", () => { }); it("Create different PeerId every run", async () => { - const {peerId: peerId1} = await runBeaconHandlerInit({}); - const {peerId: peerId2} = await runBeaconHandlerInit({}); + const {privateKey: pk1} = await runBeaconHandlerInit({}); + const {privateKey: pk2} = await runBeaconHandlerInit({}); - expect(peerId1.toString()).not.toBe(peerId2.toString()); + expect(pk1.equals(pk2)).toBe(false); }); it("Re-use existing peer", async () => { - const prevPeerId = await createSecp256k1PeerId(); + const prevPk = await generateKeyPair("secp256k1"); const peerIdFile = path.join(testFilesDir, "peer-id.json"); - fs.writeFileSync(peerIdFile, JSON.stringify(exportToJSON(prevPeerId))); - const enr = SignableENR.createV4(createPrivateKeyFromPeerId(prevPeerId).privateKey); + fs.writeFileSync(peerIdFile, JSON.stringify(exportToJSON(prevPk))); + const enr = SignableENR.createFromPrivateKey(prevPk); const enrFilePath = path.join(testFilesDir, "enr"); fs.writeFileSync(enrFilePath, enr.encodeTxt()); - const {peerId} = await runBeaconHandlerInit({ + const {privateKey} = await runBeaconHandlerInit({ persistNetworkIdentity: true, }); - expect(peerId.toString()).toBe(prevPeerId.toString()); + expect(privateKey.equals(prevPk)).toBe(true); }); it("Set known deposit contract", async () => { @@ -117,48 +118,48 @@ describe("Test isLocalMultiAddr", () => { describe("initPeerIdAndEnr", () => { it("should not reuse peer id, persistNetworkIdentity=false", async () => { - const {peerId: peerId1} = await initPeerIdAndEnr( + const {privateKey: pk1} = await initPrivateKeyAndEnr( {persistNetworkIdentity: false} as BeaconArgs, testFilesDir, testLogger() ); - const {peerId: peerId2} = await initPeerIdAndEnr( + const {privateKey: pk2} = await initPrivateKeyAndEnr( {persistNetworkIdentity: false} as BeaconArgs, testFilesDir, testLogger() ); - expect(peerId1.toString()).not.toBe(peerId2.toString()); + expect(pk1.equals(pk2)).toBe(false); }); it("should reuse peer id, persistNetworkIdentity=true", async () => { - const {peerId: peerId1} = await initPeerIdAndEnr( + const {privateKey: pk1} = await initPrivateKeyAndEnr( {persistNetworkIdentity: true} as BeaconArgs, testFilesDir, testLogger() ); - const {peerId: peerId2} = await initPeerIdAndEnr( + const {privateKey: pk2} = await initPrivateKeyAndEnr( {persistNetworkIdentity: true} as BeaconArgs, testFilesDir, testLogger() ); - expect(peerId1.toString()).toBe(peerId2.toString()); + expect(pk1.equals(pk2)).toBe(true); }); it("should overwrite invalid peer id", async () => { const peerIdFile = path.join(testFilesDir, "peer-id.json"); - const peerId1Str = "wrong peer id file content"; - fs.writeFileSync(peerIdFile, peerId1Str); - const {peerId: peerId2} = await initPeerIdAndEnr( + const pk1Str = "wrong peer id file content"; + fs.writeFileSync(peerIdFile, pk1Str); + const {privateKey: pk2} = await initPrivateKeyAndEnr( {persistNetworkIdentity: true} as BeaconArgs, testFilesDir, testLogger() ); - const filePeerId = await createFromJSON(JSON.parse(fs.readFileSync(peerIdFile, "utf-8"))); + const filePk = createFromJSON(JSON.parse(fs.readFileSync(peerIdFile, "utf-8"))); - expect(peerId1Str).not.toBe(peerId2.toString()); - expect(filePeerId.toString()).toBe(peerId2.toString()); + expect(pk1Str).not.toBe(peerIdFromPrivateKey(pk2).toString()); + expect(filePk.equals(pk2)).toBe(true); }); it("should overwrite invalid enr", async () => { @@ -166,7 +167,7 @@ describe("initPeerIdAndEnr", () => { const invalidEnr = "wrong enr file content"; fs.writeFileSync(enrFilePath, invalidEnr); - await initPeerIdAndEnr({persistNetworkIdentity: true} as BeaconArgs, testFilesDir, testLogger()); + await initPrivateKeyAndEnr({persistNetworkIdentity: true} as BeaconArgs, testFilesDir, testLogger()); const validEnr = fs.readFileSync(enrFilePath, "utf-8"); @@ -174,13 +175,13 @@ describe("initPeerIdAndEnr", () => { }); it("should overwrite enr that doesn't match peer id", async () => { - const otherPeerId = await createSecp256k1PeerId(); - const otherEnr = SignableENR.createFromPeerId(otherPeerId); + const otherPk = await generateKeyPair("secp256k1"); + const otherEnr = SignableENR.createFromPrivateKey(otherPk); const enrFilePath = path.join(testFilesDir, "enr"); const otherEnrStr = otherEnr.encodeTxt(); fs.writeFileSync(enrFilePath, otherEnrStr); - const {enr} = await initPeerIdAndEnr({persistNetworkIdentity: true} as BeaconArgs, testFilesDir, testLogger()); + const {enr} = await initPrivateKeyAndEnr({persistNetworkIdentity: true} as BeaconArgs, testFilesDir, testLogger()); expect(enr.nodeId).not.toBe(otherEnr); }); diff --git a/packages/cli/test/unit/cmds/initPeerIdAndEnr.test.ts b/packages/cli/test/unit/cmds/initPeerIdAndEnr.test.ts index a207e0c0f59d..3dd9b48c298d 100644 --- a/packages/cli/test/unit/cmds/initPeerIdAndEnr.test.ts +++ b/packages/cli/test/unit/cmds/initPeerIdAndEnr.test.ts @@ -1,7 +1,8 @@ import fs from "node:fs"; import {describe, it, expect, beforeEach, afterEach} from "vitest"; import tmp from "tmp"; -import {initPeerIdAndEnr} from "../../../src/cmds/beacon/initPeerIdAndEnr.js"; +import {peerIdFromPrivateKey} from "@libp2p/peer-id"; +import {initPrivateKeyAndEnr} from "../../../src/cmds/beacon/initPeerIdAndEnr.js"; import {BeaconArgs} from "../../../src/cmds/beacon/options.js"; import {testLogger} from "../../utils.js"; @@ -17,35 +18,35 @@ describe("initPeerIdAndEnr", () => { }); it("first time should create a new enr and peer id", async () => { - const {enr, peerId} = await initPeerIdAndEnr( + const {enr, privateKey} = await initPrivateKeyAndEnr( {persistNetworkIdentity: true} as unknown as BeaconArgs, tmpDir.name, testLogger(), true ); // "enr peer id doesn't equal the returned peer id" - expect((await enr.peerId()).toString()).toBe(peerId.toString()); + expect(enr.peerId.toString()).toBe(peerIdFromPrivateKey(privateKey).toString()); expect(enr.seq).toBe(BigInt(1)); expect(enr.tcp).toBeUndefined(); expect(enr.tcp6).toBeUndefined(); }); it("second time should use ths existing enr and peer id", async () => { - const run1 = await initPeerIdAndEnr( + const run1 = await initPrivateKeyAndEnr( {persistNetworkIdentity: true} as unknown as BeaconArgs, tmpDir.name, testLogger(), true ); - const run2 = await initPeerIdAndEnr( + const run2 = await initPrivateKeyAndEnr( {persistNetworkIdentity: true} as unknown as BeaconArgs, tmpDir.name, testLogger(), true ); - expect(run1.peerId.toString()).toBe(run2.peerId.toString()); + expect(run1.privateKey.equals(run2.privateKey)).toBe(true); expect(run1.enr.encodeTxt()).toBe(run2.enr.encodeTxt()); }); }); diff --git a/packages/cli/test/unit/config/peerId.test.ts b/packages/cli/test/unit/config/peerId.test.ts index c0cdc8cff1a9..120a5e931749 100644 --- a/packages/cli/test/unit/config/peerId.test.ts +++ b/packages/cli/test/unit/config/peerId.test.ts @@ -1,16 +1,16 @@ import {describe, it, expect} from "vitest"; -import {createSecp256k1PeerId} from "@libp2p/peer-id-factory"; +import {generateKeyPair} from "@libp2p/crypto/keys"; import {getTestdirPath} from "../../utils.js"; -import {writePeerId, readPeerId} from "../../../src/config/index.js"; +import {writePrivateKey, readPrivateKey} from "../../../src/config/index.js"; describe("config / peerId", () => { const peerIdFilepath = getTestdirPath("./test-peer-id.json"); it("create, write and read PeerId", async () => { - const peerId = await createSecp256k1PeerId(); - writePeerId(peerIdFilepath, peerId); - const peerIdRead = await readPeerId(peerIdFilepath); + const privateKey = await generateKeyPair("secp256k1"); + writePrivateKey(peerIdFilepath, privateKey); + const pkRead = readPrivateKey(peerIdFilepath); - expect(peerIdRead.toString()).toBe(peerId.toString()); + expect(pkRead.toString()).toBe(privateKey.toString()); }); }); diff --git a/packages/reqresp/package.json b/packages/reqresp/package.json index 9bd9775ba2c0..d6d4fbd2b5c2 100644 --- a/packages/reqresp/package.json +++ b/packages/reqresp/package.json @@ -53,7 +53,7 @@ }, "dependencies": { "@chainsafe/fast-crc32c": "^4.1.1", - "@libp2p/interface": "^1.3.0", + "@libp2p/interface": "^2.1.2", "@lodestar/config": "^1.22.0", "@lodestar/params": "^1.22.0", "@lodestar/utils": "^1.22.0", @@ -67,10 +67,10 @@ "devDependencies": { "@lodestar/logger": "^1.22.0", "@lodestar/types": "^1.22.0", - "libp2p": "1.4.3" + "libp2p": "2.1.7" }, "peerDependencies": { - "libp2p": "~1.4.3" + "libp2p": "~2.1.7" }, "keywords": [ "ethereum", diff --git a/packages/reqresp/test/utils/peer.ts b/packages/reqresp/test/utils/peer.ts index 43edaefbafdd..cbc21eca370f 100644 --- a/packages/reqresp/test/utils/peer.ts +++ b/packages/reqresp/test/utils/peer.ts @@ -1,5 +1,6 @@ import {PeerId} from "@libp2p/interface"; -import {peerIdFromBytes} from "@libp2p/peer-id"; +import {peerIdFromPublicKey} from "@libp2p/peer-id"; +import {publicKeyFromProtobuf} from "@libp2p/crypto/keys"; /** * Returns a valid PeerId with opts `bits: 256, keyType: "secp256k1"` @@ -7,5 +8,5 @@ import {peerIdFromBytes} from "@libp2p/peer-id"; */ export function getValidPeerId(): PeerId { const id = Buffer.from("002508021221039481269fe831799b1a0f1d521c1395b4831514859e4559c44d155eae46f03819", "hex"); - return peerIdFromBytes(id); + return peerIdFromPublicKey(publicKeyFromProtobuf(id)); } diff --git a/yarn.lock b/yarn.lock index 3907e9f4e441..32c923a514e9 100644 --- a/yarn.lock +++ b/yarn.lock @@ -456,14 +456,14 @@ "@chainsafe/blst-linux-x64-musl" "2.0.3" "@chainsafe/blst-win32-x64-msvc" "2.0.3" -"@chainsafe/discv5@^9.0.0": - version "9.0.0" - resolved "https://registry.yarnpkg.com/@chainsafe/discv5/-/discv5-9.0.0.tgz#05d4d9d671894b41f0fafa8f32c48ae3ed761bd1" - integrity sha512-7s23ziqsHG/KRgkX79qB/w8kuqPrY8aJaF2aRDy9cScJocJ6ZaOnXhEc8Ku1AcSyrvfGp+tY8R4rDABcxRY+Wg== +"@chainsafe/discv5@^10.0.1": + version "10.0.1" + resolved "https://registry.yarnpkg.com/@chainsafe/discv5/-/discv5-10.0.1.tgz#1aefe3826b19b1f66e76c737a7a49ae7c77d7664" + integrity sha512-YpvqOMOn/sQMHU97lonvRnbtLZQW1Vqjcwtofd0hOJ6ohtxn+Ne7Cos8qCOFkhRHirGG6irHej4akh/BlBscSA== dependencies: - "@chainsafe/enr" "^3.0.0" - "@libp2p/crypto" "^4.0.1" - "@libp2p/interface" "^1.1.1" + "@chainsafe/enr" "^4.0.1" + "@libp2p/crypto" "^5.0.1" + "@libp2p/interface" "^2.0.1" "@multiformats/multiaddr" "^12.1.10" bcrypto "^5.4.0" bigint-buffer "^1.1.5" @@ -472,17 +472,17 @@ rlp "^2.2.6" strict-event-emitter-types "^2.0.0" -"@chainsafe/enr@^3.0.0": - version "3.0.0" - resolved "https://registry.yarnpkg.com/@chainsafe/enr/-/enr-3.0.0.tgz#71c83d4381d703bbcd19245ce733eb7c779a30ed" - integrity sha512-D8M8sqnvOim0jWlTdr2IhLyVe0GSUgpk+QO6UaLY4pQVdW1myJP8REp7xdbv1193ULVEkJQFTJAZexTOtmu3jw== +"@chainsafe/enr@^4.0.1": + version "4.0.1" + resolved "https://registry.yarnpkg.com/@chainsafe/enr/-/enr-4.0.1.tgz#9c9ad8cd84aedc1242d7e7ac99d670c0f8ee3c0d" + integrity sha512-eYGZC6Wq9UNtD5AZLO21w9DctRkEAhMZ/kIa+eggT5lVRcVSI06O7PmSXOSRW6z+Td/9MQKGEDtuyYa1esWlSg== dependencies: - "@libp2p/crypto" "^4.0.1" - "@libp2p/interface" "^1.1.1" - "@libp2p/peer-id" "^4.0.4" + "@libp2p/crypto" "^5.0.1" + "@libp2p/interface" "^2.0.1" + "@libp2p/peer-id" "^5.0.1" "@multiformats/multiaddr" "^12.1.10" bigint-buffer "^1.1.5" - ethereum-cryptography "^2.1.3" + ethereum-cryptography "^2.2.0" rlp "^2.2.6" uint8-varint "^2.0.2" uint8arrays "^5.0.1" @@ -528,54 +528,37 @@ resolved "https://registry.yarnpkg.com/@chainsafe/is-ip/-/is-ip-2.0.2.tgz#7311e7403f11d8c5cfa48111f56fcecaac37c9f6" integrity sha512-ndGqEMG1W5WkGagaqOZHpPU172AGdxr+LD15sv3WIUvT5oCFUrG1Y0CW/v2Egwj4JXEvSibaIIIqImsm98y1nA== -"@chainsafe/libp2p-gossipsub@^13.0.0": - version "13.0.0" - resolved "https://registry.yarnpkg.com/@chainsafe/libp2p-gossipsub/-/libp2p-gossipsub-13.0.0.tgz#b1dfa5c2d455d77ab8dfc97f5eb8961861bb623e" - integrity sha512-2q+v429uZjMl6N3d+j9QCMj8YO0aiYvLSN1t0aTdpMXQHCHLJaaT9PtNn845B1Li7/uZjYESmikgVt8r7keH0w== +"@chainsafe/libp2p-gossipsub@^14.1.0": + version "14.1.0" + resolved "https://registry.yarnpkg.com/@chainsafe/libp2p-gossipsub/-/libp2p-gossipsub-14.1.0.tgz#0003a214c2a88b04ab7c256c70ec439717958f09" + integrity sha512-nzFBbHOoRFa/bXUSzmJaXOgHI+EttTldhLJ33yWcM0DxnWhLKychHkCDLoJO3THa1+dnzrDJoxj3N3/V0WoPVw== dependencies: - "@libp2p/crypto" "^4.0.1" - "@libp2p/interface" "^1.1.2" - "@libp2p/interface-internal" "^1.0.7" - "@libp2p/peer-id" "^4.0.5" - "@libp2p/pubsub" "^9.0.8" + "@libp2p/crypto" "^5.0.0" + "@libp2p/interface" "^2.0.0" + "@libp2p/interface-internal" "^2.0.0" + "@libp2p/peer-id" "^5.0.0" + "@libp2p/pubsub" "^10.0.0" "@multiformats/multiaddr" "^12.1.14" denque "^2.1.0" it-length-prefixed "^9.0.4" it-pipe "^3.0.1" it-pushable "^3.2.3" multiformats "^13.0.1" - protons-runtime "5.4.0" + protons-runtime "^5.5.0" uint8arraylist "^2.4.8" uint8arrays "^5.0.1" -"@chainsafe/libp2p-identify@^1.0.0": - version "1.0.0" - resolved "https://registry.yarnpkg.com/@chainsafe/libp2p-identify/-/libp2p-identify-1.0.0.tgz#28191e619715a87c140d8b516ee85cb7d39e41e0" - integrity sha512-X+VWUC0xeCFIulE4BU5M8FmTxZ/OKzku+9/1UaX2EG1LcqQkCDrPi6CCODbE0SraqImG4aVHRbiCFWxKEfE8wQ== - dependencies: - "@libp2p/interface" "^1.1.2" - "@libp2p/interface-internal" "^1.0.7" - "@libp2p/peer-id" "^4.0.5" - "@libp2p/peer-record" "^7.0.7" - "@multiformats/multiaddr" "^12.1.10" - "@multiformats/multiaddr-matcher" "^1.1.0" - it-protobuf-stream "^1.1.1" - protons-runtime "^5.0.0" - uint8arraylist "^2.4.7" - uint8arrays "^5.0.0" - wherearewe "^2.0.1" - -"@chainsafe/libp2p-noise@^15.0.0": - version "15.0.0" - resolved "https://registry.yarnpkg.com/@chainsafe/libp2p-noise/-/libp2p-noise-15.0.0.tgz#c3f38a31d03d96b475f7e35b592a22f5fe9269a0" - integrity sha512-O8Y/WVU4J/qrnG72jwVhbmdXiBzv1dT9B3PMClCRmZ9z/5vVPEGRVXE/SVYeGF3bNuBTLoh+F+GaKG/9UHlMhg== +"@chainsafe/libp2p-noise@^16.0.0": + version "16.0.0" + resolved "https://registry.yarnpkg.com/@chainsafe/libp2p-noise/-/libp2p-noise-16.0.0.tgz#52bb558490065439b0026950d7d99567da5c2c96" + integrity sha512-8rqr8V1RD2/lVbfL0Bb//N8iPOFof11cUe8v8z8xJT7fUhCAbtCCSM4jbwI4HCnw0MvHLmcpmAfDCFRwcWzoeA== dependencies: "@chainsafe/as-chacha20poly1305" "^0.1.0" "@chainsafe/as-sha256" "^0.4.1" - "@libp2p/crypto" "^4.0.0" - "@libp2p/interface" "^1.0.0" - "@libp2p/peer-id" "^4.0.0" - "@noble/ciphers" "^0.4.0" + "@libp2p/crypto" "^5.0.0" + "@libp2p/interface" "^2.0.0" + "@libp2p/peer-id" "^5.0.0" + "@noble/ciphers" "^0.6.0" "@noble/curves" "^1.1.0" "@noble/hashes" "^1.3.1" it-length-prefixed "^9.0.1" @@ -583,7 +566,7 @@ it-pair "^2.0.6" it-pipe "^3.0.1" it-stream-types "^2.0.1" - protons-runtime "^5.0.0" + protons-runtime "^5.5.0" uint8arraylist "^2.4.3" uint8arrays "^5.0.0" wherearewe "^2.0.1" @@ -1686,247 +1669,277 @@ yargs "16.2.0" yargs-parser "20.2.4" -"@libp2p/bootstrap@^10.0.21": - version "10.0.21" - resolved "https://registry.yarnpkg.com/@libp2p/bootstrap/-/bootstrap-10.0.21.tgz#be8b528604dc9634002f54d978ce6d5648d6a3ff" - integrity sha512-a9OGwyRM1ucq7ECUaxB4HdNoxCj21vXHcKce9khf44V5rUngF8Qzy07DI6/OaPyxJlXlDS19IJ7igaiYKx0TJw== +"@libp2p/bootstrap@^11.0.4": + version "11.0.7" + resolved "https://registry.yarnpkg.com/@libp2p/bootstrap/-/bootstrap-11.0.7.tgz#ecb14834fff03a184a3a7fd211d2ef85b3002fc6" + integrity sha512-PRDMVXf67+ASYTco6APqPy4HF03mQ8UX+BbBZcMAMpnlPsetYfWgQg3YiBe56J+PVQLs0FPsGpfLmAg7PUguQA== dependencies: - "@libp2p/interface" "^1.3.0" - "@libp2p/peer-id" "^4.1.0" + "@libp2p/interface" "^2.1.2" + "@libp2p/interface-internal" "^2.0.7" + "@libp2p/peer-id" "^5.0.4" "@multiformats/mafmt" "^12.1.6" - "@multiformats/multiaddr" "^12.2.1" + "@multiformats/multiaddr" "^12.2.3" -"@libp2p/crypto@^4.0.0", "@libp2p/crypto@^4.0.1", "@libp2p/crypto@^4.1.0": - version "4.1.0" - resolved "https://registry.yarnpkg.com/@libp2p/crypto/-/crypto-4.1.0.tgz#722060a77ced262dc89c7e42fc19ae67506b74ac" - integrity sha512-Gu4jkSdrVk1LOeyiOAuktmtN5pbSq6b9byzch2CfclFGZgXrHg3b46I0Fy63nZBc60Wq2KID3MQMVuRkVkDwAw== +"@libp2p/crypto@^5.0.0", "@libp2p/crypto@^5.0.1", "@libp2p/crypto@^5.0.4": + version "5.0.4" + resolved "https://registry.yarnpkg.com/@libp2p/crypto/-/crypto-5.0.4.tgz#26f24025f3dd2be959360c6b58c94ccadb04ed63" + integrity sha512-v5xsngOlDu8JP3GQDvK+2YYzTELl7/aPfXPbIzKEcy7ON2hu79t1BZMuavjPsr+WWIPNg5yKst6IJfRilzwXRQ== dependencies: - "@libp2p/interface" "^1.3.0" + "@libp2p/interface" "^2.1.2" "@noble/curves" "^1.4.0" "@noble/hashes" "^1.4.0" asn1js "^3.0.5" multiformats "^13.1.0" protons-runtime "^5.4.0" uint8arraylist "^2.4.8" - uint8arrays "^5.0.3" - -"@libp2p/identify@^1.0.20": - version "1.0.20" - resolved "https://registry.yarnpkg.com/@libp2p/identify/-/identify-1.0.20.tgz#cce6c4efad77afe6c0b26b0704a902f2fdbaeab2" - integrity sha512-bhn57ZI4MIMn0p3S6YNc8Sr5ReA8We8bVU25lNAefVUO3gMeQOMZ6FdTVJKbxoSumvZ+q8ciB2IOvu4rMU7o1g== - dependencies: - "@libp2p/interface" "^1.3.0" - "@libp2p/interface-internal" "^1.1.1" - "@libp2p/peer-id" "^4.1.0" - "@libp2p/peer-record" "^7.0.15" - "@multiformats/multiaddr" "^12.2.1" - "@multiformats/multiaddr-matcher" "^1.2.0" - it-protobuf-stream "^1.1.2" + uint8arrays "^5.1.0" + +"@libp2p/identify@^3.0.4": + version "3.0.7" + resolved "https://registry.yarnpkg.com/@libp2p/identify/-/identify-3.0.7.tgz#a7541d6775cf652314bf2209b281b402e8dedc35" + integrity sha512-4Ns/0HN9lvQAox8eaJruKXakOtikduk6kPlz+KYmFMgVE5/kRBRf7h0aK/8cyU9sQPbSZLCaJ3gBWoDrfMIu2w== + dependencies: + "@libp2p/crypto" "^5.0.4" + "@libp2p/interface" "^2.1.2" + "@libp2p/interface-internal" "^2.0.7" + "@libp2p/peer-id" "^5.0.4" + "@libp2p/peer-record" "^8.0.7" + "@libp2p/utils" "^6.1.0" + "@multiformats/multiaddr" "^12.2.3" + "@multiformats/multiaddr-matcher" "^1.2.1" + it-drain "^3.0.7" + it-parallel "^3.0.7" + it-protobuf-stream "^1.1.3" protons-runtime "^5.4.0" uint8arraylist "^2.4.8" - uint8arrays "^5.0.3" + uint8arrays "^5.1.0" wherearewe "^2.0.1" -"@libp2p/interface-internal@^1.0.7", "@libp2p/interface-internal@^1.1.1": - version "1.1.1" - resolved "https://registry.yarnpkg.com/@libp2p/interface-internal/-/interface-internal-1.1.1.tgz#ff16b4fee4a3d3e39121e26eeeab42e9257f5f49" - integrity sha512-lLPd7yysXqpb1oiPZAn57w3CQdD33C+mu6pfUuPYI5yWMgwWq8V3XE4IMG1IyHUGEYZAuGglghAH9YQNbtticw== +"@libp2p/interface-internal@^2.0.0", "@libp2p/interface-internal@^2.0.7": + version "2.0.7" + resolved "https://registry.yarnpkg.com/@libp2p/interface-internal/-/interface-internal-2.0.7.tgz#ceefa71553ce5aec9be793fcc646680f7d289806" + integrity sha512-numJBYHajL7W1BuURkQ4tlZ4sUGNGI3GWkhTmL2fS+LxYS2hUVTxcemHtUZGpcJQ17GiCqq+j4GE3bkBagOb0g== dependencies: - "@libp2p/interface" "^1.3.0" - "@libp2p/peer-collections" "^5.1.11" - "@multiformats/multiaddr" "^12.2.1" + "@libp2p/interface" "^2.1.2" + "@libp2p/peer-collections" "^6.0.7" + "@multiformats/multiaddr" "^12.2.3" + progress-events "^1.0.0" uint8arraylist "^2.4.8" -"@libp2p/interface@^1.0.0", "@libp2p/interface@^1.1.1", "@libp2p/interface@^1.1.2", "@libp2p/interface@^1.3.0": - version "1.3.0" - resolved "https://registry.yarnpkg.com/@libp2p/interface/-/interface-1.3.0.tgz#c4fcee2878aa8d37357974b6c7395cb2a645eb50" - integrity sha512-K72Km0Co1Z+pXpggWuoAvUUbvwZYvjCcywrHj2Ym3jt2anTE3hzL4rlZrrkzA0YhNTRFRiZ04dnu6WMXT5/4+A== +"@libp2p/interface@^1.7.0": + version "1.7.0" + resolved "https://registry.yarnpkg.com/@libp2p/interface/-/interface-1.7.0.tgz#b75b6032a6b0d0d5a13e551dcf4d481a8ca9a88f" + integrity sha512-/zFyaIaIGW0aihhsH7/93vQdpWInUzFocxF11RO/029Y6h0SVjs24HHbils+DqaFDTqN+L7oNlBx2rM2MnmTjA== dependencies: - "@multiformats/multiaddr" "^12.2.1" + "@multiformats/multiaddr" "^12.2.3" it-pushable "^3.2.3" it-stream-types "^2.0.1" multiformats "^13.1.0" progress-events "^1.0.0" uint8arraylist "^2.4.8" -"@libp2p/logger@^4.0.11", "@libp2p/logger@^4.0.6": - version "4.0.11" - resolved "https://registry.yarnpkg.com/@libp2p/logger/-/logger-4.0.11.tgz#671692a0cceee73a0c0bf9b5f05ea14fde05f5e5" - integrity sha512-WsZBup1Q+ec4C7i2YiCx0elFrejqJea3Fmkzy3t4fAek7Ofyh4GQonk3A4R7XsG5yq8+Hu1fpsGhIK8EVQsqZQ== +"@libp2p/interface@^2.0.0", "@libp2p/interface@^2.0.1", "@libp2p/interface@^2.1.2": + version "2.1.2" + resolved "https://registry.yarnpkg.com/@libp2p/interface/-/interface-2.1.2.tgz#7b38047a7d2d35a6a4e0f0f22fbdeeec98b85321" + integrity sha512-uD4NapC+1qGX7RmgC1aehQm3pMs1MpO1DwuhUlAo1M6CyNxfs1Ha9jhg2T+G4u4CAJM6wffZTyPGnKnrR+M8Fw== dependencies: - "@libp2p/interface" "^1.3.0" - "@multiformats/multiaddr" "^12.2.1" - debug "^4.3.4" + "@multiformats/multiaddr" "^12.2.3" + it-pushable "^3.2.3" + it-stream-types "^2.0.1" + multiformats "^13.1.0" + progress-events "^1.0.0" + uint8arraylist "^2.4.8" + +"@libp2p/logger@^4.0.6": + version "4.0.20" + resolved "https://registry.yarnpkg.com/@libp2p/logger/-/logger-4.0.20.tgz#bcb7fa83f3803d8ec37926747a18108728589c13" + integrity sha512-TTh2dhHsOTAlMPxSa9ncFPHa/0jTt+0AQxwHdlxg/OGLAgc9VRhnrhHUbJZp07Crcw4T/MOfS4KhjlxgqYgJRw== + dependencies: + "@libp2p/interface" "^1.7.0" + "@multiformats/multiaddr" "^12.2.3" interface-datastore "^8.2.11" multiformats "^13.1.0" + weald "^1.0.2" -"@libp2p/mdns@^10.0.21": - version "10.0.21" - resolved "https://registry.yarnpkg.com/@libp2p/mdns/-/mdns-10.0.21.tgz#028a388b73de703e4c762fd4937f217648c8128c" - integrity sha512-/lmjsZJvhfEXeSodqKECiRZk8mqApESc3OI6MhHxNvRBsfncY93IZM7lR6jwlmyQ2DOL5rCkm2rcr9geIsVzmQ== +"@libp2p/logger@^5.1.0": + version "5.1.0" + resolved "https://registry.yarnpkg.com/@libp2p/logger/-/logger-5.1.0.tgz#d580e2ee89e3f4224129cc12d727b45494aad6e5" + integrity sha512-hmkk1TONYRe+kKs5QTxkayIfj9qicp8hcrJ1Ac9QfTW/jdaUlnqd1uop4QcOD5GV6qNMq+v1qaMFWFYSN9RcPA== dependencies: - "@libp2p/interface" "^1.3.0" - "@libp2p/interface-internal" "^1.1.1" - "@libp2p/peer-id" "^4.1.0" - "@libp2p/utils" "^5.3.2" - "@multiformats/multiaddr" "^12.2.1" + "@libp2p/interface" "^2.1.2" + "@multiformats/multiaddr" "^12.2.3" + interface-datastore "^8.3.0" + multiformats "^13.1.0" + weald "^1.0.2" + +"@libp2p/mdns@^11.0.4": + version "11.0.7" + resolved "https://registry.yarnpkg.com/@libp2p/mdns/-/mdns-11.0.7.tgz#ab968f952085a59d3ea829727e79f631fa049376" + integrity sha512-CW0MbN2bQvSVsZmYT8Ul5a2TOiwhU3aBKyHyCuf5WA70Nu6Lc72YSc+vRT2EIw5Ihb+dbxC/mXrhY1xKdXaWCg== + dependencies: + "@libp2p/interface" "^2.1.2" + "@libp2p/interface-internal" "^2.0.7" + "@libp2p/peer-id" "^5.0.4" + "@libp2p/utils" "^6.1.0" + "@multiformats/multiaddr" "^12.2.3" "@types/multicast-dns" "^7.2.4" dns-packet "^5.6.1" multicast-dns "^7.2.5" -"@libp2p/mplex@^10.0.21": - version "10.0.21" - resolved "https://registry.yarnpkg.com/@libp2p/mplex/-/mplex-10.0.21.tgz#530de45f23dd36d5ac35e21a1c259767c5bfdab1" - integrity sha512-F7pK/xG9LNG3KhZBMb6SsiR7MI18na1x1e1qr8EvlyJcmdT0OiiHCnjDXWrmy+wh6uTD2qhRM+ea1vQEhKANXw== +"@libp2p/mplex@^11.0.4": + version "11.0.7" + resolved "https://registry.yarnpkg.com/@libp2p/mplex/-/mplex-11.0.7.tgz#18f5af4d59bbd9bdf64c9ddda30020c6b674010d" + integrity sha512-q13aTXf6+kEQk67bnlDnXBy8TAU19zxrNrxzwTTW3m9HEyPEKoA1YJuSqZuDjxfP31BbMshs3xxnlXgph5SpUw== dependencies: - "@libp2p/interface" "^1.3.0" - "@libp2p/utils" "^5.3.2" + "@libp2p/interface" "^2.1.2" + "@libp2p/utils" "^6.1.0" it-pipe "^3.0.1" it-pushable "^3.2.3" it-stream-types "^2.0.1" uint8-varint "^2.0.4" uint8arraylist "^2.4.8" - uint8arrays "^5.0.3" + uint8arrays "^5.1.0" -"@libp2p/multistream-select@^5.1.8": - version "5.1.8" - resolved "https://registry.yarnpkg.com/@libp2p/multistream-select/-/multistream-select-5.1.8.tgz#c484534496625da2a20873874b33e90d3ef2a95e" - integrity sha512-mYbYyjKhNOGIaS3kefs+koofGmiBvLukcnS+BVCZDGjYxAjhaes9PB++VyuX/D0lTZSk08P3cIBvw2sN+amOVQ== +"@libp2p/multistream-select@^6.0.5": + version "6.0.5" + resolved "https://registry.yarnpkg.com/@libp2p/multistream-select/-/multistream-select-6.0.5.tgz#919c923ac13573a44de6945695f1d1882ba35da4" + integrity sha512-iOMHcF/NzeShmnRLf9KI39bgfxptklbf6Tv9NvBbICfYO/IJB6KDI6bOif5eXXqUqZjHrQJ3jrRppOEwk2HV4g== dependencies: - "@libp2p/interface" "^1.3.0" + "@libp2p/interface" "^2.1.2" it-length-prefixed "^9.0.4" - it-length-prefixed-stream "^1.1.6" + it-length-prefixed-stream "^1.1.7" it-stream-types "^2.0.1" p-defer "^4.0.1" race-signal "^1.0.2" uint8-varint "^2.0.4" uint8arraylist "^2.4.8" - uint8arrays "^5.0.3" + uint8arrays "^5.1.0" -"@libp2p/peer-collections@^5.1.11": - version "5.1.11" - resolved "https://registry.yarnpkg.com/@libp2p/peer-collections/-/peer-collections-5.1.11.tgz#55589fccb4daf6a9f611f3e4126d2721d856aaca" - integrity sha512-w8ZeXfsAxBQiYgRnvpD3mxGORxwAXFsIhAOxFXl8scFhuE1j086PoTfRTuKYfp4DAyNHWkhUd+LQaXN0OG/Fgg== +"@libp2p/peer-collections@^6.0.7": + version "6.0.7" + resolved "https://registry.yarnpkg.com/@libp2p/peer-collections/-/peer-collections-6.0.7.tgz#8347e08aebbdf4a39962bb87e5ae86cc0aadfcb4" + integrity sha512-e3o994iEUvPR58x8Y5iE6lvrkv48oJXp/A1XIxMB4D/kA4OlY5BjDpHpR4nE4+EkzhIbslbMLAfip2FStyjtHg== dependencies: - "@libp2p/interface" "^1.3.0" - "@libp2p/peer-id" "^4.1.0" - -"@libp2p/peer-id-factory@^4.1.0": - version "4.1.0" - resolved "https://registry.yarnpkg.com/@libp2p/peer-id-factory/-/peer-id-factory-4.1.0.tgz#e134ff61c38d1a0fd210bf1fbdcd9116a74f2919" - integrity sha512-EMovpqtqj+5s+QpzSkVundoPQ88/GQMShB79Y6zLUkGZ73VtqWds/9e1WsrHBx6HhvmkmXFOrzcW8qfml3sE7A== - dependencies: - "@libp2p/crypto" "^4.1.0" - "@libp2p/interface" "^1.3.0" - "@libp2p/peer-id" "^4.1.0" - protons-runtime "^5.4.0" - uint8arraylist "^2.4.8" - uint8arrays "^5.0.3" + "@libp2p/interface" "^2.1.2" + "@libp2p/peer-id" "^5.0.4" + "@libp2p/utils" "^6.1.0" + multiformats "^13.2.2" -"@libp2p/peer-id@^4.0.0", "@libp2p/peer-id@^4.0.4", "@libp2p/peer-id@^4.0.5", "@libp2p/peer-id@^4.1.0": - version "4.1.0" - resolved "https://registry.yarnpkg.com/@libp2p/peer-id/-/peer-id-4.1.0.tgz#460e07d5b25339cf80afcb5e30c4f701423d1755" - integrity sha512-XmuqEfz3H+Cwq72V3opXg7wK2WnB08VEnG5nLILefLg+qo1KMlUP5pCP3ffyvYIvxMnsRla/xPYRDEBtL2JMpg== +"@libp2p/peer-id@^5.0.0", "@libp2p/peer-id@^5.0.1", "@libp2p/peer-id@^5.0.4": + version "5.0.4" + resolved "https://registry.yarnpkg.com/@libp2p/peer-id/-/peer-id-5.0.4.tgz#5a71f449b97098a5b12631b6be898a016a82c6bb" + integrity sha512-CHNbQ4Odlc+YDTtv6BzWdGSaJ1I3Wb6iHNV7YB59v0ivSsd0NzlR31qWpK/ByUAMT+hfzQzR1dK9s3e7zS4/zQ== dependencies: - "@libp2p/interface" "^1.3.0" + "@libp2p/crypto" "^5.0.4" + "@libp2p/interface" "^2.1.2" multiformats "^13.1.0" - uint8arrays "^5.0.3" - -"@libp2p/peer-record@^7.0.15", "@libp2p/peer-record@^7.0.7": - version "7.0.15" - resolved "https://registry.yarnpkg.com/@libp2p/peer-record/-/peer-record-7.0.15.tgz#063f302fb52ebe6c548a4533e3fa3b910efdfc84" - integrity sha512-VNDjLAuDF+CHf50+50CZQeT341kJm0GuWhuOqlzonOlJihpm5314Xe1BV3oeLgrtdp1ikLvQ099JqZN/l4KIQQ== - dependencies: - "@libp2p/crypto" "^4.1.0" - "@libp2p/interface" "^1.3.0" - "@libp2p/peer-id" "^4.1.0" - "@libp2p/utils" "^5.3.2" - "@multiformats/multiaddr" "^12.2.1" + uint8arrays "^5.1.0" + +"@libp2p/peer-record@^8.0.7": + version "8.0.7" + resolved "https://registry.yarnpkg.com/@libp2p/peer-record/-/peer-record-8.0.7.tgz#a092b2405e1130b8211f8ef15748b453096029d8" + integrity sha512-YsN8R+5O0MQwYQ0UGqERJJVRx7hAU4/nxiby91wzbgdfuL4qVPXHG4k0OAAtxVGLYa0q7KeXBpBG8qoaKhOXMQ== + dependencies: + "@libp2p/crypto" "^5.0.4" + "@libp2p/interface" "^2.1.2" + "@libp2p/peer-id" "^5.0.4" + "@libp2p/utils" "^6.1.0" + "@multiformats/multiaddr" "^12.2.3" + multiformats "^13.2.2" protons-runtime "^5.4.0" uint8-varint "^2.0.4" uint8arraylist "^2.4.8" - uint8arrays "^5.0.3" - -"@libp2p/peer-store@^10.0.16": - version "10.0.16" - resolved "https://registry.yarnpkg.com/@libp2p/peer-store/-/peer-store-10.0.16.tgz#0bde6e2185e416a137d8adb7b2c381bfe4acf535" - integrity sha512-xzitLNXnCG8eAs3KT5j0sBkK0ooChv4QDqjEzCNr+Gzwryi2fn386KlPoCGNkbeAUsIHS81TY/ldK8o8NBac7Q== - dependencies: - "@libp2p/interface" "^1.3.0" - "@libp2p/peer-collections" "^5.1.11" - "@libp2p/peer-id" "^4.1.0" - "@libp2p/peer-record" "^7.0.15" - "@multiformats/multiaddr" "^12.2.1" - interface-datastore "^8.2.11" - it-all "^3.0.4" + uint8arrays "^5.1.0" + +"@libp2p/peer-store@^11.0.7": + version "11.0.7" + resolved "https://registry.yarnpkg.com/@libp2p/peer-store/-/peer-store-11.0.7.tgz#e9a57d8a0ce1b3d0559a11b7e6633620f4297276" + integrity sha512-h8W/XVYfKTmJhhnh2Mdub23CzPv24l5g1RRwFsEKCkWAe95M/fvDMPTM2ahRUB64qfnFT5X4XNFFyJFMsVtjLA== + dependencies: + "@libp2p/crypto" "^5.0.4" + "@libp2p/interface" "^2.1.2" + "@libp2p/peer-collections" "^6.0.7" + "@libp2p/peer-id" "^5.0.4" + "@libp2p/peer-record" "^8.0.7" + "@multiformats/multiaddr" "^12.2.3" + interface-datastore "^8.3.0" + it-all "^3.0.6" mortice "^3.0.4" multiformats "^13.1.0" protons-runtime "^5.4.0" uint8arraylist "^2.4.8" - uint8arrays "^5.0.3" + uint8arrays "^5.1.0" -"@libp2p/prometheus-metrics@^3.0.21": - version "3.0.21" - resolved "https://registry.yarnpkg.com/@libp2p/prometheus-metrics/-/prometheus-metrics-3.0.21.tgz#78b3327a614aacc62886597d6c6eb67c5597b8db" - integrity sha512-sqU8pI9CG/b86YUEt3IaE3ZSbauBfKbxFRdSiYVRN8EbliGxQC9blgwUcGDfWW2qcXZEgM4m2FTDLZrujFDbzA== +"@libp2p/prometheus-metrics@^4.1.2": + version "4.2.1" + resolved "https://registry.yarnpkg.com/@libp2p/prometheus-metrics/-/prometheus-metrics-4.2.1.tgz#a563e05cac1f67a161824301cacdfd659bc3052c" + integrity sha512-Mt93FWjP1Jz5G/FsG7cf0J4Y1nYs4eQvx1RjtuEghoQcSzD8nSupeMt67YRQG87R/qrs0jdiGtYxmoCoagsIDw== dependencies: - "@libp2p/interface" "^1.3.0" - it-foreach "^2.0.6" + "@libp2p/interface" "^2.1.2" + it-foreach "^2.1.0" it-stream-types "^2.0.1" - prom-client "^15.1.1" + prom-client "^15.1.2" uint8arraylist "^2.4.8" -"@libp2p/pubsub@^9.0.8": - version "9.0.16" - resolved "https://registry.yarnpkg.com/@libp2p/pubsub/-/pubsub-9.0.16.tgz#90857f494213f7a596df15081956514728e14aa2" - integrity sha512-SCV0eZuYMyhHhBFzUBslHjvfwKfL2UMZSSr08c7MsTrqvQQSVdiCEeGKfoR70h7BUvBBQkPLcCqTFZGRoYX8dA== - dependencies: - "@libp2p/crypto" "^4.1.0" - "@libp2p/interface" "^1.3.0" - "@libp2p/interface-internal" "^1.1.1" - "@libp2p/peer-collections" "^5.1.11" - "@libp2p/peer-id" "^4.1.0" - "@libp2p/utils" "^5.3.2" +"@libp2p/pubsub@^10.0.0": + version "10.0.7" + resolved "https://registry.yarnpkg.com/@libp2p/pubsub/-/pubsub-10.0.7.tgz#1b7e0b7e96b75a8a1f557171ef4d72c17879e5c0" + integrity sha512-XYAYaASilesqxonjhiEENF/jXoT3jcftNYySkiyajrw3rZnLVkfJMRese3lkFqkIZqy7K/7aAtYEDJLeSrJDiQ== + dependencies: + "@libp2p/crypto" "^5.0.4" + "@libp2p/interface" "^2.1.2" + "@libp2p/interface-internal" "^2.0.7" + "@libp2p/peer-collections" "^6.0.7" + "@libp2p/peer-id" "^5.0.4" + "@libp2p/utils" "^6.1.0" it-length-prefixed "^9.0.4" it-pipe "^3.0.1" it-pushable "^3.2.3" multiformats "^13.1.0" p-queue "^8.0.1" uint8arraylist "^2.4.8" - uint8arrays "^5.0.3" + uint8arrays "^5.1.0" -"@libp2p/tcp@9.0.23": - version "9.0.23" - resolved "https://registry.yarnpkg.com/@libp2p/tcp/-/tcp-9.0.23.tgz#44eed016fdbe4725726d451a67af548507f5591b" - integrity sha512-ERX7b//PEmy4AwhjkjLx83ZpfwTlrbDt12TEn4+ZDqtsx1lzgCjuNVUy3joSWMu9ySIvMjnzxm7mxlkAJd8buw== +"@libp2p/tcp@10.0.4": + version "10.0.4" + resolved "https://registry.yarnpkg.com/@libp2p/tcp/-/tcp-10.0.4.tgz#9fdcd4ef5940816d366ee29e7e8150a5a4bd2f11" + integrity sha512-53WIxkKNMHJphTK/VUJvL5jPrkEitZpZqUSA8zN7e02OXwwOC/X3U03xvVFdrjGL32rW524+7I+SrvS+hVdNCw== dependencies: - "@libp2p/interface" "^1.3.0" - "@libp2p/utils" "^5.3.2" + "@libp2p/interface" "^2.1.2" + "@libp2p/utils" "^6.0.4" "@multiformats/mafmt" "^12.1.6" - "@multiformats/multiaddr" "^12.2.1" + "@multiformats/multiaddr" "^12.2.3" "@types/sinon" "^17.0.3" - stream-to-it "^1.0.0" + progress-events "^1.0.0" + stream-to-it "^1.0.1" -"@libp2p/utils@^5.3.2": - version "5.3.2" - resolved "https://registry.yarnpkg.com/@libp2p/utils/-/utils-5.3.2.tgz#044881910350fb22ed0f9db35e6f68f7e8948801" - integrity sha512-3HVixx17xT7JCEY931Gd2E2WmtY0RQirDeb6OZ1YD0T3VdWUMxH7pdf1gZpCHjQTg18ISIItZnFCGy+NyoYv6Q== +"@libp2p/utils@^6.0.4", "@libp2p/utils@^6.1.0": + version "6.1.0" + resolved "https://registry.yarnpkg.com/@libp2p/utils/-/utils-6.1.0.tgz#5ccece78a38bec2c2d759136ccc78494838c2b87" + integrity sha512-pxuUI8QgeS06bMZRpy0JnACPhrrCJS5/rVNTcnQK8lV1ag2bjwkGG/359AwjeEolzYQeLrmmqnZyawd1Y74wpw== dependencies: "@chainsafe/is-ip" "^2.0.2" - "@libp2p/interface" "^1.3.0" - "@libp2p/logger" "^4.0.11" - "@multiformats/multiaddr" "^12.2.1" - "@multiformats/multiaddr-matcher" "^1.2.0" + "@libp2p/crypto" "^5.0.4" + "@libp2p/interface" "^2.1.2" + "@libp2p/logger" "^5.1.0" + "@multiformats/multiaddr" "^12.2.3" + "@sindresorhus/fnv1a" "^3.1.0" + "@types/murmurhash3js-revisited" "^3.0.3" + any-signal "^4.1.1" delay "^6.0.0" get-iterator "^2.0.1" is-loopback-addr "^2.0.2" + it-foreach "^2.1.1" + it-pipe "^3.0.1" it-pushable "^3.2.3" it-stream-types "^2.0.1" + murmurhash3js-revisited "^3.0.0" netmask "^2.0.2" p-defer "^4.0.1" - race-event "^1.2.0" + race-event "^1.3.0" race-signal "^1.0.2" uint8arraylist "^2.4.8" + uint8arrays "^5.1.0" "@lukeed/ms@^2.0.2": version "2.0.2" @@ -1993,7 +2006,7 @@ outvariant "^1.2.1" strict-event-emitter "^0.5.1" -"@multiformats/dns@^1.0.3", "@multiformats/dns@^1.0.5": +"@multiformats/dns@^1.0.3", "@multiformats/dns@^1.0.6": version "1.0.6" resolved "https://registry.yarnpkg.com/@multiformats/dns/-/dns-1.0.6.tgz#b8c7de11459a02a5f4e609d35d3cdb95cb6ad152" integrity sha512-nt/5UqjMPtyvkG9BQYdJ4GfLK3nMqGpFZOzf4hAmIa0sJh2LlS9YKXZ4FgwBDsaHvzZqR/rUFIywIc7pkHNNuw== @@ -2013,23 +2026,22 @@ dependencies: "@multiformats/multiaddr" "^12.0.0" -"@multiformats/multiaddr-matcher@^1.1.0", "@multiformats/multiaddr-matcher@^1.2.0": - version "1.2.0" - resolved "https://registry.yarnpkg.com/@multiformats/multiaddr-matcher/-/multiaddr-matcher-1.2.0.tgz#8a2beae9eff394861668e6a2776fb1e7bf719c81" - integrity sha512-LH6yR7h3HSNKcxuvvi2UpLuowuVkYC6H9Y3jqmKuTai8XtKnXtW6NcDZFD/ooTBY+H4yX/scoJpjOalHrk5qdQ== +"@multiformats/multiaddr-matcher@^1.2.1": + version "1.2.4" + resolved "https://registry.yarnpkg.com/@multiformats/multiaddr-matcher/-/multiaddr-matcher-1.2.4.tgz#affb3c63b5cd83b44156be19583981651373ec2e" + integrity sha512-GgpqzQFL4Mj8t7cLNHC5nuYUuSm0kTtSUyYswiyWwTSUY3XwRAMx0UiFWQg+ETk0u+/IvFaHxfnyEoH3tasvwg== dependencies: "@chainsafe/is-ip" "^2.0.1" "@multiformats/multiaddr" "^12.0.0" multiformats "^13.0.0" -"@multiformats/multiaddr@^12.0.0", "@multiformats/multiaddr@^12.1.10", "@multiformats/multiaddr@^12.1.14", "@multiformats/multiaddr@^12.1.3", "@multiformats/multiaddr@^12.2.1": - version "12.2.1" - resolved "https://registry.yarnpkg.com/@multiformats/multiaddr/-/multiaddr-12.2.1.tgz#d95d1590b17dbe39dcefbb4d832d14434d3fe075" - integrity sha512-UwjoArBbv64FlaetV4DDwh+PUMfzXUBltxQwdh+uTYnGFzVa8ZfJsn1vt1RJlJ6+Xtrm3RMekF/B+K338i2L5Q== +"@multiformats/multiaddr@^12.0.0", "@multiformats/multiaddr@^12.1.10", "@multiformats/multiaddr@^12.1.14", "@multiformats/multiaddr@^12.1.3", "@multiformats/multiaddr@^12.2.3": + version "12.3.1" + resolved "https://registry.yarnpkg.com/@multiformats/multiaddr/-/multiaddr-12.3.1.tgz#953ceb4ae3b39125b7b2c721230ea7b398cf49fe" + integrity sha512-yoGODQY4nIj41ENJClucS8FtBoe8w682bzbKldEQr9lSlfdHqAsRC+vpJAOBpiMwPps1tHua4kxrDmvprdhoDQ== dependencies: "@chainsafe/is-ip" "^2.0.1" "@chainsafe/netmask" "^2.0.0" - "@libp2p/interface" "^1.0.0" "@multiformats/dns" "^1.0.3" multiformats "^13.0.0" uint8-varint "^2.0.1" @@ -2100,12 +2112,19 @@ resolved "https://registry.yarnpkg.com/@napi-rs/snappy-win32-x64-msvc/-/snappy-win32-x64-msvc-7.2.2.tgz#4f598d3a5d50904d9f72433819f68b21eaec4f7d" integrity sha512-a43cyx1nK0daw6BZxVcvDEXxKMFLSBSDTAhsFD0VqSKcC7MGUBMaqyoWUcMiI7LBSz4bxUmxDWKfCYzpEmeb3w== -"@noble/ciphers@^0.4.0": - version "0.4.0" - resolved "https://registry.yarnpkg.com/@noble/ciphers/-/ciphers-0.4.0.tgz#e3f69e3ce935683dd8dadb636652a5cb5cd5958c" - integrity sha512-xaUaUUDWbHIFSxaQ/pIe+33VG2mfJp6N/KxKLmZr5biWdNznCAmfu24QRhX10BbVAuqOahAoyp0S4M9md6GPDw== +"@noble/ciphers@^0.6.0": + version "0.6.0" + resolved "https://registry.yarnpkg.com/@noble/ciphers/-/ciphers-0.6.0.tgz#a3d82c72ce71ba43128e7eb71757b5ecb75b1273" + integrity sha512-mIbq/R9QXk5/cTfESb1OKtyFnk7oc1Om/8onA1158K9/OZUQFDEVy55jVTato+xmp3XX6F6Qh0zz0Nc1AxAlRQ== -"@noble/curves@1.3.0", "@noble/curves@^1.1.0", "@noble/curves@~1.3.0": +"@noble/curves@1.4.2", "@noble/curves@~1.4.0": + version "1.4.2" + resolved "https://registry.yarnpkg.com/@noble/curves/-/curves-1.4.2.tgz#40309198c76ed71bc6dbf7ba24e81ceb4d0d1fe9" + integrity sha512-TavHr8qycMChk8UwMld0ZDRvatedkzWfH8IiaeGCfymOP5i0hSCozz9vHOL0nkwk7HRMlFnAiKpS2jrUmSybcw== + dependencies: + "@noble/hashes" "1.4.0" + +"@noble/curves@^1.1.0": version "1.3.0" resolved "https://registry.yarnpkg.com/@noble/curves/-/curves-1.3.0.tgz#01be46da4fd195822dab821e72f71bf4aeec635e" integrity sha512-t01iSXPuN+Eqzb4eBX0S5oubSqXbK/xXa1Ne18Hj8f9pStxztHCE2gfboSp/dZRLSqfuLpRK2nDXDK+W9puocA== @@ -2124,12 +2143,12 @@ resolved "https://registry.yarnpkg.com/@noble/hashes/-/hashes-1.1.2.tgz#e9e035b9b166ca0af657a7848eb2718f0f22f183" integrity sha512-KYRCASVTv6aeUi1tsF8/vpyR7zpfs3FUzy2Jqm+MU+LmUKhQ0y2FpfwqkCcxSg2ua4GALJd8k2R76WxwZGbQpA== -"@noble/hashes@1.3.3", "@noble/hashes@^1.0.0", "@noble/hashes@^1.3.0", "@noble/hashes@^1.3.1", "@noble/hashes@~1.3.2": +"@noble/hashes@1.3.3", "@noble/hashes@^1.0.0", "@noble/hashes@^1.3.0", "@noble/hashes@^1.3.1": version "1.3.3" resolved "https://registry.yarnpkg.com/@noble/hashes/-/hashes-1.3.3.tgz#39908da56a4adc270147bb07968bf3b16cfe1699" integrity sha512-V7/fPHgl+jsVPXqqeOzT8egNj2iBIVt+ECeMMG8TdcnTikP3oaBtUVqpT/gYCR68aEBJSF+XbYUxStjbFMqIIA== -"@noble/hashes@1.4.0", "@noble/hashes@^1.4.0": +"@noble/hashes@1.4.0", "@noble/hashes@^1.4.0", "@noble/hashes@~1.4.0": version "1.4.0" resolved "https://registry.yarnpkg.com/@noble/hashes/-/hashes-1.4.0.tgz#45814aa329f30e4fe0ba49426f49dfccdd066426" integrity sha512-V1JJ1WTRUqHHrOSh597hURcMqVKVGL/ea3kv0gSnEdsEZ0/+VyPghM1lMNGc00z7CIQorSvbKpuJkxvuHbvdbg== @@ -2702,11 +2721,11 @@ integrity sha512-2LuNTFBIO0m7kKIQvvPHN6UE63VjpmL9rnEEaOOaiSPbZK+zUOYIzBAWcED+3XYzhYsd/0mD57VdxAEqqV52CQ== "@puppeteer/browsers@1.4.6", "@puppeteer/browsers@^1.6.0", "@puppeteer/browsers@^2.1.0": - version "2.3.0" - resolved "https://registry.yarnpkg.com/@puppeteer/browsers/-/browsers-2.3.0.tgz#791ea7d80450fea24eb19fb1d70c367ad4e08cae" - integrity sha512-ioXoq9gPxkss4MYhD+SFaU9p1IHFUX0ILAWFPyjGaBdjLsYAlZw6j1iLA0N/m12uVHLFDfSYNF7EQccjinIMDA== + version "2.4.0" + resolved "https://registry.yarnpkg.com/@puppeteer/browsers/-/browsers-2.4.0.tgz#a0dd0f4e381e53f509109ae83b891db5972750f5" + integrity sha512-x8J1csfIygOwf6D6qUAZ0ASk3z63zPb7wkNeHRerCMh82qWKUrOgkuP005AJC8lDL6/evtXETGEJVcwykKT4/g== dependencies: - debug "^4.3.5" + debug "^4.3.6" extract-zip "^2.0.1" progress "^2.0.3" proxy-agent "^6.4.0" @@ -2870,27 +2889,27 @@ resolved "https://registry.yarnpkg.com/@scure/base/-/base-1.0.0.tgz#109fb595021de285f05a7db6806f2f48296fcee7" integrity sha512-gIVaYhUsy+9s58m/ETjSJVKHhKTBMmcRb9cEV5/5dwvfDlfORjKrFsDeDHWRrm6RjcPvCLZFwGJjAjLj1gg4HA== -"@scure/base@~1.1.4": - version "1.1.5" - resolved "https://registry.yarnpkg.com/@scure/base/-/base-1.1.5.tgz#1d85d17269fe97694b9c592552dd9e5e33552157" - integrity sha512-Brj9FiG2W1MRQSTB212YVPRrcbjkv48FoZi/u4l/zds/ieRrqsh7aUf6CLwkAq61oKXr/ZlTzlY66gLIj3TFTQ== +"@scure/base@~1.1.6": + version "1.1.8" + resolved "https://registry.yarnpkg.com/@scure/base/-/base-1.1.8.tgz#8f23646c352f020c83bca750a82789e246d42b50" + integrity sha512-6CyAclxj3Nb0XT7GHK6K4zK6k2xJm6E4Ft0Ohjt4WgegiFUHEtFb2CGzmPmGBwoIhrLsqNLYfLr04Y1GePrzZg== -"@scure/bip32@1.3.3": - version "1.3.3" - resolved "https://registry.yarnpkg.com/@scure/bip32/-/bip32-1.3.3.tgz#a9624991dc8767087c57999a5d79488f48eae6c8" - integrity sha512-LJaN3HwRbfQK0X1xFSi0Q9amqOgzQnnDngIt+ZlsBC3Bm7/nE7K0kwshZHyaru79yIVRv/e1mQAjZyuZG6jOFQ== +"@scure/bip32@1.4.0": + version "1.4.0" + resolved "https://registry.yarnpkg.com/@scure/bip32/-/bip32-1.4.0.tgz#4e1f1e196abedcef395b33b9674a042524e20d67" + integrity sha512-sVUpc0Vq3tXCkDGYVWGIZTRfnvu8LoTDaev7vbwh0omSvVORONr960MQWdKqJDCReIEmTj3PAr73O3aoxz7OPg== dependencies: - "@noble/curves" "~1.3.0" - "@noble/hashes" "~1.3.2" - "@scure/base" "~1.1.4" + "@noble/curves" "~1.4.0" + "@noble/hashes" "~1.4.0" + "@scure/base" "~1.1.6" -"@scure/bip39@1.2.2": - version "1.2.2" - resolved "https://registry.yarnpkg.com/@scure/bip39/-/bip39-1.2.2.tgz#f3426813f4ced11a47489cbcf7294aa963966527" - integrity sha512-HYf9TUXG80beW+hGAt3TRM8wU6pQoYur9iNypTROm42dorCGmLnFe3eWjz3gOq6G62H2WRh0FCzAR1PI+29zIA== +"@scure/bip39@1.3.0": + version "1.3.0" + resolved "https://registry.yarnpkg.com/@scure/bip39/-/bip39-1.3.0.tgz#0f258c16823ddd00739461ac31398b4e7d6a18c3" + integrity sha512-disdg7gHuTDZtY+ZdkmLpPCk7fxZSu3gBiEGuoC1XYxv9cGx3Z6cpTggCgW6odSOOIXCiDjuGejW+aJKCY/pIQ== dependencies: - "@noble/hashes" "~1.3.2" - "@scure/base" "~1.1.4" + "@noble/hashes" "~1.4.0" + "@scure/base" "~1.1.6" "@scure/bip39@^1.0.0": version "1.0.0" @@ -2934,6 +2953,11 @@ resolved "https://registry.yarnpkg.com/@sinclair/typebox/-/typebox-0.27.8.tgz#6667fac16c436b5434a387a34dedb013198f6e6e" integrity sha512-+Fj43pSMwJs4KRrH/938Uf+uAELIgVBmQzg/q1YG10djyfA3TnrU8N8XzqCh/okZdszqBQTZf96idMfE5lnwTA== +"@sindresorhus/fnv1a@^3.1.0": + version "3.1.0" + resolved "https://registry.yarnpkg.com/@sindresorhus/fnv1a/-/fnv1a-3.1.0.tgz#f8e46597298f6fd4c12dc901cdd4e73beb4d24fa" + integrity sha512-KV321z5m/0nuAg83W1dPLy85HpHDk7Sdi4fJbwvacWsEhAh+rZUW4ZfGcXmUIvjZg4ss2bcwNlRhJ7GBEUG08w== + "@sindresorhus/is@^4.0.0": version "4.6.0" resolved "https://registry.yarnpkg.com/@sindresorhus/is/-/is-4.6.0.tgz#3c7c9c46e678feefe7a2e5bb609d3dbd665ffb3f" @@ -3248,6 +3272,11 @@ "@types/dns-packet" "*" "@types/node" "*" +"@types/murmurhash3js-revisited@^3.0.3": + version "3.0.3" + resolved "https://registry.yarnpkg.com/@types/murmurhash3js-revisited/-/murmurhash3js-revisited-3.0.3.tgz#94e247168a18342477639126da8f01353437e8d0" + integrity sha512-QvlqvYtGBYIDeO8dFdY4djkRubcrc+yTJtBc7n8VZPlJDUS/00A+PssbvERM8f9bYRmcaSEHPZgZojeQj7kzAA== + "@types/mute-stream@^0.0.4": version "0.0.4" resolved "https://registry.yarnpkg.com/@types/mute-stream/-/mute-stream-0.0.4.tgz#77208e56a08767af6c5e1237be8888e2f255c478" @@ -3336,6 +3365,11 @@ resolved "https://registry.npmjs.org/@types/retry/-/retry-0.12.1.tgz" integrity sha512-xoDlM2S4ortawSWORYqsdU+2rxdh4LRW9ytc3zmT37RIKQh6IHyKwwtKhKis9ah8ol07DCkZxPt8BBvPjC6v4g== +"@types/retry@0.12.2": + version "0.12.2" + resolved "https://registry.yarnpkg.com/@types/retry/-/retry-0.12.2.tgz#ed279a64fa438bb69f2480eda44937912bb7480a" + integrity sha512-XISRgDJ2Tc5q4TRqvgJtzsRkFYNJzZrhTdtMoGVBttwzzQJkPnS3WWTFc7kuDRoPtPakl+T+OfdEUjYJj7Jbow== + "@types/sinon@^17.0.3": version "17.0.3" resolved "https://registry.yarnpkg.com/@types/sinon/-/sinon-17.0.3.tgz#9aa7e62f0a323b9ead177ed23a36ea757141a5fa" @@ -3718,6 +3752,19 @@ abstract-level@^1.0.0, abstract-level@^1.0.2, abstract-level@^1.0.3: module-error "^1.0.1" queue-microtask "^1.2.3" +abstract-level@^1.0.4: + version "1.0.4" + resolved "https://registry.yarnpkg.com/abstract-level/-/abstract-level-1.0.4.tgz#3ad8d684c51cc9cbc9cf9612a7100b716c414b57" + integrity sha512-eUP/6pbXBkMbXFdx4IH2fVgvB7M0JvR7/lIL33zcs0IBcwjdzSSl31TOJsaCzmKSSDF9h8QYSOJux4Nd4YJqFg== + dependencies: + buffer "^6.0.3" + catering "^2.1.0" + is-buffer "^2.0.5" + level-supports "^4.0.0" + level-transcoder "^1.0.1" + module-error "^1.0.1" + queue-microtask "^1.2.3" + abstract-logging@^2.0.1: version "2.0.1" resolved "https://registry.yarnpkg.com/abstract-logging/-/abstract-logging-2.0.1.tgz#6b0c371df212db7129b57d2e7fcf282b8bf1c839" @@ -5349,15 +5396,14 @@ data-urls@^5.0.0: whatwg-mimetype "^4.0.0" whatwg-url "^14.0.0" -datastore-core@^9.0.0, datastore-core@^9.1.1, datastore-core@^9.2.9: - version "9.2.9" - resolved "https://registry.yarnpkg.com/datastore-core/-/datastore-core-9.2.9.tgz#74b4dd53d4597b59038488ba5f92a7f81769f8df" - integrity sha512-wraWTPsbtdE7FFaVo3pwPuTB/zXsgwGGAm8BgBYwYAuzZCTS0MfXmd/HH1vR9s0/NFFjOVmBkGiWCvKxZ+QjVw== +datastore-core@10.0.0, datastore-core@^10.0.0: + version "10.0.0" + resolved "https://registry.yarnpkg.com/datastore-core/-/datastore-core-10.0.0.tgz#86abe346338e88c3326fb7aeb90eff3613cf542f" + integrity sha512-/b5KDmSAIFizS/ZzTTU+ZdfOcQc6mRmbc4/EK/WOzbEO5c0KWyjRLsZ3DWwh9wiPu93V7pX1oC+Or61k8UPPsg== dependencies: "@libp2p/logger" "^4.0.6" - err-code "^3.0.1" interface-datastore "^8.0.0" - interface-store "^5.0.0" + interface-store "6.0.0" it-drain "^3.0.5" it-filter "^3.0.4" it-map "^3.0.5" @@ -5367,18 +5413,19 @@ datastore-core@^9.0.0, datastore-core@^9.1.1, datastore-core@^9.2.9: it-sort "^3.0.4" it-take "^3.0.4" -datastore-level@*, datastore-level@^10.1.1: - version "10.1.1" - resolved "https://registry.yarnpkg.com/datastore-level/-/datastore-level-10.1.1.tgz#390dc6ca17dc691947a3e81c984b4b6064812e81" - integrity sha512-4fQPf/6fIXdcC0XZPGMiNuoOmF82Vhdz+LPTmbzR+CbbnCri6eOcFdzBPnDsAAuPOCV6Zld1EhgM2cRArw1+sQ== +datastore-level@*, datastore-level@^11.0.0: + version "11.0.0" + resolved "https://registry.yarnpkg.com/datastore-level/-/datastore-level-11.0.0.tgz#c0f7324bd74e15bec01f2911f5740fbf59c344f7" + integrity sha512-ATSEfGoWTAHgDeZaYukeHu0FgyhjW3FKUw3XtcIpfBl4UF2kLNnYRBfzCeH+3RA0QaZvbSWpgYk6Gwf7m1oCtg== dependencies: - datastore-core "^9.0.0" + datastore-core "10.0.0" interface-datastore "^8.0.0" - it-filter "^3.0.0" - it-map "^3.0.1" - it-sort "^3.0.1" - it-take "^3.0.1" - level "^8.0.0" + interface-store "6.0.0" + it-filter "^3.0.4" + it-map "^3.0.5" + it-sort "^3.0.4" + it-take "^3.0.4" + level "^8.0.1" dateformat@^3.0.3: version "3.0.3" @@ -5404,6 +5451,13 @@ debug@^4.3.5: dependencies: ms "2.1.2" +debug@^4.3.6: + version "4.3.7" + resolved "https://registry.yarnpkg.com/debug/-/debug-4.3.7.tgz#87945b4151a011d76d95a198d7111c865c360a52" + integrity sha512-Er2nc/H7RrMXZBFCEim6TCmMk02Z8vLC2Rbi1KEBggpo0fS6l0S1nnapwmIi3yW/+GOJap1Krg4w0Hg80oCqgQ== + dependencies: + ms "^2.1.3" + decamelize-keys@^1.1.0: version "1.1.0" resolved "https://registry.yarnpkg.com/decamelize-keys/-/decamelize-keys-1.1.0.tgz#d171a87933252807eb3cb61dc1c1445d078df2d9" @@ -6001,15 +6055,15 @@ esutils@^2.0.2: resolved "https://registry.npmjs.org/esutils/-/esutils-2.0.3.tgz" integrity sha512-kVscqXk4OCp68SZ0dkgEKVi6/8ij300KBWTJq32P/dYeWTSwK41WyTxalN1eRmA5Z9UU/LX9D7FWSmV9SAYx6g== -ethereum-cryptography@^2.0.0, ethereum-cryptography@^2.1.3: - version "2.1.3" - resolved "https://registry.yarnpkg.com/ethereum-cryptography/-/ethereum-cryptography-2.1.3.tgz#1352270ed3b339fe25af5ceeadcf1b9c8e30768a" - integrity sha512-BlwbIL7/P45W8FGW2r7LGuvoEZ+7PWsniMvQ4p5s2xCyw9tmaDlpfsN9HjAucbF+t/qpVHwZUisgfK24TCW8aA== +ethereum-cryptography@^2.0.0, ethereum-cryptography@^2.2.0: + version "2.2.1" + resolved "https://registry.yarnpkg.com/ethereum-cryptography/-/ethereum-cryptography-2.2.1.tgz#58f2810f8e020aecb97de8c8c76147600b0b8ccf" + integrity sha512-r/W8lkHSiTLxUxW8Rf3u4HGB0xQweG2RyETjywylKZSzLWoWAijRz8WCuOtJ6wah+avllXBqZuk29HCCvhEIRg== dependencies: - "@noble/curves" "1.3.0" - "@noble/hashes" "1.3.3" - "@scure/bip32" "1.3.3" - "@scure/bip39" "1.2.2" + "@noble/curves" "1.4.2" + "@noble/hashes" "1.4.0" + "@scure/bip32" "1.4.0" + "@scure/bip39" "1.3.0" ethers@^5.7.1: version "5.7.2" @@ -7396,18 +7450,18 @@ inquirer@^9.1.5: through "^2.3.6" wrap-ansi "^8.1.0" -interface-datastore@^8.0.0, interface-datastore@^8.2.11, interface-datastore@^8.2.7: - version "8.2.11" - resolved "https://registry.yarnpkg.com/interface-datastore/-/interface-datastore-8.2.11.tgz#1d555ce6218ab6cba6291fc361debe9713590207" - integrity sha512-9E0iXehfp/j0UbZ2mvlYB4K9pP7uQBCppfuy8WHs1EHF6wLQrM9+zwyX+8Qt6HnH4GKZRyXX/CNXm6oD4+QYgA== +interface-datastore@^8.0.0, interface-datastore@^8.2.11, interface-datastore@^8.3.0: + version "8.3.0" + resolved "https://registry.yarnpkg.com/interface-datastore/-/interface-datastore-8.3.0.tgz#0ce9a2f0f61f9fbe1c1734c6d10a0265193689f7" + integrity sha512-RM/rTSmRcnoCwGZIHrPm+nlGYVoT4R0lcFvNnDyhdFT4R6BuHHhfFP47UldVEjs98SfxLuMhaNMsyjI918saHw== dependencies: - interface-store "^5.0.0" + interface-store "6.0.0" uint8arrays "^5.0.2" -interface-store@^5.0.0: - version "5.1.0" - resolved "https://registry.yarnpkg.com/interface-store/-/interface-store-5.1.0.tgz#1735cead844fe452d62c307fafbaaa1d261e6ff3" - integrity sha512-mjUwX3XSoreoxCS3sXS3pSRsGnUjl9T06KBqt/T7AgE9Sgp4diH64ZyURJKnj2T5WmCvTbC0Dm+mwQV5hfLSBQ== +interface-store@6.0.0: + version "6.0.0" + resolved "https://registry.yarnpkg.com/interface-store/-/interface-store-6.0.0.tgz#8d8277a582f69d819134e125b686e147099a4728" + integrity sha512-HkjsDPsjA7SKkCr+TH1elUQApAAM3X3JPwrz3vFzaf614wI+ZD6GVvwKGZCHYcbSRqeZP/uzVPqezzeISeo5kA== internal-slot@^1.0.5: version "1.0.5" @@ -7593,6 +7647,11 @@ is-negative-zero@^2.0.2: resolved "https://registry.yarnpkg.com/is-negative-zero/-/is-negative-zero-2.0.2.tgz#7bf6f03a28003b8b3965de3ac26f664d765f3150" integrity sha512-dqJvarLawXsFbNDeJW7zAz8ItJ9cd28YufuuFzh0G8pNHjJMnY08Dv7sYX2uF5UpQOwieAeOExEYAWWfu7ZZUA== +is-network-error@^1.0.0: + version "1.1.0" + resolved "https://registry.yarnpkg.com/is-network-error/-/is-network-error-1.1.0.tgz#d26a760e3770226d11c169052f266a4803d9c997" + integrity sha512-tUdRRAnhT+OtCZR/LxZelH/C7QtjtFrTu5tXCA8pl55eTUElUHT+GPYV8MBMBvea/j+NxQqVt3LbWMRir7Gx9g== + is-node-process@^1.2.0: version "1.2.0" resolved "https://registry.yarnpkg.com/is-node-process/-/is-node-process-1.2.0.tgz#ea02a1b90ddb3934a19aea414e88edef7e11d134" @@ -7817,6 +7876,11 @@ it-all@^3.0.0, it-all@^3.0.4: resolved "https://registry.yarnpkg.com/it-all/-/it-all-3.0.4.tgz#08f2e3eb3df04fa4525a343dcacfbdf91ffee162" integrity sha512-UMiy0i9DqCHBdWvMbzdYvVGa5/w4t1cc4nchpbnjdLhklglv8mQeEYnii0gvKESJuL1zV32Cqdb33R6/GPfxpQ== +it-all@^3.0.6: + version "3.0.6" + resolved "https://registry.yarnpkg.com/it-all/-/it-all-3.0.6.tgz#30a4f922ae9ca0945b0f720d3478ae6f5b6707ab" + integrity sha512-HXZWbxCgQZJfrv5rXvaVeaayXED8nTKx9tj9fpBhmcUJcedVZshMMMqTj0RG2+scGypb9Ut1zd1ifbf3lA8L+Q== + it-byte-stream@^1.0.0: version "1.0.0" resolved "https://registry.yarnpkg.com/it-byte-stream/-/it-byte-stream-1.0.0.tgz#07645e1c94444760bc7abecebf187b83777b0351" @@ -7826,29 +7890,38 @@ it-byte-stream@^1.0.0: it-stream-types "^2.0.1" uint8arraylist "^2.4.1" -it-drain@^3.0.3, it-drain@^3.0.5: +it-byte-stream@^1.0.12: + version "1.1.0" + resolved "https://registry.yarnpkg.com/it-byte-stream/-/it-byte-stream-1.1.0.tgz#f5b80b713fb71a34cbff2390b7232b103cf625bb" + integrity sha512-WWponBWdKEa6o2U3NX+wGMY8X1EkWXcQvpC+3CUqKb4ZzK30q3EPqiTjFxLf9tNVgdF/MNAtx/XclpVfgaz9KQ== + dependencies: + it-queueless-pushable "^1.0.0" + it-stream-types "^2.0.1" + uint8arraylist "^2.4.8" + +it-drain@^3.0.3, it-drain@^3.0.5, it-drain@^3.0.7: version "3.0.7" resolved "https://registry.yarnpkg.com/it-drain/-/it-drain-3.0.7.tgz#671a5d0220802c5bce9e68fc2b07088540fbc674" integrity sha512-vy6S1JKjjHSIFHgBpLpD1zhkCRl3z1zYWUxE14+kAYf+BL9ssWSFImJfhl361IIcwr0ofw8etzg11VqqB+ntUA== -it-filter@^3.0.0, it-filter@^3.0.4: +it-filter@^3.0.4: version "3.1.0" resolved "https://registry.yarnpkg.com/it-filter/-/it-filter-3.1.0.tgz#16e2914f7f54de44a19c03eb8289027643f33a1b" integrity sha512-FiYuzdsUhmMZJTJQ8YLdgX3ArjQmAtCG1lyrtZd+92/2eC6YO9UoybdrwVj/yyZkuXAPykrSipLuZ+KSKpt29A== dependencies: it-peekable "^3.0.0" -it-foreach@^2.0.6: - version "2.1.0" - resolved "https://registry.yarnpkg.com/it-foreach/-/it-foreach-2.1.0.tgz#37dd606d92d93ac82ee3fdeffeec7f9f8dd76cf8" - integrity sha512-nobWUecq9E2ED1kcXz2o27yN6KePauSdmxJNMwCduWByrF4WNB2UgBHjr9QV2jPXpEWPDuzxZas9fVhQj1Vovg== +it-foreach@^2.1.0, it-foreach@^2.1.1: + version "2.1.1" + resolved "https://registry.yarnpkg.com/it-foreach/-/it-foreach-2.1.1.tgz#93e311a1057dd0ff7631f914dc9c2c963f27a4b8" + integrity sha512-ID4Gxnavk/LVQLQESAQ9hR6dR63Ih6X+8VdxEktX8rpz2dCGAbZpey/eljTNbMfV2UKXHiu6UsneoNBZuac97g== dependencies: it-peekable "^3.0.0" -it-length-prefixed-stream@^1.0.0, it-length-prefixed-stream@^1.1.6: - version "1.1.7" - resolved "https://registry.yarnpkg.com/it-length-prefixed-stream/-/it-length-prefixed-stream-1.1.7.tgz#de4fec7da005f9a593e3eccd901c183154be09f9" - integrity sha512-tH38h/wChpR6As/PD6yWZlpoMuB4wDW2Rxf3QbSt4+O1HTsLYbyZasNhTyIuvQqhebQ30OYrdM0yr9ig5qUvYQ== +it-length-prefixed-stream@^1.0.0, it-length-prefixed-stream@^1.1.7: + version "1.2.0" + resolved "https://registry.yarnpkg.com/it-length-prefixed-stream/-/it-length-prefixed-stream-1.2.0.tgz#1f6ad78c60dea3b16364f86a0b78058f4d66a04e" + integrity sha512-vX7dzSl/2UMYYsAr0FQdPNVR5xYEETaeboZ+eXxNBjgARuvxnWA6OedW8lC5/J3ebMTC98JhA3eH76eTijUOsA== dependencies: it-byte-stream "^1.0.0" it-stream-types "^2.0.1" @@ -7867,14 +7940,14 @@ it-length-prefixed@^9.0.1, it-length-prefixed@^9.0.4: uint8arraylist "^2.0.0" uint8arrays "^5.0.1" -it-map@^3.0.1, it-map@^3.0.5: +it-map@^3.0.5: version "3.1.0" resolved "https://registry.yarnpkg.com/it-map/-/it-map-3.1.0.tgz#a66e5447d2ed8167ff90d19b183f6a3f8ae6e1b9" integrity sha512-B7zNmHYRE0qes8oTiNYU7jXEF5WvKZNAUosskCks1JT9Z4DNwRClrQyd+C/hgITG8ewDbVZMGx9VXAx3KMY2kA== dependencies: it-peekable "^3.0.0" -it-merge@^3.0.0, it-merge@^3.0.3: +it-merge@^3.0.0, it-merge@^3.0.3, it-merge@^3.0.5: version "3.0.5" resolved "https://registry.yarnpkg.com/it-merge/-/it-merge-3.0.5.tgz#2b0d1d07c825b9d20c4c2889aab8e07322fd803e" integrity sha512-2l7+mPf85pyRF5pqi0dKcA54E5Jm/2FyY5GsOaN51Ta0ipC7YZ3szuAsH8wOoB6eKY4XsU4k2X+mzPmFBMayEA== @@ -7889,12 +7962,12 @@ it-pair@^2.0.6: it-stream-types "^2.0.1" p-defer "^4.0.0" -it-parallel@^3.0.6: - version "3.0.6" - resolved "https://registry.yarnpkg.com/it-parallel/-/it-parallel-3.0.6.tgz#d8f9efa56dac5f960545b3a148d2ca171694d228" - integrity sha512-i7UM7I9LTkDJw3YIqXHFAPZX6CWYzGc+X3irdNrVExI4vPazrJdI7t5OqrSVN8CONXLAunCiqaSV/zZRbQR56A== +it-parallel@^3.0.7: + version "3.0.8" + resolved "https://registry.yarnpkg.com/it-parallel/-/it-parallel-3.0.8.tgz#fb4a5344732ddae9eff7c7b21908aa1f223638d4" + integrity sha512-URLhs6eG4Hdr4OdvgBBPDzOjBeSSmI+Kqex2rv/aAyYClME26RYHirLVhZsZP5M+ZP6M34iRlXk8Wlqtezuqpg== dependencies: - p-defer "^4.0.0" + p-defer "^4.0.1" it-peekable@^3.0.0: version "3.0.1" @@ -7910,10 +7983,10 @@ it-pipe@^3.0.1: it-pushable "^3.1.2" it-stream-types "^2.0.1" -it-protobuf-stream@^1.1.1, it-protobuf-stream@^1.1.2: - version "1.1.3" - resolved "https://registry.yarnpkg.com/it-protobuf-stream/-/it-protobuf-stream-1.1.3.tgz#66d95ad55b66827fbd057e45bd411917437bc116" - integrity sha512-96n+e6X8CXL0JerxTJuEnfivmfLzGKpIGAlJLoH7HEGo2nPRrMe+HxeWGwDF4Un3FphI/Z62JNxSvq/5DxfiQw== +it-protobuf-stream@^1.1.3: + version "1.1.5" + resolved "https://registry.yarnpkg.com/it-protobuf-stream/-/it-protobuf-stream-1.1.5.tgz#70da43abfb6beaaf7c53262d8cfd176d463b08f0" + integrity sha512-H70idW45As3cEbU4uSoZ9IYHUIV3YM69/2mmXYR7gOlPabWjuyNi3/abK11geiiq3la27Sos/mXr68JljjKtEQ== dependencies: it-length-prefixed-stream "^1.0.0" it-stream-types "^2.0.1" @@ -7926,6 +7999,14 @@ it-pushable@^3.1.2, it-pushable@^3.2.0, it-pushable@^3.2.3: dependencies: p-defer "^4.0.0" +it-queueless-pushable@^1.0.0: + version "1.0.0" + resolved "https://registry.yarnpkg.com/it-queueless-pushable/-/it-queueless-pushable-1.0.0.tgz#917b52964cd6465d6436f923552c407c5ee3d11c" + integrity sha512-HbcAbcuQj7a9EBxiRCZ+77FxWutgs/pY5ZvEyQnylWPGNFojCLAUwhcZjf5OuEQ9+y+vSa7w1GQBe8xJdmIn5A== + dependencies: + p-defer "^4.0.1" + race-signal "^1.0.2" + it-reader@^6.0.1: version "6.0.4" resolved "https://registry.yarnpkg.com/it-reader/-/it-reader-6.0.4.tgz#439cb88225dcd15116be0ffde9e846a928c3871a" @@ -7934,7 +8015,7 @@ it-reader@^6.0.1: it-stream-types "^2.0.1" uint8arraylist "^2.0.0" -it-sort@^3.0.1, it-sort@^3.0.4: +it-sort@^3.0.4: version "3.0.5" resolved "https://registry.yarnpkg.com/it-sort/-/it-sort-3.0.5.tgz#7209710c64e83e130659e00b2e42df4b36643f7e" integrity sha512-vFo3wYR+aRDwklp8iH8LKeePmWqXGQrS8JqEdZmbJ58DIGj67n0RT/t5BR8iYps/C/v5IdWsbow1bOCEUfY+hA== @@ -7946,7 +8027,7 @@ it-stream-types@^2.0.1: resolved "https://registry.yarnpkg.com/it-stream-types/-/it-stream-types-2.0.1.tgz#69cb4d7e79e707b8257a8997e02751ccb6c3af32" integrity sha512-6DmOs5r7ERDbvS4q8yLKENcj6Yecr7QQTqWApbZdfAUTEC947d+PEha7PCqhm//9oxaLYL7TWRekwhoXl2s6fg== -it-take@^3.0.1, it-take@^3.0.4: +it-take@^3.0.4: version "3.0.5" resolved "https://registry.yarnpkg.com/it-take/-/it-take-3.0.5.tgz#c5a82cb160d5d7767954d84c6ce30d680f884b77" integrity sha512-4CzqXzx7FAeXsRYBTH0GhkxerH8Sv0nEGIXrO0ZIpECHth59Dm9ZYZ161VPrCQccWIL/Vu6M9YptlbMiEpCIlQ== @@ -8307,6 +8388,15 @@ level@^8.0.0: browser-level "^1.0.1" classic-level "^1.2.0" +level@^8.0.1: + version "8.0.1" + resolved "https://registry.yarnpkg.com/level/-/level-8.0.1.tgz#737161db1bc317193aca4e7b6f436e7e1df64379" + integrity sha512-oPBGkheysuw7DmzFQYyFe8NAia5jFLAgEnkgWnK3OXAuJr8qFT+xBQIwokAZPME2bhPFzS8hlYcL16m8UZrtwQ== + dependencies: + abstract-level "^1.0.4" + browser-level "^1.0.1" + classic-level "^1.2.0" + libnpmaccess@7.0.2: version "7.0.2" resolved "https://registry.yarnpkg.com/libnpmaccess/-/libnpmaccess-7.0.2.tgz#7f056c8c933dd9c8ba771fa6493556b53c5aac52" @@ -8329,32 +8419,37 @@ libnpmpublish@7.3.0: sigstore "^1.4.0" ssri "^10.0.1" -libp2p@1.4.3: - version "1.4.3" - resolved "https://registry.yarnpkg.com/libp2p/-/libp2p-1.4.3.tgz#830453eec2982e5c0faf79558a0aaa87d1e5b150" - integrity sha512-/J+bqE+bYw6iiyPBlBZk1PrZo182f9W1zSzWcMrNy+CQCG/WdJllft/WxvhNKHK1KuIS/JsL9gvhuRhtpqmMKg== - dependencies: - "@libp2p/crypto" "^4.1.0" - "@libp2p/interface" "^1.3.0" - "@libp2p/interface-internal" "^1.1.1" - "@libp2p/logger" "^4.0.11" - "@libp2p/multistream-select" "^5.1.8" - "@libp2p/peer-collections" "^5.1.11" - "@libp2p/peer-id" "^4.1.0" - "@libp2p/peer-id-factory" "^4.1.0" - "@libp2p/peer-store" "^10.0.16" - "@libp2p/utils" "^5.3.2" - "@multiformats/dns" "^1.0.5" - "@multiformats/multiaddr" "^12.2.1" - "@multiformats/multiaddr-matcher" "^1.2.0" +libp2p@2.1.7: + version "2.1.7" + resolved "https://registry.yarnpkg.com/libp2p/-/libp2p-2.1.7.tgz#e0d921cba459c78c63d783aafea6ead98a75e57f" + integrity sha512-nUxws8eHeI4jREZJFNdif20c8jYnqPkmvioI3y/hICgXchkhcKzgT1E3jEd2CVT+isskr5LnJ1n70aw6bt0m6w== + dependencies: + "@libp2p/crypto" "^5.0.4" + "@libp2p/interface" "^2.1.2" + "@libp2p/interface-internal" "^2.0.7" + "@libp2p/logger" "^5.1.0" + "@libp2p/multistream-select" "^6.0.5" + "@libp2p/peer-collections" "^6.0.7" + "@libp2p/peer-id" "^5.0.4" + "@libp2p/peer-store" "^11.0.7" + "@libp2p/utils" "^6.1.0" + "@multiformats/dns" "^1.0.6" + "@multiformats/multiaddr" "^12.2.3" + "@multiformats/multiaddr-matcher" "^1.2.1" any-signal "^4.1.1" - datastore-core "^9.2.9" - interface-datastore "^8.2.11" - it-merge "^3.0.3" - it-parallel "^3.0.6" + datastore-core "^10.0.0" + interface-datastore "^8.3.0" + it-byte-stream "^1.0.12" + it-merge "^3.0.5" + it-parallel "^3.0.7" merge-options "^3.0.4" multiformats "^13.1.0" - uint8arrays "^5.0.3" + p-defer "^4.0.1" + p-retry "^6.2.0" + progress-events "^1.0.0" + race-event "^1.3.0" + race-signal "^1.0.2" + uint8arrays "^5.1.0" light-my-request@^6.0.0: version "6.0.0" @@ -9177,11 +9272,16 @@ ms@2.1.2: resolved "https://registry.yarnpkg.com/ms/-/ms-2.1.2.tgz#d09d1f357b443f493382a8eb3ccd183872ae6009" integrity sha512-sGkPx+VjMtmA6MX27oA4FBFELFCZZ4S4XqeGOXCv68tT+jb3vk/RyaKWP0PTKyWtmLSM0b+adUTEvbs1PEaH2w== -ms@2.1.3, ms@^2.0.0, ms@^2.1.1: +ms@2.1.3, ms@^2.0.0, ms@^2.1.1, ms@^2.1.3: version "2.1.3" resolved "https://registry.yarnpkg.com/ms/-/ms-2.1.3.tgz#574c8138ce1d2b5861f0b44579dbadd60c6615b2" integrity sha512-6FlzubTLZG3J2a/NVCAleEhjzq5oxgHyaCU9yYXvcLsvoVaHJq/s5xXI6/XXP6tz7R9xAOtHnSO/tXtF3WRTlA== +ms@^3.0.0-canary.1: + version "3.0.0-canary.1" + resolved "https://registry.yarnpkg.com/ms/-/ms-3.0.0-canary.1.tgz#c7b34fbce381492fd0b345d1cf56e14d67b77b80" + integrity sha512-kh8ARjh8rMN7Du2igDRO9QJnqCb2xYTJxyQYK7vJJS4TvLLmsbyhiKpSW+t+y26gyOyMd0riphX0GeWKU3ky5g== + msw@^2.3.1: version "2.3.2" resolved "https://registry.yarnpkg.com/msw/-/msw-2.3.2.tgz#ea4f45b51f833fa3b2215c4093bcda28dbe25a83" @@ -9223,10 +9323,10 @@ multiformats@^11.0.1: resolved "https://registry.yarnpkg.com/multiformats/-/multiformats-11.0.2.tgz#b14735efc42cd8581e73895e66bebb9752151b60" integrity sha512-b5mYMkOkARIuVZCpvijFj9a6m5wMVLC7cf/jIPd5D/ARDOfLC5+IFkbgDXQgcU2goIsTD/O9NY4DI/Mt4OGvlg== -multiformats@^13.0.0, multiformats@^13.0.1, multiformats@^13.1.0: - version "13.1.0" - resolved "https://registry.yarnpkg.com/multiformats/-/multiformats-13.1.0.tgz#5aa9d2175108a448fc3bdb54ba8a3d0b6cab3ac3" - integrity sha512-HzdtdBwxsIkzpeXzhQ5mAhhuxcHbjEHH+JQoxt7hG/2HGFjjwyolLo7hbaexcnhoEuV4e0TNJ8kkpMjiEYY4VQ== +multiformats@^13.0.0, multiformats@^13.0.1, multiformats@^13.1.0, multiformats@^13.2.2: + version "13.2.2" + resolved "https://registry.yarnpkg.com/multiformats/-/multiformats-13.2.2.tgz#16da153ee8b68d8c9da31b52176e90b3cd8b43ef" + integrity sha512-RWI+nyf0q64vyOxL8LbKtjJMki0sogRL/8axvklNtiTM0iFCVtHwME9w6+0P1/v4dQvsIg8A45oT3ka1t/M/+A== multimatch@5.0.0: version "5.0.0" @@ -9239,6 +9339,11 @@ multimatch@5.0.0: arrify "^2.0.1" minimatch "^3.0.4" +murmurhash3js-revisited@^3.0.0: + version "3.0.0" + resolved "https://registry.yarnpkg.com/murmurhash3js-revisited/-/murmurhash3js-revisited-3.0.0.tgz#6bd36e25de8f73394222adc6e41fa3fac08a5869" + integrity sha512-/sF3ee6zvScXMb1XFJ8gDsSnY+X8PbOyjIuBhtgis10W2Jx4ZjIhikUCIF9c4gpJxVnQIsPAFrSwTCuAjicP6g== + mute-stream@0.0.8: version "0.0.8" resolved "https://registry.yarnpkg.com/mute-stream/-/mute-stream-0.0.8.tgz#1630c42b2251ff81e2a283de96a5497ea92e5e0d" @@ -9947,6 +10052,15 @@ p-reduce@2.1.0, p-reduce@^2.0.0, p-reduce@^2.1.0: resolved "https://registry.yarnpkg.com/p-reduce/-/p-reduce-2.1.0.tgz#09408da49507c6c274faa31f28df334bc712b64a" integrity sha512-2USApvnsutq8uoxZBGbbWM0JIYLiEMJ9RlaN7fAzVNb9OZN0SHjjTTfIcb667XynS5Y1VhwDJVDa72TnPzAYWw== +p-retry@^6.2.0: + version "6.2.0" + resolved "https://registry.yarnpkg.com/p-retry/-/p-retry-6.2.0.tgz#8d6df01af298750009691ce2f9b3ad2d5968f3bd" + integrity sha512-JA6nkq6hKyWLLasXQXUrO4z8BUZGUt/LjlJxx8Gb2+2ntodU/SS63YZ8b0LUTbQ8ZB9iwOfhEPhg4ykKnn2KsA== + dependencies: + "@types/retry" "0.12.2" + is-network-error "^1.0.0" + retry "^0.13.1" + p-timeout@^3.2.0: version "3.2.0" resolved "https://registry.yarnpkg.com/p-timeout/-/p-timeout-3.2.0.tgz#c7e17abc971d2a7962ef83626b35d635acf23dfe" @@ -10357,10 +10471,10 @@ progress@^2.0.3: resolved "https://registry.npmjs.org/progress/-/progress-2.0.3.tgz" integrity sha512-7PiHtLll5LdnKIMw100I+8xJXR5gW2QwWYkT6iJva0bXitZKa/XMrSbdmg3r2Xnaidz9Qumd0VPaMrZlF9V9sA== -prom-client@^15.1.0, prom-client@^15.1.1: - version "15.1.2" - resolved "https://registry.yarnpkg.com/prom-client/-/prom-client-15.1.2.tgz#78d79f12c35d395ca97edf7111c18210cf07f815" - integrity sha512-on3h1iXb04QFLLThrmVYg1SChBQ9N1c+nKAjebBjokBqipddH3uxmOUcEkTnzmJ8Jh/5TSUnUqS40i2QB2dJHQ== +prom-client@^15.1.0, prom-client@^15.1.2: + version "15.1.3" + resolved "https://registry.yarnpkg.com/prom-client/-/prom-client-15.1.3.tgz#69fa8de93a88bc9783173db5f758dc1c69fa8fc2" + integrity sha512-6ZiOBfCywsD4k1BN9IX0uZhF+tJkV8q8llP64G5Hajs4JOeVLPCwpPVcpXy3BwYiUGgyJzsJJQeOIv7+hDSq8g== dependencies: "@opentelemetry/api" "^1.4.0" tdigest "^0.1.1" @@ -10406,10 +10520,10 @@ protocols@^2.0.0, protocols@^2.0.1: resolved "https://registry.yarnpkg.com/protocols/-/protocols-2.0.1.tgz#8f155da3fc0f32644e83c5782c8e8212ccf70a86" integrity sha512-/XJ368cyBJ7fzLMwLKv1e4vLxOju2MNAIokcr7meSaNcVbWz/CPcW22cP04mwxOErdA5mwjA8Q6w/cdAQxVn7Q== -protons-runtime@5.4.0, protons-runtime@^5.0.0, protons-runtime@^5.4.0: - version "5.4.0" - resolved "https://registry.yarnpkg.com/protons-runtime/-/protons-runtime-5.4.0.tgz#2751ce22cae6c35eebba89acfd9d783419ae3726" - integrity sha512-XfA++W/WlQOSyjUyuF5lgYBfXZUEMP01Oh1C2dSwZAlF2e/ZrMRPfWonXj6BGM+o8Xciv7w0tsRMKYwYEuQvaw== +protons-runtime@^5.4.0, protons-runtime@^5.5.0: + version "5.5.0" + resolved "https://registry.yarnpkg.com/protons-runtime/-/protons-runtime-5.5.0.tgz#ea06d9ef843aad77ea5de3e1ebafa81b58c24570" + integrity sha512-EsALjF9QsrEk6gbCx3lmfHxVN0ah7nG3cY7GySD4xf4g8cr7g543zB88Foh897Sr1RQJ9yDCUsoT1i1H/cVUFA== dependencies: uint8-varint "^2.0.2" uint8arraylist "^2.4.3" @@ -10558,7 +10672,7 @@ quick-lru@^5.1.1: resolved "https://registry.npmjs.org/quick-lru/-/quick-lru-5.1.1.tgz" integrity sha512-WuyALRjWPDGtt/wzJiadO5AXY+8hZ80hVpe6MyivgraREW751X3SbhRvG3eLKOYN+8VEvqLcf3wdnt44Z4S4SA== -race-event@^1.2.0: +race-event@^1.3.0: version "1.3.0" resolved "https://registry.yarnpkg.com/race-event/-/race-event-1.3.0.tgz#854f34118c31addf877898bd9f8e4dcfac9de7a2" integrity sha512-kaLm7axfOnahIqD3jQ4l1e471FIFcEGebXEnhxyLscuUzV8C94xVHtWEqDDXxll7+yu/6lW0w1Ff4HbtvHvOHg== @@ -10854,6 +10968,11 @@ retry@^0.12.0: resolved "https://registry.yarnpkg.com/retry/-/retry-0.12.0.tgz#1b42a6266a21f07421d1b0b54b7dc167b01c013b" integrity sha512-9LkiTwjUh6rT555DtE9rTX+BKByPfrMzEAtnlEtdEwr3Nkffwiihqe2bWADg+OQRjt9gl6ICdmB/ZFDCGAtSow== +retry@^0.13.1: + version "0.13.1" + resolved "https://registry.yarnpkg.com/retry/-/retry-0.13.1.tgz#185b1587acf67919d63b357349e03537b2484658" + integrity sha512-XQBQ3I8W1Cge0Seh+6gjj03LbmRFWuoszgK9ooCpwYIrhhoO80pfq4cUkU5DkknwfOfFteRwlZ56PYOGYyFWdg== + reusify@^1.0.4: version "1.0.4" resolved "https://registry.yarnpkg.com/reusify/-/reusify-1.0.4.tgz#90da382b1e126efc02146e90845a88db12925d76" @@ -11540,7 +11659,7 @@ stream-http@^3.2.0: readable-stream "^3.6.0" xtend "^4.0.2" -stream-to-it@^1.0.0: +stream-to-it@^1.0.1: version "1.0.1" resolved "https://registry.yarnpkg.com/stream-to-it/-/stream-to-it-1.0.1.tgz#7d5e1b04bab70facd48273279bfa49f0d0165950" integrity sha512-AqHYAYPHcmvMrcLNgncE/q0Aj/ajP6A4qGhxP6EVn7K3YTNs0bJpJyk57wc2Heb7MUL64jurvmnmui8D9kjZgA== @@ -11776,6 +11895,11 @@ supports-color@^7.1.0: dependencies: has-flag "^4.0.0" +supports-color@^9.4.0: + version "9.4.0" + resolved "https://registry.yarnpkg.com/supports-color/-/supports-color-9.4.0.tgz#17bfcf686288f531db3dea3215510621ccb55954" + integrity sha512-VL+lNrEoIXww1coLPOmiEmK/0sGigko5COxI09KzHc2VJXJsQ37UaQ+8quuxjDeA7+KnLGTWRyOXSLLR2Wb4jw== + supports-preserve-symlinks-flag@^1.0.0: version "1.0.0" resolved "https://registry.yarnpkg.com/supports-preserve-symlinks-flag/-/supports-preserve-symlinks-flag-1.0.0.tgz#6eda4bd344a3c94aea376d4cc31bc77311039e09" @@ -12307,10 +12431,10 @@ uint8arraylist@^2.0.0, uint8arraylist@^2.4.1, uint8arraylist@^2.4.3, uint8arrayl dependencies: uint8arrays "^5.0.1" -uint8arrays@^5.0.0, uint8arrays@^5.0.1, uint8arrays@^5.0.2, uint8arrays@^5.0.3: - version "5.0.3" - resolved "https://registry.yarnpkg.com/uint8arrays/-/uint8arrays-5.0.3.tgz#92b894d9c4269ba97c51544d6e1f279fe6f80d1f" - integrity sha512-6LBuKji28kHjgPJMkQ6GDaBb1lRwIhyOYq6pDGwYMoDPfImE9SkuYENVmR0yu9yGgs2clHUSY9fKDukR+AXfqQ== +uint8arrays@^5.0.0, uint8arrays@^5.0.1, uint8arrays@^5.0.2, uint8arrays@^5.1.0: + version "5.1.0" + resolved "https://registry.yarnpkg.com/uint8arrays/-/uint8arrays-5.1.0.tgz#14047c9bdf825d025b7391299436e5e50e7270f1" + integrity sha512-vA6nFepEmlSKkMBnLBaUMVvAC4G3CTmO58C12y4sq6WPDOR7mOFYOi7GlrQ4djeSbP6JG9Pv9tJDM97PedRSww== dependencies: multiformats "^13.0.0" @@ -12675,6 +12799,14 @@ wcwidth@^1.0.0, wcwidth@^1.0.1: dependencies: defaults "^1.0.3" +weald@^1.0.2: + version "1.0.2" + resolved "https://registry.yarnpkg.com/weald/-/weald-1.0.2.tgz#a51fb3a8dbf5fa2b71ef09f9a267c86a46742238" + integrity sha512-iG5cIuBwsPe1ZcoGGd4X6QYlepU1vLr4l4oWpzQWqeJPSo9B8bxxyE6xlnj3TCmThtha7gyVL+uuZgUFkPyfDg== + dependencies: + ms "^3.0.0-canary.1" + supports-color "^9.4.0" + web-streams-polyfill@^3.0.3: version "3.2.1" resolved "https://registry.yarnpkg.com/web-streams-polyfill/-/web-streams-polyfill-3.2.1.tgz#71c2718c52b45fd49dbeee88634b3a60ceab42a6" From f4f14d69db9614804ca3164a854df4cea4885790 Mon Sep 17 00:00:00 2001 From: Cayman Date: Fri, 11 Oct 2024 17:21:08 -0400 Subject: [PATCH 52/52] chore: bump package versions to 1.23.0 --- lerna.json | 2 +- packages/api/package.json | 10 ++++----- packages/beacon-node/package.json | 28 +++++++++++++------------- packages/cli/package.json | 26 ++++++++++++------------ packages/config/package.json | 8 ++++---- packages/db/package.json | 8 ++++---- packages/flare/package.json | 14 ++++++------- packages/fork-choice/package.json | 12 +++++------ packages/light-client/package.json | 12 +++++------ packages/logger/package.json | 6 +++--- packages/params/package.json | 2 +- packages/prover/package.json | 18 ++++++++--------- packages/reqresp/package.json | 12 +++++------ packages/spec-test-util/package.json | 4 ++-- packages/state-transition/package.json | 12 +++++------ packages/test-utils/package.json | 6 +++--- packages/types/package.json | 4 ++-- packages/utils/package.json | 2 +- packages/validator/package.json | 18 ++++++++--------- 19 files changed, 102 insertions(+), 102 deletions(-) diff --git a/lerna.json b/lerna.json index 0ffc65fe5402..6d76d7f4a488 100644 --- a/lerna.json +++ b/lerna.json @@ -4,7 +4,7 @@ ], "npmClient": "yarn", "useNx": true, - "version": "1.22.0", + "version": "1.23.0", "stream": true, "command": { "version": { diff --git a/packages/api/package.json b/packages/api/package.json index 58566a0b23f6..3c5b73a30f3f 100644 --- a/packages/api/package.json +++ b/packages/api/package.json @@ -11,7 +11,7 @@ "bugs": { "url": "https://github.com/ChainSafe/lodestar/issues" }, - "version": "1.22.0", + "version": "1.23.0", "type": "module", "exports": { ".": { @@ -72,10 +72,10 @@ "dependencies": { "@chainsafe/persistent-merkle-tree": "^0.8.0", "@chainsafe/ssz": "^0.17.1", - "@lodestar/config": "^1.22.0", - "@lodestar/params": "^1.22.0", - "@lodestar/types": "^1.22.0", - "@lodestar/utils": "^1.22.0", + "@lodestar/config": "^1.23.0", + "@lodestar/params": "^1.23.0", + "@lodestar/types": "^1.23.0", + "@lodestar/utils": "^1.23.0", "eventsource": "^2.0.2", "qs": "^6.11.1" }, diff --git a/packages/beacon-node/package.json b/packages/beacon-node/package.json index e3d095b6f1e0..137519ef8920 100644 --- a/packages/beacon-node/package.json +++ b/packages/beacon-node/package.json @@ -11,7 +11,7 @@ "bugs": { "url": "https://github.com/ChainSafe/lodestar/issues" }, - "version": "1.22.0", + "version": "1.23.0", "type": "module", "exports": { ".": { @@ -102,9 +102,9 @@ "@chainsafe/libp2p-noise": "^16.0.0", "@chainsafe/persistent-merkle-tree": "^0.8.0", "@chainsafe/prometheus-gc-stats": "^1.0.0", + "@chainsafe/pubkey-index-map": "2.0.0", "@chainsafe/ssz": "^0.17.1", "@chainsafe/threads": "^1.11.1", - "@chainsafe/pubkey-index-map": "2.0.0", "@ethersproject/abi": "^5.7.0", "@fastify/bearer-auth": "^10.0.1", "@fastify/cors": "^10.0.1", @@ -119,18 +119,18 @@ "@libp2p/peer-id": "^5.0.4", "@libp2p/prometheus-metrics": "^4.1.2", "@libp2p/tcp": "10.0.4", - "@lodestar/api": "^1.22.0", - "@lodestar/config": "^1.22.0", - "@lodestar/db": "^1.22.0", - "@lodestar/fork-choice": "^1.22.0", - "@lodestar/light-client": "^1.22.0", - "@lodestar/logger": "^1.22.0", - "@lodestar/params": "^1.22.0", - "@lodestar/reqresp": "^1.22.0", - "@lodestar/state-transition": "^1.22.0", - "@lodestar/types": "^1.22.0", - "@lodestar/utils": "^1.22.0", - "@lodestar/validator": "^1.22.0", + "@lodestar/api": "^1.23.0", + "@lodestar/config": "^1.23.0", + "@lodestar/db": "^1.23.0", + "@lodestar/fork-choice": "^1.23.0", + "@lodestar/light-client": "^1.23.0", + "@lodestar/logger": "^1.23.0", + "@lodestar/params": "^1.23.0", + "@lodestar/reqresp": "^1.23.0", + "@lodestar/state-transition": "^1.23.0", + "@lodestar/types": "^1.23.0", + "@lodestar/utils": "^1.23.0", + "@lodestar/validator": "^1.23.0", "@multiformats/multiaddr": "^12.1.3", "c-kzg": "^2.1.2", "datastore-core": "^10.0.0", diff --git a/packages/cli/package.json b/packages/cli/package.json index 67d0dfd332cc..ae690de244d0 100644 --- a/packages/cli/package.json +++ b/packages/cli/package.json @@ -1,6 +1,6 @@ { "name": "@chainsafe/lodestar", - "version": "1.22.0", + "version": "1.23.0", "description": "Command line interface for lodestar", "author": "ChainSafe Systems", "license": "LGPL-3.0", @@ -62,17 +62,17 @@ "@libp2p/crypto": "^5.0.4", "@libp2p/interface": "^2.1.2", "@libp2p/peer-id": "^5.0.4", - "@lodestar/api": "^1.22.0", - "@lodestar/beacon-node": "^1.22.0", - "@lodestar/config": "^1.22.0", - "@lodestar/db": "^1.22.0", - "@lodestar/light-client": "^1.22.0", - "@lodestar/logger": "^1.22.0", - "@lodestar/params": "^1.22.0", - "@lodestar/state-transition": "^1.22.0", - "@lodestar/types": "^1.22.0", - "@lodestar/utils": "^1.22.0", - "@lodestar/validator": "^1.22.0", + "@lodestar/api": "^1.23.0", + "@lodestar/beacon-node": "^1.23.0", + "@lodestar/config": "^1.23.0", + "@lodestar/db": "^1.23.0", + "@lodestar/light-client": "^1.23.0", + "@lodestar/logger": "^1.23.0", + "@lodestar/params": "^1.23.0", + "@lodestar/state-transition": "^1.23.0", + "@lodestar/types": "^1.23.0", + "@lodestar/utils": "^1.23.0", + "@lodestar/validator": "^1.23.0", "@multiformats/multiaddr": "^12.1.3", "deepmerge": "^4.3.1", "ethers": "^6.7.0", @@ -88,7 +88,7 @@ "yargs": "^17.7.1" }, "devDependencies": { - "@lodestar/test-utils": "^1.22.0", + "@lodestar/test-utils": "^1.23.0", "@types/debug": "^4.1.7", "@types/got": "^9.6.12", "@types/inquirer": "^9.0.3", diff --git a/packages/config/package.json b/packages/config/package.json index 434000db2a0f..7f74d1807e13 100644 --- a/packages/config/package.json +++ b/packages/config/package.json @@ -1,6 +1,6 @@ { "name": "@lodestar/config", - "version": "1.22.0", + "version": "1.23.0", "description": "Chain configuration required for lodestar", "author": "ChainSafe Systems", "license": "Apache-2.0", @@ -65,8 +65,8 @@ ], "dependencies": { "@chainsafe/ssz": "^0.17.1", - "@lodestar/params": "^1.22.0", - "@lodestar/utils": "^1.22.0", - "@lodestar/types": "^1.22.0" + "@lodestar/params": "^1.23.0", + "@lodestar/types": "^1.23.0", + "@lodestar/utils": "^1.23.0" } } diff --git a/packages/db/package.json b/packages/db/package.json index 2a10d36766bf..634378f9695d 100644 --- a/packages/db/package.json +++ b/packages/db/package.json @@ -1,6 +1,6 @@ { "name": "@lodestar/db", - "version": "1.22.0", + "version": "1.23.0", "description": "DB modules of Lodestar", "author": "ChainSafe Systems", "homepage": "https://github.com/ChainSafe/lodestar#readme", @@ -36,12 +36,12 @@ }, "dependencies": { "@chainsafe/ssz": "^0.17.1", - "@lodestar/config": "^1.22.0", - "@lodestar/utils": "^1.22.0", + "@lodestar/config": "^1.23.0", + "@lodestar/utils": "^1.23.0", "classic-level": "^1.4.1", "it-all": "^3.0.4" }, "devDependencies": { - "@lodestar/logger": "^1.22.0" + "@lodestar/logger": "^1.23.0" } } diff --git a/packages/flare/package.json b/packages/flare/package.json index a08e5fe0edc1..58032f532040 100644 --- a/packages/flare/package.json +++ b/packages/flare/package.json @@ -1,6 +1,6 @@ { "name": "@lodestar/flare", - "version": "1.22.0", + "version": "1.23.0", "description": "Beacon chain debugging tool", "author": "ChainSafe Systems", "license": "Apache-2.0", @@ -60,12 +60,12 @@ "dependencies": { "@chainsafe/bls-keygen": "^0.4.0", "@chainsafe/blst": "^2.0.3", - "@lodestar/api": "^1.22.0", - "@lodestar/config": "^1.22.0", - "@lodestar/params": "^1.22.0", - "@lodestar/state-transition": "^1.22.0", - "@lodestar/types": "^1.22.0", - "@lodestar/utils": "^1.22.0", + "@lodestar/api": "^1.23.0", + "@lodestar/config": "^1.23.0", + "@lodestar/params": "^1.23.0", + "@lodestar/state-transition": "^1.23.0", + "@lodestar/types": "^1.23.0", + "@lodestar/utils": "^1.23.0", "source-map-support": "^0.5.21", "yargs": "^17.7.1" }, diff --git a/packages/fork-choice/package.json b/packages/fork-choice/package.json index 2197ad90a9fd..ed05049f176c 100644 --- a/packages/fork-choice/package.json +++ b/packages/fork-choice/package.json @@ -11,7 +11,7 @@ "bugs": { "url": "https://github.com/ChainSafe/lodestar/issues" }, - "version": "1.22.0", + "version": "1.23.0", "type": "module", "exports": "./lib/index.js", "types": "./lib/index.d.ts", @@ -37,11 +37,11 @@ }, "dependencies": { "@chainsafe/ssz": "^0.17.1", - "@lodestar/config": "^1.22.0", - "@lodestar/params": "^1.22.0", - "@lodestar/state-transition": "^1.22.0", - "@lodestar/types": "^1.22.0", - "@lodestar/utils": "^1.22.0" + "@lodestar/config": "^1.23.0", + "@lodestar/params": "^1.23.0", + "@lodestar/state-transition": "^1.23.0", + "@lodestar/types": "^1.23.0", + "@lodestar/utils": "^1.23.0" }, "keywords": [ "ethereum", diff --git a/packages/light-client/package.json b/packages/light-client/package.json index a503d6bc510e..48a6d816558d 100644 --- a/packages/light-client/package.json +++ b/packages/light-client/package.json @@ -11,7 +11,7 @@ "bugs": { "url": "https://github.com/ChainSafe/lodestar/issues" }, - "version": "1.22.0", + "version": "1.23.0", "type": "module", "exports": { ".": { @@ -77,11 +77,11 @@ "@chainsafe/blst": "^0.2.0", "@chainsafe/persistent-merkle-tree": "^0.8.0", "@chainsafe/ssz": "^0.17.1", - "@lodestar/api": "^1.22.0", - "@lodestar/config": "^1.22.0", - "@lodestar/params": "^1.22.0", - "@lodestar/types": "^1.22.0", - "@lodestar/utils": "^1.22.0", + "@lodestar/api": "^1.23.0", + "@lodestar/config": "^1.23.0", + "@lodestar/params": "^1.23.0", + "@lodestar/types": "^1.23.0", + "@lodestar/utils": "^1.23.0", "mitt": "^3.0.0" }, "devDependencies": { diff --git a/packages/logger/package.json b/packages/logger/package.json index 3d6ee5a0d874..b9e9beef39be 100644 --- a/packages/logger/package.json +++ b/packages/logger/package.json @@ -11,7 +11,7 @@ "bugs": { "url": "https://github.com/ChainSafe/lodestar/issues" }, - "version": "1.22.0", + "version": "1.23.0", "type": "module", "exports": { ".": { @@ -66,14 +66,14 @@ }, "types": "lib/index.d.ts", "dependencies": { - "@lodestar/utils": "^1.22.0", + "@lodestar/utils": "^1.23.0", "winston": "^3.8.2", "winston-daily-rotate-file": "^4.7.1", "winston-transport": "^4.5.0" }, "devDependencies": { "@chainsafe/threads": "^1.11.1", - "@lodestar/test-utils": "^1.22.0", + "@lodestar/test-utils": "^1.23.0", "@types/triple-beam": "^1.3.2", "triple-beam": "^1.3.0" }, diff --git a/packages/params/package.json b/packages/params/package.json index 33b8415170f1..ce78e826ef18 100644 --- a/packages/params/package.json +++ b/packages/params/package.json @@ -1,6 +1,6 @@ { "name": "@lodestar/params", - "version": "1.22.0", + "version": "1.23.0", "description": "Chain parameters required for lodestar", "author": "ChainSafe Systems", "license": "Apache-2.0", diff --git a/packages/prover/package.json b/packages/prover/package.json index 9bfe7f21e480..eee42f4226c2 100644 --- a/packages/prover/package.json +++ b/packages/prover/package.json @@ -11,7 +11,7 @@ "bugs": { "url": "https://github.com/ChainSafe/lodestar/issues" }, - "version": "1.22.0", + "version": "1.23.0", "type": "module", "exports": { ".": { @@ -69,13 +69,13 @@ "@ethereumjs/tx": "^4.1.2", "@ethereumjs/util": "^8.0.6", "@ethereumjs/vm": "^6.4.2", - "@lodestar/api": "^1.22.0", - "@lodestar/config": "^1.22.0", - "@lodestar/light-client": "^1.22.0", - "@lodestar/logger": "^1.22.0", - "@lodestar/params": "^1.22.0", - "@lodestar/types": "^1.22.0", - "@lodestar/utils": "^1.22.0", + "@lodestar/api": "^1.23.0", + "@lodestar/config": "^1.23.0", + "@lodestar/light-client": "^1.23.0", + "@lodestar/logger": "^1.23.0", + "@lodestar/params": "^1.23.0", + "@lodestar/types": "^1.23.0", + "@lodestar/utils": "^1.23.0", "ethereum-cryptography": "^2.0.0", "find-up": "^6.3.0", "http-proxy": "^1.18.1", @@ -84,7 +84,7 @@ "yargs": "^17.7.1" }, "devDependencies": { - "@lodestar/test-utils": "^1.22.0", + "@lodestar/test-utils": "^1.23.0", "@types/http-proxy": "^1.17.10", "@types/yargs": "^17.0.24", "axios": "^1.3.4", diff --git a/packages/reqresp/package.json b/packages/reqresp/package.json index d6d4fbd2b5c2..77ef171595bc 100644 --- a/packages/reqresp/package.json +++ b/packages/reqresp/package.json @@ -11,7 +11,7 @@ "bugs": { "url": "https://github.com/ChainSafe/lodestar/issues" }, - "version": "1.22.0", + "version": "1.23.0", "type": "module", "exports": { ".": { @@ -54,9 +54,9 @@ "dependencies": { "@chainsafe/fast-crc32c": "^4.1.1", "@libp2p/interface": "^2.1.2", - "@lodestar/config": "^1.22.0", - "@lodestar/params": "^1.22.0", - "@lodestar/utils": "^1.22.0", + "@lodestar/config": "^1.23.0", + "@lodestar/params": "^1.23.0", + "@lodestar/utils": "^1.23.0", "it-all": "^3.0.4", "it-pipe": "^3.0.1", "snappy": "^7.2.2", @@ -65,8 +65,8 @@ "uint8arraylist": "^2.4.7" }, "devDependencies": { - "@lodestar/logger": "^1.22.0", - "@lodestar/types": "^1.22.0", + "@lodestar/logger": "^1.23.0", + "@lodestar/types": "^1.23.0", "libp2p": "2.1.7" }, "peerDependencies": { diff --git a/packages/spec-test-util/package.json b/packages/spec-test-util/package.json index 501d13024159..6f58e55d2201 100644 --- a/packages/spec-test-util/package.json +++ b/packages/spec-test-util/package.json @@ -1,6 +1,6 @@ { "name": "@lodestar/spec-test-util", - "version": "1.22.0", + "version": "1.23.0", "description": "Spec test suite generator from yaml test files", "author": "ChainSafe Systems", "license": "Apache-2.0", @@ -62,7 +62,7 @@ "blockchain" ], "dependencies": { - "@lodestar/utils": "^1.22.0", + "@lodestar/utils": "^1.23.0", "axios": "^1.3.4", "rimraf": "^4.4.1", "snappyjs": "^0.7.0", diff --git a/packages/state-transition/package.json b/packages/state-transition/package.json index a01d835bae95..7fad42d3947c 100644 --- a/packages/state-transition/package.json +++ b/packages/state-transition/package.json @@ -11,7 +11,7 @@ "bugs": { "url": "https://github.com/ChainSafe/lodestar/issues" }, - "version": "1.22.0", + "version": "1.23.0", "type": "module", "exports": { ".": { @@ -62,13 +62,13 @@ "@chainsafe/blst": "^2.0.3", "@chainsafe/persistent-merkle-tree": "^0.8.0", "@chainsafe/persistent-ts": "^0.19.1", + "@chainsafe/pubkey-index-map": "2.0.0", "@chainsafe/ssz": "^0.17.1", "@chainsafe/swap-or-not-shuffle": "^0.0.2", - "@lodestar/config": "^1.22.0", - "@lodestar/params": "^1.22.0", - "@lodestar/types": "^1.22.0", - "@chainsafe/pubkey-index-map": "2.0.0", - "@lodestar/utils": "^1.22.0", + "@lodestar/config": "^1.23.0", + "@lodestar/params": "^1.23.0", + "@lodestar/types": "^1.23.0", + "@lodestar/utils": "^1.23.0", "bigint-buffer": "^1.1.5", "immutable": "^4.3.2" }, diff --git a/packages/test-utils/package.json b/packages/test-utils/package.json index b2a589581055..e84e5fca3771 100644 --- a/packages/test-utils/package.json +++ b/packages/test-utils/package.json @@ -1,7 +1,7 @@ { "name": "@lodestar/test-utils", "private": true, - "version": "1.22.0", + "version": "1.23.0", "description": "Test utilities reused across other packages", "author": "ChainSafe Systems", "license": "Apache-2.0", @@ -59,8 +59,8 @@ "dependencies": { "@chainsafe/bls-keystore": "^3.1.0", "@chainsafe/blst": "^2.0.3", - "@lodestar/params": "^1.22.0", - "@lodestar/utils": "^1.22.0", + "@lodestar/params": "^1.23.0", + "@lodestar/utils": "^1.23.0", "axios": "^1.3.4", "testcontainers": "^10.2.1", "tmp": "^0.2.1", diff --git a/packages/types/package.json b/packages/types/package.json index 1c020b409071..857024ca165a 100644 --- a/packages/types/package.json +++ b/packages/types/package.json @@ -11,7 +11,7 @@ "bugs": { "url": "https://github.com/ChainSafe/lodestar/issues" }, - "version": "1.22.0", + "version": "1.23.0", "type": "module", "exports": { ".": { @@ -74,7 +74,7 @@ "types": "lib/index.d.ts", "dependencies": { "@chainsafe/ssz": "^0.17.1", - "@lodestar/params": "^1.22.0", + "@lodestar/params": "^1.23.0", "ethereum-cryptography": "^2.0.0" }, "keywords": [ diff --git a/packages/utils/package.json b/packages/utils/package.json index 6c8218741e30..9b6f5e797e68 100644 --- a/packages/utils/package.json +++ b/packages/utils/package.json @@ -11,7 +11,7 @@ "bugs": { "url": "https://github.com/ChainSafe/lodestar/issues" }, - "version": "1.22.0", + "version": "1.23.0", "type": "module", "exports": "./lib/index.js", "files": [ diff --git a/packages/validator/package.json b/packages/validator/package.json index 932eedac1dba..457757fd7e62 100644 --- a/packages/validator/package.json +++ b/packages/validator/package.json @@ -1,6 +1,6 @@ { "name": "@lodestar/validator", - "version": "1.22.0", + "version": "1.23.0", "description": "A Typescript implementation of the validator client", "author": "ChainSafe Systems", "license": "LGPL-3.0", @@ -47,17 +47,17 @@ "dependencies": { "@chainsafe/blst": "^2.0.3", "@chainsafe/ssz": "^0.17.1", - "@lodestar/api": "^1.22.0", - "@lodestar/config": "^1.22.0", - "@lodestar/db": "^1.22.0", - "@lodestar/params": "^1.22.0", - "@lodestar/state-transition": "^1.22.0", - "@lodestar/types": "^1.22.0", - "@lodestar/utils": "^1.22.0", + "@lodestar/api": "^1.23.0", + "@lodestar/config": "^1.23.0", + "@lodestar/db": "^1.23.0", + "@lodestar/params": "^1.23.0", + "@lodestar/state-transition": "^1.23.0", + "@lodestar/types": "^1.23.0", + "@lodestar/utils": "^1.23.0", "strict-event-emitter-types": "^2.0.0" }, "devDependencies": { - "@lodestar/test-utils": "^1.22.0", + "@lodestar/test-utils": "^1.23.0", "bigint-buffer": "^1.1.5", "rimraf": "^4.4.1" }