//! Run an XMR/BTC swap in the role of Bob. //! Bob holds BTC and wishes receive XMR. pub use self::{amounts::*, message0::*, message1::*, message2::*, message3::*, state::*}; use anyhow::Result; use libp2p::{ core::{identity::Keypair, Multiaddr}, NetworkBehaviour, PeerId, }; use tracing::{debug, info}; use crate::{ bitcoin::EncryptedSignature, network::{ peer_tracker::{self, PeerTracker}, transport::SwapTransport, TokioExecutor, }, protocol::{alice, bob}, SwapAmounts, }; mod amounts; pub mod event_loop; mod message0; mod message1; mod message2; mod message3; pub mod state; pub mod swap; pub type Swarm = libp2p::Swarm; pub fn new_swarm(transport: SwapTransport, behaviour: Behaviour) -> Result { let local_peer_id = behaviour.peer_id(); let swarm = libp2p::swarm::SwarmBuilder::new(transport, behaviour, local_peer_id.clone()) .executor(Box::new(TokioExecutor { handle: tokio::runtime::Handle::current(), })) .build(); info!("Initialized swarm with identity {}", local_peer_id); Ok(swarm) } #[derive(Debug, Clone)] pub enum OutEvent { ConnectionEstablished(PeerId), Amounts(SwapAmounts), Message0(Box), Message1(Box), Message2(alice::Message2), Message3, } impl From for OutEvent { fn from(event: peer_tracker::OutEvent) -> Self { match event { peer_tracker::OutEvent::ConnectionEstablished(id) => { OutEvent::ConnectionEstablished(id) } } } } impl From for OutEvent { fn from(event: amounts::OutEvent) -> Self { match event { amounts::OutEvent::Amounts(amounts) => OutEvent::Amounts(amounts), } } } impl From for OutEvent { fn from(event: message0::OutEvent) -> Self { match event { message0::OutEvent::Msg(msg) => OutEvent::Message0(Box::new(msg)), } } } impl From for OutEvent { fn from(event: message1::OutEvent) -> Self { match event { message1::OutEvent::Msg(msg) => OutEvent::Message1(Box::new(msg)), } } } impl From for OutEvent { fn from(event: message2::OutEvent) -> Self { match event { message2::OutEvent::Msg(msg) => OutEvent::Message2(msg), } } } impl From for OutEvent { fn from(event: message3::OutEvent) -> Self { match event { message3::OutEvent::Msg => OutEvent::Message3, } } } /// A `NetworkBehaviour` that represents an XMR/BTC swap node as Bob. #[derive(NetworkBehaviour)] #[behaviour(out_event = "OutEvent", event_process = false)] #[allow(missing_debug_implementations)] pub struct Behaviour { pt: PeerTracker, amounts: Amounts, message0: Message0Behaviour, message1: Message1Behaviour, message2: Message2Behaviour, message3: Message3Behaviour, #[behaviour(ignore)] identity: Keypair, } impl Behaviour { pub fn identity(&self) -> Keypair { self.identity.clone() } pub fn peer_id(&self) -> PeerId { PeerId::from(self.identity.public()) } /// Sends a message to Alice to get current amounts based on `btc`. pub fn request_amounts(&mut self, alice: PeerId, btc: u64) { let btc = ::bitcoin::Amount::from_sat(btc); let _id = self.amounts.request_amounts(alice.clone(), btc); info!("Requesting amounts from: {}", alice); } /// Sends Bob's first message to Alice. pub fn send_message0(&mut self, alice: PeerId, msg: bob::Message0) { self.message0.send(alice, msg); debug!("Sent Message0"); } /// Sends Bob's second message to Alice. pub fn send_message1(&mut self, alice: PeerId, msg: bob::Message1) { self.message1.send(alice, msg); debug!("Sent Message1"); } /// Sends Bob's third message to Alice. pub fn send_message2(&mut self, alice: PeerId, msg: bob::Message2) { self.message2.send(alice, msg); debug!("Sent Message2"); } /// Sends Bob's fourth message to Alice. pub fn send_message3(&mut self, alice: PeerId, tx_redeem_encsig: EncryptedSignature) { let msg = bob::Message3 { tx_redeem_encsig }; self.message3.send(alice, msg); debug!("Sent Message3"); } /// Add a known address for the given peer pub fn add_address(&mut self, peer_id: PeerId, address: Multiaddr) { self.pt.add_address(peer_id, address) } } impl Default for Behaviour { fn default() -> Behaviour { let identity = Keypair::generate_ed25519(); Self { pt: PeerTracker::default(), amounts: Amounts::default(), message0: Message0Behaviour::default(), message1: Message1Behaviour::default(), message2: Message2Behaviour::default(), message3: Message3Behaviour::default(), identity, } } }