From 598c1ec54e6592b9eccfcdd21dba1a303e550b2c Mon Sep 17 00:00:00 2001 From: Nico Flaig Date: Mon, 13 Oct 2025 14:44:41 +0100 Subject: [PATCH] feat: update networking config to match CL spec (#8510) **Motivation** Conform to CL spec **Description** - move networking constants to config - remove constants no longer part of spec - enable "p2p-interface.md" in config test Closes https://github.com/ChainSafe/lodestar/issues/6351 Closes https://github.com/ChainSafe/lodestar/issues/7529 --- .../src/api/impl/config/constants.ts | 14 +++++--- .../src/api/impl/validator/index.ts | 7 ++-- packages/beacon-node/src/chain/chain.ts | 2 +- .../opPools/syncContributionAndProofPool.ts | 5 +-- .../src/chain/validation/attestation.ts | 13 ++++---- .../beacon-node/src/chain/validation/block.ts | 3 +- .../validation/lightClientOptimisticUpdate.ts | 5 +-- .../beacon-node/src/constants/constants.ts | 6 ---- packages/beacon-node/src/constants/network.ts | 19 ----------- .../beacon-node/src/network/discv5/utils.ts | 3 +- .../src/network/gossip/gossipsub.ts | 11 +------ .../reqresp/handlers/blobSidecarsByRange.ts | 12 +++---- .../reqresp/handlers/blobSidecarsByRoot.ts | 10 +++--- .../src/network/subnets/attnetsService.ts | 12 +++---- .../beacon-node/src/network/subnets/util.ts | 24 +++++++------- packages/beacon-node/src/util/clock.ts | 7 ++-- .../test/e2e/api/impl/config.test.ts | 2 +- .../test/mocks/mockedBeaconChain.ts | 2 +- .../test/unit/api/impl/config/config.test.ts | 1 + .../opPools/syncCommitteeContribution.test.ts | 3 +- .../network/subnets/attnetsService.test.ts | 33 ++++++++----------- .../test/unit/network/subnets/util.test.ts | 3 +- .../beacon-node/test/unit/util/clock.test.ts | 7 ++-- .../config/src/chainConfig/configs/mainnet.ts | 20 +++++++++-- .../config/src/chainConfig/configs/minimal.ts | 20 +++++++++-- packages/config/src/chainConfig/types.ts | 24 ++++++++++++-- packages/params/src/index.ts | 17 ++++++---- .../src/rate_limiter/selfRateLimiter.ts | 3 +- .../types/test/unit/constants/blobs.test.ts | 4 +-- packages/validator/src/util/params.ts | 8 +++++ 30 files changed, 165 insertions(+), 135 deletions(-) diff --git a/packages/beacon-node/src/api/impl/config/constants.ts b/packages/beacon-node/src/api/impl/config/constants.ts index d8e152b8ee..64988f5626 100644 --- a/packages/beacon-node/src/api/impl/config/constants.ts +++ b/packages/beacon-node/src/api/impl/config/constants.ts @@ -1,5 +1,7 @@ import { ATTESTATION_SUBNET_COUNT, + ATTESTATION_SUBNET_EXTRA_BITS, + ATTESTATION_SUBNET_PREFIX_BITS, BASE_REWARDS_PER_EPOCH, BLOB_TX_TYPE, BLS_WITHDRAWAL_PREFIX, @@ -25,15 +27,15 @@ import { DOMAIN_SYNC_COMMITTEE, DOMAIN_SYNC_COMMITTEE_SELECTION_PROOF, DOMAIN_VOLUNTARY_EXIT, - EPOCHS_PER_RANDOM_SUBNET_SUBSCRIPTION, ETH1_ADDRESS_WITHDRAWAL_PREFIX, FAR_FUTURE_EPOCH, FULL_EXIT_REQUEST_AMOUNT, GENESIS_EPOCH, GENESIS_SLOT, JUSTIFICATION_BITS_LENGTH, + MAX_CONCURRENT_REQUESTS, + NODE_ID_BITS, PROPOSER_WEIGHT, - RANDOM_SUBNETS_PER_VALIDATOR, SYNC_COMMITTEE_SUBNET_COUNT, SYNC_REWARD_WEIGHT, TARGET_AGGREGATORS_PER_COMMITTEE, @@ -84,9 +86,13 @@ export const specConstants = { // phase0/validator.md TARGET_AGGREGATORS_PER_COMMITTEE, - RANDOM_SUBNETS_PER_VALIDATOR, - EPOCHS_PER_RANDOM_SUBNET_SUBSCRIPTION, + + // phase0/p2p-interface.md + NODE_ID_BITS, + MAX_CONCURRENT_REQUESTS, ATTESTATION_SUBNET_COUNT, + ATTESTATION_SUBNET_EXTRA_BITS, + ATTESTATION_SUBNET_PREFIX_BITS, // altair/beacon-chain.md // ## Participation flag indices diff --git a/packages/beacon-node/src/api/impl/validator/index.ts b/packages/beacon-node/src/api/impl/validator/index.ts index efc52d9b00..f61d686aec 100644 --- a/packages/beacon-node/src/api/impl/validator/index.ts +++ b/packages/beacon-node/src/api/impl/validator/index.ts @@ -179,10 +179,13 @@ export function getValidatorApi( /** * Validator clock may be advanced from beacon's clock. If the validator requests a resource in a * future slot, wait some time instead of rejecting the request because it's in the future. - * This value is the same to MAXIMUM_GOSSIP_CLOCK_DISPARITY_SEC. + * This value is the same to MAXIMUM_GOSSIP_CLOCK_DISPARITY. * For very fast networks, reduce clock disparity to half a slot. */ - const MAX_API_CLOCK_DISPARITY_SEC = Math.min(0.5, config.SLOT_DURATION_MS / 2000); + const MAX_API_CLOCK_DISPARITY_SEC = Math.min( + config.MAXIMUM_GOSSIP_CLOCK_DISPARITY / 1000, + config.SLOT_DURATION_MS / 2000 + ); const MAX_API_CLOCK_DISPARITY_MS = MAX_API_CLOCK_DISPARITY_SEC * 1000; /** Compute and cache the genesis block root */ diff --git a/packages/beacon-node/src/chain/chain.ts b/packages/beacon-node/src/chain/chain.ts index 59c8cce307..d688150b84 100644 --- a/packages/beacon-node/src/chain/chain.ts +++ b/packages/beacon-node/src/chain/chain.ts @@ -257,7 +257,7 @@ export class BeaconChain implements IBeaconChain { this.attestationPool = new AttestationPool(config, clock, this.opts?.preaggregateSlotDistance, metrics); this.aggregatedAttestationPool = new AggregatedAttestationPool(this.config, metrics); this.syncCommitteeMessagePool = new SyncCommitteeMessagePool(config, clock, this.opts?.preaggregateSlotDistance); - this.syncContributionAndProofPool = new SyncContributionAndProofPool(clock, metrics, logger); + this.syncContributionAndProofPool = new SyncContributionAndProofPool(config, clock, metrics, logger); this.seenAggregatedAttestations = new SeenAggregatedAttestations(metrics); this.seenContributionAndProof = new SeenContributionAndProof(metrics); diff --git a/packages/beacon-node/src/chain/opPools/syncContributionAndProofPool.ts b/packages/beacon-node/src/chain/opPools/syncContributionAndProofPool.ts index 52e85673e3..5630b48ab1 100644 --- a/packages/beacon-node/src/chain/opPools/syncContributionAndProofPool.ts +++ b/packages/beacon-node/src/chain/opPools/syncContributionAndProofPool.ts @@ -1,10 +1,10 @@ import {Signature, aggregateSignatures} from "@chainsafe/blst"; import {BitArray} from "@chainsafe/ssz"; +import {ChainForkConfig} from "@lodestar/config"; import {SYNC_COMMITTEE_SIZE, SYNC_COMMITTEE_SUBNET_SIZE} from "@lodestar/params"; import {G2_POINT_AT_INFINITY} from "@lodestar/state-transition"; import {Root, Slot, SubnetID, altair, ssz} from "@lodestar/types"; import {Logger, MapDef, toRootHex} from "@lodestar/utils"; -import {MAXIMUM_GOSSIP_CLOCK_DISPARITY} from "../../constants/constants.js"; import {Metrics} from "../../metrics/metrics.js"; import {IClock} from "../../util/clock.js"; import {InsertOutcome, OpPoolError, OpPoolErrorCode} from "./types.js"; @@ -51,6 +51,7 @@ export class SyncContributionAndProofPool { private lowestPermissibleSlot = 0; constructor( + private readonly config: ChainForkConfig, private readonly clock: IClock, private readonly metrics: Metrics | null = null, private logger: Logger | null = null @@ -92,7 +93,7 @@ export class SyncContributionAndProofPool { // Reject ContributionAndProofs of previous slots // for api ContributionAndProofs, we allow them to be added to the pool - if (!priority && slot < this.clock.slotWithPastTolerance(MAXIMUM_GOSSIP_CLOCK_DISPARITY)) { + if (!priority && slot < this.clock.slotWithPastTolerance(this.config.MAXIMUM_GOSSIP_CLOCK_DISPARITY / 1000)) { return InsertOutcome.Late; } diff --git a/packages/beacon-node/src/chain/validation/attestation.ts b/packages/beacon-node/src/chain/validation/attestation.ts index 0c3bd1cd9b..cf026222a3 100644 --- a/packages/beacon-node/src/chain/validation/attestation.ts +++ b/packages/beacon-node/src/chain/validation/attestation.ts @@ -36,7 +36,6 @@ import { ssz, } from "@lodestar/types"; import {assert, toRootHex} from "@lodestar/utils"; -import {MAXIMUM_GOSSIP_CLOCK_DISPARITY_SEC} from "../../constants/index.js"; import {sszDeserializeSingleAttestation} from "../../network/gossip/topic.js"; import {getShufflingDependentRoot} from "../../util/dependentRoot.js"; import { @@ -570,8 +569,8 @@ async function validateAttestationNoSignatureCheck( * Note: We do not queue future attestations for later processing */ export function verifyPropagationSlotRange(fork: ForkName, chain: IBeaconChain, attestationSlot: Slot): void { - // slot with future tolerance of MAXIMUM_GOSSIP_CLOCK_DISPARITY_SEC - const latestPermissibleSlot = chain.clock.slotWithFutureTolerance(MAXIMUM_GOSSIP_CLOCK_DISPARITY_SEC); + // slot with future tolerance of MAXIMUM_GOSSIP_CLOCK_DISPARITY + const latestPermissibleSlot = chain.clock.slotWithFutureTolerance(chain.config.MAXIMUM_GOSSIP_CLOCK_DISPARITY / 1000); if (attestationSlot > latestPermissibleSlot) { throw new AttestationError(GossipAction.IGNORE, { code: AttestationErrorCode.FUTURE_SLOT, @@ -586,9 +585,9 @@ export function verifyPropagationSlotRange(fork: ForkName, chain: IBeaconChain, // see: https://github.com/ethereum/consensus-specs/pull/3360 if (ForkSeq[fork] < ForkSeq.deneb) { const earliestPermissibleSlot = Math.max( - // slot with past tolerance of MAXIMUM_GOSSIP_CLOCK_DISPARITY_SEC - // ATTESTATION_PROPAGATION_SLOT_RANGE = SLOTS_PER_EPOCH - chain.clock.slotWithPastTolerance(MAXIMUM_GOSSIP_CLOCK_DISPARITY_SEC) - SLOTS_PER_EPOCH, + // slot with past tolerance of MAXIMUM_GOSSIP_CLOCK_DISPARITY + chain.clock.slotWithPastTolerance(chain.config.MAXIMUM_GOSSIP_CLOCK_DISPARITY / 1000) - + chain.config.ATTESTATION_PROPAGATION_SLOT_RANGE, 0 ); @@ -614,7 +613,7 @@ export function verifyPropagationSlotRange(fork: ForkName, chain: IBeaconChain, // lower bound for previous epoch is same as epoch of earliestPermissibleSlot const currentEpochWithPastTolerance = computeEpochAtSlot( - chain.clock.slotWithPastTolerance(MAXIMUM_GOSSIP_CLOCK_DISPARITY_SEC) + chain.clock.slotWithPastTolerance(chain.config.MAXIMUM_GOSSIP_CLOCK_DISPARITY / 1000) ); const earliestPermissiblePreviousEpoch = Math.max(currentEpochWithPastTolerance - 1, 0); diff --git a/packages/beacon-node/src/chain/validation/block.ts b/packages/beacon-node/src/chain/validation/block.ts index cd4c52129d..2e837a5b51 100644 --- a/packages/beacon-node/src/chain/validation/block.ts +++ b/packages/beacon-node/src/chain/validation/block.ts @@ -11,7 +11,6 @@ import { } from "@lodestar/state-transition"; import {SignedBeaconBlock, deneb} from "@lodestar/types"; import {sleep, toRootHex} from "@lodestar/utils"; -import {MAXIMUM_GOSSIP_CLOCK_DISPARITY} from "../../constants/index.js"; import {BlockErrorCode, BlockGossipError, GossipAction} from "../errors/index.js"; import {IBeaconChain} from "../interface.js"; import {RegenCaller} from "../regen/index.js"; @@ -179,7 +178,7 @@ export async function validateGossipBlock( // gossip validation promise without any extra infrastructure. // Do the sleep at the end, since regen and signature validation can already take longer than `msToBlockSlot`. const msToBlockSlot = computeTimeAtSlot(config, blockSlot, chain.genesisTime) * 1000 - Date.now(); - if (msToBlockSlot <= MAXIMUM_GOSSIP_CLOCK_DISPARITY && msToBlockSlot > 0) { + if (msToBlockSlot <= config.MAXIMUM_GOSSIP_CLOCK_DISPARITY && msToBlockSlot > 0) { // If block is between 0 and 500 ms early, hold it in a promise. Equivalent to a pending queue. await sleep(msToBlockSlot); } diff --git a/packages/beacon-node/src/chain/validation/lightClientOptimisticUpdate.ts b/packages/beacon-node/src/chain/validation/lightClientOptimisticUpdate.ts index 1c12eec3b4..ae9a830862 100644 --- a/packages/beacon-node/src/chain/validation/lightClientOptimisticUpdate.ts +++ b/packages/beacon-node/src/chain/validation/lightClientOptimisticUpdate.ts @@ -1,6 +1,5 @@ import {ChainForkConfig} from "@lodestar/config"; import {LightClientOptimisticUpdate} from "@lodestar/types"; -import {MAXIMUM_GOSSIP_CLOCK_DISPARITY} from "../../constants/index.js"; import {assertLightClientServer} from "../../node/utils/lightclient.js"; import {IClock} from "../../util/clock.js"; import {GossipAction} from "../errors/index.js"; @@ -64,5 +63,7 @@ export function updateReceivedTooEarly( update: Pick ): boolean { const fork = config.getForkName(update.signatureSlot); - return clock.msFromSlot(update.signatureSlot) < config.getSyncMessageDueMs(fork) - MAXIMUM_GOSSIP_CLOCK_DISPARITY; + return ( + clock.msFromSlot(update.signatureSlot) < config.getSyncMessageDueMs(fork) - config.MAXIMUM_GOSSIP_CLOCK_DISPARITY + ); } diff --git a/packages/beacon-node/src/constants/constants.ts b/packages/beacon-node/src/constants/constants.ts index 3587114e33..c5a6a7c893 100644 --- a/packages/beacon-node/src/constants/constants.ts +++ b/packages/beacon-node/src/constants/constants.ts @@ -7,9 +7,3 @@ export const ZERO_HASH = Buffer.alloc(32, 0); export const ZERO_HASH_HEX = "0x" + "00".repeat(32); export const EMPTY_SIGNATURE = Buffer.alloc(96, 0); export const GRAFFITI_SIZE = 32; - -/** - * The maximum milliseconds of clock disparity assumed between honest nodes. - */ -export const MAXIMUM_GOSSIP_CLOCK_DISPARITY = 500; -export const MAXIMUM_GOSSIP_CLOCK_DISPARITY_SEC = MAXIMUM_GOSSIP_CLOCK_DISPARITY / 1000; diff --git a/packages/beacon-node/src/constants/network.ts b/packages/beacon-node/src/constants/network.ts index cdc43efb22..c786bf25a3 100644 --- a/packages/beacon-node/src/constants/network.ts +++ b/packages/beacon-node/src/constants/network.ts @@ -1,22 +1,3 @@ -/** - * For more info on some of these constants: - * https://github.com/ethereum/consensus-specs/blob/v1.1.10/specs/phase0/p2p-interface.md#configuration - */ - -// Gossip constants - -/** - * The maximum number of slots during which an attestation can be propagated. - */ -export const ATTESTATION_PROPAGATION_SLOT_RANGE = 32; - -/** The maximum allowed size of uncompressed gossip messages. */ -export const GOSSIP_MAX_SIZE = 2 ** 20; -export const GOSSIP_MAX_SIZE_BELLATRIX = 10 * GOSSIP_MAX_SIZE; -/** The maximum allowed size of uncompressed req/resp chunked responses. */ -export const MAX_CHUNK_SIZE = 2 ** 20; -export const MAX_CHUNK_SIZE_BELLATRIX = 10 * MAX_CHUNK_SIZE; - export enum GoodByeReasonCode { INBOUND_DISCONNECT = -1, CLIENT_SHUTDOWN = 1, diff --git a/packages/beacon-node/src/network/discv5/utils.ts b/packages/beacon-node/src/network/discv5/utils.ts index 8a1d092bf9..961607991a 100644 --- a/packages/beacon-node/src/network/discv5/utils.ts +++ b/packages/beacon-node/src/network/discv5/utils.ts @@ -1,6 +1,5 @@ import {ENR} from "@chainsafe/enr"; import {BeaconConfig} from "@lodestar/config"; -import {MAXIMUM_GOSSIP_CLOCK_DISPARITY} from "../../constants/constants.js"; import {IClock} from "../../util/clock.js"; import {ENRKey} from "../metadata.js"; @@ -35,7 +34,7 @@ export function enrRelevance(enr: ENR, config: BeaconConfig, clock: IClock): ENR } // Check if fork digest's fork matches ours - const currentSlot = clock.slotWithFutureTolerance(MAXIMUM_GOSSIP_CLOCK_DISPARITY); + const currentSlot = clock.slotWithFutureTolerance(config.MAXIMUM_GOSSIP_CLOCK_DISPARITY / 1000); const localForkInfo = config.getForkInfo(currentSlot); // We only connect if the ENR's fork matches our current fork. // We also allow it to be the previous fork due to delay and infrequent update of DHT. diff --git a/packages/beacon-node/src/network/gossip/gossipsub.ts b/packages/beacon-node/src/network/gossip/gossipsub.ts index 843b51e46b..09eb190d11 100644 --- a/packages/beacon-node/src/network/gossip/gossipsub.ts +++ b/packages/beacon-node/src/network/gossip/gossipsub.ts @@ -6,7 +6,6 @@ import {BeaconConfig, ForkBoundary} from "@lodestar/config"; import {ATTESTATION_SUBNET_COUNT, SLOTS_PER_EPOCH, SYNC_COMMITTEE_SUBNET_COUNT} from "@lodestar/params"; import {SubnetID} from "@lodestar/types"; import {Logger, Map2d, Map2dArr} from "@lodestar/utils"; -import {GOSSIP_MAX_SIZE, GOSSIP_MAX_SIZE_BELLATRIX} from "../../constants/network.js"; import {RegistryMetricCreator} from "../../metrics/index.js"; import {callInNextEventLoop} from "../../util/eventLoop.js"; import {NetworkEvent, NetworkEventBus, NetworkEventData} from "../events.js"; @@ -117,15 +116,7 @@ export class Eth2Gossipsub extends GossipSub { fastMsgIdFn: fastMsgIdFn, msgIdFn: msgIdFn.bind(msgIdFn, gossipTopicCache), msgIdToStrFn: msgIdToStrFn, - // Use the bellatrix max size if the merge is configured. pre-merge using this size - // could only be an issue on outgoing payloads, its highly unlikely we will send out - // a chunk bigger than GOSSIP_MAX_SIZE pre merge even on mainnet network. - // - // TODO: figure out a way to dynamically transition to the size - dataTransform: new DataTransformSnappy( - gossipTopicCache, - Number.isFinite(config.BELLATRIX_FORK_EPOCH) ? GOSSIP_MAX_SIZE_BELLATRIX : GOSSIP_MAX_SIZE - ), + dataTransform: new DataTransformSnappy(gossipTopicCache, config.MAX_PAYLOAD_SIZE), metricsRegister: metricsRegister as MetricsRegister | null, metricsTopicStrToLabel: metricsRegister ? getMetricsTopicStrToLabel(networkConfig, {disableLightClientServer: opts.disableLightClientServer ?? false}) diff --git a/packages/beacon-node/src/network/reqresp/handlers/blobSidecarsByRange.ts b/packages/beacon-node/src/network/reqresp/handlers/blobSidecarsByRange.ts index 793a5cf1ae..03628b4033 100644 --- a/packages/beacon-node/src/network/reqresp/handlers/blobSidecarsByRange.ts +++ b/packages/beacon-node/src/network/reqresp/handlers/blobSidecarsByRange.ts @@ -1,5 +1,5 @@ import {ChainConfig} from "@lodestar/config"; -import {BLOBSIDECAR_FIXED_SIZE, GENESIS_SLOT} from "@lodestar/params"; +import {BLOB_SIDECAR_FIXED_SIZE, GENESIS_SLOT} from "@lodestar/params"; import {RespStatus, ResponseError, ResponseOutgoing} from "@lodestar/reqresp"; import {computeEpochAtSlot} from "@lodestar/state-transition"; import {Slot, deneb} from "@lodestar/types"; @@ -71,17 +71,17 @@ export function* iterateBlobBytesFromWrapper( blockSlot: Slot ): Iterable { const allBlobSideCarsBytes = blobSideCarsBytesWrapped.slice(BLOB_SIDECARS_IN_WRAPPER_INDEX); - const blobsLen = allBlobSideCarsBytes.length / BLOBSIDECAR_FIXED_SIZE; + const blobsLen = allBlobSideCarsBytes.length / BLOB_SIDECAR_FIXED_SIZE; for (let index = 0; index < blobsLen; index++) { const blobSideCarBytes = allBlobSideCarsBytes.slice( - index * BLOBSIDECAR_FIXED_SIZE, - (index + 1) * BLOBSIDECAR_FIXED_SIZE + index * BLOB_SIDECAR_FIXED_SIZE, + (index + 1) * BLOB_SIDECAR_FIXED_SIZE ); - if (blobSideCarBytes.length !== BLOBSIDECAR_FIXED_SIZE) { + if (blobSideCarBytes.length !== BLOB_SIDECAR_FIXED_SIZE) { throw new ResponseError( RespStatus.SERVER_ERROR, - `Invalid blobSidecar index=${index} bytes length=${blobSideCarBytes.length} expected=${BLOBSIDECAR_FIXED_SIZE} for slot ${blockSlot} blobsLen=${blobsLen}` + `Invalid blobSidecar index=${index} bytes length=${blobSideCarBytes.length} expected=${BLOB_SIDECAR_FIXED_SIZE} for slot ${blockSlot} blobsLen=${blobsLen}` ); } yield { diff --git a/packages/beacon-node/src/network/reqresp/handlers/blobSidecarsByRoot.ts b/packages/beacon-node/src/network/reqresp/handlers/blobSidecarsByRoot.ts index 103a97570f..6416520a3e 100644 --- a/packages/beacon-node/src/network/reqresp/handlers/blobSidecarsByRoot.ts +++ b/packages/beacon-node/src/network/reqresp/handlers/blobSidecarsByRoot.ts @@ -1,4 +1,4 @@ -import {BLOBSIDECAR_FIXED_SIZE} from "@lodestar/params"; +import {BLOB_SIDECAR_FIXED_SIZE} from "@lodestar/params"; import {RespStatus, ResponseError, ResponseOutgoing} from "@lodestar/reqresp"; import {computeEpochAtSlot} from "@lodestar/state-transition"; import {RootHex} from "@lodestar/types"; @@ -45,12 +45,12 @@ export async function* onBlobSidecarsByRoot( } const blobSidecarBytes = lastFetchedSideCars.bytes.slice( - index * BLOBSIDECAR_FIXED_SIZE, - (index + 1) * BLOBSIDECAR_FIXED_SIZE + index * BLOB_SIDECAR_FIXED_SIZE, + (index + 1) * BLOB_SIDECAR_FIXED_SIZE ); - if (blobSidecarBytes.length !== BLOBSIDECAR_FIXED_SIZE) { + if (blobSidecarBytes.length !== BLOB_SIDECAR_FIXED_SIZE) { throw Error( - `Inconsistent state, blobSidecar blockRoot=${blockRootHex} index=${index} blobSidecarBytes=${blobSidecarBytes.length} expected=${BLOBSIDECAR_FIXED_SIZE}` + `Inconsistent state, blobSidecar blockRoot=${blockRootHex} index=${index} blobSidecarBytes=${blobSidecarBytes.length} expected=${BLOB_SIDECAR_FIXED_SIZE}` ); } diff --git a/packages/beacon-node/src/network/subnets/attnetsService.ts b/packages/beacon-node/src/network/subnets/attnetsService.ts index 0f9ea16b4c..20fd2ff07b 100644 --- a/packages/beacon-node/src/network/subnets/attnetsService.ts +++ b/packages/beacon-node/src/network/subnets/attnetsService.ts @@ -1,5 +1,5 @@ import {BeaconConfig, ForkBoundary} from "@lodestar/config"; -import {ATTESTATION_SUBNET_COUNT, EPOCHS_PER_RANDOM_SUBNET_SUBSCRIPTION, SLOTS_PER_EPOCH} from "@lodestar/params"; +import {ATTESTATION_SUBNET_COUNT, SLOTS_PER_EPOCH} from "@lodestar/params"; import {computeEpochAtSlot} from "@lodestar/state-transition"; import {Epoch, Slot, SubnetID, ssz} from "@lodestar/types"; import {Logger, MapDef} from "@lodestar/utils"; @@ -92,8 +92,8 @@ export class AttnetsService implements IAttnetsService { const shortLivedSubnets = this.committeeSubnets.getActiveTtl(this.clock.currentSlot); const longLivedSubscriptionsToSlot = - (Math.floor(this.clock.currentEpoch / EPOCHS_PER_RANDOM_SUBNET_SUBSCRIPTION) + 1) * - EPOCHS_PER_RANDOM_SUBNET_SUBSCRIPTION * + (Math.floor(this.clock.currentEpoch / this.config.EPOCHS_PER_SUBNET_SUBSCRIPTION) + 1) * + this.config.EPOCHS_PER_SUBNET_SUBSCRIPTION * SLOTS_PER_EPOCH; const longLivedSubnets = Array.from(this.longLivedSubscriptions).map((subnet) => ({ subnet, @@ -234,11 +234,11 @@ export class AttnetsService implements IAttnetsService { /** * Run per epoch, clean-up operations that are not urgent - * Subscribe to new random subnets every EPOCHS_PER_RANDOM_SUBNET_SUBSCRIPTION epochs + * Subscribe to new random subnets every EPOCHS_PER_SUBNET_SUBSCRIPTION epochs */ private onEpoch = (epoch: Epoch): void => { try { - if (epoch % EPOCHS_PER_RANDOM_SUBNET_SUBSCRIPTION === 0) { + if (epoch % this.config.EPOCHS_PER_SUBNET_SUBSCRIPTION === 0) { this.recomputeLongLivedSubnets(); } } catch (e) { @@ -253,7 +253,7 @@ export class AttnetsService implements IAttnetsService { } const oldSubnets = this.longLivedSubscriptions; - const newSubnets = computeSubscribedSubnet(this.nodeId, this.clock.currentEpoch); + const newSubnets = computeSubscribedSubnet(this.config, this.nodeId, this.clock.currentEpoch); this.logger.verbose("Recomputing long-lived subscriptions", { epoch: this.clock.currentEpoch, oldSubnets: Array.from(oldSubnets).join(","), diff --git a/packages/beacon-node/src/network/subnets/util.ts b/packages/beacon-node/src/network/subnets/util.ts index cb2dcff0bf..c2a8a15986 100644 --- a/packages/beacon-node/src/network/subnets/util.ts +++ b/packages/beacon-node/src/network/subnets/util.ts @@ -1,11 +1,6 @@ import {digest} from "@chainsafe/as-sha256"; -import { - ATTESTATION_SUBNET_COUNT, - ATTESTATION_SUBNET_PREFIX_BITS, - EPOCHS_PER_SUBNET_SUBSCRIPTION, - NODE_ID_BITS, - SUBNETS_PER_NODE, -} from "@lodestar/params"; +import {ChainConfig} from "@lodestar/config"; +import {ATTESTATION_SUBNET_COUNT, ATTESTATION_SUBNET_PREFIX_BITS, NODE_ID_BITS} from "@lodestar/params"; import {computeShuffledIndex} from "@lodestar/state-transition"; import {Epoch, ssz} from "@lodestar/types"; import {NodeId} from "./interface.js"; @@ -13,10 +8,10 @@ import {NodeId} from "./interface.js"; /** * Spec https://github.com/ethereum/consensus-specs/blob/v1.4.0-alpha.3/specs/phase0/p2p-interface.md */ -export function computeSubscribedSubnet(nodeId: NodeId, epoch: Epoch): number[] { +export function computeSubscribedSubnet(config: ChainConfig, nodeId: NodeId, epoch: Epoch): number[] { const subnets: number[] = []; - for (let index = 0; index < SUBNETS_PER_NODE; index++) { - subnets.push(computeSubscribedSubnetByIndex(nodeId, epoch, index)); + for (let index = 0; index < config.SUBNETS_PER_NODE; index++) { + subnets.push(computeSubscribedSubnetByIndex(config, nodeId, epoch, index)); } return subnets; } @@ -24,11 +19,16 @@ export function computeSubscribedSubnet(nodeId: NodeId, epoch: Epoch): number[] /** * Spec https://github.com/ethereum/consensus-specs/blob/v1.4.0-alpha.3/specs/phase0/p2p-interface.md */ -export function computeSubscribedSubnetByIndex(nodeId: NodeId, epoch: Epoch, index: number): number { +export function computeSubscribedSubnetByIndex( + config: ChainConfig, + nodeId: NodeId, + epoch: Epoch, + index: number +): number { const nodeIdPrefix = getNodeIdPrefix(nodeId); const nodeOffset = getNodeOffset(nodeId); const permutationSeed = digest( - ssz.UintNum64.serialize(Math.floor((epoch + nodeOffset) / EPOCHS_PER_SUBNET_SUBSCRIPTION)) + ssz.UintNum64.serialize(Math.floor((epoch + nodeOffset) / config.EPOCHS_PER_SUBNET_SUBSCRIPTION)) ); const permutatedPrefix = computeShuffledIndex(nodeIdPrefix, 1 << ATTESTATION_SUBNET_PREFIX_BITS, permutationSeed); return (permutatedPrefix + index) % ATTESTATION_SUBNET_COUNT; diff --git a/packages/beacon-node/src/util/clock.ts b/packages/beacon-node/src/util/clock.ts index 8af8d2b282..bd530ef61d 100644 --- a/packages/beacon-node/src/util/clock.ts +++ b/packages/beacon-node/src/util/clock.ts @@ -4,7 +4,6 @@ import {ChainForkConfig} from "@lodestar/config"; import {computeEpochAtSlot, computeTimeAtSlot, getCurrentSlot} from "@lodestar/state-transition"; import type {Epoch, Slot} from "@lodestar/types"; import {ErrorAborted} from "@lodestar/utils"; -import {MAXIMUM_GOSSIP_CLOCK_DISPARITY} from "../constants/constants.js"; export enum ClockEvent { /** @@ -101,7 +100,7 @@ export class Clock extends EventEmitter implements IClock { get currentSlotWithGossipDisparity(): Slot { const currentSlot = this.currentSlot; const nextSlotTime = computeTimeAtSlot(this.config, currentSlot + 1, this.genesisTime) * 1000; - return nextSlotTime - Date.now() < MAXIMUM_GOSSIP_CLOCK_DISPARITY ? currentSlot + 1 : currentSlot; + return nextSlotTime - Date.now() < this.config.MAXIMUM_GOSSIP_CLOCK_DISPARITY ? currentSlot + 1 : currentSlot; } get currentEpoch(): Epoch { @@ -130,12 +129,12 @@ export class Clock extends EventEmitter implements IClock { } const nextSlotTime = computeTimeAtSlot(this.config, currentSlot + 1, this.genesisTime) * 1000; // we're too close to next slot, accept next slot - if (nextSlotTime - Date.now() < MAXIMUM_GOSSIP_CLOCK_DISPARITY) { + if (nextSlotTime - Date.now() < this.config.MAXIMUM_GOSSIP_CLOCK_DISPARITY) { return slot === currentSlot + 1; } const currentSlotTime = computeTimeAtSlot(this.config, currentSlot, this.genesisTime) * 1000; // we've just passed the current slot, accept previous slot - if (Date.now() - currentSlotTime < MAXIMUM_GOSSIP_CLOCK_DISPARITY) { + if (Date.now() - currentSlotTime < this.config.MAXIMUM_GOSSIP_CLOCK_DISPARITY) { return slot === currentSlot - 1; } return false; diff --git a/packages/beacon-node/test/e2e/api/impl/config.test.ts b/packages/beacon-node/test/e2e/api/impl/config.test.ts index 28cc0b7bb0..2bb042f1da 100644 --- a/packages/beacon-node/test/e2e/api/impl/config.test.ts +++ b/packages/beacon-node/test/e2e/api/impl/config.test.ts @@ -46,7 +46,7 @@ async function downloadRemoteConstants(commit: string): Promise { for (const forkName of Object.values(ForkName)) { // If some future fork does not specify one of this docs, refactor to fetch some docs only on some forks - for (const docName of ["beacon-chain.md", "validator.md"]) { + for (const docName of ["beacon-chain.md", "validator.md", "p2p-interface.md"]) { downloadedSpecs.push( fetch(`https://raw.githubusercontent.com/ethereum/consensus-specs/${commit}/specs/${forkName}/${docName}`).then( (res) => res.text() diff --git a/packages/beacon-node/test/mocks/mockedBeaconChain.ts b/packages/beacon-node/test/mocks/mockedBeaconChain.ts index 15a1ae4e0e..e475a6d981 100644 --- a/packages/beacon-node/test/mocks/mockedBeaconChain.ts +++ b/packages/beacon-node/test/mocks/mockedBeaconChain.ts @@ -138,7 +138,7 @@ vi.mock("../../src/chain/chain.js", async (importActual) => { eth1: new Eth1ForBlockProduction(), opPool: new OpPool(), aggregatedAttestationPool: new AggregatedAttestationPool(config), - syncContributionAndProofPool: new SyncContributionAndProofPool(clock), + syncContributionAndProofPool: new SyncContributionAndProofPool(config, clock), // @ts-expect-error beaconProposerCache: new BeaconProposerCache(), shufflingCache: new ShufflingCache(), diff --git a/packages/beacon-node/test/unit/api/impl/config/config.test.ts b/packages/beacon-node/test/unit/api/impl/config/config.test.ts index 0c38717142..7f5bfb53a6 100644 --- a/packages/beacon-node/test/unit/api/impl/config/config.test.ts +++ b/packages/beacon-node/test/unit/api/impl/config/config.test.ts @@ -35,6 +35,7 @@ describe("config api implementation", () => { expect(specJson.SECONDS_PER_ETH1_BLOCK).toBe("14"); expect(specJson.DEPOSIT_CONTRACT_ADDRESS).toBe("0x00000000219ab540356cbb839cbe05303d7705fa"); + expect(specJson.DEPOSIT_REQUEST_TYPE).toBe("0x00"); }); }); }); diff --git a/packages/beacon-node/test/unit/chain/opPools/syncCommitteeContribution.test.ts b/packages/beacon-node/test/unit/chain/opPools/syncCommitteeContribution.test.ts index f7fa88ffe8..467b78e63b 100644 --- a/packages/beacon-node/test/unit/chain/opPools/syncCommitteeContribution.test.ts +++ b/packages/beacon-node/test/unit/chain/opPools/syncCommitteeContribution.test.ts @@ -1,6 +1,7 @@ import {beforeAll, beforeEach, describe, expect, it, vi} from "vitest"; import {SecretKey, Signature, fastAggregateVerify} from "@chainsafe/blst"; import {BitArray} from "@chainsafe/ssz"; +import {config} from "@lodestar/config/default"; import {SYNC_COMMITTEE_SIZE, SYNC_COMMITTEE_SUBNET_COUNT} from "@lodestar/params"; import {newFilledArray} from "@lodestar/state-transition"; import {ssz} from "@lodestar/types"; @@ -29,7 +30,7 @@ describe("chain / opPools / SyncContributionAndProofPool", () => { beforeEach(() => { vi.spyOn(clockStub, "slotWithPastTolerance").mockReturnValue(slot); - cache = new SyncContributionAndProofPool(clockStub); + cache = new SyncContributionAndProofPool(config, clockStub); cache.add(contributionAndProof, syncCommitteeParticipants); }); 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 3d811e107d..1442d50984 100644 --- a/packages/beacon-node/test/unit/network/subnets/attnetsService.test.ts +++ b/packages/beacon-node/test/unit/network/subnets/attnetsService.test.ts @@ -1,13 +1,6 @@ import {MockedObject, afterEach, beforeEach, describe, expect, it, vi} from "vitest"; import {createBeaconConfig} from "@lodestar/config"; -import { - ATTESTATION_SUBNET_COUNT, - EPOCHS_PER_SUBNET_SUBSCRIPTION, - ForkName, - GENESIS_EPOCH, - SLOTS_PER_EPOCH, - SUBNETS_PER_NODE, -} from "@lodestar/params"; +import {ATTESTATION_SUBNET_COUNT, ForkName, GENESIS_EPOCH, SLOTS_PER_EPOCH} from "@lodestar/params"; import {ZERO_HASH, getCurrentSlot} from "@lodestar/state-transition"; import {SubnetID} from "@lodestar/types"; import {bigIntToBytes} from "@lodestar/utils"; @@ -78,10 +71,10 @@ describe("AttnetsService", () => { it("should change long lived subnets after EPOCHS_PER_SUBNET_SUBSCRIPTION", () => { expect(gossipStub.subscribeTopic).toBeCalledTimes(2); - expect(gossipStub.subscribeTopic).toBeCalledTimes(SUBNETS_PER_NODE); - vi.advanceTimersByTime(config.SLOT_DURATION_MS * SLOTS_PER_EPOCH * EPOCHS_PER_SUBNET_SUBSCRIPTION); + expect(gossipStub.subscribeTopic).toBeCalledTimes(config.SUBNETS_PER_NODE); + vi.advanceTimersByTime(config.SLOT_DURATION_MS * SLOTS_PER_EPOCH * config.EPOCHS_PER_SUBNET_SUBSCRIPTION); // SUBNETS_PER_NODE = 2 => 2 more calls - expect(gossipStub.subscribeTopic).toBeCalledTimes(2 * SUBNETS_PER_NODE); + expect(gossipStub.subscribeTopic).toBeCalledTimes(2 * config.SUBNETS_PER_NODE); }); it("should subscribe to new fork 2 epochs before ALTAIR_FORK_EPOCH", () => { @@ -94,7 +87,7 @@ describe("AttnetsService", () => { expect(gossipStub.subscribeTopic).toBeCalledTimes(2); const firstSubnet = (gossipStub.subscribeTopic.mock.calls[0][0] as unknown as {subnet: SubnetID}).subnet; const secondSubnet = (gossipStub.subscribeTopic.mock.calls[1][0] as unknown as {subnet: SubnetID}).subnet; - expect(gossipStub.subscribeTopic).toBeCalledTimes(SUBNETS_PER_NODE); + expect(gossipStub.subscribeTopic).toBeCalledTimes(config.SUBNETS_PER_NODE); vi.advanceTimersByTime(config.SLOT_DURATION_MS * SLOTS_PER_EPOCH * (ALTAIR_FORK_EPOCH - 2)); service.subscribeSubnetsNextBoundary({fork: ForkName.altair, epoch: config.ALTAIR_FORK_EPOCH}); // SUBNETS_PER_NODE = 2 => 2 more calls @@ -108,7 +101,7 @@ describe("AttnetsService", () => { subnet: secondSubnet, }) ); - expect(gossipStub.subscribeTopic).toBeCalledTimes(2 * SUBNETS_PER_NODE); + expect(gossipStub.subscribeTopic).toBeCalledTimes(2 * config.SUBNETS_PER_NODE); // 2 epochs after the fork vi.advanceTimersByTime(config.SLOT_DURATION_MS * 4); service.unsubscribeSubnetsPrevBoundary({fork: ForkName.phase0, epoch: GENESIS_EPOCH}); @@ -122,7 +115,7 @@ describe("AttnetsService", () => { }); it("should not subscribe to new short lived subnet if not aggregator", () => { - expect(gossipStub.subscribeTopic).toBeCalledTimes(SUBNETS_PER_NODE); + expect(gossipStub.subscribeTopic).toBeCalledTimes(config.SUBNETS_PER_NODE); const firstSubnet = (gossipStub.subscribeTopic.mock.calls[0][0] as unknown as {subnet: SubnetID}).subnet; const secondSubnet = (gossipStub.subscribeTopic.mock.calls[1][0] as unknown as {subnet: SubnetID}).subnet; // should subscribe to new short lived subnet @@ -137,11 +130,11 @@ describe("AttnetsService", () => { }; service.addCommitteeSubscriptions([subscription]); // no new subscription - expect(gossipStub.subscribeTopic).toBeCalledTimes(SUBNETS_PER_NODE); + expect(gossipStub.subscribeTopic).toBeCalledTimes(config.SUBNETS_PER_NODE); }); it("should subscribe to new short lived subnet if aggregator", () => { - expect(gossipStub.subscribeTopic).toBeCalledTimes(SUBNETS_PER_NODE); + expect(gossipStub.subscribeTopic).toBeCalledTimes(config.SUBNETS_PER_NODE); const firstSubnet = (gossipStub.subscribeTopic.mock.calls[0][0] as unknown as {subnet: SubnetID}).subnet; const secondSubnet = (gossipStub.subscribeTopic.mock.calls[1][0] as unknown as {subnet: SubnetID}).subnet; // should subscribe to new short lived subnet @@ -156,17 +149,17 @@ describe("AttnetsService", () => { }; service.addCommitteeSubscriptions([subscription]); // it does not subscribe immediately - expect(gossipStub.subscribeTopic).toBeCalledTimes(SUBNETS_PER_NODE); + expect(gossipStub.subscribeTopic).toBeCalledTimes(config.SUBNETS_PER_NODE); vi.advanceTimersByTime(config.SLOT_DURATION_MS * (subscription.slot - 2)); // then subscribe 2 slots before dutied slot - expect(gossipStub.subscribeTopic).toBeCalledTimes(SUBNETS_PER_NODE + 1); + expect(gossipStub.subscribeTopic).toBeCalledTimes(config.SUBNETS_PER_NODE + 1); // then unsubscribe after the expiration vi.advanceTimersByTime(config.SLOT_DURATION_MS * (subscription.slot + 1)); expect(gossipStub.unsubscribeTopic).toHaveBeenCalledWith(expect.objectContaining({subnet: newSubnet})); }); it("should not subscribe to existing short lived subnet if aggregator", () => { - expect(gossipStub.subscribeTopic).toBeCalledTimes(SUBNETS_PER_NODE); + expect(gossipStub.subscribeTopic).toBeCalledTimes(config.SUBNETS_PER_NODE); const firstSubnet = (gossipStub.subscribeTopic.mock.calls[0][0] as unknown as {subnet: SubnetID}).subnet; // should not subscribe to existing short lived subnet const subscription: CommitteeSubscription = { @@ -176,7 +169,7 @@ describe("AttnetsService", () => { isAggregator: true, }; service.addCommitteeSubscriptions([subscription]); - expect(gossipStub.subscribeTopic).toBeCalledTimes(SUBNETS_PER_NODE); + expect(gossipStub.subscribeTopic).toBeCalledTimes(config.SUBNETS_PER_NODE); // then should not subscribe after the expiration vi.advanceTimersByTime(config.SLOT_DURATION_MS * (subscription.slot + 1)); expect(gossipStub.unsubscribeTopic).not.toHaveBeenCalled(); diff --git a/packages/beacon-node/test/unit/network/subnets/util.test.ts b/packages/beacon-node/test/unit/network/subnets/util.test.ts index 3ce997b05e..b64049c732 100644 --- a/packages/beacon-node/test/unit/network/subnets/util.test.ts +++ b/packages/beacon-node/test/unit/network/subnets/util.test.ts @@ -1,4 +1,5 @@ import {describe, expect, it} from "vitest"; +import {config} from "@lodestar/config/default"; import {ATTESTATION_SUBNET_PREFIX_BITS, NODE_ID_BITS} from "@lodestar/params"; import {bigIntToBytes} from "@lodestar/utils"; import {computeSubscribedSubnet, getNodeIdPrefix, getNodeOffset} from "../../../../src/network/subnets/util.js"; @@ -99,7 +100,7 @@ describe("computeSubscribedSubnet", () => { for (const [index, {nodeId, epoch, expected}] of testCases.entries()) { it(`test case ${index}`, () => { // node is is of type uint256 = 32 bytes - expect(computeSubscribedSubnet(bigIntToBytes(BigInt(nodeId), 32, "be"), epoch)).toEqual(expected); + expect(computeSubscribedSubnet(config, bigIntToBytes(BigInt(nodeId), 32, "be"), epoch)).toEqual(expected); }); } }); diff --git a/packages/beacon-node/test/unit/util/clock.test.ts b/packages/beacon-node/test/unit/util/clock.test.ts index f8b14c48d1..96ea14b7a7 100644 --- a/packages/beacon-node/test/unit/util/clock.test.ts +++ b/packages/beacon-node/test/unit/util/clock.test.ts @@ -1,7 +1,6 @@ import {afterEach, beforeEach, describe, expect, it, vi} from "vitest"; import {config} from "@lodestar/config/default"; import {SLOTS_PER_EPOCH} from "@lodestar/params"; -import {MAXIMUM_GOSSIP_CLOCK_DISPARITY} from "../../../src/constants/index.js"; import {Clock, ClockEvent} from "../../../src/util/clock.js"; describe("Clock", () => { @@ -44,7 +43,7 @@ describe("Clock", () => { describe("currentSlotWithGossipDisparity", () => { it("should be next slot", () => { - vi.advanceTimersByTime(config.SLOT_DURATION_MS - (MAXIMUM_GOSSIP_CLOCK_DISPARITY - 50)); + vi.advanceTimersByTime(config.SLOT_DURATION_MS - (config.MAXIMUM_GOSSIP_CLOCK_DISPARITY - 50)); expect(clock.currentSlotWithGossipDisparity).toBe(clock.currentSlot + 1); }); @@ -64,14 +63,14 @@ describe("Clock", () => { const nextSlot = clock.currentSlot + 1; // "current slot could NOT be next slot if it's far away from next slot" expect(clock.isCurrentSlotGivenGossipDisparity(nextSlot)).toBe(false); - vi.advanceTimersByTime(config.SLOT_DURATION_MS - (MAXIMUM_GOSSIP_CLOCK_DISPARITY - 50)); + vi.advanceTimersByTime(config.SLOT_DURATION_MS - (config.MAXIMUM_GOSSIP_CLOCK_DISPARITY - 50)); // "current slot could be next slot if it's too close to next slot" expect(clock.isCurrentSlotGivenGossipDisparity(nextSlot)).toBe(true); }); it("should accept previous slot if it's just passed current slot", () => { const previousSlot = clock.currentSlot - 1; - vi.advanceTimersByTime(MAXIMUM_GOSSIP_CLOCK_DISPARITY - 50); + vi.advanceTimersByTime(config.MAXIMUM_GOSSIP_CLOCK_DISPARITY - 50); // "current slot could be previous slot if it's just passed to a slot" expect(clock.isCurrentSlotGivenGossipDisparity(previousSlot)).toBe(true); vi.advanceTimersByTime(100); diff --git a/packages/config/src/chainConfig/configs/mainnet.ts b/packages/config/src/chainConfig/configs/mainnet.ts index 6a89a0ac4c..73ba8cabdf 100644 --- a/packages/config/src/chainConfig/configs/mainnet.ts +++ b/packages/config/src/chainConfig/configs/mainnet.ts @@ -130,10 +130,22 @@ export const chainConfig: ChainConfig = { // Networking // --------------------------------------------------------------- - // 2**10 (= 1024) + // 10 * 2**20 (= 10,485,760) bytes, 10 MiB + MAX_PAYLOAD_SIZE: 10485760, + // 2**10 (= 1,024) blocks MAX_REQUEST_BLOCKS: 1024, - // `MIN_VALIDATOR_WITHDRAWABILITY_DELAY + CHURN_LIMIT_QUOTIENT // 2` (= 33024, ~5 months) + // 2**8 (= 256) epochs + EPOCHS_PER_SUBNET_SUBSCRIPTION: 256, + // MIN_VALIDATOR_WITHDRAWABILITY_DELAY + CHURN_LIMIT_QUOTIENT // 2 (= 33,024) epochs MIN_EPOCHS_FOR_BLOCK_REQUESTS: 33024, + // 2**5 (= 32) slots + ATTESTATION_PROPAGATION_SLOT_RANGE: 32, + // 500ms + MAXIMUM_GOSSIP_CLOCK_DISPARITY: 500, + MESSAGE_DOMAIN_INVALID_SNAPPY: b("0x00000000"), + MESSAGE_DOMAIN_VALID_SNAPPY: b("0x01000000"), + // 2 subnets per node + SUBNETS_PER_NODE: 2, // Deneb // 2**7 (= 128) @@ -166,6 +178,10 @@ export const chainConfig: ChainConfig = { // `2**12` (= 4096 epochs, ~18 days) MIN_EPOCHS_FOR_DATA_COLUMN_SIDECARS_REQUESTS: 4096, + // Gloas + // 2**7 (= 128) payloads + MAX_REQUEST_PAYLOADS: 128, + // Blob Scheduling // --------------------------------------------------------------- BLOB_SCHEDULE: [], diff --git a/packages/config/src/chainConfig/configs/minimal.ts b/packages/config/src/chainConfig/configs/minimal.ts index eb156ec486..bbc7cd8320 100644 --- a/packages/config/src/chainConfig/configs/minimal.ts +++ b/packages/config/src/chainConfig/configs/minimal.ts @@ -125,10 +125,22 @@ export const chainConfig: ChainConfig = { // Networking // --------------------------------------------------------------- - // 2**10 (= 1024) + // 10 * 2**20 (= 10,485,760) bytes, 10 MiB + MAX_PAYLOAD_SIZE: 10485760, + // 2**10 (= 1,024) blocks MAX_REQUEST_BLOCKS: 1024, - // [customized] `MIN_VALIDATOR_WITHDRAWABILITY_DELAY + CHURN_LIMIT_QUOTIENT // 2` (= 272) + // 2**8 (= 256) epochs + EPOCHS_PER_SUBNET_SUBSCRIPTION: 256, + // [customized] MIN_VALIDATOR_WITHDRAWABILITY_DELAY + CHURN_LIMIT_QUOTIENT // 2 (= 272) epochs MIN_EPOCHS_FOR_BLOCK_REQUESTS: 272, + // 2**5 (= 32) slots + ATTESTATION_PROPAGATION_SLOT_RANGE: 32, + // 500ms + MAXIMUM_GOSSIP_CLOCK_DISPARITY: 500, + MESSAGE_DOMAIN_INVALID_SNAPPY: b("0x00000000"), + MESSAGE_DOMAIN_VALID_SNAPPY: b("0x01000000"), + // 2 subnets per node + SUBNETS_PER_NODE: 2, // Deneb // 2**7 (= 128) @@ -161,6 +173,10 @@ export const chainConfig: ChainConfig = { // `2**12` (= 4096 epochs, ~18 days) MIN_EPOCHS_FOR_DATA_COLUMN_SIDECARS_REQUESTS: 4096, + // Gloas + // 2**7 (= 128) payloads + MAX_REQUEST_PAYLOADS: 128, + // Blob Scheduling // --------------------------------------------------------------- BLOB_SCHEDULE: [], diff --git a/packages/config/src/chainConfig/types.ts b/packages/config/src/chainConfig/types.ts index 09023c0416..166ea87d98 100644 --- a/packages/config/src/chainConfig/types.ts +++ b/packages/config/src/chainConfig/types.ts @@ -91,9 +91,16 @@ export type ChainConfig = { DEPOSIT_CONTRACT_ADDRESS: Uint8Array; // Networking + MAX_PAYLOAD_SIZE: number; MAX_REQUEST_BLOCKS: number; - MAX_REQUEST_BLOCKS_DENEB: number; + EPOCHS_PER_SUBNET_SUBSCRIPTION: number; MIN_EPOCHS_FOR_BLOCK_REQUESTS: number; + ATTESTATION_PROPAGATION_SLOT_RANGE: number; + MAXIMUM_GOSSIP_CLOCK_DISPARITY: number; + MESSAGE_DOMAIN_INVALID_SNAPPY: Uint8Array; + MESSAGE_DOMAIN_VALID_SNAPPY: Uint8Array; + SUBNETS_PER_NODE: number; + MAX_REQUEST_BLOCKS_DENEB: number; MIN_EPOCHS_FOR_BLOB_SIDECARS_REQUESTS: number; MIN_EPOCHS_FOR_DATA_COLUMN_SIDECARS_REQUESTS: number; BLOB_SIDECAR_SUBNET_COUNT: number; @@ -112,6 +119,9 @@ export type ChainConfig = { VALIDATOR_CUSTODY_REQUIREMENT: number; BALANCE_PER_ADDITIONAL_CUSTODY_GROUP: number; + // Gloas + MAX_REQUEST_PAYLOADS: number; + // Blob Scheduling BLOB_SCHEDULE: BlobSchedule; }; @@ -196,9 +206,16 @@ export const chainConfigTypes: SpecTypes = { DEPOSIT_CONTRACT_ADDRESS: "bytes", // Networking + MAX_PAYLOAD_SIZE: "number", MAX_REQUEST_BLOCKS: "number", - MAX_REQUEST_BLOCKS_DENEB: "number", + EPOCHS_PER_SUBNET_SUBSCRIPTION: "number", MIN_EPOCHS_FOR_BLOCK_REQUESTS: "number", + ATTESTATION_PROPAGATION_SLOT_RANGE: "number", + MAXIMUM_GOSSIP_CLOCK_DISPARITY: "number", + MESSAGE_DOMAIN_INVALID_SNAPPY: "bytes", + MESSAGE_DOMAIN_VALID_SNAPPY: "bytes", + SUBNETS_PER_NODE: "number", + MAX_REQUEST_BLOCKS_DENEB: "number", MIN_EPOCHS_FOR_BLOB_SIDECARS_REQUESTS: "number", MIN_EPOCHS_FOR_DATA_COLUMN_SIDECARS_REQUESTS: "number", BLOB_SIDECAR_SUBNET_COUNT: "number", @@ -217,6 +234,9 @@ export const chainConfigTypes: SpecTypes = { VALIDATOR_CUSTODY_REQUIREMENT: "number", BALANCE_PER_ADDITIONAL_CUSTODY_GROUP: "number", + // Gloas + MAX_REQUEST_PAYLOADS: "number", + // Blob Scheduling BLOB_SCHEDULE: "blob_schedule", }; diff --git a/packages/params/src/index.ts b/packages/params/src/index.ts index b7f512957a..bcee6d82e1 100644 --- a/packages/params/src/index.ts +++ b/packages/params/src/index.ts @@ -193,14 +193,17 @@ export const PARTICIPATION_FLAG_WEIGHTS = [TIMELY_SOURCE_WEIGHT, TIMELY_TARGET_W // phase0 validator export const TARGET_AGGREGATORS_PER_COMMITTEE = 16; -export const RANDOM_SUBNETS_PER_VALIDATOR = 1; -export const EPOCHS_PER_RANDOM_SUBNET_SUBSCRIPTION = 256; + +// phase0 networking + +export const NODE_ID_BITS = 256; +export const MAX_CONCURRENT_REQUESTS = 2; + /** Rationale: https://github.com/ethereum/consensus-specs/blob/v1.1.10/specs/phase0/p2p-interface.md#why-are-there-attestation_subnet_count-attestation-subnets */ export const ATTESTATION_SUBNET_COUNT = 64; -export const SUBNETS_PER_NODE = 2; -export const NODE_ID_BITS = 256; -export const ATTESTATION_SUBNET_PREFIX_BITS = Math.log2(ATTESTATION_SUBNET_COUNT); -export const EPOCHS_PER_SUBNET_SUBSCRIPTION = 256; +export const ATTESTATION_SUBNET_EXTRA_BITS = 0; +export const ATTESTATION_SUBNET_PREFIX_BITS = + Math.ceil(Math.log2(ATTESTATION_SUBNET_COUNT)) + ATTESTATION_SUBNET_EXTRA_BITS; // altair validator @@ -284,7 +287,7 @@ export const KZG_COMMITMENT_GINDEX0 = 221184; export const KZG_COMMITMENT_SUBTREE_INDEX0 = KZG_COMMITMENT_GINDEX0 - 2 ** KZG_COMMITMENT_INCLUSION_PROOF_DEPTH; // ssz.deneb.BlobSidecars.elementType.fixedSize -export const BLOBSIDECAR_FIXED_SIZE = 131928; +export const BLOB_SIDECAR_FIXED_SIZE = 131928; // Electra Misc export const UNSET_DEPOSIT_REQUESTS_START_INDEX = 2n ** 64n - 1n; diff --git a/packages/reqresp/src/rate_limiter/selfRateLimiter.ts b/packages/reqresp/src/rate_limiter/selfRateLimiter.ts index a5ac8bb5c4..5d26f4c025 100644 --- a/packages/reqresp/src/rate_limiter/selfRateLimiter.ts +++ b/packages/reqresp/src/rate_limiter/selfRateLimiter.ts @@ -1,9 +1,8 @@ +import {MAX_CONCURRENT_REQUESTS} from "@lodestar/params"; import {Logger, MapDef} from "@lodestar/utils"; type PeerIdStr = string; type ProtocolID = string; -/** https://github.com/ethereum/consensus-specs/blob/master/specs/phase0/p2p-interface.md#constants */ -const MAX_CONCURRENT_REQUESTS = 2; /** Sometimes a peer request comes AFTER libp2p disconnect event, check for such peers every 2 minutes */ export const CHECK_DISCONNECTED_PEERS_INTERVAL_MS = 2 * 60 * 1000; diff --git a/packages/types/test/unit/constants/blobs.test.ts b/packages/types/test/unit/constants/blobs.test.ts index 1149fca69e..17075f5e53 100644 --- a/packages/types/test/unit/constants/blobs.test.ts +++ b/packages/types/test/unit/constants/blobs.test.ts @@ -7,12 +7,12 @@ import {ssz} from "../../../src/index.js"; // guarantee that these constants are correct. describe(`${constants.ACTIVE_PRESET}/ blobs pre-computed constants`, () => { - const BLOBSIDECAR_FIXED_SIZE = ssz.deneb.BlobSidecars.elementType.fixedSize; + const BLOB_SIDECAR_FIXED_SIZE = ssz.deneb.BlobSidecars.elementType.fixedSize; const KZG_COMMITMENT_GINDEX0 = Number(ssz.deneb.BeaconBlockBody.getPathInfo(["blobKzgCommitments", 0]).gindex); const KZG_COMMITMENT_SUBTREE_INDEX0 = KZG_COMMITMENT_GINDEX0 - 2 ** constants.KZG_COMMITMENT_INCLUSION_PROOF_DEPTH; const correctConstants = { - BLOBSIDECAR_FIXED_SIZE, + BLOB_SIDECAR_FIXED_SIZE, KZG_COMMITMENT_GINDEX0, KZG_COMMITMENT_SUBTREE_INDEX0, }; diff --git a/packages/validator/src/util/params.ts b/packages/validator/src/util/params.ts index dbb6ad9e06..bd6cd2a535 100644 --- a/packages/validator/src/util/params.ts +++ b/packages/validator/src/util/params.ts @@ -179,6 +179,13 @@ function getSpecCriticalParams(localConfig: ChainConfig): Record