Skip to content

Commit

Permalink
Replace quote with spot-price protocol
Browse files Browse the repository at this point in the history
This is essentially functionally equivalent but includes some
cleanups by removing a layer of abstraction: `spot_price::Behaviour`
is now just a type-alias for a request-response behaviour.
  • Loading branch information
thomaseizinger committed Mar 3, 2021
1 parent 2440964 commit 7042ed9
Show file tree
Hide file tree
Showing 11 changed files with 293 additions and 347 deletions.
1 change: 1 addition & 0 deletions swap/src/network.rs
Original file line number Diff line number Diff line change
@@ -1,5 +1,6 @@
pub mod peer_tracker;
pub mod request_response;
pub mod spot_price;
pub mod transport;

use futures::prelude::*;
Expand Down
9 changes: 0 additions & 9 deletions swap/src/network/request_response.rs
Original file line number Diff line number Diff line change
Expand Up @@ -13,21 +13,12 @@ pub const TIMEOUT: u64 = 3600; // One hour.
/// Message receive buffer.
pub const BUF_SIZE: usize = 1024 * 1024;

#[derive(Debug, Clone, Copy, Default)]
pub struct Swap;

#[derive(Debug, Clone, Copy, Default)]
pub struct TransferProofProtocol;

#[derive(Debug, Clone, Copy, Default)]
pub struct EncryptedSignatureProtocol;

impl ProtocolName for Swap {
fn protocol_name(&self) -> &[u8] {
b"/comit/xmr/btc/swap/1.0.0"
}
}

