From a57604576bda833b03b2dd33f6fd7bf6b3ab37df Mon Sep 17 00:00:00 2001 From: Hamza Khalid Date: Mon, 9 Dec 2024 11:53:10 +0500 Subject: [PATCH] Optional mdns --- .github/workflows/ec2-deployment.yml | 2 + packages/ciphernode/Dockerfile | 2 +- packages/ciphernode/config/src/app_config.rs | 7 ++ .../ciphernode/enclave_node/src/aggregator.rs | 1 + .../ciphernode/enclave_node/src/ciphernode.rs | 1 + .../evm/src/ciphernode_registry_sol.rs | 2 +- packages/ciphernode/net/src/bin/p2p_test.rs | 7 +- .../ciphernode/net/src/network_manager.rs | 13 ++- packages/ciphernode/net/src/network_peer.rs | 98 ++++++++++--------- .../ciphernode/net/tests/docker-compose.yaml | 15 +-- packages/ciphernode/net/tests/entrypoint.sh | 7 -- 11 files changed, 82 insertions(+), 73 deletions(-) diff --git a/.github/workflows/ec2-deployment.yml b/.github/workflows/ec2-deployment.yml index 2742cd5f..39766064 100644 --- a/.github/workflows/ec2-deployment.yml +++ b/.github/workflows/ec2-deployment.yml @@ -57,12 +57,14 @@ jobs: - name: Deploy to EC2 uses: appleboy/ssh-action@v1.2.0 + if: github.ref == 'refs/heads/main' with: host: ${{ secrets.EC2_HOST }} username: ${{ secrets.EC2_USERNAME }} key: ${{ secrets.EC2_KEY }} script: | # Pull the latest image + echo "Pulling latest image $IMAGE_NAME:latest" docker pull $IMAGE_NAME:latest # Cd into the directory diff --git a/packages/ciphernode/Dockerfile b/packages/ciphernode/Dockerfile index b58b1541..03fe4cd4 100644 --- a/packages/ciphernode/Dockerfile +++ b/packages/ciphernode/Dockerfile @@ -14,7 +14,7 @@ COPY --from=evm-builder /build/packages/evm/artifacts ../evm/artifacts RUN cargo build --release # Runtime stage -FROM debian:bookworm-slim +FROM debian:stable-slim # Install runtime dependencies RUN apt-get update && apt-get install -y --no-install-recommends iptables ca-certificates jq && \ diff --git a/packages/ciphernode/config/src/app_config.rs b/packages/ciphernode/config/src/app_config.rs index e7e073b1..49f7d0ac 100644 --- a/packages/ciphernode/config/src/app_config.rs +++ b/packages/ciphernode/config/src/app_config.rs @@ -91,6 +91,8 @@ pub struct AppConfig { peers: Vec, /// The port to use for the quic listener quic_port: u16, + /// Whether to enable mDNS discovery + enable_mdns: bool, } impl Default for AppConfig { @@ -107,6 +109,7 @@ impl Default for AppConfig { // generation via ipns fetch for the latest nodes address: None, quic_port: 9091, + enable_mdns: false, } } } @@ -186,6 +189,10 @@ impl AppConfig { pub fn quic_port(&self) -> u16 { self.quic_port } + + pub fn enable_mdns(&self) -> bool { + self.enable_mdns + } } /// Load the config at the config_file or the default location if not provided diff --git a/packages/ciphernode/enclave_node/src/aggregator.rs b/packages/ciphernode/enclave_node/src/aggregator.rs index b1802520..4a7fc431 100644 --- a/packages/ciphernode/enclave_node/src/aggregator.rs +++ b/packages/ciphernode/enclave_node/src/aggregator.rs @@ -86,6 +86,7 @@ pub async fn setup_aggregator( config.peers(), &cipher, config.quic_port(), + config.enable_mdns(), repositories.libp2pid(), ) .await?; diff --git a/packages/ciphernode/enclave_node/src/ciphernode.rs b/packages/ciphernode/enclave_node/src/ciphernode.rs index 714cea34..2b60177c 100644 --- a/packages/ciphernode/enclave_node/src/ciphernode.rs +++ b/packages/ciphernode/enclave_node/src/ciphernode.rs @@ -78,6 +78,7 @@ pub async fn setup_ciphernode( config.peers(), &cipher, config.quic_port(), + config.enable_mdns(), repositories.libp2pid(), ) .await?; diff --git a/packages/ciphernode/evm/src/ciphernode_registry_sol.rs b/packages/ciphernode/evm/src/ciphernode_registry_sol.rs index a616411b..d4846a50 100644 --- a/packages/ciphernode/evm/src/ciphernode_registry_sol.rs +++ b/packages/ciphernode/evm/src/ciphernode_registry_sol.rs @@ -3,7 +3,7 @@ use crate::{ helpers::{ReadonlyProvider, WithChainId}, EvmEventReader, }; -use actix::{Actor, Addr}; +use actix::Addr; use alloy::{ primitives::{LogData, B256}, sol, diff --git a/packages/ciphernode/net/src/bin/p2p_test.rs b/packages/ciphernode/net/src/bin/p2p_test.rs index 15435f2a..e44f43b8 100644 --- a/packages/ciphernode/net/src/bin/p2p_test.rs +++ b/packages/ciphernode/net/src/bin/p2p_test.rs @@ -30,10 +30,15 @@ async fn main() -> Result<()> { .ok() .and_then(|p| p.parse::().ok()); + let enable_mdns = env::var("ENABLE_MDNS") + .unwrap_or("false".to_string()) + .parse::() + .unwrap(); + let peers: Vec = dial_to.iter().cloned().collect(); let id = libp2p::identity::Keypair::generate_ed25519(); - let mut peer = NetworkPeer::new(&id, peers, udp_port, "test-topic")?; + let mut peer = NetworkPeer::new(&id, peers, udp_port, "test-topic", enable_mdns)?; // Extract input and outputs let tx = peer.tx(); diff --git a/packages/ciphernode/net/src/network_manager.rs b/packages/ciphernode/net/src/network_manager.rs index d5e2e966..8969c908 100644 --- a/packages/ciphernode/net/src/network_manager.rs +++ b/packages/ciphernode/net/src/network_manager.rs @@ -8,11 +8,10 @@ use cipher::Cipher; use data::Repository; use enclave_core::{EnclaveEvent, EventBus, EventId, Subscribe}; use libp2p::identity::ed25519; +use std::collections::HashSet; use std::sync::Arc; -use std::{collections::HashSet, error::Error}; use tokio::sync::mpsc::{Receiver, Sender}; use tracing::{error, info, instrument, trace}; -use zeroize::Zeroize; /// NetworkManager Actor converts between EventBus events and Libp2p events forwarding them to a /// NetworkPeer for propagation over the p2p network @@ -73,6 +72,7 @@ impl NetworkManager { peers: Vec, cipher: &Arc, quic_port: u16, + enable_mdns: bool, repository: Repository>, ) -> Result<(Addr, tokio::task::JoinHandle>, String)> { info!("Reading from repository"); @@ -94,8 +94,13 @@ impl NetworkManager { let ed25519_keypair = ed25519::Keypair::try_from_bytes(&mut bytes)?; let keypair: libp2p::identity::Keypair = ed25519_keypair.try_into()?; - let mut peer = - NetworkPeer::new(&keypair, peers, Some(quic_port), "tmp-enclave-gossip-topic")?; + let mut peer = NetworkPeer::new( + &keypair, + peers, + Some(quic_port), + "tmp-enclave-gossip-topic", + enable_mdns, + )?; let rx = peer.rx().ok_or(anyhow!("Peer rx already taken"))?; let p2p_addr = NetworkManager::setup(bus, peer.tx(), rx); let handle = tokio::spawn(async move { Ok(peer.start().await?) }); diff --git a/packages/ciphernode/net/src/network_peer.rs b/packages/ciphernode/net/src/network_peer.rs index 8e1d80d6..17151076 100644 --- a/packages/ciphernode/net/src/network_peer.rs +++ b/packages/ciphernode/net/src/network_peer.rs @@ -7,14 +7,14 @@ use libp2p::{ identity::Keypair, kad::{store::MemoryStore, Behaviour as KademliaBehaviour}, mdns, - swarm::{NetworkBehaviour, SwarmEvent}, + swarm::{behaviour::toggle::Toggle, NetworkBehaviour, SwarmEvent}, Multiaddr, Swarm, }; use std::hash::{Hash, Hasher}; use std::{hash::DefaultHasher, io::Error, time::Duration}; use tokio::{ select, - sync::mpsc::{self, channel, Receiver, Sender}, + sync::mpsc::{channel, Receiver, Sender}, }; use tracing::{debug, error, info, trace, warn}; @@ -23,7 +23,7 @@ pub struct NodeBehaviour { gossipsub: gossipsub::Behaviour, kademlia: KademliaBehaviour, connection_limits: connection_limits::Behaviour, - mdns: mdns::tokio::Behaviour, + mdns: Toggle, identify: IdentifyBehaviour, } @@ -44,6 +44,7 @@ impl NetworkPeer { peers: Vec, udp_port: Option, topic: &str, + enable_mdns: bool, ) -> Result { let (to_bus_tx, from_net_rx) = channel(100); // TODO : tune this param let (to_net_tx, from_bus_rx) = channel(100); // TODO : tune this param @@ -51,7 +52,7 @@ impl NetworkPeer { let swarm = libp2p::SwarmBuilder::with_existing_identity(id.clone()) .with_tokio() .with_quic() - .with_behaviour(create_mdns_kad_behaviour())? + .with_behaviour(|key| create_mdns_kad_behaviour(enable_mdns, key))? .with_swarm_config(|c| c.with_idle_connection_timeout(Duration::from_secs(60))) .build(); @@ -115,50 +116,53 @@ impl NetworkPeer { } } -fn create_mdns_kad_behaviour() -> impl FnOnce( - &Keypair, -) -> std::result::Result< - NodeBehaviour, - Box, -> { - |key| { - let connection_limits = connection_limits::Behaviour::new(ConnectionLimits::default()); - let identify_config = IdentifyBehaviour::new( - identify::Config::new("/kad/0.1.0".into(), key.public()) - .with_interval(Duration::from_secs(60)), // do this so we can get timeouts for dropped WebRTC connections - ); - let message_id_fn = |message: &gossipsub::Message| { - let mut s = DefaultHasher::new(); - message.data.hash(&mut s); - gossipsub::MessageId::from(s.finish().to_string()) - }; +fn create_mdns_kad_behaviour( + enable_mdns: bool, + key: &Keypair, +) -> std::result::Result> { + let connection_limits = connection_limits::Behaviour::new(ConnectionLimits::default()); + let identify_config = IdentifyBehaviour::new( + identify::Config::new("/kad/0.1.0".into(), key.public()) + .with_interval(Duration::from_secs(60)), + ); + + let message_id_fn = |message: &gossipsub::Message| { + let mut s = DefaultHasher::new(); + message.data.hash(&mut s); + gossipsub::MessageId::from(s.finish().to_string()) + }; - // TODO: Allow for config inputs to new() - let gossipsub_config = gossipsub::ConfigBuilder::default() - .heartbeat_interval(Duration::from_secs(10)) - .validation_mode(gossipsub::ValidationMode::Strict) - .message_id_fn(message_id_fn) - .build() - .map_err(|msg| Error::new(std::io::ErrorKind::Other, msg))?; - - let gossipsub = gossipsub::Behaviour::new( - gossipsub::MessageAuthenticity::Signed(key.clone()), - gossipsub_config, - )?; - - let mdns = mdns::tokio::Behaviour::new(mdns::Config::default(), key.public().to_peer_id())?; - - Ok(NodeBehaviour { - gossipsub, - kademlia: KademliaBehaviour::new( - key.public().to_peer_id(), - MemoryStore::new(key.public().to_peer_id()), - ), - mdns, - connection_limits, - identify: identify_config, - }) - } + let gossipsub_config = gossipsub::ConfigBuilder::default() + .heartbeat_interval(Duration::from_secs(10)) + .validation_mode(gossipsub::ValidationMode::Strict) + .message_id_fn(message_id_fn) + .build() + .map_err(|msg| Error::new(std::io::ErrorKind::Other, msg))?; + + let gossipsub = gossipsub::Behaviour::new( + gossipsub::MessageAuthenticity::Signed(key.clone()), + gossipsub_config, + )?; + + let mdns = if enable_mdns { + Toggle::from(Some(mdns::tokio::Behaviour::new( + mdns::Config::default(), + key.public().to_peer_id(), + )?)) + } else { + Toggle::from(None) + }; + + Ok(NodeBehaviour { + gossipsub, + kademlia: KademliaBehaviour::new( + key.public().to_peer_id(), + MemoryStore::new(key.public().to_peer_id()), + ), + mdns, + connection_limits, + identify: identify_config, + }) } async fn process_swarm_event( diff --git a/packages/ciphernode/net/tests/docker-compose.yaml b/packages/ciphernode/net/tests/docker-compose.yaml index f55d3698..d54a3046 100644 --- a/packages/ciphernode/net/tests/docker-compose.yaml +++ b/packages/ciphernode/net/tests/docker-compose.yaml @@ -11,11 +11,8 @@ services: environment: QUIC_PORT: 9091 DIAL_TO: "/ip4/172.16.238.12/udp/9091/quic-v1" - BLOCK_MDNS: "${BLOCK_MDNS:-false}" + ENABLE_MDNS: "${ENABLE_MDNS:-true}" entrypoint: ["/app/entrypoint.sh"] - cap_add: - - NET_ADMIN - - NET_RAW bob: image: p2p-test-image @@ -26,11 +23,8 @@ services: environment: QUIC_PORT: 9091 DIAL_TO: "/ip4/172.16.238.12/udp/9091/quic-v1" - BLOCK_MDNS: "${BLOCK_MDNS:-false}" + ENABLE_MDNS: "${ENABLE_MDNS:-true}" entrypoint: ["/app/entrypoint.sh"] - cap_add: - - NET_ADMIN - - NET_RAW charlie: image: p2p-test-image @@ -40,11 +34,8 @@ services: command: ["/app/p2p_test", "charlie"] environment: QUIC_PORT: 9091 - BLOCK_MDNS: "${BLOCK_MDNS:-false}" + ENABLE_MDNS: "${ENABLE_MDNS:-true}" entrypoint: ["/app/entrypoint.sh"] - cap_add: - - NET_ADMIN - - NET_RAW networks: app_net: diff --git a/packages/ciphernode/net/tests/entrypoint.sh b/packages/ciphernode/net/tests/entrypoint.sh index dfc54f53..a6453106 100755 --- a/packages/ciphernode/net/tests/entrypoint.sh +++ b/packages/ciphernode/net/tests/entrypoint.sh @@ -1,11 +1,4 @@ #!/bin/bash set -e -if [ "${BLOCK_MDNS:-false}" = "true" ]; then - iptables -A INPUT -p udp --dport 5353 -j DROP - iptables -A OUTPUT -p udp --dport 5353 -j DROP - iptables -L | grep DROP -fi - -# Execute the original command exec "$@"