---
# System prepended metadata

title: Untitled

---

## Consensus Beacon P2P


## Rough Outline

(1) Run `discv5` discovery to find peers who can gossip to us
(2) connect to these peers with the `gossipsub` protocol on the light client topics
(3) route any data from these topics to the relevant _existing_ components for processing light client data


### Implementation Details

#### (1) Discovery

Initialize a `discv5` server to find gossip peers.

For each node, we need to filter connected peers.

```rust=
/// Starts the p2p discovery server
pub async fn start_p2p(&mut self) -> Result<(), NodeError> {
    // listening address and port
    let listen_addr = "0.0.0.0:9000"
        .parse::<SocketAddr>()
        .map_err(|e| NodeError::P2PError(eyre::eyre!(e)))?;

    // construct a local ENR
    let enr_key = enr::CombinedKey::generate_secp256k1();
    let enr = enr::EnrBuilder::new("v4")
        .build(&enr_key)
        .map_err(|e| NodeError::P2PError(eyre::eyre!(e)))?;

    // default configuration
    let config = Discv5ConfigBuilder::new().build();

    // construct the discv5 server
    let discv5 =
        Discv5::new(enr, enr_key, config).map_err(|e| NodeError::P2PError(eyre::eyre!(e)))?;

    // Set the server
    let server = Arc::new(discv5);
    self.disc = Some(Arc::clone(&server));

    // Start
    let mut cloned = Arc::clone(&server);
    tokio::spawn(async move {
        if let Some(serv) = Arc::get_mut(&mut cloned) {
            if let Err(e) = serv.start(listen_addr).await {
                log::warn!("Failed to start p2p discovery server. Error: {:?}", e);
            }

            let mut event_stream = serv.event_stream().await.unwrap();
            loop {
                match event_stream.recv().await {
                    Some(Discv5Event::SocketUpdated(addr)) => {
                        println!("Nodes ENR socket address has been updated to: {:?}", addr);
                    }
                    Some(Discv5Event::Discovered(enr)) => {
                        println!("A peer has been discovered: {}", enr.node_id());
                    }
                    _ => {}
                }
            }
        } else {
            log::warn!("Failed to get mutable reference to the discv5 p2p discovery server inside client node.");
        }
    });

    Ok(())
}
```


**Resources**
- https://github.com/sigp/discv5


#### (2) peer on `gossipsub`

For each new connected peer, we need to construct a `libp2p_core::Multiaddr` from the node's ENR.

need a way to accept bootstrap peers
need some way to filter peers (maybe? not sure if there is a way to do this via the ENR yet)
need a way to manage peers once we find them (likey just drop into libp2p peer table)


given a good peer set, it should be straightforward to ask the libp2p library to attempt the relevant gossipsub topics and provide us with a way to capture the gossiped data (this can be fed into the next part)



#### (3) integration with Helios

Currently Helios's consensus layer is driven mostly by `ConsensusClient`. When it needs to any data, it fetches it via any struct that implements the `ConsensusRpc` trait.

> @ralexstokes: i'd suggest renaming the trait so it is more general than RPC, and likely removing the `ConsensusRpc::new` fn
> and then we just need to add some logic to expose this trait from the gossip sub events/messages

We want the interface for fetching data to be the same regardless of whether it is via RPC or P2P. However, it is acceptable if we need to change what that interface is to support both.

Option 1: Use mostly the same interface. With this we would just need the RPC to run in a background thread managing peers and caching messages, and `ConsensusClient` could just interact with it via a `ConsensusRpc` trait impl. This requires less changes to the surrounding consensus package.

Option 2: Switch two a message driven architecture. We could instead have the P2P receive messages, and have the P2P object drive the rest of the consensus as it receives new messages. We can also make the RPC sync use the same interface. This requires a much broader change to Helios, but might be better in the long run.

Any Opinions?

> @ralexstokes: i haven't grokked the full architecture but it looks like we should be able to pretty easily `impl ConsensusRpc` around some gossipsub component and then the rest of the codebase can just use this -- i think bc it is already an `async` trait we won't have an issue w/ concurrency here
> so i'd push for option 1 to get something working sooner rather than later


