Skip to content

Commit

Permalink
refactor: use SubnetID type from CL spec instead of number (#7298)
Browse files Browse the repository at this point in the history
* refactor: use `SubnetID` type from CL spec instead of `number`

* Consistently use SubnetID for sync committee
  • Loading branch information
nflaig authored Jan 8, 2025
1 parent cb1c695 commit 877b1ae
Show file tree
Hide file tree
Showing 29 changed files with 102 additions and 95 deletions.
4 changes: 2 additions & 2 deletions packages/beacon-node/src/api/impl/validator/utils.ts
Original file line number Diff line number Diff line change
@@ -1,15 +1,15 @@
import {routes} from "@lodestar/api";
import {ATTESTATION_SUBNET_COUNT} from "@lodestar/params";
import {BeaconStateAllForks, computeSlotsSinceEpochStart} from "@lodestar/state-transition";
import {BLSPubkey, CommitteeIndex, ProducedBlockSource, Slot, ValidatorIndex} from "@lodestar/types";
import {BLSPubkey, CommitteeIndex, ProducedBlockSource, Slot, SubnetID, ValidatorIndex} from "@lodestar/types";
import {MAX_BUILDER_BOOST_FACTOR} from "@lodestar/validator";
import {BlockSelectionResult, BuilderBlockSelectionReason, EngineBlockSelectionReason} from "./index.js";

export function computeSubnetForCommitteesAtSlot(
slot: Slot,
committeesAtSlot: number,
committeeIndex: CommitteeIndex
): number {
): SubnetID {
const slotsSinceEpochStart = computeSlotsSinceEpochStart(slot);
const committeesSinceEpochStart = committeesAtSlot * slotsSinceEpochStart;
return (committeesSinceEpochStart + committeeIndex) % ATTESTATION_SUBNET_COUNT;
Expand Down
4 changes: 2 additions & 2 deletions packages/beacon-node/src/chain/errors/blobSidecarError.ts
Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@
import {RootHex, Slot, ValidatorIndex} from "@lodestar/types";
import {RootHex, Slot, SubnetID, ValidatorIndex} from "@lodestar/types";
import {GossipActionError} from "./gossipValidation.js";

export enum BlobSidecarErrorCode {
Expand Down Expand Up @@ -28,7 +28,7 @@ export enum BlobSidecarErrorCode {

export type BlobSidecarErrorType =
| {code: BlobSidecarErrorCode.INDEX_TOO_LARGE; blobIdx: number; maxBlobsPerBlock: number}
| {code: BlobSidecarErrorCode.INVALID_INDEX; blobIdx: number; subnet: number}
| {code: BlobSidecarErrorCode.INVALID_INDEX; blobIdx: number; subnet: SubnetID}
| {code: BlobSidecarErrorCode.INVALID_KZG; blobIdx: number}
| {code: BlobSidecarErrorCode.INVALID_KZG_TXS}
| {code: BlobSidecarErrorCode.INCORRECT_SLOT; blockSlot: Slot; blobSlot: Slot; blobIdx: number}
Expand Down
Original file line number Diff line number Diff line change
@@ -1,7 +1,7 @@
import {Signature, aggregateSignatures} from "@chainsafe/blst";
import {BitArray} from "@chainsafe/ssz";
import {SYNC_COMMITTEE_SIZE, SYNC_COMMITTEE_SUBNET_COUNT} from "@lodestar/params";
import {Root, Slot, SubcommitteeIndex, altair} from "@lodestar/types";
import {Root, Slot, SubcommitteeIndex, SubnetID, altair} from "@lodestar/types";
import {MapDef, toRootHex} from "@lodestar/utils";
import {IClock} from "../../util/clock.js";
import {InsertOutcome, OpPoolError, OpPoolErrorCode} from "./types.js";
Expand All @@ -26,7 +26,6 @@ type ContributionFast = Omit<altair.SyncCommitteeContribution, "aggregationBits"

/** Hex string of `contribution.beaconBlockRoot` */
type BlockRootHex = string;
type Subnet = SubcommitteeIndex;

/**
* Preaggregate SyncCommitteeMessage into SyncCommitteeContribution
Expand All @@ -40,8 +39,8 @@ export class SyncCommitteeMessagePool {
* */
private readonly contributionsByRootBySubnetBySlot = new MapDef<
Slot,
MapDef<Subnet, Map<BlockRootHex, ContributionFast>>
>(() => new MapDef<Subnet, Map<BlockRootHex, ContributionFast>>(() => new Map<BlockRootHex, ContributionFast>()));
MapDef<SubnetID, Map<BlockRootHex, ContributionFast>>
>(() => new MapDef<SubnetID, Map<BlockRootHex, ContributionFast>>(() => new Map<BlockRootHex, ContributionFast>()));
private lowestPermissibleSlot = 0;

constructor(
Expand All @@ -62,7 +61,7 @@ export class SyncCommitteeMessagePool {
}

// TODO: indexInSubcommittee: number should be indicesInSyncCommittee
add(subnet: Subnet, signature: altair.SyncCommitteeMessage, indexInSubcommittee: number): InsertOutcome {
add(subnet: SubnetID, signature: altair.SyncCommitteeMessage, indexInSubcommittee: number): InsertOutcome {
const {slot, beaconBlockRoot} = signature;
const rootHex = toRootHex(beaconBlockRoot);
const lowestPermissibleSlot = this.lowestPermissibleSlot;
Expand Down Expand Up @@ -146,7 +145,7 @@ function aggregateSignatureInto(
* Format `signature` into an efficient `contribution` to add more signatures in with aggregateSignatureInto()
*/
function signatureToAggregate(
subnet: number,
subnet: SubnetID,
signature: altair.SyncCommitteeMessage,
indexInSubcommittee: number
): ContributionFast {
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -2,7 +2,7 @@ import {Signature, aggregateSignatures} from "@chainsafe/blst";
import {BitArray} from "@chainsafe/ssz";
import {SYNC_COMMITTEE_SIZE, SYNC_COMMITTEE_SUBNET_SIZE} from "@lodestar/params";
import {G2_POINT_AT_INFINITY} from "@lodestar/state-transition";
import {Root, Slot, altair, ssz} from "@lodestar/types";
import {Root, Slot, SubnetID, altair, ssz} from "@lodestar/types";
import {MapDef, toRootHex} from "@lodestar/utils";
import {InsertOutcome, OpPoolError, OpPoolErrorCode} from "./types.js";
import {pruneBySlot, signatureFromBytesNoCheck} from "./utils.js";
Expand Down Expand Up @@ -33,7 +33,6 @@ export type SyncContributionFast = {

/** Hex string of `contribution.beaconBlockRoot` */
type BlockRootHex = string;
type Subnet = number;

/**
* Cache SyncCommitteeContribution and seen ContributionAndProof.
Expand All @@ -43,8 +42,8 @@ type Subnet = number;
export class SyncContributionAndProofPool {
private readonly bestContributionBySubnetRootBySlot = new MapDef<
Slot,
MapDef<BlockRootHex, Map<Subnet, SyncContributionFast>>
>(() => new MapDef<BlockRootHex, Map<Subnet, SyncContributionFast>>(() => new Map<number, SyncContributionFast>()));
MapDef<BlockRootHex, Map<SubnetID, SyncContributionFast>>
>(() => new MapDef<BlockRootHex, Map<SubnetID, SyncContributionFast>>(() => new Map<number, SyncContributionFast>()));

private lowestPermissibleSlot = 0;

Expand Down
Original file line number Diff line number Diff line change
@@ -1,5 +1,5 @@
import {BitArray} from "@chainsafe/ssz";
import {CommitteeIndex, RootHex, Slot, phase0} from "@lodestar/types";
import {CommitteeIndex, RootHex, Slot, SubnetID, phase0} from "@lodestar/types";
import {MapDef} from "@lodestar/utils";
import {Metrics} from "../../metrics/metrics.js";
import {InsertOutcome} from "../opPools/types.js";
Expand All @@ -23,7 +23,7 @@ export type AttestationDataCacheEntry = {
// caching this for 3 slots take 600 instances max, this is nothing compared to attestations processed per slot
// for example in a mainnet node subscribing to all subnets, attestations are processed up to 20k per slot
attestationData: phase0.AttestationData;
subnet: number;
subnet: SubnetID;
};

export enum RejectReason {
Expand Down
2 changes: 1 addition & 1 deletion packages/beacon-node/src/chain/seenCache/seenCommittee.ts
Original file line number Diff line number Diff line change
Expand Up @@ -38,6 +38,6 @@ export class SeenSyncCommitteeMessages {
}
}

function seenCacheKey(subnet: number, validatorIndex: ValidatorIndex): ValidatorSubnetKey {
function seenCacheKey(subnet: SubcommitteeIndex, validatorIndex: ValidatorIndex): ValidatorSubnetKey {
return `${subnet}-${validatorIndex}`;
}
11 changes: 6 additions & 5 deletions packages/beacon-node/src/chain/validation/attestation.ts
Original file line number Diff line number Diff line change
Expand Up @@ -27,6 +27,7 @@ import {
Root,
RootHex,
Slot,
SubnetID,
electra,
isElectraAttestation,
phase0,
Expand Down Expand Up @@ -58,7 +59,7 @@ export type BatchResult = {
export type AttestationValidationResult = {
attestation: Attestation;
indexedAttestation: IndexedAttestation;
subnet: number;
subnet: SubnetID;
attDataRootHex: RootHex;
committeeIndex: CommitteeIndex;
};
Expand Down Expand Up @@ -93,7 +94,7 @@ export async function validateGossipAttestationsSameAttData(
fork: ForkName,
chain: IBeaconChain,
attestationOrBytesArr: GossipAttestation[],
subnet: number,
subnet: SubnetID,
// for unit test, consumers do not need to pass this
step0ValidationFn = validateAttestationNoSignatureCheck
): Promise<BatchResult> {
Expand Down Expand Up @@ -232,7 +233,7 @@ async function validateAttestationNoSignatureCheck(
chain: IBeaconChain,
attestationOrBytes: AttestationOrBytes,
/** Optional, to allow verifying attestations through API with unknown subnet */
subnet: number | null
subnet: SubnetID | null
): Promise<Step0Result> {
// Do checks in this order:
// - do early checks (w/o indexed attestation)
Expand Down Expand Up @@ -342,7 +343,7 @@ async function validateAttestationNoSignatureCheck(

let committeeValidatorIndices: Uint32Array;
let getSigningRoot: () => Uint8Array;
let expectedSubnet: number;
let expectedSubnet: SubnetID;
if (attestationOrCache.cache) {
committeeValidatorIndices = attestationOrCache.cache.committeeValidatorIndices;
const signingRoot = attestationOrCache.cache.signingRoot;
Expand Down Expand Up @@ -762,7 +763,7 @@ export function getCommitteeIndices(
/**
* Compute the correct subnet for a slot/committee index
*/
export function computeSubnetForSlot(shuffling: EpochShuffling, slot: number, committeeIndex: number): number {
export function computeSubnetForSlot(shuffling: EpochShuffling, slot: number, committeeIndex: number): SubnetID {
const slotsSinceEpochStart = slot % SLOTS_PER_EPOCH;
const committeesSinceEpochStart = shuffling.committeesPerSlot * slotsSinceEpochStart;
return (committeesSinceEpochStart + committeeIndex) % ATTESTATION_SUBNET_COUNT;
Expand Down
6 changes: 3 additions & 3 deletions packages/beacon-node/src/chain/validation/blobSidecar.ts
Original file line number Diff line number Diff line change
@@ -1,7 +1,7 @@
import {ChainConfig} from "@lodestar/config";
import {KZG_COMMITMENT_INCLUSION_PROOF_DEPTH, KZG_COMMITMENT_SUBTREE_INDEX0} from "@lodestar/params";
import {computeStartSlotAtEpoch, getBlockHeaderProposerSignatureSet} from "@lodestar/state-transition";
import {BlobIndex, Root, Slot, deneb, ssz} from "@lodestar/types";
import {BlobIndex, Root, Slot, SubnetID, deneb, ssz} from "@lodestar/types";
import {toRootHex, verifyMerkleBranch} from "@lodestar/utils";

import {byteArrayEquals} from "../../util/bytes.js";
Expand All @@ -14,7 +14,7 @@ import {RegenCaller} from "../regen/index.js";
export async function validateGossipBlobSidecar(
chain: IBeaconChain,
blobSidecar: deneb.BlobSidecar,
subnet: number
subnet: SubnetID
): Promise<void> {
const blobSlot = blobSidecar.signedBlockHeader.message.slot;

Expand Down Expand Up @@ -236,6 +236,6 @@ function validateInclusionProof(blobSidecar: deneb.BlobSidecar): boolean {
);
}

function computeSubnetForBlobSidecar(blobIndex: BlobIndex, config: ChainConfig): number {
function computeSubnetForBlobSidecar(blobIndex: BlobIndex, config: ChainConfig): SubnetID {
return blobIndex % config.BLOB_SIDECAR_SUBNET_COUNT;
}
8 changes: 4 additions & 4 deletions packages/beacon-node/src/chain/validation/syncCommittee.ts
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
import {SYNC_COMMITTEE_SUBNET_COUNT, SYNC_COMMITTEE_SUBNET_SIZE} from "@lodestar/params";
import {CachedBeaconStateAllForks} from "@lodestar/state-transition";
import {altair} from "@lodestar/types";
import {SubnetID, altair} from "@lodestar/types";
import {toRootHex} from "@lodestar/utils";
import {GossipAction, SyncCommitteeError, SyncCommitteeErrorCode} from "../errors/index.js";
import {IBeaconChain} from "../interface.js";
Expand All @@ -14,7 +14,7 @@ type IndexInSubcommittee = number;
export async function validateGossipSyncCommittee(
chain: IBeaconChain,
syncCommittee: altair.SyncCommitteeMessage,
subnet: number
subnet: SubnetID
): Promise<{indexInSubcommittee: IndexInSubcommittee}> {
const {slot, validatorIndex, beaconBlockRoot} = syncCommittee;
const messageRoot = toRootHex(beaconBlockRoot);
Expand Down Expand Up @@ -103,7 +103,7 @@ async function validateSyncCommitteeSigOnly(
export function validateGossipSyncCommitteeExceptSig(
chain: IBeaconChain,
headState: CachedBeaconStateAllForks,
subnet: number,
subnet: SubnetID,
data: Pick<altair.SyncCommitteeMessage, "slot" | "validatorIndex">
): IndexInSubcommittee {
const {slot, validatorIndex} = data;
Expand Down Expand Up @@ -144,7 +144,7 @@ export function validateGossipSyncCommitteeExceptSig(
*/
function getIndexInSubcommittee(
headState: CachedBeaconStateAllForks,
subnet: number,
subnet: SubnetID,
data: Pick<altair.SyncCommitteeMessage, "slot" | "validatorIndex">
): IndexInSubcommittee | null {
const syncCommittee = headState.epochCtx.getIndexedSyncCommittee(data.slot);
Expand Down
4 changes: 2 additions & 2 deletions packages/beacon-node/src/metrics/validatorMonitor.ts
Original file line number Diff line number Diff line change
Expand Up @@ -10,7 +10,7 @@ import {
parseAttesterFlags,
parseParticipationFlags,
} from "@lodestar/state-transition";
import {BeaconBlock, RootHex, altair, deneb} from "@lodestar/types";
import {BeaconBlock, RootHex, SubnetID, altair, deneb} from "@lodestar/types";
import {Epoch, Slot, ValidatorIndex} from "@lodestar/types";
import {IndexedAttestation, SignedAggregateAndProof} from "@lodestar/types";
import {LogData, LogHandler, LogLevel, Logger, MapDef, MapDefMax, toRootHex} from "@lodestar/utils";
Expand Down Expand Up @@ -52,7 +52,7 @@ export type ValidatorMonitor = {
onPoolSubmitUnaggregatedAttestation(
seenTimestampSec: number,
indexedAttestation: IndexedAttestation,
subnet: number,
subnet: SubnetID,
sentPeers: number
): void;
onPoolSubmitAggregatedAttestation(
Expand Down
13 changes: 7 additions & 6 deletions packages/beacon-node/src/network/core/metrics.ts
Original file line number Diff line number Diff line change
@@ -1,3 +1,4 @@
import {SubnetID} from "@lodestar/types";
import {RegistryMetricCreator} from "../../metrics/utils/registryMetricCreator.js";
import {SubnetType} from "../metadata.js";
import {DiscoveredPeerStatus} from "../peers/discover.js";
Expand Down Expand Up @@ -194,14 +195,14 @@ export function createNetworkCoreMetrics(register: RegistryMetricCreator) {
name: "lodestar_attnets_service_committee_subscriptions_total",
help: "Count of committee subscriptions",
}),
subscriptionsCommitteeMeshPeers: register.histogram<{subnet: number}>({
subscriptionsCommitteeMeshPeers: register.histogram<{subnet: SubnetID}>({
name: "lodestar_attnets_service_committee_subscriptions_mesh_peers",
help: "Histogram of mesh peers per committee subscription",
labelNames: ["subnet"],
// Dlow = 6, D = 8, DHi = 12 plus 2 more buckets
buckets: [0, 4, 6, 8, 12],
}),
subscriptionsCommitteeTimeToStableMesh: register.histogram<{subnet: number}>({
subscriptionsCommitteeTimeToStableMesh: register.histogram<{subnet: SubnetID}>({
name: "lodestar_attnets_service_committee_subscriptions_time_to_stable_mesh_seconds",
help: "Histogram of time until committee subscription is considered healthy (>= 6 mesh peers)",
labelNames: ["subnet"],
Expand All @@ -216,12 +217,12 @@ export function createNetworkCoreMetrics(register: RegistryMetricCreator) {
name: "lodestar_attnets_service_long_lived_subscriptions_total",
help: "Count of long lived subscriptions",
}),
subscribeSubnets: register.gauge<{subnet: number; src: SubnetSource}>({
subscribeSubnets: register.gauge<{subnet: SubnetID; src: SubnetSource}>({
name: "lodestar_attnets_service_subscribe_subnets_total",
help: "Count of subscribe_subnets calls",
labelNames: ["subnet", "src"],
}),
unsubscribeSubnets: register.gauge<{subnet: number; src: SubnetSource}>({
unsubscribeSubnets: register.gauge<{subnet: SubnetID; src: SubnetSource}>({
name: "lodestar_attnets_service_unsubscribe_subnets_total",
help: "Count of unsubscribe_subnets calls",
labelNames: ["subnet", "src"],
Expand All @@ -237,12 +238,12 @@ export function createNetworkCoreMetrics(register: RegistryMetricCreator) {
name: "lodestar_syncnets_service_committee_subscriptions_total",
help: "Count of syncnet committee subscriptions",
}),
subscribeSubnets: register.gauge<{subnet: number}>({
subscribeSubnets: register.gauge<{subnet: SubnetID}>({
name: "lodestar_syncnets_service_subscribe_subnets_total",
help: "Count of syncnet subscribe_subnets calls",
labelNames: ["subnet"],
}),
unsubscribeSubnets: register.gauge<{subnet: number}>({
unsubscribeSubnets: register.gauge<{subnet: SubnetID}>({
name: "lodestar_syncnets_service_unsubscribe_subnets_total",
help: "Count of syncnet unsubscribe_subnets calls",
labelNames: ["subnet"],
Expand Down
3 changes: 2 additions & 1 deletion packages/beacon-node/src/network/gossip/gossipsub.ts
Original file line number Diff line number Diff line change
Expand Up @@ -4,6 +4,7 @@ import {PeerScoreParams} from "@chainsafe/libp2p-gossipsub/score";
import {SignaturePolicy, TopicStr} from "@chainsafe/libp2p-gossipsub/types";
import {BeaconConfig} from "@lodestar/config";
import {ATTESTATION_SUBNET_COUNT, ForkName, 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";
Expand Down Expand Up @@ -319,7 +320,7 @@ export class Eth2Gossipsub extends GossipSub {
* Left pad subnets to two characters. Assumes ATTESTATION_SUBNET_COUNT < 99
* Otherwise grafana sorts the mesh peers chart as: [1,11,12,13,...]
*/
function attSubnetLabel(subnet: number): string {
function attSubnetLabel(subnet: SubnetID): string {
if (subnet > 9) return String(subnet);

return `0${subnet}`;
Expand Down
7 changes: 4 additions & 3 deletions packages/beacon-node/src/network/gossip/interface.ts
Original file line number Diff line number Diff line change
Expand Up @@ -9,6 +9,7 @@ import {
SignedAggregateAndProof,
SignedBeaconBlock,
Slot,
SubnetID,
altair,
capella,
deneb,
Expand Down Expand Up @@ -54,16 +55,16 @@ export interface IGossipTopic {

export type GossipTopicTypeMap = {
[GossipType.beacon_block]: {type: GossipType.beacon_block};
[GossipType.blob_sidecar]: {type: GossipType.blob_sidecar; subnet: number};
[GossipType.blob_sidecar]: {type: GossipType.blob_sidecar; subnet: SubnetID};
[GossipType.beacon_aggregate_and_proof]: {type: GossipType.beacon_aggregate_and_proof};
[GossipType.beacon_attestation]: {type: GossipType.beacon_attestation; subnet: number};
[GossipType.beacon_attestation]: {type: GossipType.beacon_attestation; subnet: SubnetID};
[GossipType.voluntary_exit]: {type: GossipType.voluntary_exit};
[GossipType.proposer_slashing]: {type: GossipType.proposer_slashing};
[GossipType.attester_slashing]: {type: GossipType.attester_slashing};
[GossipType.sync_committee_contribution_and_proof]: {
type: GossipType.sync_committee_contribution_and_proof;
};
[GossipType.sync_committee]: {type: GossipType.sync_committee; subnet: number};
[GossipType.sync_committee]: {type: GossipType.sync_committee; subnet: SubnetID};
[GossipType.light_client_finality_update]: {type: GossipType.light_client_finality_update};
[GossipType.light_client_optimistic_update]: {type: GossipType.light_client_optimistic_update};
[GossipType.bls_to_execution_change]: {type: GossipType.bls_to_execution_change};
Expand Down
5 changes: 3 additions & 2 deletions packages/beacon-node/src/network/gossip/metrics.ts
Original file line number Diff line number Diff line change
@@ -1,4 +1,5 @@
import {ForkName} from "@lodestar/params";
import {SubnetID} from "@lodestar/types";
import {RegistryMetricCreator} from "../../metrics/index.js";
import {GossipType} from "./interface.js";

Expand Down Expand Up @@ -33,7 +34,7 @@ export function createEth2GossipsubMetrics(register: RegistryMetricCreator) {
help: "Number of connected mesh peers per beacon attestation subnet",
labelNames: ["subnet", "fork"],
}),
peersBySyncCommitteeSubnet: register.gauge<{subnet: number; fork: ForkName}>({
peersBySyncCommitteeSubnet: register.gauge<{subnet: SubnetID; fork: ForkName}>({
name: "lodestar_gossip_mesh_peers_by_sync_committee_subnet_count",
help: "Number of connected mesh peers per sync committee subnet",
labelNames: ["subnet", "fork"],
Expand All @@ -50,7 +51,7 @@ export function createEth2GossipsubMetrics(register: RegistryMetricCreator) {
help: "Number of connected topic peers per beacon attestation subnet",
labelNames: ["subnet", "fork"],
}),
peersBySyncCommitteeSubnet: register.gauge<{subnet: number; fork: ForkName}>({
peersBySyncCommitteeSubnet: register.gauge<{subnet: SubnetID; fork: ForkName}>({
name: "lodestar_gossip_topic_peers_by_sync_committee_subnet_count",
help: "Number of connected topic peers per sync committee subnet",
labelNames: ["subnet", "fork"],
Expand Down
Loading

0 comments on commit 877b1ae

Please sign in to comment.