142: Rename Swap amounts to Swap req/res r=D4nte a=D4nte

As per #140

Question: Do we prefer `Negotiation Request/Response` to `Swap Request/Response`?

Co-authored-by: Franck Royer <franck@coblox.tech>
This commit is contained in:
bors[bot] 2021-01-21 02:18:26 +00:00 committed by GitHub
commit fbfc17c489
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
14 changed files with 192 additions and 179 deletions

View File

@ -1,6 +1,3 @@
use ::bitcoin::hashes::core::fmt::Display;
use serde::{Deserialize, Serialize};
use crate::{ use crate::{
bitcoin::{EncryptedSignature, TxCancel, TxRefund}, bitcoin::{EncryptedSignature, TxCancel, TxRefund},
monero, monero,
@ -8,6 +5,8 @@ use crate::{
protocol::{alice, alice::AliceState}, protocol::{alice, alice::AliceState},
SwapAmounts, SwapAmounts,
}; };
use ::bitcoin::hashes::core::fmt::Display;
use serde::{Deserialize, Serialize};
// Large enum variant is fine because this is only used for database // Large enum variant is fine because this is only used for database
// and is dropped once written in DB. // and is dropped once written in DB.

View File

@ -1,10 +1,9 @@
use ::bitcoin::hashes::core::fmt::Display;
use serde::{Deserialize, Serialize};
use crate::{ use crate::{
protocol::{bob, bob::BobState}, protocol::{bob, bob::BobState},
SwapAmounts, SwapAmounts,
}; };
use ::bitcoin::hashes::core::fmt::Display;
use serde::{Deserialize, Serialize};
#[derive(Clone, Debug, Deserialize, Serialize, PartialEq)] #[derive(Clone, Debug, Deserialize, Serialize, PartialEq)]
pub enum Bob { pub enum Bob {

View File

@ -31,19 +31,6 @@ pub mod trace;
pub type Never = std::convert::Infallible; pub type Never = std::convert::Infallible;
/// Commands sent from Bob to the main task.
#[derive(Clone, Copy, Debug)]
pub enum Cmd {
VerifyAmounts(SwapAmounts),
}
/// Responses sent from the main task back to Bob.
#[derive(Clone, Copy, Debug, PartialEq)]
pub enum Rsp {
VerifiedAmounts,
Abort,
}
/// XMR/BTC swap amounts. /// XMR/BTC swap amounts.
#[derive(Copy, Clone, Debug, Serialize, Deserialize, PartialEq)] #[derive(Copy, Clone, Debug, Serialize, Deserialize, PartialEq)]
// TODO(Franck): review necessity of this struct // TODO(Franck): review necessity of this struct

View File

@ -8,10 +8,7 @@ use serde::{Deserialize, Serialize};
use std::{fmt::Debug, io, marker::PhantomData}; use std::{fmt::Debug, io, marker::PhantomData};
use tracing::debug; use tracing::debug;
use crate::{ use crate::protocol::{alice, bob};
protocol::{alice, bob},
SwapAmounts,
};
/// Time to wait for a response back once we send a request. /// Time to wait for a response back once we send a request.
pub const TIMEOUT: u64 = 3600; // One hour. pub const TIMEOUT: u64 = 3600; // One hour.
@ -25,8 +22,7 @@ const BUF_SIZE: usize = 1024 * 1024;
/// Messages Bob sends to Alice. /// Messages Bob sends to Alice.
#[derive(Clone, Debug, Serialize, Deserialize)] #[derive(Clone, Debug, Serialize, Deserialize)]
pub enum BobToAlice { pub enum BobToAlice {
#[serde(with = "::bitcoin::util::amount::serde::as_sat")] SwapRequest(bob::SwapRequest),
AmountsFromBtc(::bitcoin::Amount),
Message0(Box<bob::Message0>), Message0(Box<bob::Message0>),
Message1(bob::Message1), Message1(bob::Message1),
Message2(bob::Message2), Message2(bob::Message2),
@ -36,7 +32,7 @@ pub enum BobToAlice {
/// Messages Alice sends to Bob. /// Messages Alice sends to Bob.
#[derive(Clone, Debug, Serialize, Deserialize)] #[derive(Clone, Debug, Serialize, Deserialize)]
pub enum AliceToBob { pub enum AliceToBob {
Amounts(SwapAmounts), SwapResponse(alice::SwapResponse),
Message0(Box<alice::Message0>), Message0(Box<alice::Message0>),
Message1(Box<alice::Message1>), Message1(Box<alice::Message1>),
Message2(alice::Message2), Message2(alice::Message2),
@ -44,7 +40,7 @@ pub enum AliceToBob {
} }
#[derive(Debug, Clone, Copy, Default)] #[derive(Debug, Clone, Copy, Default)]
pub struct AmountsProtocol; pub struct Swap;
#[derive(Debug, Clone, Copy, Default)] #[derive(Debug, Clone, Copy, Default)]
pub struct Message0Protocol; pub struct Message0Protocol;
@ -58,9 +54,9 @@ pub struct Message2Protocol;
#[derive(Debug, Clone, Copy, Default)] #[derive(Debug, Clone, Copy, Default)]
pub struct Message3Protocol; pub struct Message3Protocol;
impl ProtocolName for AmountsProtocol { impl ProtocolName for Swap {
fn protocol_name(&self) -> &[u8] { fn protocol_name(&self) -> &[u8] {
b"/xmr/btc/amounts/1.0.0" b"/xmr/btc/swap/1.0.0"
} }
} }

View File

@ -1,36 +1,40 @@
//! Run an XMR/BTC swap in the role of Alice. //! Run an XMR/BTC swap in the role of Alice.
//! Alice holds XMR and wishes receive BTC. //! Alice holds XMR and wishes receive BTC.
use anyhow::{bail, Result};
use libp2p::{request_response::ResponseChannel, NetworkBehaviour, PeerId};
use tracing::{debug, info};
use crate::{ use crate::{
bitcoin, database, monero, bitcoin,
config::Config,
database,
database::Database,
monero,
network::{ network::{
peer_tracker::{self, PeerTracker}, peer_tracker::{self, PeerTracker},
request_response::AliceToBob, request_response::AliceToBob,
transport::build,
Seed as NetworkSeed, Seed as NetworkSeed,
}, },
protocol::bob, protocol::bob,
seed::Seed,
SwapAmounts, SwapAmounts,
}; };
use anyhow::{bail, Result};
use libp2p::{
core::Multiaddr, identity::Keypair, request_response::ResponseChannel, NetworkBehaviour, PeerId,
};
use rand::rngs::OsRng;
use std::{path::PathBuf, sync::Arc};
use tracing::{debug, info};
use uuid::Uuid;
pub use self::{ pub use self::{
amounts::*,
event_loop::{EventLoop, EventLoopHandle}, event_loop::{EventLoop, EventLoopHandle},
message0::Message0, message0::Message0,
message1::Message1, message1::Message1,
message2::Message2, message2::Message2,
state::*, state::*,
swap::{run, run_until}, swap::{run, run_until},
swap_response::*,
}; };
use crate::{config::Config, database::Database, network::transport::build, seed::Seed};
use libp2p::{core::Multiaddr, identity::Keypair};
use rand::rngs::OsRng;
use std::{path::PathBuf, sync::Arc};
use uuid::Uuid;
mod amounts;
pub mod event_loop; pub mod event_loop;
mod message0; mod message0;
mod message1; mod message1;
@ -39,6 +43,7 @@ mod message3;
pub mod state; pub mod state;
mod steps; mod steps;
pub mod swap; pub mod swap;
mod swap_response;
pub struct Swap { pub struct Swap {
pub state: AliceState, pub state: AliceState,
@ -217,8 +222,9 @@ pub enum OutEvent {
ConnectionEstablished(PeerId), ConnectionEstablished(PeerId),
// TODO (Franck): Change this to get both amounts so parties can verify the amounts are // TODO (Franck): Change this to get both amounts so parties can verify the amounts are
// expected early on. // expected early on.
Request(Box<amounts::OutEvent>), /* Not-uniform with Bob on purpose, ready for adding Xmr Request(Box<swap_response::OutEvent>), /* Not-uniform with Bob on purpose, ready for adding
* event. */ * Xmr
* event. */
Message0 { Message0 {
msg: Box<bob::Message0>, msg: Box<bob::Message0>,
channel: ResponseChannel<AliceToBob>, channel: ResponseChannel<AliceToBob>,
@ -244,8 +250,8 @@ impl From<peer_tracker::OutEvent> for OutEvent {
} }
} }
impl From<amounts::OutEvent> for OutEvent { impl From<swap_response::OutEvent> for OutEvent {
fn from(event: amounts::OutEvent) -> Self { fn from(event: swap_response::OutEvent) -> Self {
OutEvent::Request(Box::new(event)) OutEvent::Request(Box::new(event))
} }
} }
@ -291,7 +297,7 @@ impl From<message3::OutEvent> for OutEvent {
#[allow(missing_debug_implementations)] #[allow(missing_debug_implementations)]
pub struct Behaviour { pub struct Behaviour {
pt: PeerTracker, pt: PeerTracker,
amounts: Amounts, amounts: swap_response::Behaviour,
message0: message0::Behaviour, message0: message0::Behaviour,
message1: message1::Behaviour, message1: message1::Behaviour,
message2: message2::Behaviour, message2: message2::Behaviour,
@ -300,9 +306,12 @@ pub struct Behaviour {
impl Behaviour { impl Behaviour {
/// Alice always sends her messages as a response to a request from Bob. /// Alice always sends her messages as a response to a request from Bob.
pub fn send_amounts(&mut self, channel: ResponseChannel<AliceToBob>, amounts: SwapAmounts) { pub fn send_swap_response(
let msg = AliceToBob::Amounts(amounts); &mut self,
self.amounts.send(channel, msg); channel: ResponseChannel<AliceToBob>,
swap_response: SwapResponse,
) {
self.amounts.send(channel, swap_response);
info!("Sent amounts response"); info!("Sent amounts response");
} }

View File

@ -9,10 +9,9 @@ use crate::{
network::{request_response::AliceToBob, transport::SwapTransport, TokioExecutor}, network::{request_response::AliceToBob, transport::SwapTransport, TokioExecutor},
protocol::{ protocol::{
alice, alice,
alice::{Behaviour, OutEvent}, alice::{Behaviour, OutEvent, SwapResponse},
bob, bob,
}, },
SwapAmounts,
}; };
#[allow(missing_debug_implementations)] #[allow(missing_debug_implementations)]
@ -40,9 +39,9 @@ pub struct EventLoopHandle {
msg1: Receiver<(bob::Message1, ResponseChannel<AliceToBob>)>, msg1: Receiver<(bob::Message1, ResponseChannel<AliceToBob>)>,
msg2: Receiver<(bob::Message2, ResponseChannel<AliceToBob>)>, msg2: Receiver<(bob::Message2, ResponseChannel<AliceToBob>)>,
msg3: Receiver<bob::Message3>, msg3: Receiver<bob::Message3>,
request: Receiver<crate::protocol::alice::amounts::OutEvent>, request: Receiver<crate::protocol::alice::swap_response::OutEvent>,
conn_established: Receiver<PeerId>, conn_established: Receiver<PeerId>,
send_amounts: Sender<(ResponseChannel<AliceToBob>, SwapAmounts)>, send_swap_response: Sender<(ResponseChannel<AliceToBob>, SwapResponse)>,
send_msg0: Sender<(ResponseChannel<AliceToBob>, alice::Message0)>, send_msg0: Sender<(ResponseChannel<AliceToBob>, alice::Message0)>,
send_msg1: Sender<(ResponseChannel<AliceToBob>, alice::Message1)>, send_msg1: Sender<(ResponseChannel<AliceToBob>, alice::Message1)>,
send_msg2: Sender<(ResponseChannel<AliceToBob>, alice::Message2)>, send_msg2: Sender<(ResponseChannel<AliceToBob>, alice::Message2)>,
@ -84,19 +83,24 @@ impl EventLoopHandle {
.ok_or_else(|| anyhow!("Failed to receive Bitcoin encrypted signature from Bob")) .ok_or_else(|| anyhow!("Failed to receive Bitcoin encrypted signature from Bob"))
} }
pub async fn recv_request(&mut self) -> Result<crate::protocol::alice::amounts::OutEvent> { pub async fn recv_request(
&mut self,
) -> Result<crate::protocol::alice::swap_response::OutEvent> {
self.request self.request
.recv() .recv()
.await .await
.ok_or_else(|| anyhow!("Failed to receive amounts request from Bob")) .ok_or_else(|| anyhow!("Failed to receive amounts request from Bob"))
} }
pub async fn send_amounts( pub async fn send_swap_response(
&mut self, &mut self,
channel: ResponseChannel<AliceToBob>, channel: ResponseChannel<AliceToBob>,
amounts: SwapAmounts, swap_response: SwapResponse,
) -> Result<()> { ) -> Result<()> {
let _ = self.send_amounts.send((channel, amounts)).await?; let _ = self
.send_swap_response
.send((channel, swap_response))
.await?;
Ok(()) Ok(())
} }
@ -135,9 +139,9 @@ pub struct EventLoop {
msg1: Sender<(bob::Message1, ResponseChannel<AliceToBob>)>, msg1: Sender<(bob::Message1, ResponseChannel<AliceToBob>)>,
msg2: Sender<(bob::Message2, ResponseChannel<AliceToBob>)>, msg2: Sender<(bob::Message2, ResponseChannel<AliceToBob>)>,
msg3: Sender<bob::Message3>, msg3: Sender<bob::Message3>,
request: Sender<crate::protocol::alice::amounts::OutEvent>, request: Sender<crate::protocol::alice::swap_response::OutEvent>,
conn_established: Sender<PeerId>, conn_established: Sender<PeerId>,
send_amounts: Receiver<(ResponseChannel<AliceToBob>, SwapAmounts)>, send_swap_response: Receiver<(ResponseChannel<AliceToBob>, SwapResponse)>,
send_msg0: Receiver<(ResponseChannel<AliceToBob>, alice::Message0)>, send_msg0: Receiver<(ResponseChannel<AliceToBob>, alice::Message0)>,
send_msg1: Receiver<(ResponseChannel<AliceToBob>, alice::Message1)>, send_msg1: Receiver<(ResponseChannel<AliceToBob>, alice::Message1)>,
send_msg2: Receiver<(ResponseChannel<AliceToBob>, alice::Message2)>, send_msg2: Receiver<(ResponseChannel<AliceToBob>, alice::Message2)>,
@ -165,7 +169,7 @@ impl EventLoop {
let msg3 = Channels::new(); let msg3 = Channels::new();
let request = Channels::new(); let request = Channels::new();
let conn_established = Channels::new(); let conn_established = Channels::new();
let send_amounts = Channels::new(); let send_swap_response = Channels::new();
let send_msg0 = Channels::new(); let send_msg0 = Channels::new();
let send_msg1 = Channels::new(); let send_msg1 = Channels::new();
let send_msg2 = Channels::new(); let send_msg2 = Channels::new();
@ -178,7 +182,7 @@ impl EventLoop {
msg3: msg3.sender, msg3: msg3.sender,
request: request.sender, request: request.sender,
conn_established: conn_established.sender, conn_established: conn_established.sender,
send_amounts: send_amounts.receiver, send_swap_response: send_swap_response.receiver,
send_msg0: send_msg0.receiver, send_msg0: send_msg0.receiver,
send_msg1: send_msg1.receiver, send_msg1: send_msg1.receiver,
send_msg2: send_msg2.receiver, send_msg2: send_msg2.receiver,
@ -191,7 +195,7 @@ impl EventLoop {
msg3: msg3.receiver, msg3: msg3.receiver,
request: request.receiver, request: request.receiver,
conn_established: conn_established.receiver, conn_established: conn_established.receiver,
send_amounts: send_amounts.sender, send_swap_response: send_swap_response.sender,
send_msg0: send_msg0.sender, send_msg0: send_msg0.sender,
send_msg1: send_msg1.sender, send_msg1: send_msg1.sender,
send_msg2: send_msg2.sender, send_msg2: send_msg2.sender,
@ -225,9 +229,9 @@ impl EventLoop {
} }
} }
}, },
amounts = self.send_amounts.next().fuse() => { swap_response = self.send_swap_response.next().fuse() => {
if let Some((channel, amounts)) = amounts { if let Some((channel, swap_response)) = swap_response {
self.swarm.send_amounts(channel, amounts); self.swarm.send_swap_response(channel, swap_response);
} }
}, },
msg0 = self.send_msg0.next().fuse() => { msg0 = self.send_msg0.next().fuse() => {

View File

@ -268,7 +268,6 @@ impl State2 {
S_b_monero: self.S_b_monero, S_b_monero: self.S_b_monero,
S_b_bitcoin: self.S_b_bitcoin, S_b_bitcoin: self.S_b_bitcoin,
v: self.v, v: self.v,
// TODO(Franck): Review if these amounts are actually needed
btc: self.btc, btc: self.btc,
xmr: self.xmr, xmr: self.xmr,
cancel_timelock: self.cancel_timelock, cancel_timelock: self.cancel_timelock,
@ -323,7 +322,6 @@ impl State3 {
S_b_monero: self.S_b_monero, S_b_monero: self.S_b_monero,
S_b_bitcoin: self.S_b_bitcoin, S_b_bitcoin: self.S_b_bitcoin,
v: self.v, v: self.v,
btc: self.btc,
xmr: self.xmr, xmr: self.xmr,
cancel_timelock: self.cancel_timelock, cancel_timelock: self.cancel_timelock,
punish_timelock: self.punish_timelock, punish_timelock: self.punish_timelock,
@ -370,8 +368,6 @@ pub struct State4 {
S_b_monero: monero::PublicKey, S_b_monero: monero::PublicKey,
S_b_bitcoin: bitcoin::PublicKey, S_b_bitcoin: bitcoin::PublicKey,
v: monero::PrivateViewKey, v: monero::PrivateViewKey,
#[serde(with = "::bitcoin::util::amount::serde::as_sat")]
btc: bitcoin::Amount,
xmr: monero::Amount, xmr: monero::Amount,
cancel_timelock: Timelock, cancel_timelock: Timelock,
punish_timelock: Timelock, punish_timelock: Timelock,
@ -404,8 +400,6 @@ impl State4 {
S_b_monero: self.S_b_monero, S_b_monero: self.S_b_monero,
S_b_bitcoin: self.S_b_bitcoin, S_b_bitcoin: self.S_b_bitcoin,
v: self.v, v: self.v,
btc: self.btc,
xmr: self.xmr,
cancel_timelock: self.cancel_timelock, cancel_timelock: self.cancel_timelock,
punish_timelock: self.punish_timelock, punish_timelock: self.punish_timelock,
refund_address: self.refund_address, refund_address: self.refund_address,
@ -467,9 +461,6 @@ pub struct State5 {
S_b_monero: monero::PublicKey, S_b_monero: monero::PublicKey,
S_b_bitcoin: bitcoin::PublicKey, S_b_bitcoin: bitcoin::PublicKey,
v: monero::PrivateViewKey, v: monero::PrivateViewKey,
#[serde(with = "::bitcoin::util::amount::serde::as_sat")]
btc: bitcoin::Amount,
xmr: monero::Amount,
cancel_timelock: Timelock, cancel_timelock: Timelock,
punish_timelock: Timelock, punish_timelock: Timelock,
refund_address: bitcoin::Address, refund_address: bitcoin::Address,
@ -499,8 +490,6 @@ impl State5 {
S_b_monero: self.S_b_monero, S_b_monero: self.S_b_monero,
S_b_bitcoin: self.S_b_bitcoin, S_b_bitcoin: self.S_b_bitcoin,
v: self.v, v: self.v,
btc: self.btc,
xmr: self.xmr,
cancel_timelock: self.cancel_timelock, cancel_timelock: self.cancel_timelock,
punish_timelock: self.punish_timelock, punish_timelock: self.punish_timelock,
refund_address: self.refund_address, refund_address: self.refund_address,
@ -557,9 +546,6 @@ pub struct State6 {
S_b_monero: monero::PublicKey, S_b_monero: monero::PublicKey,
S_b_bitcoin: bitcoin::PublicKey, S_b_bitcoin: bitcoin::PublicKey,
v: monero::PrivateViewKey, v: monero::PrivateViewKey,
#[serde(with = "::bitcoin::util::amount::serde::as_sat")]
btc: bitcoin::Amount,
xmr: monero::Amount,
cancel_timelock: Timelock, cancel_timelock: Timelock,
punish_timelock: Timelock, punish_timelock: Timelock,
refund_address: bitcoin::Address, refund_address: bitcoin::Address,

View File

@ -1,4 +1,4 @@
use anyhow::{bail, Context, Result}; use anyhow::{Context, Result};
use ecdsa_fun::{adaptor::Adaptor, nonce::Deterministic}; use ecdsa_fun::{adaptor::Adaptor, nonce::Deterministic};
use futures::{ use futures::{
future::{select, Either}, future::{select, Either},
@ -24,13 +24,16 @@ use crate::{
monero, monero,
monero::Transfer, monero::Transfer,
network::request_response::AliceToBob, network::request_response::AliceToBob,
protocol::{alice, alice::event_loop::EventLoopHandle}, protocol::{
alice,
alice::{event_loop::EventLoopHandle, SwapResponse},
},
SwapAmounts, SwapAmounts,
}; };
pub async fn negotiate( pub async fn negotiate(
state0: alice::State0, state0: alice::State0,
amounts: SwapAmounts, xmr_amount: monero::Amount,
event_loop_handle: &mut EventLoopHandle, event_loop_handle: &mut EventLoopHandle,
config: Config, config: Config,
) -> Result<(ResponseChannel<AliceToBob>, alice::State3)> { ) -> Result<(ResponseChannel<AliceToBob>, alice::State3)> {
@ -46,18 +49,10 @@ pub async fn negotiate(
let event = timeout(config.bob_time_to_act, event_loop_handle.recv_request()) let event = timeout(config.bob_time_to_act, event_loop_handle.recv_request())
.await .await
.context("Failed to receive amounts from Bob")??; .context("Failed to receive swap request from Bob")??;
if event.btc != amounts.btc {
bail!(
"Bob proposed a different amount; got {}, expected: {}",
event.btc,
amounts.btc
);
}
event_loop_handle event_loop_handle
.send_amounts(event.channel, amounts) .send_swap_response(event.channel, SwapResponse { xmr_amount })
.await?; .await?;
let (bob_message0, channel) = let (bob_message0, channel) =

View File

@ -105,7 +105,7 @@ async fn run_until_internal(
match state { match state {
AliceState::Started { amounts, state0 } => { AliceState::Started { amounts, state0 } => {
let (channel, state3) = let (channel, state3) =
negotiate(state0, amounts, &mut event_loop_handle, config).await?; negotiate(state0, amounts.xmr, &mut event_loop_handle, config).await?;
let state = AliceState::Negotiated { let state = AliceState::Negotiated {
channel: Some(channel), channel: Some(channel),

View File

@ -6,6 +6,7 @@ use libp2p::{
swarm::{NetworkBehaviourAction, NetworkBehaviourEventProcess, PollParameters}, swarm::{NetworkBehaviourAction, NetworkBehaviourEventProcess, PollParameters},
NetworkBehaviour, NetworkBehaviour,
}; };
use serde::{Deserialize, Serialize};
use std::{ use std::{
collections::VecDeque, collections::VecDeque,
task::{Context, Poll}, task::{Context, Poll},
@ -14,29 +15,37 @@ use std::{
use tracing::{debug, error}; use tracing::{debug, error};
use crate::{ use crate::{
network::request_response::{AliceToBob, AmountsProtocol, BobToAlice, Codec, TIMEOUT}, monero,
protocol::alice::amounts, network::request_response::{AliceToBob, BobToAlice, Codec, Swap, TIMEOUT},
protocol::bob,
}; };
#[derive(Debug)] #[derive(Debug)]
pub struct OutEvent { pub struct OutEvent {
pub btc: ::bitcoin::Amount, pub msg: bob::SwapRequest,
pub channel: ResponseChannel<AliceToBob>, pub channel: ResponseChannel<AliceToBob>,
} }
/// A `NetworkBehaviour` that represents getting the amounts of an XMR/BTC swap. #[derive(Copy, Clone, Debug, Serialize, Deserialize)]
pub struct SwapResponse {
pub xmr_amount: monero::Amount,
}
/// A `NetworkBehaviour` that represents negotiate a swap using Swap
/// request/response.
#[derive(NetworkBehaviour)] #[derive(NetworkBehaviour)]
#[behaviour(out_event = "OutEvent", poll_method = "poll")] #[behaviour(out_event = "OutEvent", poll_method = "poll")]
#[allow(missing_debug_implementations)] #[allow(missing_debug_implementations)]
pub struct Amounts { pub struct Behaviour {
rr: RequestResponse<Codec<AmountsProtocol>>, rr: RequestResponse<Codec<Swap>>,
#[behaviour(ignore)] #[behaviour(ignore)]
events: VecDeque<OutEvent>, events: VecDeque<OutEvent>,
} }
impl Amounts { impl Behaviour {
/// Alice always sends her messages as a response to a request from Bob. /// Alice always sends her messages as a response to a request from Bob.
pub fn send(&mut self, channel: ResponseChannel<AliceToBob>, msg: AliceToBob) { pub fn send(&mut self, channel: ResponseChannel<AliceToBob>, msg: SwapResponse) {
let msg = AliceToBob::SwapResponse(msg);
self.rr.send_response(channel, msg); self.rr.send_response(channel, msg);
} }
@ -44,7 +53,7 @@ impl Amounts {
&mut self, &mut self,
_: &mut Context<'_>, _: &mut Context<'_>,
_: &mut impl PollParameters, _: &mut impl PollParameters,
) -> Poll<NetworkBehaviourAction<RequestProtocol<Codec<AmountsProtocol>>, OutEvent>> { ) -> Poll<NetworkBehaviourAction<RequestProtocol<Codec<Swap>>, OutEvent>> {
if let Some(event) = self.events.pop_front() { if let Some(event) = self.events.pop_front() {
return Poll::Ready(NetworkBehaviourAction::GenerateEvent(event)); return Poll::Ready(NetworkBehaviourAction::GenerateEvent(event));
} }
@ -53,7 +62,7 @@ impl Amounts {
} }
} }
impl Default for Amounts { impl Default for Behaviour {
fn default() -> Self { fn default() -> Self {
let timeout = Duration::from_secs(TIMEOUT); let timeout = Duration::from_secs(TIMEOUT);
@ -63,7 +72,7 @@ impl Default for Amounts {
Self { Self {
rr: RequestResponse::new( rr: RequestResponse::new(
Codec::default(), Codec::default(),
vec![(AmountsProtocol, ProtocolSupport::Full)], vec![(Swap, ProtocolSupport::Full)],
config, config,
), ),
events: Default::default(), events: Default::default(),
@ -71,7 +80,7 @@ impl Default for Amounts {
} }
} }
impl NetworkBehaviourEventProcess<RequestResponseEvent<BobToAlice, AliceToBob>> for Amounts { impl NetworkBehaviourEventProcess<RequestResponseEvent<BobToAlice, AliceToBob>> for Behaviour {
fn inject_event(&mut self, event: RequestResponseEvent<BobToAlice, AliceToBob>) { fn inject_event(&mut self, event: RequestResponseEvent<BobToAlice, AliceToBob>) {
match event { match event {
RequestResponseEvent::Message { RequestResponseEvent::Message {
@ -81,9 +90,9 @@ impl NetworkBehaviourEventProcess<RequestResponseEvent<BobToAlice, AliceToBob>>
}, },
.. ..
} => { } => {
if let BobToAlice::AmountsFromBtc(btc) = request { if let BobToAlice::SwapRequest(msg) = request {
debug!("Received amounts request"); debug!("Received swap request");
self.events.push_back(amounts::OutEvent { btc, channel }) self.events.push_back(OutEvent { msg, channel })
} }
} }
RequestResponseEvent::Message { RequestResponseEvent::Message {

View File

@ -1,20 +1,28 @@
//! Run an XMR/BTC swap in the role of Bob. //! Run an XMR/BTC swap in the role of Bob.
//! Bob holds BTC and wishes receive XMR. //! Bob holds BTC and wishes receive XMR.
use anyhow::{bail, Result};
use libp2p::{core::Multiaddr, NetworkBehaviour, PeerId};
use tracing::{debug, info};
use crate::{ use crate::{
bitcoin, bitcoin,
bitcoin::EncryptedSignature, bitcoin::EncryptedSignature,
database, monero, network, config::Config,
network::peer_tracker::{self, PeerTracker}, database,
database::Database,
monero, network,
network::{
peer_tracker::{self, PeerTracker},
transport::build,
},
protocol::{alice, bob}, protocol::{alice, bob},
seed::Seed,
SwapAmounts, SwapAmounts,
}; };
use anyhow::{bail, Result};
use libp2p::{core::Multiaddr, identity::Keypair, NetworkBehaviour, PeerId};
use rand::rngs::OsRng;
use std::{path::PathBuf, sync::Arc};
use tracing::{debug, info};
use uuid::Uuid;
pub use self::{ pub use self::{
amounts::*,
event_loop::{EventLoop, EventLoopHandle}, event_loop::{EventLoop, EventLoopHandle},
message0::Message0, message0::Message0,
message1::Message1, message1::Message1,
@ -22,14 +30,9 @@ pub use self::{
message3::Message3, message3::Message3,
state::*, state::*,
swap::{run, run_until}, swap::{run, run_until},
swap_request::*,
}; };
use crate::{config::Config, database::Database, network::transport::build, seed::Seed};
use libp2p::identity::Keypair;
use rand::rngs::OsRng;
use std::{path::PathBuf, sync::Arc};
use uuid::Uuid;
mod amounts;
pub mod event_loop; pub mod event_loop;
mod message0; mod message0;
mod message1; mod message1;
@ -37,6 +40,7 @@ mod message2;
mod message3; mod message3;
pub mod state; pub mod state;
pub mod swap; pub mod swap;
mod swap_request;
pub struct Swap { pub struct Swap {
pub state: BobState, pub state: BobState,
@ -204,7 +208,7 @@ impl Builder {
#[derive(Debug, Clone)] #[derive(Debug, Clone)]
pub enum OutEvent { pub enum OutEvent {
ConnectionEstablished(PeerId), ConnectionEstablished(PeerId),
Amounts(SwapAmounts), SwapResponse(alice::SwapResponse),
Message0(Box<alice::Message0>), Message0(Box<alice::Message0>),
Message1(Box<alice::Message1>), Message1(Box<alice::Message1>),
Message2(alice::Message2), Message2(alice::Message2),
@ -221,11 +225,9 @@ impl From<peer_tracker::OutEvent> for OutEvent {
} }
} }
impl From<amounts::OutEvent> for OutEvent { impl From<swap_request::OutEvent> for OutEvent {
fn from(event: amounts::OutEvent) -> Self { fn from(event: swap_request::OutEvent) -> Self {
match event { OutEvent::SwapResponse(event.swap_response)
amounts::OutEvent::Amounts(amounts) => OutEvent::Amounts(amounts),
}
} }
} }
@ -267,7 +269,7 @@ impl From<message3::OutEvent> for OutEvent {
#[allow(missing_debug_implementations)] #[allow(missing_debug_implementations)]
pub struct Behaviour { pub struct Behaviour {
pt: PeerTracker, pt: PeerTracker,
amounts: Amounts, swap_request: swap_request::Behaviour,
message0: message0::Behaviour, message0: message0::Behaviour,
message1: message1::Behaviour, message1: message1::Behaviour,
message2: message2::Behaviour, message2: message2::Behaviour,
@ -275,11 +277,10 @@ pub struct Behaviour {
} }
impl Behaviour { impl Behaviour {
/// Sends a message to Alice to get current amounts based on `btc`. /// Sends a swap request to Alice to negotiate the swap.
pub fn request_amounts(&mut self, alice: PeerId, btc: u64) { pub fn send_swap_request(&mut self, alice: PeerId, swap_request: SwapRequest) {
let btc = ::bitcoin::Amount::from_sat(btc); let _id = self.swap_request.send(alice.clone(), swap_request);
let _id = self.amounts.request_amounts(alice.clone(), btc); info!("Requesting swap from: {}", alice);
info!("Requesting amounts from: {}", alice);
} }
/// Sends Bob's first message to Alice. /// Sends Bob's first message to Alice.

View File

@ -1,3 +1,12 @@
use crate::{
bitcoin::EncryptedSignature,
network::{transport::SwapTransport, TokioExecutor},
protocol::{
alice,
alice::SwapResponse,
bob::{self, Behaviour, OutEvent, SwapRequest},
},
};
use anyhow::{anyhow, Result}; use anyhow::{anyhow, Result};
use futures::FutureExt; use futures::FutureExt;
use libp2p::{core::Multiaddr, PeerId}; use libp2p::{core::Multiaddr, PeerId};
@ -7,15 +16,6 @@ use tokio::{
}; };
use tracing::{debug, error, info}; use tracing::{debug, error, info};
use crate::{
bitcoin::EncryptedSignature,
network::{transport::SwapTransport, TokioExecutor},
protocol::{
alice,
bob::{self, Behaviour, OutEvent},
},
};
#[derive(Debug)] #[derive(Debug)]
pub struct Channels<T> { pub struct Channels<T> {
sender: Sender<T>, sender: Sender<T>,
@ -37,12 +37,13 @@ impl<T> Default for Channels<T> {
#[derive(Debug)] #[derive(Debug)]
pub struct EventLoopHandle { pub struct EventLoopHandle {
swap_response: Receiver<SwapResponse>,
msg0: Receiver<alice::Message0>, msg0: Receiver<alice::Message0>,
msg1: Receiver<alice::Message1>, msg1: Receiver<alice::Message1>,
msg2: Receiver<alice::Message2>, msg2: Receiver<alice::Message2>,
request_amounts: Sender<::bitcoin::Amount>,
conn_established: Receiver<PeerId>, conn_established: Receiver<PeerId>,
dial_alice: Sender<()>, dial_alice: Sender<()>,
send_swap_request: Sender<SwapRequest>,
send_msg0: Sender<bob::Message0>, send_msg0: Sender<bob::Message0>,
send_msg1: Sender<bob::Message1>, send_msg1: Sender<bob::Message1>,
send_msg2: Sender<bob::Message2>, send_msg2: Sender<bob::Message2>,
@ -50,25 +51,32 @@ pub struct EventLoopHandle {
} }
impl EventLoopHandle { impl EventLoopHandle {
pub async fn recv_swap_response(&mut self) -> Result<SwapResponse> {
self.swap_response
.recv()
.await
.ok_or_else(|| anyhow!("Failed to receive swap response from Alice"))
}
pub async fn recv_message0(&mut self) -> Result<alice::Message0> { pub async fn recv_message0(&mut self) -> Result<alice::Message0> {
self.msg0 self.msg0
.recv() .recv()
.await .await
.ok_or_else(|| anyhow!("Failed to receive message 0 from Bob")) .ok_or_else(|| anyhow!("Failed to receive message 0 from Alice"))
} }
pub async fn recv_message1(&mut self) -> Result<alice::Message1> { pub async fn recv_message1(&mut self) -> Result<alice::Message1> {
self.msg1 self.msg1
.recv() .recv()
.await .await
.ok_or_else(|| anyhow!("Failed to receive message 1 from Bob")) .ok_or_else(|| anyhow!("Failed to receive message 1 from Alice"))
} }
pub async fn recv_message2(&mut self) -> Result<alice::Message2> { pub async fn recv_message2(&mut self) -> Result<alice::Message2> {
self.msg2 self.msg2
.recv() .recv()
.await .await
.ok_or_else(|| anyhow!("Failed o receive message 2 from Bob")) .ok_or_else(|| anyhow!("Failed o receive message 2 from Alice"))
} }
/// Dials other party and wait for the connection to be established. /// Dials other party and wait for the connection to be established.
@ -85,8 +93,8 @@ impl EventLoopHandle {
Ok(()) Ok(())
} }
pub async fn request_amounts(&mut self, btc_amount: ::bitcoin::Amount) -> Result<()> { pub async fn send_swap_request(&mut self, swap_request: SwapRequest) -> Result<()> {
let _ = self.request_amounts.send(btc_amount).await?; let _ = self.send_swap_request.send(swap_request).await?;
Ok(()) Ok(())
} }
@ -115,12 +123,13 @@ impl EventLoopHandle {
pub struct EventLoop { pub struct EventLoop {
swarm: libp2p::Swarm<Behaviour>, swarm: libp2p::Swarm<Behaviour>,
alice_peer_id: PeerId, alice_peer_id: PeerId,
swap_response: Sender<SwapResponse>,
msg0: Sender<alice::Message0>, msg0: Sender<alice::Message0>,
msg1: Sender<alice::Message1>, msg1: Sender<alice::Message1>,
msg2: Sender<alice::Message2>, msg2: Sender<alice::Message2>,
conn_established: Sender<PeerId>, conn_established: Sender<PeerId>,
request_amounts: Receiver<::bitcoin::Amount>,
dial_alice: Receiver<()>, dial_alice: Receiver<()>,
send_swap_request: Receiver<SwapRequest>,
send_msg0: Receiver<bob::Message0>, send_msg0: Receiver<bob::Message0>,
send_msg1: Receiver<bob::Message1>, send_msg1: Receiver<bob::Message1>,
send_msg2: Receiver<bob::Message2>, send_msg2: Receiver<bob::Message2>,
@ -143,12 +152,13 @@ impl EventLoop {
swarm.add_address(alice_peer_id.clone(), alice_addr); swarm.add_address(alice_peer_id.clone(), alice_addr);
let amounts = Channels::new(); let swap_response = Channels::new();
let msg0 = Channels::new(); let msg0 = Channels::new();
let msg1 = Channels::new(); let msg1 = Channels::new();
let msg2 = Channels::new(); let msg2 = Channels::new();
let conn_established = Channels::new(); let conn_established = Channels::new();
let dial_alice = Channels::new(); let dial_alice = Channels::new();
let send_swap_request = Channels::new();
let send_msg0 = Channels::new(); let send_msg0 = Channels::new();
let send_msg1 = Channels::new(); let send_msg1 = Channels::new();
let send_msg2 = Channels::new(); let send_msg2 = Channels::new();
@ -157,12 +167,13 @@ impl EventLoop {
let event_loop = EventLoop { let event_loop = EventLoop {
swarm, swarm,
alice_peer_id, alice_peer_id,
request_amounts: amounts.receiver, swap_response: swap_response.sender,
msg0: msg0.sender, msg0: msg0.sender,
msg1: msg1.sender, msg1: msg1.sender,
msg2: msg2.sender, msg2: msg2.sender,
conn_established: conn_established.sender, conn_established: conn_established.sender,
dial_alice: dial_alice.receiver, dial_alice: dial_alice.receiver,
send_swap_request: send_swap_request.receiver,
send_msg0: send_msg0.receiver, send_msg0: send_msg0.receiver,
send_msg1: send_msg1.receiver, send_msg1: send_msg1.receiver,
send_msg2: send_msg2.receiver, send_msg2: send_msg2.receiver,
@ -170,12 +181,13 @@ impl EventLoop {
}; };
let handle = EventLoopHandle { let handle = EventLoopHandle {
request_amounts: amounts.sender, swap_response: swap_response.receiver,
msg0: msg0.receiver, msg0: msg0.receiver,
msg1: msg1.receiver, msg1: msg1.receiver,
msg2: msg2.receiver, msg2: msg2.receiver,
conn_established: conn_established.receiver, conn_established: conn_established.receiver,
dial_alice: dial_alice.sender, dial_alice: dial_alice.sender,
send_swap_request: send_swap_request.sender,
send_msg0: send_msg0.sender, send_msg0: send_msg0.sender,
send_msg1: send_msg1.sender, send_msg1: send_msg1.sender,
send_msg2: send_msg2.sender, send_msg2: send_msg2.sender,
@ -193,7 +205,9 @@ impl EventLoop {
OutEvent::ConnectionEstablished(peer_id) => { OutEvent::ConnectionEstablished(peer_id) => {
let _ = self.conn_established.send(peer_id).await; let _ = self.conn_established.send(peer_id).await;
} }
OutEvent::Amounts(_amounts) => info!("Amounts received from Alice"), OutEvent::SwapResponse(msg) => {
let _ = self.swap_response.send(msg).await;
},
OutEvent::Message0(msg) => { OutEvent::Message0(msg) => {
let _ = self.msg0.send(*msg).await; let _ = self.msg0.send(*msg).await;
} }
@ -222,9 +236,9 @@ impl EventLoop {
} }
} }
}, },
amounts = self.request_amounts.next().fuse() => { swap_request = self.send_swap_request.next().fuse() => {
if let Some(btc_amount) = amounts { if let Some(swap_request) = swap_request {
self.swarm.request_amounts(self.alice_peer_id.clone(), btc_amount.as_sat()); self.swarm.send_swap_request(self.alice_peer_id.clone(), swap_request);
} }
}, },

View File

@ -11,7 +11,7 @@ use crate::{
config::Config, config::Config,
database::{Database, Swap}, database::{Database, Swap},
monero, monero,
protocol::bob::{self, event_loop::EventLoopHandle, state::*}, protocol::bob::{self, event_loop::EventLoopHandle, state::*, SwapRequest},
ExpiredTimelocks, SwapAmounts, ExpiredTimelocks, SwapAmounts,
}; };
@ -373,7 +373,15 @@ where
R: RngCore + CryptoRng + Send, R: RngCore + CryptoRng + Send,
{ {
tracing::trace!("Starting negotiate"); tracing::trace!("Starting negotiate");
swarm.request_amounts(amounts.btc).await?; swarm
.send_swap_request(SwapRequest {
btc_amount: amounts.btc,
})
.await?;
// TODO: Use this once Bob's CLI is modified to only pass xmr amount in
// argument.
let _swap_response = swarm.recv_swap_response().await?;
swarm.send_message0(state0.next_message(&mut rng)).await?; swarm.send_message0(state0.next_message(&mut rng)).await?;
let msg0 = swarm.recv_message0().await?; let msg0 = swarm.recv_message0().await?;

View File

@ -1,3 +1,7 @@
use crate::{
network::request_response::{AliceToBob, BobToAlice, Codec, Swap, TIMEOUT},
protocol::alice::SwapResponse,
};
use anyhow::Result; use anyhow::Result;
use libp2p::{ use libp2p::{
request_response::{ request_response::{
@ -7,6 +11,7 @@ use libp2p::{
swarm::{NetworkBehaviourAction, NetworkBehaviourEventProcess, PollParameters}, swarm::{NetworkBehaviourAction, NetworkBehaviourEventProcess, PollParameters},
NetworkBehaviour, PeerId, NetworkBehaviour, PeerId,
}; };
use serde::{Deserialize, Serialize};
use std::{ use std::{
collections::VecDeque, collections::VecDeque,
task::{Context, Poll}, task::{Context, Poll},
@ -14,29 +19,30 @@ use std::{
}; };
use tracing::{debug, error}; use tracing::{debug, error};
use crate::{ #[derive(Clone, Debug, Serialize, Deserialize)]
network::request_response::{AliceToBob, AmountsProtocol, BobToAlice, Codec, TIMEOUT}, pub struct SwapRequest {
SwapAmounts, #[serde(with = "::bitcoin::util::amount::serde::as_sat")]
}; pub btc_amount: bitcoin::Amount,
#[derive(Copy, Clone, Debug)]
pub enum OutEvent {
Amounts(SwapAmounts),
} }
/// A `NetworkBehaviour` that represents getting the amounts of an XMR/BTC swap. #[derive(Copy, Clone, Debug)]
pub struct OutEvent {
pub swap_response: SwapResponse,
}
/// A `NetworkBehaviour` that represents doing the negotiation of a swap.
#[derive(NetworkBehaviour)] #[derive(NetworkBehaviour)]
#[behaviour(out_event = "OutEvent", poll_method = "poll")] #[behaviour(out_event = "OutEvent", poll_method = "poll")]
#[allow(missing_debug_implementations)] #[allow(missing_debug_implementations)]
pub struct Amounts { pub struct Behaviour {
rr: RequestResponse<Codec<AmountsProtocol>>, rr: RequestResponse<Codec<Swap>>,
#[behaviour(ignore)] #[behaviour(ignore)]
events: VecDeque<OutEvent>, events: VecDeque<OutEvent>,
} }
impl Amounts { impl Behaviour {
pub fn request_amounts(&mut self, alice: PeerId, btc: ::bitcoin::Amount) -> Result<RequestId> { pub fn send(&mut self, alice: PeerId, swap_request: SwapRequest) -> Result<RequestId> {
let msg = BobToAlice::AmountsFromBtc(btc); let msg = BobToAlice::SwapRequest(swap_request);
let id = self.rr.send_request(&alice, msg); let id = self.rr.send_request(&alice, msg);
Ok(id) Ok(id)
@ -46,7 +52,7 @@ impl Amounts {
&mut self, &mut self,
_: &mut Context<'_>, _: &mut Context<'_>,
_: &mut impl PollParameters, _: &mut impl PollParameters,
) -> Poll<NetworkBehaviourAction<RequestProtocol<Codec<AmountsProtocol>>, OutEvent>> { ) -> Poll<NetworkBehaviourAction<RequestProtocol<Codec<Swap>>, OutEvent>> {
if let Some(event) = self.events.pop_front() { if let Some(event) = self.events.pop_front() {
return Poll::Ready(NetworkBehaviourAction::GenerateEvent(event)); return Poll::Ready(NetworkBehaviourAction::GenerateEvent(event));
} }
@ -55,7 +61,7 @@ impl Amounts {
} }
} }
impl Default for Amounts { impl Default for Behaviour {
fn default() -> Self { fn default() -> Self {
let timeout = Duration::from_secs(TIMEOUT); let timeout = Duration::from_secs(TIMEOUT);
@ -65,7 +71,7 @@ impl Default for Amounts {
Self { Self {
rr: RequestResponse::new( rr: RequestResponse::new(
Codec::default(), Codec::default(),
vec![(AmountsProtocol, ProtocolSupport::Full)], vec![(Swap, ProtocolSupport::Full)],
config, config,
), ),
events: Default::default(), events: Default::default(),
@ -73,7 +79,7 @@ impl Default for Amounts {
} }
} }
impl NetworkBehaviourEventProcess<RequestResponseEvent<BobToAlice, AliceToBob>> for Amounts { impl NetworkBehaviourEventProcess<RequestResponseEvent<BobToAlice, AliceToBob>> for Behaviour {
fn inject_event(&mut self, event: RequestResponseEvent<BobToAlice, AliceToBob>) { fn inject_event(&mut self, event: RequestResponseEvent<BobToAlice, AliceToBob>) {
match event { match event {
RequestResponseEvent::Message { RequestResponseEvent::Message {
@ -84,9 +90,9 @@ impl NetworkBehaviourEventProcess<RequestResponseEvent<BobToAlice, AliceToBob>>
message: RequestResponseMessage::Response { response, .. }, message: RequestResponseMessage::Response { response, .. },
.. ..
} => { } => {
if let AliceToBob::Amounts(p) = response { if let AliceToBob::SwapResponse(swap_response) = response {
debug!("Received amounts response"); debug!("Received swap response");
self.events.push_back(OutEvent::Amounts(p)); self.events.push_back(OutEvent { swap_response });
} }
} }
RequestResponseEvent::InboundFailure { error, .. } => { RequestResponseEvent::InboundFailure { error, .. } => {