Skip to content

3.3 Code Lodestar Gossip Handling

Gossipsub#

'sub' means pubsub protocol and 'gossipsub' means a pubsub protocol built on gossip protocol. Its code is https://github.com/ChainSafe/lodestar/blob/v1.5.1/packages/beacon-node/src/network/gossip/gossipsub.ts and it was initialized by:

this.gossip = new Eth2Gossipsub(opts, {
      config,
      libp2p,
      logger,
      metrics,
      signal,
      gossipHandlers: gossipHandlers ?? getGossipHandlers({chain, config, logger, network: this, metrics}, opts),
      eth2Context: {
        activeValidatorCount: chain.getHeadState().epochCtx.currentShuffling.activeIndices.length,
        currentSlot: this.clock.currentSlot,
        currentEpoch: this.clock.currentEpoch,
      },
      peersData: this.peersData,
    });

Its core logic is in https://github.com/ChainSafe/lodestar/blob/v1.5.1/packages/beacon-node/src/network/gossip/handlers/index.ts - function getGossipHandlers, where it defines the logic for each message, such as GossipType.beacon_block or GossipType.beacon_block_and_blobs_sidecar. A lot of the topics are defined here in 'phase0'. Some newer ones are defined in later upgrades.

Attestation Subnets(attnets) and Sync Subnets(syncnets)#

Attestations are aggregated in subnets before broadcasted globally. The gossip topic beacon_attestation_{subnet_id} segregates clients into different subnets. Code is in https://github.com/ChainSafe/lodestar/blob/v1.5.1/packages/beacon-node/src/network/subnets/attnetsService.ts

The 'sync subnets' is in https://github.com/ChainSafe/lodestar/blob/v1.5.1/packages/beacon-node/src/network/subnets/syncnetsService.ts and it looks like simplified attnetsService.ts.

The subnets subscription is called in https://github.com/ChainSafe/lodestar/blob/v1.5.1/packages/beacon-node/src/network/network.ts (the code below is simplified to focus on attnetsService) at the start of each epoch and during each network upgrades, e.g. altair, deneb, etc. It does some polyfills when Ethereum decides to change topic name, e.g. from beacon_block to beacon_block_and_blobs_sidecar.

private onEpoch = (epoch: Epoch): void => {
    try {
      const activeForks = getActiveForks(this.config, epoch);
      for (let i = 0; i < activeForks.length; i++) {
        if (activeForks[i + 1]) {
          const prevFork = activeForks[i];
          const nextFork = activeForks[i + 1];
          const forkEpoch = this.config.forks[nextFork].epoch;

          // Before fork transition
          if (epoch === forkEpoch - FORK_EPOCH_LOOKAHEAD) {
            this.attnetsService.subscribeSubnetsToNextFork(nextFork);
            this.syncnetsService.subscribeSubnetsToNextFork(nextFork);
          }

          // After fork transition
          if (epoch === forkEpoch + FORK_EPOCH_LOOKAHEAD) {
            this.attnetsService.unsubscribeSubnetsFromPrevFork(prevFork);
            this.syncnetsService.unsubscribeSubnetsFromPrevFork(prevFork);
          }
        }
      }
    } catch (e) {
      this.logger.error("Error on BeaconGossipHandler.onEpoch", {epoch}, e as Error);
    }
  };

attnetsService has 2 periodic functions itself: onSlot and onEpoch. onSlot cleans up unused subnets. onEpoch cleans up offline validators. The difference in known has an influence in the next subnet subscription (in function rebalanceRandomSubnets). See more in specs: