diff --git a/Cargo.toml b/Cargo.toml new file mode 100644 index 00000000..18740d41 --- /dev/null +++ b/Cargo.toml @@ -0,0 +1,26 @@ +[package] +name = "starknet-p2p-tests" +version = "0.1.0" +edition = "2021" + +[dependencies] +libp2p = { version = "0.53.2", features = [ + "autonat", + "dcutr", + "dns", + "gossipsub", + "identify", + "kad", + "macros", + "noise", + "ping", + "relay", + "request-response", + "serde", + "tcp", + "tokio", + "yamux", +] } + +tokio = { version = "1.28.0", features = ["full", "test-util"] } +anyhow = "1.0" \ No newline at end of file diff --git a/src/lib.rs b/src/lib.rs new file mode 100644 index 00000000..1310e3ef --- /dev/null +++ b/src/lib.rs @@ -0,0 +1,3 @@ +pub mod protocol; +pub mod tools; +pub mod tests; diff --git a/src/main.rs b/src/main.rs new file mode 100644 index 00000000..e7a11a96 --- /dev/null +++ b/src/main.rs @@ -0,0 +1,3 @@ +fn main() { + println!("Hello, world!"); +} diff --git a/src/protocol/mod.rs b/src/protocol/mod.rs new file mode 100644 index 00000000..6968b8dc --- /dev/null +++ b/src/protocol/mod.rs @@ -0,0 +1 @@ +pub mod starknet; \ No newline at end of file diff --git a/src/protocol/starknet.rs b/src/protocol/starknet.rs new file mode 100644 index 00000000..52424a16 --- /dev/null +++ b/src/protocol/starknet.rs @@ -0,0 +1,73 @@ +use libp2p::{ + core::{ + muxing::StreamMuxerBox, + transport::OrTransport, + upgrade, + }, dns, futures, identity, noise, relay, swarm, tcp, yamux, Multiaddr, PeerId, Swarm, Transport +}; +use libp2p::swarm::SwarmEvent; +use futures::StreamExt; + +use std::{error::Error, time::Duration}; + +pub async fn initialize_p2p(addr: &str) -> Result<(), Box> { + // Generate a keypair for the local peer + let local_key = identity::Keypair::generate_ed25519(); + let local_peer_id = local_key.public().to_peer_id(); + + // Create a multiaddr for the local peer + let local_multiaddr: Multiaddr = format!("/ip4/127.0.0.1/tcp/7777/p2p/{}", local_peer_id).parse()?; + println!("Local peer address: {}", local_multiaddr); + + // Initialize the relay transport + let (relay_transport, relay_behaviour) = relay::client::new(local_peer_id.clone()); + + // Create the transport + let transport = create_transport(&local_key, relay_transport); + + // Create the Swarm + let mut swarm = Swarm::new( + transport, + relay_behaviour, + local_peer_id, + swarm::Config::with_tokio_executor() + .with_idle_connection_timeout(Duration::from_secs(3600 * 365)) + ); + + let multiaddr: Multiaddr = addr.parse()?; + + swarm.dial(multiaddr.clone())?; + println!("Dialing peer at address: {}", multiaddr); + + // Handle events + loop { + match swarm.next().await { + Some(SwarmEvent::ConnectionEstablished { peer_id, .. }) => { + println!("Connected to peer: {}", peer_id); + return Ok(()); + } + Some(SwarmEvent::OutgoingConnectionError { error, .. }) => { + return Err(format!("Failed to connect to peer: {:?}", error).into()); + } + _ => {} + } + } +} + +pub fn create_transport( + keypair: &libp2p::identity::Keypair, + relay_transport: libp2p::relay::client::Transport, +) -> libp2p::core::transport::Boxed<(PeerId, StreamMuxerBox)> { + let transport = tcp::tokio::Transport::new(tcp::Config::new()); + let transport = OrTransport::new(transport, relay_transport); + let transport = dns::tokio::Transport::system(transport).unwrap(); + + let noise_config = + noise::Config::new(keypair).expect("Signing libp2p-noise static DH keypair failed."); + + transport + .upgrade(upgrade::Version::V1) + .authenticate(noise_config) + .multiplex(yamux::Config::default()) + .boxed() +} diff --git a/src/tests/mod.rs b/src/tests/mod.rs new file mode 100644 index 00000000..9bcc7bfc --- /dev/null +++ b/src/tests/mod.rs @@ -0,0 +1 @@ +pub mod tests_p2p; diff --git a/src/tests/tests_p2p.rs b/src/tests/tests_p2p.rs new file mode 100644 index 00000000..2948b10e --- /dev/null +++ b/src/tests/tests_p2p.rs @@ -0,0 +1,10 @@ + +#[test] +fn test_connect_to_peer() { + let node = crate::tools::synthetic_node::SyntheticNode::new(); + let peer_address = "/ip4/35.237.66.77/tcp/7777/p2p/12D3KooWR8ikUDiinyE5wgdYiqsdLfJRsBDYKGii6L3oyoipVEaV"; + + let result = node.connect(peer_address); + + assert!(result.is_ok(), "Failed to connect: {:?}", result.err().unwrap()); +} \ No newline at end of file diff --git a/src/tools/mod.rs b/src/tools/mod.rs new file mode 100644 index 00000000..65505155 --- /dev/null +++ b/src/tools/mod.rs @@ -0,0 +1 @@ +pub mod synthetic_node; \ No newline at end of file diff --git a/src/tools/synthetic_node.rs b/src/tools/synthetic_node.rs new file mode 100644 index 00000000..d65d40fa --- /dev/null +++ b/src/tools/synthetic_node.rs @@ -0,0 +1,18 @@ +use crate::protocol::starknet; +use tokio::runtime::Runtime; +use std::error::Error; + +pub struct SyntheticNode; + +impl SyntheticNode { + pub fn new() -> Self { + SyntheticNode + } + + pub fn connect(&self, address: &str) -> Result<(), Box> { + let runtime = Runtime::new().expect("Failed to create Tokio runtime"); + runtime.block_on(async { + starknet::initialize_p2p(address).await + }) + } +} \ No newline at end of file