From d1926800dfdbfba213a0b5060777055d8b1dbae4 Mon Sep 17 00:00:00 2001 From: tv Date: Tue, 27 Oct 2026 02:22:24 +0100 Subject: add libp2p transport --- src/simtest/identity.rs | 71 +++++++++++++++++++++++++++++++++++++++++++++++++ 1 file changed, 71 insertions(+) (limited to 'src/simtest/identity.rs') diff --git a/src/simtest/identity.rs b/src/simtest/identity.rs index 9859d0e..6f468a3 100644 --- a/src/simtest/identity.rs +++ b/src/simtest/identity.rs @@ -170,3 +170,74 @@ async fn nodes_on_both_transports_carry_the_others() { assert!(a.transport.can_reach(b.local_id())); assert!(c.transport.can_reach(b.local_id())); } + +/// Whole nodes over libp2p's in-memory transport, under the identity layer: seeds are +/// multiaddrs, and members find each other's listen addresses in the member list. +#[cfg(feature = "libp2p")] +#[tokio::test(flavor = "multi_thread", worker_threads = 4)] +async fn nodes_over_libp2p() { + use crate::transport::p2p::{Libp2pConfig, Libp2pTransport}; + use ::libp2p::identity::Keypair; + use sha2::Digest; + + fn key(id: &str) -> Keypair { + let mut seed: [u8; 32] = sha2::Sha256::digest(format!("libp2p {id}").as_bytes()).into(); + Keypair::ed25519_from_bytes(&mut seed).unwrap() + } + // Memory ports are process-wide; these are this test's. + let address = |id: &str| -> ::libp2p::Multiaddr { + let port = 50_000 + u64::from(id.as_bytes()[0]); + format!("/memory/{port}").parse().unwrap() + }; + let on_libp2p = |id: &'static str| { + move |config: &mut crate::node::NodeConfig| { + let transport = Libp2pTransport::start(Libp2pConfig { + key: key(id), + listen: vec![address(id)], + memory: true, + }) + .unwrap(); + config.transport = Arc::new(transport); + config.identity.as_mut().unwrap().scheme = "libp2p"; + } + }; + let a_peer = key("a").public().to_peer_id(); + let seed = format!("libp2p:{}", address("a").with_p2p(a_peer).unwrap()); + + let sim = Sim::with_identity(56); + let a = sim.start_with("a", &[], Start::Genesis, on_libp2p("a")); + let others: Vec = ["b", "c", "d"] + .into_iter() + .map(|id| sim.start_with(id, &[seed.as_str()], Start::Join, on_libp2p(id))) + .collect(); + let mut all: Vec<&AppState> = vec![&a]; + all.extend(others.iter()); + sim.wait_ready(&all, SOON).await; + + write(&others[2], "from/d", json!("d")).await; + sim.wait_converged(&all, SOON).await; + for node in &all { + assert_eq!(read(node, "from/d").await, Some(json!("d"))); + peers_are_node_ids(node).await; + } + let d_id = others[2].local_id().to_owned(); + let expected = format!( + "libp2p:{}", + address("d") + .with_p2p(key("d").public().to_peer_id()) + .unwrap() + ); + let a = &a; + sim.wait_until( + "d's listen address is in the member list", + SOON, + move || { + let (d_id, expected) = (d_id.clone(), expected.clone()); + async move { + let replica = a.doc.read().await; + members::addresses(&replica.doc, &d_id) == [expected] + } + }, + ) + .await; +} -- cgit v1.3.1