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>
pull/153/head
bors[bot] 3 years ago committed by GitHub
commit fbfc17c489
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23

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

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

@ -31,19 +31,6 @@ pub mod trace;
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.
#[derive(Copy, Clone, Debug, Serialize, Deserialize, PartialEq)]
// TODO(Franck): review necessity of this struct

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

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

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

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

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

@ -105,7 +105,7 @@ async fn run_until_internal(
match state {
AliceState::Started { amounts, state0 } => {
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 {
channel: Some(channel),

@ -6,6 +6,7 @@ use libp2p::{
swarm::{NetworkBehaviourAction, NetworkBehaviourEventProcess, PollParameters},
NetworkBehaviour,
};
use serde::{Deserialize, Serialize};
use std::{
collections::VecDeque,
task::{Context, Poll},
@ -14,29 +15,37 @@ use std::{
use tracing::{debug, error};
use crate::{
network::request_response::{AliceToBob, AmountsProtocol, BobToAlice, Codec, TIMEOUT},
protocol::alice::amounts,
monero,
network::request_response::{AliceToBob, BobToAlice, Codec, Swap, TIMEOUT},
protocol::bob,
};
#[derive(Debug)]
pub struct OutEvent {
pub btc: ::bitcoin::Amount,
pub msg: bob::SwapRequest,
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)]
#[behaviour(out_event = "OutEvent", poll_method = "poll")]
#[allow(missing_debug_implementations)]
pub struct Amounts {
rr: RequestResponse<Codec<AmountsProtocol>>,
pub struct Behaviour {
rr: RequestResponse<Codec<Swap>>,
#[behaviour(ignore)]
events: VecDeque<OutEvent>,
}
impl Amounts {
impl Behaviour {
/// 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);
}
@ -44,7 +53,7 @@ impl Amounts {
&mut self,
_: &mut Context<'_>,
_: &mut impl PollParameters,
) -> Poll<NetworkBehaviourAction<RequestProtocol<Codec<AmountsProtocol>>, OutEvent>> {
) -> Poll<NetworkBehaviourAction<RequestProtocol<Codec<Swap>>, OutEvent>> {
if let Some(event) = self.events.pop_front() {
return Poll::Ready(NetworkBehaviourAction::GenerateEvent(event));
}
@ -53,7 +62,7 @@ impl Amounts {
}
}
impl Default for Amounts {
impl Default for Behaviour {
fn default() -> Self {
let timeout = Duration::from_secs(TIMEOUT);
@ -63,7 +72,7 @@ impl Default for Amounts {
Self {
rr: RequestResponse::new(
Codec::default(),
vec![(AmountsProtocol, ProtocolSupport::Full)],
vec![(Swap, ProtocolSupport::Full)],
config,
),
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>) {
match event {
RequestResponseEvent::Message {
@ -81,9 +90,9 @@ impl NetworkBehaviourEventProcess<RequestResponseEvent<BobToAlice, AliceToBob>>
},
..
} => {
if let BobToAlice::AmountsFromBtc(btc) = request {
debug!("Received amounts request");
self.events.push_back(amounts::OutEvent { btc, channel })
if let BobToAlice::SwapRequest(msg) = request {
debug!("Received swap request");
self.events.push_back(OutEvent { msg, channel })
}
}
RequestResponseEvent::Message {

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

@ -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 futures::FutureExt;
use libp2p::{core::Multiaddr, PeerId};
@ -7,15 +16,6 @@ use tokio::{
};
use tracing::{debug, error, info};
use crate::{
bitcoin::EncryptedSignature,
network::{transport::SwapTransport, TokioExecutor},
protocol::{
alice,
bob::{self, Behaviour, OutEvent},
},
};
#[derive(Debug)]
pub struct Channels<T> {
sender: Sender<T>,
@ -37,12 +37,13 @@ impl<T> Default for Channels<T> {
#[derive(Debug)]
pub struct EventLoopHandle {
swap_response: Receiver<SwapResponse>,
msg0: Receiver<alice::Message0>,
msg1: Receiver<alice::Message1>,
msg2: Receiver<alice::Message2>,
request_amounts: Sender<::bitcoin::Amount>,
conn_established: Receiver<PeerId>,
dial_alice: Sender<()>,
send_swap_request: Sender<SwapRequest>,
send_msg0: Sender<bob::Message0>,
send_msg1: Sender<bob::Message1>,
send_msg2: Sender<bob::Message2>,
@ -50,25 +51,32 @@ pub struct 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> {
self.msg0
.recv()
.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> {
self.msg1
.recv()
.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> {
self.msg2
.recv()
.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.
@ -85,8 +93,8 @@ impl EventLoopHandle {
Ok(())
}
pub async fn request_amounts(&mut self, btc_amount: ::bitcoin::Amount) -> Result<()> {
let _ = self.request_amounts.send(btc_amount).await?;
pub async fn send_swap_request(&mut self, swap_request: SwapRequest) -> Result<()> {
let _ = self.send_swap_request.send(swap_request).await?;
Ok(())
}
@ -115,12 +123,13 @@ impl EventLoopHandle {
pub struct EventLoop {
swarm: libp2p::Swarm<Behaviour>,
alice_peer_id: PeerId,
swap_response: Sender<SwapResponse>,
msg0: Sender<alice::Message0>,
msg1: Sender<alice::Message1>,
msg2: Sender<alice::Message2>,
conn_established: Sender<PeerId>,
request_amounts: Receiver<::bitcoin::Amount>,
dial_alice: Receiver<()>,
send_swap_request: Receiver<SwapRequest>,
send_msg0: Receiver<bob::Message0>,
send_msg1: Receiver<bob::Message1>,
send_msg2: Receiver<bob::Message2>,
@ -143,12 +152,13 @@ impl EventLoop {
swarm.add_address(alice_peer_id.clone(), alice_addr);
let amounts = Channels::new();
let swap_response = Channels::new();
let msg0 = Channels::new();
let msg1 = Channels::new();
let msg2 = Channels::new();
let conn_established = Channels::new();
let dial_alice = Channels::new();
let send_swap_request = Channels::new();
let send_msg0 = Channels::new();
let send_msg1 = Channels::new();
let send_msg2 = Channels::new();
@ -157,12 +167,13 @@ impl EventLoop {
let event_loop = EventLoop {
swarm,
alice_peer_id,
request_amounts: amounts.receiver,
swap_response: swap_response.sender,
msg0: msg0.sender,
msg1: msg1.sender,
msg2: msg2.sender,
conn_established: conn_established.sender,
dial_alice: dial_alice.receiver,
send_swap_request: send_swap_request.receiver,
send_msg0: send_msg0.receiver,
send_msg1: send_msg1.receiver,
send_msg2: send_msg2.receiver,
@ -170,12 +181,13 @@ impl EventLoop {
};
let handle = EventLoopHandle {
request_amounts: amounts.sender,
swap_response: swap_response.receiver,
msg0: msg0.receiver,
msg1: msg1.receiver,
msg2: msg2.receiver,
conn_established: conn_established.receiver,
dial_alice: dial_alice.sender,
send_swap_request: send_swap_request.sender,
send_msg0: send_msg0.sender,
send_msg1: send_msg1.sender,
send_msg2: send_msg2.sender,
@ -193,7 +205,9 @@ impl EventLoop {
OutEvent::ConnectionEstablished(peer_id) => {
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) => {
let _ = self.msg0.send(*msg).await;
}
@ -222,9 +236,9 @@ impl EventLoop {
}
}
},
amounts = self.request_amounts.next().fuse() => {
if let Some(btc_amount) = amounts {
self.swarm.request_amounts(self.alice_peer_id.clone(), btc_amount.as_sat());
swap_request = self.send_swap_request.next().fuse() => {
if let Some(swap_request) = swap_request {
self.swarm.send_swap_request(self.alice_peer_id.clone(), swap_request);
}
},

@ -11,7 +11,7 @@ use crate::{
config::Config,
database::{Database, Swap},
monero,
protocol::bob::{self, event_loop::EventLoopHandle, state::*},
protocol::bob::{self, event_loop::EventLoopHandle, state::*, SwapRequest},
ExpiredTimelocks, SwapAmounts,
};
@ -373,7 +373,15 @@ where
R: RngCore + CryptoRng + Send,
{
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?;
let msg0 = swarm.recv_message0().await?;

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