diff --git a/Cargo.lock b/Cargo.lock index b56d9e3a612..b362ebb0dcb 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -5193,6 +5193,7 @@ dependencies = [ "env_logger", "ethexe-db", "ethexe-signer", + "futures", "gear-core", "gprimitives", "libp2p 0.54.1", @@ -9163,6 +9164,7 @@ dependencies = [ "libp2p-request-response 0.27.0", "libp2p-swarm 0.45.1", "libp2p-tcp 0.42.0", + "libp2p-tls 0.5.0", "libp2p-upnp", "libp2p-yamux 0.46.0", "multiaddr 0.18.1", diff --git a/ethexe/cli/src/chain_spec.rs b/ethexe/cli/src/chain_spec.rs index 68de05fb116..5b9bb910c82 100644 --- a/ethexe/cli/src/chain_spec.rs +++ b/ethexe/cli/src/chain_spec.rs @@ -17,7 +17,9 @@ pub fn testnet_config() -> ChainSpec { ethereum_router_address: "0xf90d2956B6F36194fbac181Fb95b2f67274821da".to_string(), bootnodes: vec![ "/ip4/54.183.94.171/udp/20333/quic-v1/p2p/12D3KooWQ5kJQs2WK5kzmBMShCNidpySDuLjt7aqZoVimdyCPRDz".parse().unwrap(), - "/ip4/54.183.94.171/udp/20334/quic-v1/p2p/12D3KooWAivseD2rweVeS2fyNuVFP1hWZ2gXRtMzrNK1ci4mmoMj".parse().unwrap() + "/ip4/54.183.94.171/udp/20334/quic-v1/p2p/12D3KooWAivseD2rweVeS2fyNuVFP1hWZ2gXRtMzrNK1ci4mmoMj".parse().unwrap(), + "/ip4/54.183.94.171/tcp/20333/p2p/12D3KooWQ5kJQs2WK5kzmBMShCNidpySDuLjt7aqZoVimdyCPRDz".parse().unwrap(), + "/ip4/54.183.94.171/tcp/20334/p2p/12D3KooWAivseD2rweVeS2fyNuVFP1hWZ2gXRtMzrNK1ci4mmoMj".parse().unwrap(), ], } } diff --git a/ethexe/network/Cargo.toml b/ethexe/network/Cargo.toml index d2e4473e93b..b11721962fb 100644 --- a/ethexe/network/Cargo.toml +++ b/ethexe/network/Cargo.toml @@ -23,12 +23,13 @@ parity-scale-codec.workspace = true async-trait.workspace = true rand = { workspace = true, features = ["std", "std_rng"] } derive_more.workspace = true +futures.workspace = true void = "1.0.2" [dependencies.libp2p] git = "https://github.com/gear-tech/rust-libp2p" branch = "al/v0.54.1-patches" -features = ["mdns", "gossipsub", "kad", "identify", "ping", "secp256k1", "request-response", "quic", "tokio", "macros", "plaintext", "yamux"] +features = ["mdns", "gossipsub", "kad", "identify", "ping", "secp256k1", "request-response", "quic", "tcp", "tls", "tokio", "macros", "plaintext", "yamux"] [dev-dependencies] # newer versions are not supported on crates.io diff --git a/ethexe/network/src/lib.rs b/ethexe/network/src/lib.rs index ae71cc5e48b..184685cc145 100644 --- a/ethexe/network/src/lib.rs +++ b/ethexe/network/src/lib.rs @@ -28,9 +28,10 @@ pub mod export { use anyhow::Context; use ethexe_db::Database; use ethexe_signer::{PublicKey, Signer}; +use futures::future::Either; use libp2p::{ connection_limits, - core::upgrade, + core::{muxing::StreamMuxerBox, upgrade}, futures::StreamExt, gossipsub, identify, identity, kad, mdns, multiaddr::Protocol, @@ -39,7 +40,7 @@ use libp2p::{ dial_opts::{DialOpts, PeerCondition}, Config as SwarmConfig, NetworkBehaviour, SwarmEvent, }, - Multiaddr, PeerId, Swarm, SwarmBuilder, Transport, + yamux, Multiaddr, PeerId, Swarm, Transport, }; use std::{ collections::HashSet, @@ -47,6 +48,7 @@ use std::{ hash::{DefaultHasher, Hash, Hasher}, path::{Path, PathBuf}, str::FromStr, + time::Duration, }; use tokio::{select, sync::mpsc}; @@ -172,7 +174,7 @@ impl NetworkReceiver { #[derive(Default, Debug, Clone)] pub enum TransportType { #[default] - Quic, + QuicOrTcp, Memory, } @@ -194,7 +196,7 @@ impl NetworkEventLoopConfig { external_addresses: Default::default(), bootstrap_addresses: Default::default(), listen_addresses: ["/ip4/127.0.0.1/udp/0/quic-v1".parse().unwrap()].into(), - transport_type: TransportType::Quic, + transport_type: TransportType::QuicOrTcp, } } @@ -264,31 +266,36 @@ impl NetworkEventLoop { db: Database, transport_type: TransportType, ) -> anyhow::Result> { - match transport_type { - TransportType::Quic => Ok(SwarmBuilder::with_existing_identity(keypair) - .with_tokio() - .with_quic() - .with_behaviour(move |keypair| Behaviour::new(keypair, db))? - .build()), - - TransportType::Memory => { - let transport = libp2p::core::transport::MemoryTransport::default() - .upgrade(upgrade::Version::V1) - .authenticate(libp2p::plaintext::Config::new(&keypair)) - .multiplex(libp2p::yamux::Config::default()) - .boxed(); - let behaviour = Behaviour::new(&keypair, db).map_err(|err| anyhow::anyhow!(err))?; - let config = SwarmConfig::with_tokio_executor() - .with_substream_upgrade_protocol_override(upgrade::Version::V1); - - Ok(Swarm::new( - transport, - behaviour, - keypair.public().to_peer_id(), - config, - )) + let transport = match transport_type { + TransportType::QuicOrTcp => { + let tcp = libp2p::tcp::tokio::Transport::default() + .upgrade(upgrade::Version::V1Lazy) + .authenticate(libp2p::tls::Config::new(&keypair)?) + .multiplex(yamux::Config::default()) + .timeout(Duration::from_secs(20)); + + let quic_config = libp2p::quic::Config::new(&keypair); + let quic = libp2p::quic::tokio::Transport::new(quic_config); + + quic.or_transport(tcp) + .map(|either_output, _| match either_output { + Either::Left((peer_id, muxer)) => (peer_id, StreamMuxerBox::new(muxer)), + Either::Right((peer_id, muxer)) => (peer_id, StreamMuxerBox::new(muxer)), + }) + .boxed() } - } + TransportType::Memory => libp2p::core::transport::MemoryTransport::default() + .upgrade(upgrade::Version::V1Lazy) + .authenticate(libp2p::plaintext::Config::new(&keypair)) + .multiplex(yamux::Config::default()) + .boxed(), + }; + + let behaviour = Behaviour::new(&keypair, db)?; + let local_peer_id = keypair.public().to_peer_id(); + let config = SwarmConfig::with_tokio_executor(); + + Ok(Swarm::new(transport, behaviour, local_peer_id, config)) } pub async fn run(mut self) { @@ -491,10 +498,7 @@ pub(crate) struct Behaviour { } impl Behaviour { - fn new( - keypair: &identity::Keypair, - db: Database, - ) -> Result> { + fn new(keypair: &identity::Keypair, db: Database) -> anyhow::Result { let peer_id = keypair.public().to_peer_id(); // we use custom behaviour because