Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

refactor!: drop MetadataController dependency on BeaconChain #5443

Merged
merged 1 commit into from
May 1, 2023
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Jump to
Jump to file
Failed to load files.
Diff view
Diff view
33 changes: 11 additions & 22 deletions packages/beacon-node/src/network/metadata.ts
@@ -1,9 +1,8 @@
import {BitArray, toHexString} from "@chainsafe/ssz";
import {BitArray} from "@chainsafe/ssz";
import {ForkName} from "@lodestar/params";
import {altair, Epoch, phase0, ssz} from "@lodestar/types";
import {BeaconConfig} from "@lodestar/config";
import {Logger} from "@lodestar/utils";
import {IBeaconChain} from "../chain/index.js";
import {computeStartSlotAtEpoch} from "@lodestar/state-transition";
import {FAR_FUTURE_EPOCH} from "../constants/index.js";
import {getCurrentAndNextFork} from "./forks.js";

Expand All @@ -22,41 +21,29 @@ export type MetadataOpts = {
metadata?: altair.Metadata;
};

export type MetadataModules = {
config: BeaconConfig;
chain: IBeaconChain;
logger: Logger;
};

/**
* Implementation of Ethereum Consensus p2p MetaData.
* For the spec that this code is based on, see:
* https://github.com/ethereum/consensus-specs/blob/v1.1.10/specs/phase0/p2p-interface.md#metadata
*/
export class MetadataController {
private setEnrValue?: (key: string, value: Uint8Array) => Promise<void>;
private config: BeaconConfig;
private chain: IBeaconChain;
private _metadata: altair.Metadata;
private logger: Logger;

constructor(opts: MetadataOpts, modules: MetadataModules) {
this.config = modules.config;
this.chain = modules.chain;
this.logger = modules.logger;
this._metadata = opts.metadata || ssz.altair.Metadata.defaultValue();
constructor(private readonly config: BeaconConfig, opts?: MetadataOpts) {
this._metadata = opts?.metadata || ssz.altair.Metadata.defaultValue();
}

start(setEnrValue: ((key: string, value: Uint8Array) => Promise<void>) | undefined, currentFork: ForkName): void {
start(setEnrValue: ((key: string, value: Uint8Array) => Promise<void>) | undefined, currentEpoch: Epoch): void {
this.setEnrValue = setEnrValue;
if (this.setEnrValue) {
// updateEth2Field() MUST be called with clock epoch
this.updateEth2Field(this.chain.clock.currentEpoch);
this.updateEth2Field(currentEpoch);

void this.setEnrValue(ENRKey.attnets, ssz.phase0.AttestationSubnets.serialize(this._metadata.attnets));
// Any fork after altair included

if (currentFork !== ForkName.phase0) {
if (this.config.getForkName(computeStartSlotAtEpoch(currentEpoch)) !== ForkName.phase0) {
// Only persist syncnets if altair fork is already activated. If currentFork is altair but head is phase0
// adding syncnets to the ENR is not a problem, we will just have a useless field for a few hours.
void this.setEnrValue(ENRKey.syncnets, ssz.phase0.AttestationSubnets.serialize(this._metadata.syncnets));
Expand Down Expand Up @@ -107,11 +94,13 @@ export class MetadataController {
* 2. Network MUST call this method on fork transition.
* Current Clock implementation ensures no race conditions, epoch is correct if re-fetched
*/
updateEth2Field(epoch: Epoch): void {
updateEth2Field(epoch: Epoch): Uint8Array | null {
if (this.setEnrValue) {
const enrForkId = ssz.phase0.ENRForkID.serialize(getENRForkID(this.config, epoch));
this.logger.verbose(`Updated ENR.eth2: ${toHexString(enrForkId)}`);
void this.setEnrValue(ENRKey.eth2, enrForkId);
return enrForkId;
} else {
return null;
}
}
}
Expand Down
9 changes: 5 additions & 4 deletions packages/beacon-node/src/network/network.ts
Expand Up @@ -2,7 +2,7 @@ import {Connection} from "@libp2p/interface-connection";
import {PeerId} from "@libp2p/interface-peer-id";
import {Multiaddr} from "@multiformats/multiaddr";
import {BeaconConfig} from "@lodestar/config";
import {Logger, sleep} from "@lodestar/utils";
import {Logger, sleep, toHex} from "@lodestar/utils";
import {ATTESTATION_SUBNET_COUNT, ForkName, ForkSeq, SYNC_COMMITTEE_SUBNET_COUNT} from "@lodestar/params";
import {SignableENR} from "@chainsafe/discv5";
import {computeEpochAtSlot, computeTimeAtSlot} from "@lodestar/state-transition";
Expand Down Expand Up @@ -156,7 +156,7 @@ export class Network implements INetwork {
const clock = chain.clock;
const peersData = new PeersData();
const networkEventBus = new NetworkEventBus();
const metadata = new MetadataController({}, {config, chain, logger});
const metadata = new MetadataController(config);
const peerRpcScores = new PeerRpcScoreStore(metrics);

const libp2p = await createNodeJsLibp2p(peerId, opts, {
Expand Down Expand Up @@ -247,7 +247,7 @@ export class Network implements INetwork {
const discv5 = peerManager["discovery"]?.discv5;
const setEnrValue = discv5?.setEnrValue.bind(discv5);
// Initialize ENR with clock's fork
metadata.start(setEnrValue, config.getForkName(clock.currentSlot));
metadata.start(setEnrValue, clock.currentEpoch);
await gossip.start();
attnetsService.start();
syncnetsService.start();
Expand Down Expand Up @@ -496,7 +496,8 @@ export class Network implements INetwork {
// On fork transition
if (epoch === forkEpoch) {
// updateEth2Field() MUST be called with clock epoch, onEpoch event is emitted in response to clock events
this.metadata.updateEth2Field(epoch);
const enrForkId = this.metadata.updateEth2Field(epoch);
if (enrForkId) this.logger.verbose(`Updated ENR.eth2: ${toHex(enrForkId)}`);
this.reqResp.registerProtocolsAtFork(nextFork);
}

Expand Down
Expand Up @@ -71,7 +71,7 @@ describe("AttnetsService", function () {
});
// load getCurrentSlot first, vscode not able to debug without this
getCurrentSlot(config, Math.floor(Date.now() / 1000));
metadata = new MetadataController({}, {config, chain, logger});
metadata = new MetadataController(config);
service = new AttnetsService(config, chain, gossipStub, metadata, logger, null, {
randBetweenFn,
shuffleFn: shuffleFn as ShuffleFn,
Expand Down