fedimint-server 0.12.0-beta.2

fedimint-server' facilitates federated consensus with atomic broadcast and distributed configuration.
Documentation
use std::collections::BTreeMap;
use std::net::SocketAddr;

use fedimint_core::PeerId;
use fedimint_server_core::dashboard_ui::ConnectionType;
use iroh::{NodeAddr, SecretKey};
use iroh_next::{RelayUrl, TransportAddr};

use super::endpoint::guardian_pkarr_addr_filter;
use super::{IP2PConnector, IrohConnector, endpoint_id_stable_to_next, secret_key_stable_to_next};

#[test]
fn stable_identity_converts_to_same_iroh_v1_identity() {
    let stable_secret = SecretKey::from_bytes(&[42; 32]);
    let next_secret = secret_key_stable_to_next(&stable_secret);
    let next_id =
        endpoint_id_stable_to_next(stable_secret.public()).expect("generated public key is valid");

    assert_eq!(next_secret.to_bytes(), stable_secret.to_bytes());
    assert_eq!(next_secret.public(), next_id);
    assert_eq!(
        next_secret.public().to_string(),
        stable_secret.public().to_string()
    );
}

#[test]
fn pkarr_prefers_relay_but_keeps_direct_addresses_without_one() {
    let direct_a = TransportAddr::Ip(SocketAddr::from(([192, 0, 2, 1], 8173)));
    let direct_b = TransportAddr::Ip(SocketAddr::from(([0x2001, 0xdb8, 0, 0, 0, 0, 0, 1], 8173)));
    let relay = TransportAddr::Relay(
        "https://relay.example.com"
            .parse::<RelayUrl>()
            .expect("test relay URL is valid"),
    );
    let filter = guardian_pkarr_addr_filter();

    assert_eq!(
        filter
            .apply(&vec![direct_a.clone(), relay.clone(), direct_b.clone()])
            .as_ref(),
        &[relay]
    );
    assert_eq!(
        filter
            .apply(&vec![direct_a.clone(), direct_b.clone()])
            .as_ref(),
        &[direct_a, direct_b]
    );
    assert!(filter.apply(&Vec::new()).is_empty());
}

#[tokio::test]
async fn production_connectors_exchange_messages_over_direct_override() -> anyhow::Result<()> {
    let secret_a = SecretKey::from_bytes(&[1; 32]);
    let secret_b = SecretKey::from_bytes(&[2; 32]);
    let node_id_b = secret_b.public();
    let peer_a = PeerId::from(0);
    let peer_b = PeerId::from(1);
    let node_ids = BTreeMap::from([(peer_a, secret_a.public()), (peer_b, secret_b.public())]);
    let connector_a = IrohConnector::new_no_overrides(
        secret_a,
        SocketAddr::from(([127, 0, 0, 1], 0)),
        None,
        Vec::new(),
        node_ids.clone(),
    )
    .await?;
    let bind_addr = SocketAddr::from(([127, 0, 0, 1], 0));
    let connector_b =
        IrohConnector::new_no_overrides(secret_b, bind_addr, None, Vec::new(), node_ids).await?;
    let bound_sockets = connector_b.endpoint.bound_sockets();
    assert_eq!(bound_sockets.len(), 1);
    assert_eq!(bound_sockets[0].ip(), bind_addr.ip());
    assert_ne!(bound_sockets[0].port(), 0);
    let connector_a = connector_a.with_connection_override(
        node_id_b,
        NodeAddr::new(node_id_b).with_direct_addresses(bound_sockets),
    );

    let (outgoing, incoming) = tokio::try_join!(
        <IrohConnector as IP2PConnector<u64>>::connect(&connector_a, peer_b),
        <IrohConnector as IP2PConnector<u64>>::accept(&connector_b),
    )?;
    let (authenticated_peer, mut incoming) = incoming;
    let mut outgoing = outgoing;
    assert_eq!(authenticated_peer, peer_a);

    outgoing.send(42).await?;
    assert_eq!(incoming.receive().await?.read_to_end().await?, 42);
    assert_eq!(outgoing.connection_type(), Some(ConnectionType::Direct));

    Ok(())
}