impl ProtocolName for TransferProofProtocol {
fn protocol_name(&self) -> &[u8] {
b"/comit/xmr/btc/transfer_proof/1.0.0"
Expand Down
66 changes: 66 additions & 0 deletions swap/src/network/spot_price.rs
Original file line number Diff line number Diff line change
@@ -0,0 +1,66 @@
use crate::{bitcoin, monero, network::request_response::CborCodec};
use libp2p::{
core::ProtocolName,
request_response::{
ProtocolSupport, RequestResponse, RequestResponseConfig, RequestResponseEvent,
},
};
use serde::{Deserialize, Serialize};

pub type OutEvent = RequestResponseEvent<SpotPriceRequest, SpotPriceResponse>;

/// The spot price protocol allows parties to **initiate** a trade by requesting
/// a spot price.
///
/// A spot price is binding for both parties, i.e. after the spot-price protocol
/// completes, both parties are expected to follow up with the `execution-setup`
/// protocol.
///
/// If a party wishes to only inquire about the current price, they should use
/// the `quote` protocol instead.
#[derive(Debug, Clone, Copy, Default)]
pub struct SpotPriceProtocol;

impl ProtocolName for SpotPriceProtocol {
fn protocol_name(&self) -> &[u8] {
b"/comit/xmr/btc/spot-price/1.0.0"
}
}

#[derive(Serialize, Deserialize, Debug, Clone)]
pub struct SpotPriceRequest {
#[serde(with = "::bitcoin::util::amount::serde::as_sat")]
pub btc: bitcoin::Amount,
}

#[derive(Serialize, Deserialize, Debug, Clone)]
pub struct SpotPriceResponse {
pub xmr: monero::Amount,
}

pub type Behaviour =
RequestResponse<CborCodec<SpotPriceProtocol, SpotPriceRequest, SpotPriceResponse>>;

/// Constructs a new instance of the `spot-price` behaviour to be used by Alice.
///
/// Alice only supports inbound connections, i.e. providing spot prices for BTC
/// in XMR.
pub fn alice() -> Behaviour {
Behaviour::new(
CborCodec::default(),
vec![(SpotPriceProtocol, ProtocolSupport::Inbound)],
RequestResponseConfig::default(),
)
}

/// Constructs a new instance of the `spot-price` behaviour to be used by Bob.
///
/// Bob only supports outbound connections, i.e. requesting a spot price for a
/// given amount of BTC in XMR.
pub fn bob() -> Behaviour {
Behaviour::new(
CborCodec::default(),
vec![(SpotPriceProtocol, ProtocolSupport::Outbound)],
RequestResponseConfig::default(),
)
}
2 changes: 0 additions & 2 deletions swap/src/protocol/alice.rs
Original file line number Diff line number Diff line change
Expand Up @@ -8,7 +8,6 @@ pub use self::{
behaviour::{Behaviour, OutEvent},
event_loop::{EventLoop, EventLoopHandle},
execution_setup::Message1,
quote_response::*,
state::*,
swap::{run, run_until},
transfer_proof::TransferProof,
Expand All @@ -19,7 +18,6 @@ mod behaviour;
mod encrypted_signature;
pub mod event_loop;
mod execution_setup;
mod quote_response;
pub mod state;
mod steps;
pub mod swap;
Expand Down
124 changes: 92 additions & 32 deletions swap/src/protocol/alice/behaviour.rs
Original file line number Diff line number Diff line change
@@ -1,24 +1,35 @@
use crate::{
network::{peer_tracker, peer_tracker::PeerTracker},
bitcoin,
execution_params::ExecutionParams,
monero,
network::{
peer_tracker,
peer_tracker::PeerTracker,
spot_price,
spot_price::{SpotPriceRequest, SpotPriceResponse},
},
protocol::{
alice::{
encrypted_signature, execution_setup, quote_response, transfer_proof, QuoteResponse,
State0, State3, TransferProof,
encrypted_signature, execution_setup, transfer_proof, State0, State3, TransferProof,
},
bob::{EncryptedSignature, QuoteRequest},
bob::EncryptedSignature,
},
};
use anyhow::{Error, Result};
use libp2p::{request_response::ResponseChannel, NetworkBehaviour, PeerId};
use anyhow::{anyhow, Error, Result};
use libp2p::{
request_response::{RequestResponseMessage, ResponseChannel},
NetworkBehaviour, PeerId,
};
use rand::{CryptoRng, RngCore};
use tracing::debug;

#[derive(Debug)]
pub enum OutEvent {
ConnectionEstablished(PeerId),
QuoteRequest {
msg: QuoteRequest,
channel: ResponseChannel<QuoteResponse>,
bob_peer_id: PeerId,
SpotPriceRequested {
msg: SpotPriceRequest,
channel: ResponseChannel<SpotPriceResponse>,
peer: PeerId,
},
ExecutionSetupDone {
bob_peer_id: PeerId,
Expand All @@ -43,21 +54,37 @@ impl From<peer_tracker::OutEvent> for OutEvent {
}
}

impl From<quote_response::OutEvent> for OutEvent {
fn from(event: quote_response::OutEvent) -> Self {
use crate::protocol::alice::quote_response::OutEvent::*;
impl From<spot_price::OutEvent> for OutEvent {
fn from(event: spot_price::OutEvent) -> Self {
match event {
MsgReceived {
msg,
channel,
bob_peer_id,
} => OutEvent::QuoteRequest {
msg,
channel,
bob_peer_id,
},
ResponseSent => OutEvent::ResponseSent,
Failure(err) => OutEvent::Failure(err.context("Quote Request/Response failure")),
spot_price::OutEvent::Message {
peer,
message:
RequestResponseMessage::Request {
channel,
request: msg,
..
},
} => OutEvent::SpotPriceRequested { msg, channel, peer },
spot_price::OutEvent::Message {
message: RequestResponseMessage::Response { .. },
..
} => OutEvent::Failure(anyhow!(
"Alice is only meant to hand out spot prices, not receive them"
)),
spot_price::OutEvent::ResponseSent { .. } => OutEvent::ResponseSent,
spot_price::OutEvent::InboundFailure { peer, error, .. } => OutEvent::Failure(anyhow!(
"spot_price protocol with peer {} failed due to {:?}",
peer,
error
)),
spot_price::OutEvent::OutboundFailure { peer, error, .. } => {
OutEvent::Failure(anyhow!(
"spot_price protocol with peer {} failed due to {:?}",
peer,
error
))
}
}
}
}
Expand Down Expand Up @@ -103,29 +130,62 @@ impl From<encrypted_signature::OutEvent> for OutEvent {
}

/// A `NetworkBehaviour` that represents an XMR/BTC swap node as Alice.
#[derive(NetworkBehaviour, Default)]
#[derive(NetworkBehaviour)]
#[behaviour(out_event = "OutEvent", event_process = false)]
#[allow(missing_debug_implementations)]
pub struct Behaviour {
pt: PeerTracker,
quote_response: quote_response::Behaviour,
spot_price: spot_price::Behaviour,
execution_setup: execution_setup::Behaviour,
transfer_proof: transfer_proof::Behaviour,
encrypted_signature: encrypted_signature::Behaviour,
}

impl Default for Behaviour {
fn default() -> Self {
Self {
pt: Default::default(),
spot_price: spot_price::alice(),
execution_setup: Default::default(),
transfer_proof: Default::default(),
encrypted_signature: Default::default(),
}
}
}

impl Behaviour {
pub fn send_quote_response(
pub fn send_spot_price(
&mut self,
channel: ResponseChannel<QuoteResponse>,
quote_response: QuoteResponse,
channel: ResponseChannel<SpotPriceResponse>,
response: SpotPriceResponse,
) -> Result<()> {
self.quote_response.send(channel, quote_response)?;
self.spot_price
.send_response(channel, response)
.map_err(|_| anyhow!("failed to respond with spot price"))?;

Ok(())
}

pub fn start_execution_setup(&mut self, bob_peer_id: PeerId, state0: State0) {
self.execution_setup.run(bob_peer_id, state0);
pub async fn start_execution_setup(
&mut self,
peer: PeerId,
btc: bitcoin::Amount,
xmr: monero::Amount,
execution_params: ExecutionParams,
bitcoin_wallet: &bitcoin::Wallet,
rng: &mut (impl RngCore + CryptoRng),
) -> Result<()> {
let state0 = State0::new(btc, xmr, execution_params, bitcoin_wallet, rng).await?;

tracing::info!(
%peer,
"Starting execution setup to sell {} for {}",
xmr, btc,
);

self.execution_setup.run(peer, state0);

Ok(())
}

/// Send Transfer Proof to Bob.
Expand Down
Loading

0 comments on commit 7042ed9

Please sign in to comment.