189: The first message is more of a quote request than a swap request r=D4nte a=D4nte



Co-authored-by: Franck Royer <franck@coblox.tech>
This commit is contained in:
bors[bot] 2021-02-15 00:24:39 +00:00 committed by GitHub
commit a0753e24dc
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
9 changed files with 91 additions and 92 deletions

View File

@ -9,11 +9,11 @@ group Negotiation
Bob --> Alice: Establish connection
group Request Response Channel
Bob -> Alice: Swap request
Bob -> Alice: Quote request
note left: Btc Amount\naddress hints
note right: Alice stores peer id & address hints\nto contact Bob
Alice --> Bob: Swap response
Alice --> Bob: Quote response
note right: Exact XMR amount
end
end

View File

@ -13,9 +13,9 @@ pub use self::{
behaviour::{Behaviour, OutEvent},
event_loop::{EventLoop, EventLoopHandle},
execution_setup::Message1,
quote_response::*,
state::*,
swap::{run, run_until},
swap_response::*,
transfer_proof::TransferProof,
};
pub use execution_setup::Message3;
@ -24,10 +24,10 @@ mod behaviour;
mod encrypted_signature;
pub mod event_loop;
mod execution_setup;
mod quote_response;
pub mod state;
mod steps;
pub mod swap;
mod swap_response;
mod transfer_proof;
pub struct Swap {

View File

@ -2,10 +2,10 @@ use crate::{
network::{peer_tracker, peer_tracker::PeerTracker},
protocol::{
alice::{
encrypted_signature, execution_setup, swap_response, transfer_proof, State0, State3,
SwapResponse, TransferProof,
encrypted_signature, execution_setup, quote_response, transfer_proof, QuoteResponse,
State0, State3, TransferProof,
},
bob::{EncryptedSignature, SwapRequest},
bob::{EncryptedSignature, QuoteRequest},
},
};
use anyhow::{Error, Result};
@ -15,9 +15,9 @@ use tracing::{debug, info};
#[derive(Debug)]
pub enum OutEvent {
ConnectionEstablished(PeerId),
SwapRequest {
msg: SwapRequest,
channel: ResponseChannel<SwapResponse>,
QuoteRequest {
msg: QuoteRequest,
channel: ResponseChannel<QuoteResponse>,
bob_peer_id: PeerId,
},
ExecutionSetupDone {
@ -43,21 +43,21 @@ impl From<peer_tracker::OutEvent> for OutEvent {
}
}
impl From<swap_response::OutEvent> for OutEvent {
fn from(event: swap_response::OutEvent) -> Self {
use crate::protocol::alice::swap_response::OutEvent::*;
impl From<quote_response::OutEvent> for OutEvent {
fn from(event: quote_response::OutEvent) -> Self {
use crate::protocol::alice::quote_response::OutEvent::*;
match event {
MsgReceived {
msg,
channel,
bob_peer_id,
} => OutEvent::SwapRequest {
} => OutEvent::QuoteRequest {
msg,
channel,
bob_peer_id,
},
ResponseSent => OutEvent::ResponseSent,
Failure(err) => OutEvent::Failure(err.context("Swap Request/Response failure")),
Failure(err) => OutEvent::Failure(err.context("Quote Request/Response failure")),
}
}
}
@ -108,21 +108,20 @@ impl From<encrypted_signature::OutEvent> for OutEvent {
#[allow(missing_debug_implementations)]
pub struct Behaviour {
pt: PeerTracker,
swap_response: swap_response::Behaviour,
quote_response: quote_response::Behaviour,
execution_setup: execution_setup::Behaviour,
transfer_proof: transfer_proof::Behaviour,
encrypted_signature: encrypted_signature::Behaviour,
}
impl Behaviour {
/// Alice always sends her messages as a response to a request from Bob.
pub fn send_swap_response(
pub fn send_quote_response(
&mut self,
channel: ResponseChannel<SwapResponse>,
swap_response: SwapResponse,
channel: ResponseChannel<QuoteResponse>,
quote_response: QuoteResponse,
) -> anyhow::Result<()> {
self.swap_response.send(channel, swap_response)?;
info!("Sent swap response");
self.quote_response.send(channel, quote_response)?;
info!("Sent quote response");
Ok(())
}

View File

@ -6,8 +6,8 @@ use crate::{
network::{transport, TokioExecutor},
protocol::{
alice,
alice::{Behaviour, Builder, OutEvent, State0, State3, SwapResponse, TransferProof},
bob::{EncryptedSignature, SwapRequest},
alice::{Behaviour, Builder, OutEvent, QuoteResponse, State0, State3, TransferProof},
bob::{EncryptedSignature, QuoteRequest},
SwapAmounts,
},
seed::Seed,
@ -157,8 +157,8 @@ impl EventLoop {
OutEvent::ConnectionEstablished(alice) => {
debug!("Connection Established with {}", alice);
}
OutEvent::SwapRequest { msg, channel, bob_peer_id } => {
let _ = self.handle_swap_request(msg, channel, bob_peer_id).await;
OutEvent::QuoteRequest { msg, channel, bob_peer_id } => {
let _ = self.handle_quote_request(msg, channel, bob_peer_id).await;
}
OutEvent::ExecutionSetupDone{bob_peer_id, state3} => {
let _ = self.handle_execution_setup_done(bob_peer_id, *state3).await;
@ -188,23 +188,23 @@ impl EventLoop {
}
}
async fn handle_swap_request(
async fn handle_quote_request(
&mut self,
swap_request: SwapRequest,
channel: ResponseChannel<SwapResponse>,
quote_request: QuoteRequest,
channel: ResponseChannel<QuoteResponse>,
bob_peer_id: PeerId,
) -> Result<()> {
// 1. Check if acceptable request
// 2. Send response
let btc_amount = swap_request.btc_amount;
let btc_amount = quote_request.btc_amount;
let xmr_amount = btc_amount.as_btc() * RATE as f64;
let xmr_amount = monero::Amount::from_monero(xmr_amount)?;
let swap_response = SwapResponse { xmr_amount };
let quote_response = QuoteResponse { xmr_amount };
self.swarm
.send_swap_response(channel, swap_response)
.context("Failed to send swap response")?;
.send_quote_response(channel, quote_response)
.context("Failed to send quote response")?;
// 3. Start setup execution

View File

@ -1,7 +1,7 @@
use crate::{
monero,
network::request_response::{CborCodec, Swap, TIMEOUT},
protocol::bob::SwapRequest,
protocol::bob::QuoteRequest,
};
use anyhow::{anyhow, Error, Result};
use libp2p::{
@ -18,8 +18,8 @@ use tracing::debug;
#[derive(Debug)]
pub enum OutEvent {
MsgReceived {
msg: SwapRequest,
channel: ResponseChannel<SwapResponse>,
msg: QuoteRequest,
channel: ResponseChannel<QuoteResponse>,
bob_peer_id: PeerId,
},
ResponseSent,
@ -27,12 +27,12 @@ pub enum OutEvent {
}
#[derive(Copy, Clone, Debug, Serialize, Deserialize)]
pub struct SwapResponse {
pub struct QuoteResponse {
pub xmr_amount: monero::Amount,
}
impl From<RequestResponseEvent<SwapRequest, SwapResponse>> for OutEvent {
fn from(event: RequestResponseEvent<SwapRequest, SwapResponse>) -> Self {
impl From<RequestResponseEvent<QuoteRequest, QuoteResponse>> for OutEvent {
fn from(event: RequestResponseEvent<QuoteRequest, QuoteResponse>) -> Self {
match event {
RequestResponseEvent::Message {
peer,
@ -42,7 +42,7 @@ impl From<RequestResponseEvent<SwapRequest, SwapResponse>> for OutEvent {
},
..
} => {
debug!("Received swap request from {}", peer);
debug!("Received quote request from {}", peer);
OutEvent::MsgReceived {
msg: request,
channel,
@ -70,19 +70,19 @@ impl From<RequestResponseEvent<SwapRequest, SwapResponse>> for OutEvent {
#[behaviour(out_event = "OutEvent", event_process = false)]
#[allow(missing_debug_implementations)]
pub struct Behaviour {
rr: RequestResponse<CborCodec<Swap, SwapRequest, SwapResponse>>,
rr: RequestResponse<CborCodec<Swap, QuoteRequest, QuoteResponse>>,
}
impl Behaviour {
/// Alice always sends her messages as a response to a request from Bob.
pub fn send(
&mut self,
channel: ResponseChannel<SwapResponse>,
msg: SwapResponse,
channel: ResponseChannel<QuoteResponse>,
msg: QuoteResponse,
) -> Result<()> {
self.rr
.send_response(channel, msg)
.map_err(|_| anyhow!("Sending swap response failed"))
.map_err(|_| anyhow!("Sending quote response failed"))
}
}

View File

@ -23,10 +23,10 @@ pub use self::{
cancel::cancel,
encrypted_signature::EncryptedSignature,
event_loop::{EventLoop, EventLoopHandle},
quote_request::*,
refund::refund,
state::*,
swap::{run, run_until},
swap_request::*,
};
pub use execution_setup::{Message0, Message2, Message4};
use libp2p::request_response::ResponseChannel;
@ -35,10 +35,10 @@ pub mod cancel;
mod encrypted_signature;
pub mod event_loop;
mod execution_setup;
mod quote_request;
pub mod refund;
pub mod state;
pub mod swap;
mod swap_request;
mod transfer_proof;
pub struct Swap {
@ -205,7 +205,7 @@ impl Builder {
#[derive(Debug)]
pub enum OutEvent {
ConnectionEstablished(PeerId),
SwapResponse(alice::SwapResponse),
QuoteResponse(alice::QuoteResponse),
ExecutionSetupDone(Result<Box<State2>>),
TransferProof {
msg: Box<TransferProof>,
@ -226,12 +226,12 @@ impl From<peer_tracker::OutEvent> for OutEvent {
}
}
impl From<swap_request::OutEvent> for OutEvent {
fn from(event: swap_request::OutEvent) -> Self {
use swap_request::OutEvent::*;
impl From<quote_request::OutEvent> for OutEvent {
fn from(event: quote_request::OutEvent) -> Self {
use quote_request::OutEvent::*;
match event {
MsgReceived(swap_response) => OutEvent::SwapResponse(swap_response),
Failure(err) => OutEvent::Failure(err.context("Failre with Swap Request")),
MsgReceived(quote_response) => OutEvent::QuoteResponse(quote_response),
Failure(err) => OutEvent::Failure(err.context("Failure with Quote Request")),
}
}
}
@ -274,17 +274,17 @@ impl From<encrypted_signature::OutEvent> for OutEvent {
#[allow(missing_debug_implementations)]
pub struct Behaviour {
pt: PeerTracker,
swap_request: swap_request::Behaviour,
quote_request: quote_request::Behaviour,
execution_setup: execution_setup::Behaviour,
transfer_proof: transfer_proof::Behaviour,
encrypted_signature: encrypted_signature::Behaviour,
}
impl Behaviour {
/// 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, swap_request);
info!("Requesting swap from: {}", alice);
/// Sends a quote request to Alice to retrieve the rate.
pub fn send_quote_request(&mut self, alice: PeerId, quote_request: QuoteRequest) {
let _id = self.quote_request.send(alice, quote_request);
info!("Requesting quote from: {}", alice);
}
pub fn start_execution_setup(

View File

@ -3,8 +3,8 @@ use crate::{
bitcoin::EncryptedSignature,
network::{transport::SwapTransport, TokioExecutor},
protocol::{
alice::{SwapResponse, TransferProof},
bob::{Behaviour, OutEvent, State0, State2, SwapRequest},
alice::{QuoteResponse, TransferProof},
bob::{Behaviour, OutEvent, QuoteRequest, State0, State2},
},
};
use anyhow::{anyhow, Result};
@ -35,22 +35,22 @@ impl<T> Default for Channels<T> {
#[derive(Debug)]
pub struct EventLoopHandle {
recv_swap_response: Receiver<SwapResponse>,
recv_quote_response: Receiver<QuoteResponse>,
start_execution_setup: Sender<State0>,
done_execution_setup: Receiver<Result<State2>>,
recv_transfer_proof: Receiver<TransferProof>,
conn_established: Receiver<PeerId>,
dial_alice: Sender<()>,
send_swap_request: Sender<SwapRequest>,
send_quote_request: Sender<QuoteRequest>,
send_encrypted_signature: Sender<EncryptedSignature>,
}
impl EventLoopHandle {
pub async fn recv_swap_response(&mut self) -> Result<SwapResponse> {
self.recv_swap_response
pub async fn recv_quote_response(&mut self) -> Result<QuoteResponse> {
self.recv_quote_response
.recv()
.await
.ok_or_else(|| anyhow!("Failed to receive swap response from Alice"))
.ok_or_else(|| anyhow!("Failed to receive quote response from Alice"))
}
pub async fn execution_setup(&mut self, state0: State0) -> Result<State2> {
@ -83,8 +83,8 @@ impl EventLoopHandle {
Ok(())
}
pub async fn send_swap_request(&mut self, swap_request: SwapRequest) -> Result<()> {
let _ = self.send_swap_request.send(swap_request).await?;
pub async fn send_quote_request(&mut self, quote_request: QuoteRequest) -> Result<()> {
let _ = self.send_quote_request.send(quote_request).await?;
Ok(())
}
@ -103,13 +103,13 @@ pub struct EventLoop {
swarm: libp2p::Swarm<Behaviour>,
bitcoin_wallet: Arc<bitcoin::Wallet>,
alice_peer_id: PeerId,
recv_swap_response: Sender<SwapResponse>,
recv_quote_response: Sender<QuoteResponse>,
start_execution_setup: Receiver<State0>,
done_execution_setup: Sender<Result<State2>>,
recv_transfer_proof: Sender<TransferProof>,
dial_alice: Receiver<()>,
conn_established: Sender<PeerId>,
send_swap_request: Receiver<SwapRequest>,
send_quote_request: Receiver<QuoteRequest>,
send_encrypted_signature: Receiver<EncryptedSignature>,
}
@ -130,37 +130,37 @@ impl EventLoop {
swarm.add_address(alice_peer_id, alice_addr);
let swap_response = Channels::new();
let quote_response = Channels::new();
let start_execution_setup = Channels::new();
let done_execution_setup = Channels::new();
let recv_transfer_proof = Channels::new();
let dial_alice = Channels::new();
let conn_established = Channels::new();
let send_swap_request = Channels::new();
let send_quote_request = Channels::new();
let send_encrypted_signature = Channels::new();
let event_loop = EventLoop {
swarm,
alice_peer_id,
bitcoin_wallet,
recv_swap_response: swap_response.sender,
recv_quote_response: quote_response.sender,
start_execution_setup: start_execution_setup.receiver,
done_execution_setup: done_execution_setup.sender,
recv_transfer_proof: recv_transfer_proof.sender,
conn_established: conn_established.sender,
dial_alice: dial_alice.receiver,
send_swap_request: send_swap_request.receiver,
send_quote_request: send_quote_request.receiver,
send_encrypted_signature: send_encrypted_signature.receiver,
};
let handle = EventLoopHandle {
recv_swap_response: swap_response.receiver,
recv_quote_response: quote_response.receiver,
start_execution_setup: start_execution_setup.sender,
done_execution_setup: done_execution_setup.receiver,
recv_transfer_proof: recv_transfer_proof.receiver,
conn_established: conn_established.receiver,
dial_alice: dial_alice.sender,
send_swap_request: send_swap_request.sender,
send_quote_request: send_quote_request.sender,
send_encrypted_signature: send_encrypted_signature.sender,
};
@ -175,8 +175,8 @@ impl EventLoop {
OutEvent::ConnectionEstablished(peer_id) => {
let _ = self.conn_established.send(peer_id).await;
}
OutEvent::SwapResponse(msg) => {
let _ = self.recv_swap_response.send(msg).await;
OutEvent::QuoteResponse(msg) => {
let _ = self.recv_quote_response.send(msg).await;
},
OutEvent::ExecutionSetupDone(res) => {
let _ = self.done_execution_setup.send(res.map(|state|*state)).await;
@ -213,9 +213,9 @@ impl EventLoop {
}
}
},
swap_request = self.send_swap_request.recv().fuse() => {
if let Some(swap_request) = swap_request {
self.swarm.send_swap_request(self.alice_peer_id, swap_request);
quote_request = self.send_quote_request.recv().fuse() => {
if let Some(quote_request) = quote_request {
self.swarm.send_quote_request(self.alice_peer_id, quote_request);
}
},
option = self.start_execution_setup.recv().fuse() => {

View File

@ -1,6 +1,6 @@
use crate::{
network::request_response::{CborCodec, Swap, TIMEOUT},
protocol::alice::SwapResponse,
protocol::alice::QuoteResponse,
};
use anyhow::{anyhow, Error, Result};
use libp2p::{
@ -15,14 +15,14 @@ use std::time::Duration;
use tracing::debug;
#[derive(Clone, Copy, Debug, Serialize, Deserialize)]
pub struct SwapRequest {
pub struct QuoteRequest {
#[serde(with = "::bitcoin::util::amount::serde::as_sat")]
pub btc_amount: bitcoin::Amount,
}
#[derive(Debug)]
pub enum OutEvent {
MsgReceived(SwapResponse),
MsgReceived(QuoteResponse),
Failure(Error),
}
@ -31,12 +31,12 @@ pub enum OutEvent {
#[behaviour(out_event = "OutEvent", event_process = false)]
#[allow(missing_debug_implementations)]
pub struct Behaviour {
rr: RequestResponse<CborCodec<Swap, SwapRequest, SwapResponse>>,
rr: RequestResponse<CborCodec<Swap, QuoteRequest, QuoteResponse>>,
}
impl Behaviour {
pub fn send(&mut self, alice: PeerId, swap_request: SwapRequest) -> Result<RequestId> {
let id = self.rr.send_request(&alice, swap_request);
pub fn send(&mut self, alice: PeerId, quote_request: QuoteRequest) -> Result<RequestId> {
let id = self.rr.send_request(&alice, quote_request);
Ok(id)
}
@ -59,8 +59,8 @@ impl Default for Behaviour {
}
}
impl From<RequestResponseEvent<SwapRequest, SwapResponse>> for OutEvent {
fn from(event: RequestResponseEvent<SwapRequest, SwapResponse>) -> Self {
impl From<RequestResponseEvent<QuoteRequest, QuoteResponse>> for OutEvent {
fn from(event: RequestResponseEvent<QuoteRequest, QuoteResponse>) -> Self {
match event {
RequestResponseEvent::Message {
message: RequestResponseMessage::Request { .. },
@ -71,7 +71,7 @@ impl From<RequestResponseEvent<SwapRequest, SwapResponse>> for OutEvent {
message: RequestResponseMessage::Response { response, .. },
..
} => {
debug!("Received swap response from {}", peer);
debug!("Received quote response from {}", peer);
OutEvent::MsgReceived(response)
}
RequestResponseEvent::InboundFailure { error, .. } => {
@ -81,7 +81,7 @@ impl From<RequestResponseEvent<SwapRequest, SwapResponse>> for OutEvent {
OutEvent::Failure(anyhow!("Outbound failure: {:?}", error))
}
RequestResponseEvent::ResponseSent { .. } => {
OutEvent::Failure(anyhow!("Bob does not send a swap response to Alice"))
OutEvent::Failure(anyhow!("Bob does not send a quote response to Alice"))
}
}
}

View File

@ -5,7 +5,7 @@ use crate::{
execution_params::ExecutionParams,
monero,
protocol::{
bob::{self, event_loop::EventLoopHandle, state::*, SwapRequest},
bob::{self, event_loop::EventLoopHandle, state::*, QuoteRequest},
SwapAmounts,
},
};
@ -375,14 +375,14 @@ pub async fn negotiate(
) -> Result<bob::state::State2> {
tracing::trace!("Starting negotiate");
event_loop_handle
.send_swap_request(SwapRequest {
.send_quote_request(QuoteRequest {
btc_amount: amounts.btc,
})
.await?;
// TODO: Use this once Bob's CLI is modified to only pass xmr amount in
// argument.
let _swap_response = event_loop_handle.recv_swap_response().await?;
let _quote_response = event_loop_handle.recv_quote_response().await?;
let state2 = event_loop_handle.execution_setup(state0).await?;