Unify transfer-proof protocol to a single one

Previously, we had two implementations of this protocol. To reduce
code size, we make Alice and Bob use the same implementation.
pull/340/head
Thomas Eizinger 3 years ago
parent 9d0b9abde0
commit 9979cc9f1f
No known key found for this signature in database
GPG Key ID: 651AC83A6C6C8B96

@ -2,6 +2,7 @@ pub mod peer_tracker;
pub mod quote;
pub mod request_response;
pub mod spot_price;
pub mod transfer_proof;
pub mod transport;
use libp2p::core::Executor;

@ -15,18 +15,9 @@ pub const TIMEOUT: u64 = 3600; // One hour.
/// Message receive buffer.
pub const BUF_SIZE: usize = 1024 * 1024;
#[derive(Debug, Clone, Copy, Default)]
pub struct TransferProofProtocol;
#[derive(Debug, Clone, Copy, Default)]
pub struct EncryptedSignatureProtocol;
impl ProtocolName for TransferProofProtocol {
fn protocol_name(&self) -> &[u8] {
b"/comit/xmr/btc/transfer_proof/1.0.0"
}
}
impl ProtocolName for EncryptedSignatureProtocol {
fn protocol_name(&self) -> &[u8] {
b"/comit/xmr/btc/encrypted_signature/1.0.0"

@ -0,0 +1,44 @@
use crate::monero;
use crate::network::request_response::CborCodec;
use libp2p::core::ProtocolName;
use libp2p::request_response::{
ProtocolSupport, RequestResponse, RequestResponseConfig, RequestResponseEvent,
RequestResponseMessage,
};
use serde::{Deserialize, Serialize};
pub type OutEvent = RequestResponseEvent<Request, ()>;
#[derive(Debug, Clone, Copy, Default)]
pub struct TransferProofProtocol;
impl ProtocolName for TransferProofProtocol {
fn protocol_name(&self) -> &[u8] {
b"/comit/xmr/btc/transfer_proof/1.0.0"
}
}
#[derive(Clone, Debug, Serialize, Deserialize)]
pub struct Request {
pub tx_lock_proof: monero::TransferProof,
}
pub type Behaviour = RequestResponse<CborCodec<TransferProofProtocol, Request, ()>>;
pub type Message = RequestResponseMessage<Request, ()>;
pub fn alice() -> Behaviour {
Behaviour::new(
CborCodec::default(),
vec![(TransferProofProtocol, ProtocolSupport::Outbound)],
RequestResponseConfig::default(),
)
}
pub fn bob() -> Behaviour {
Behaviour::new(
CborCodec::default(),
vec![(TransferProofProtocol, ProtocolSupport::Inbound)],
RequestResponseConfig::default(),
)
}

@ -11,7 +11,6 @@ pub use self::event_loop::{EventLoop, EventLoopHandle};
pub use self::execution_setup::Message1;
pub use self::state::*;
pub use self::swap::{run, run_until};
pub use self::transfer_proof::TransferProof;
pub use execution_setup::Message3;
mod behaviour;
@ -20,7 +19,6 @@ pub mod event_loop;
mod execution_setup;
pub mod state;
pub mod swap;
mod transfer_proof;
pub struct Swap {
pub state: AliceState,

@ -1,9 +1,7 @@
use crate::env::Config;
use crate::network::quote::BidQuote;
use crate::network::{peer_tracker, quote, spot_price};
use crate::protocol::alice::{
encrypted_signature, execution_setup, transfer_proof, State0, State3, TransferProof,
};
use crate::network::{peer_tracker, quote, spot_price, transfer_proof};
use crate::protocol::alice::{encrypted_signature, execution_setup, State0, State3};
use crate::protocol::bob::EncryptedSignature;
use crate::{bitcoin, monero};
use anyhow::{anyhow, Error, Result};
@ -52,6 +50,13 @@ impl From<peer_tracker::OutEvent> for OutEvent {
}
impl OutEvent {
fn unexpected_request(peer: PeerId) -> OutEvent {
OutEvent::Failure {
peer,
error: anyhow!("Unexpected request received"),
}
}
fn unexpected_response(peer: PeerId) -> OutEvent {
OutEvent::Failure {
peer,
@ -84,6 +89,15 @@ impl From<(PeerId, spot_price::Message)> for OutEvent {
}
}
impl From<(PeerId, transfer_proof::Message)> for OutEvent {
fn from((peer, message): (PeerId, transfer_proof::Message)) -> Self {
match message {
transfer_proof::Message::Request { .. } => OutEvent::unexpected_request(peer),
transfer_proof::Message::Response { .. } => OutEvent::TransferProofAcknowledged(peer),
}
}
}
impl From<spot_price::OutEvent> for OutEvent {
fn from(event: spot_price::OutEvent) -> Self {
map_rr_event_to_outevent(event)
@ -96,6 +110,12 @@ impl From<quote::OutEvent> for OutEvent {
}
}
impl From<transfer_proof::OutEvent> for OutEvent {
fn from(event: transfer_proof::OutEvent) -> Self {
map_rr_event_to_outevent(event)
}
}
fn map_rr_event_to_outevent<I, O>(event: RequestResponseEvent<I, O>) -> OutEvent
where
OutEvent: From<(PeerId, RequestResponseMessage<I, O>)>,
@ -132,19 +152,6 @@ impl From<execution_setup::OutEvent> for OutEvent {
}
}
impl From<transfer_proof::OutEvent> for OutEvent {
fn from(event: transfer_proof::OutEvent) -> Self {
use crate::protocol::alice::transfer_proof::OutEvent::*;
match event {
Acknowledged(peer) => OutEvent::TransferProofAcknowledged(peer),
Failure { peer, error } => OutEvent::Failure {
peer,
error: error.context("Failure with Transfer Proof"),
},
}
}
}
impl From<encrypted_signature::OutEvent> for OutEvent {
fn from(event: encrypted_signature::OutEvent) -> Self {
use crate::protocol::alice::encrypted_signature::OutEvent::*;
@ -183,7 +190,7 @@ impl Default for Behaviour {
quote: quote::alice(),
spot_price: spot_price::alice(),
execution_setup: Default::default(),
transfer_proof: Default::default(),
transfer_proof: transfer_proof::alice(),
encrypted_signature: Default::default(),
}
}
@ -237,8 +244,8 @@ impl Behaviour {
}
/// Send Transfer Proof to Bob.
pub fn send_transfer_proof(&mut self, bob: PeerId, msg: TransferProof) {
self.transfer_proof.send(bob, msg);
pub fn send_transfer_proof(&mut self, bob: PeerId, msg: transfer_proof::Request) {
self.transfer_proof.send_request(&bob, msg);
debug!("Sent Transfer Proof");
}

@ -3,8 +3,8 @@ use crate::database::Database;
use crate::env::Config;
use crate::monero::BalanceTooLow;
use crate::network::quote::BidQuote;
use crate::network::{spot_price, transport, TokioExecutor};
use crate::protocol::alice::{AliceState, Behaviour, OutEvent, State3, Swap, TransferProof};
use crate::network::{spot_price, transfer_proof, transport, TokioExecutor};
use crate::protocol::alice::{AliceState, Behaviour, OutEvent, State3, Swap};
use crate::protocol::bob::EncryptedSignature;
use crate::seed::Seed;
use crate::{bitcoin, kraken, monero};
@ -37,7 +37,8 @@ pub struct EventLoop<RS> {
recv_encrypted_signature: HashMap<PeerId, oneshot::Sender<EncryptedSignature>>,
/// Stores a list of futures, waiting for transfer proof which will be sent
/// to the given peer.
send_transfer_proof: FuturesUnordered<BoxFuture<'static, Result<(PeerId, TransferProof)>>>,
send_transfer_proof:
FuturesUnordered<BoxFuture<'static, Result<(PeerId, transfer_proof::Request)>>>,
swap_sender: mpsc::Sender<Swap>,
}
@ -307,7 +308,7 @@ impl LatestRate for kraken::RateUpdateStream {
#[derive(Debug)]
pub struct EventLoopHandle {
recv_encrypted_signature: Option<oneshot::Receiver<EncryptedSignature>>,
send_transfer_proof: Option<oneshot::Sender<TransferProof>>,
send_transfer_proof: Option<oneshot::Sender<transfer_proof::Request>>,
}
impl EventLoopHandle {
@ -327,7 +328,7 @@ impl EventLoopHandle {
.send_transfer_proof
.take()
.context("Transfer proof was already sent")?
.send(TransferProof { tx_lock_proof: msg })
.send(transfer_proof::Request { tx_lock_proof: msg })
.is_err()
{
bail!("Failed to send transfer proof, receiver no longer listening?")

@ -1,82 +0,0 @@
use crate::monero;
use crate::network::request_response::{CborCodec, TransferProofProtocol, TIMEOUT};
use anyhow::{anyhow, Error};
use libp2p::request_response::{
ProtocolSupport, RequestResponse, RequestResponseConfig, RequestResponseEvent,
RequestResponseMessage,
};
use libp2p::{NetworkBehaviour, PeerId};
use serde::{Deserialize, Serialize};
use std::time::Duration;
#[derive(Clone, Debug, Serialize, Deserialize)]
pub struct TransferProof {
pub tx_lock_proof: monero::TransferProof,
}
#[derive(Debug)]
pub enum OutEvent {
Acknowledged(PeerId),
Failure { peer: PeerId, error: Error },
}
/// A `NetworkBehaviour` that represents sending the Monero transfer proof to
/// Bob.
#[derive(NetworkBehaviour)]
#[behaviour(out_event = "OutEvent", event_process = false)]
#[allow(missing_debug_implementations)]
pub struct Behaviour {
rr: RequestResponse<CborCodec<TransferProofProtocol, TransferProof, ()>>,
}
impl Behaviour {
pub fn send(&mut self, bob: PeerId, msg: TransferProof) {
let _id = self.rr.send_request(&bob, msg);
}
}
impl Default for Behaviour {
fn default() -> Self {
let timeout = Duration::from_secs(TIMEOUT);
let mut config = RequestResponseConfig::default();
config.set_request_timeout(timeout);
Self {
rr: RequestResponse::new(
CborCodec::default(),
vec![(TransferProofProtocol, ProtocolSupport::Outbound)],
config,
),
}
}
}
impl From<RequestResponseEvent<TransferProof, ()>> for OutEvent {
fn from(event: RequestResponseEvent<TransferProof, ()>) -> Self {
match event {
RequestResponseEvent::Message {
message: RequestResponseMessage::Request { .. },
peer,
} => OutEvent::Failure {
peer,
error: anyhow!("Alice should never get a transfer proof request from Bob"),
},
RequestResponseEvent::Message {
message: RequestResponseMessage::Response { .. },
peer,
} => OutEvent::Acknowledged(peer),
RequestResponseEvent::InboundFailure { error, peer, .. } => OutEvent::Failure {
peer,
error: anyhow!("Inbound failure: {:?}", error),
},
RequestResponseEvent::OutboundFailure { error, peer, .. } => OutEvent::Failure {
peer,
error: anyhow!("Outbound failure: {:?}", error),
},
RequestResponseEvent::ResponseSent { peer, .. } => OutEvent::Failure {
peer,
error: anyhow!("Alice should not send a response"),
},
}
}
}

@ -1,7 +1,6 @@
use crate::database::Database;
use crate::env::Config;
use crate::network::{peer_tracker, spot_price};
use crate::protocol::alice::TransferProof;
use crate::protocol::bob;
use crate::{bitcoin, monero};
use anyhow::{anyhow, Error, Result};
@ -19,8 +18,8 @@ pub use self::event_loop::{EventLoop, EventLoopHandle};
pub use self::refund::refund;
pub use self::state::*;
pub use self::swap::{run, run_until};
use crate::network::quote;
use crate::network::quote::BidQuote;
use crate::network::{quote, transfer_proof};
pub mod cancel;
mod encrypted_signature;
@ -29,7 +28,6 @@ mod execution_setup;
pub mod refund;
pub mod state;
pub mod swap;
mod transfer_proof;
pub struct Swap {
pub state: BobState,
@ -117,8 +115,8 @@ pub enum OutEvent {
QuoteReceived(BidQuote),
SpotPriceReceived(spot_price::Response),
ExecutionSetupDone(Result<Box<State2>>),
TransferProof {
msg: Box<TransferProof>,
TransferProofReceived {
msg: Box<transfer_proof::Request>,
channel: ResponseChannel<()>,
},
EncryptedSignatureAcknowledged,
@ -130,6 +128,10 @@ impl OutEvent {
fn unexpected_request() -> OutEvent {
OutEvent::CommunicationError(anyhow!("Unexpected request received"))
}
fn unexpected_response() -> OutEvent {
OutEvent::CommunicationError(anyhow!("Unexpected response received"))
}
}
impl From<quote::Message> for OutEvent {
@ -150,6 +152,20 @@ impl From<spot_price::Message> for OutEvent {
}
}
impl From<transfer_proof::Message> for OutEvent {
fn from(message: transfer_proof::Message) -> Self {
match message {
transfer_proof::Message::Request {
request, channel, ..
} => OutEvent::TransferProofReceived {
msg: Box::new(request),
channel,
},
transfer_proof::Message::Response { .. } => OutEvent::unexpected_response(),
}
}
}
impl From<peer_tracker::OutEvent> for OutEvent {
fn from(event: peer_tracker::OutEvent) -> Self {
match event {
@ -172,6 +188,12 @@ impl From<quote::OutEvent> for OutEvent {
}
}
impl From<transfer_proof::OutEvent> for OutEvent {
fn from(event: transfer_proof::OutEvent) -> Self {
map_rr_event_to_outevent(event)
}
}
fn map_rr_event_to_outevent<I, O>(event: RequestResponseEvent<I, O>) -> OutEvent
where
OutEvent: From<RequestResponseMessage<I, O>>,
@ -202,22 +224,6 @@ impl From<execution_setup::OutEvent> for OutEvent {
}
}
impl From<transfer_proof::OutEvent> for OutEvent {
fn from(event: transfer_proof::OutEvent) -> Self {
use transfer_proof::OutEvent::*;
match event {
MsgReceived { msg, channel } => OutEvent::TransferProof {
msg: Box::new(msg),
channel,
},
AckSent => OutEvent::ResponseSent,
Failure(err) => {
OutEvent::CommunicationError(err.context("Failure with Transfer Proof"))
}
}
}
}
impl From<encrypted_signature::OutEvent> for OutEvent {
fn from(event: encrypted_signature::OutEvent) -> Self {
use encrypted_signature::OutEvent::*;
@ -250,7 +256,7 @@ impl Default for Behaviour {
quote: quote::bob(),
spot_price: spot_price::bob(),
execution_setup: Default::default(),
transfer_proof: Default::default(),
transfer_proof: transfer_proof::bob(),
encrypted_signature: Default::default(),
}
}

@ -1,7 +1,6 @@
use crate::bitcoin::EncryptedSignature;
use crate::network::quote::BidQuote;
use crate::network::{spot_price, transport, TokioExecutor};
use crate::protocol::alice::TransferProof;
use crate::network::{spot_price, transfer_proof, transport, TokioExecutor};
use crate::protocol::bob::{Behaviour, OutEvent, State0, State2};
use crate::{bitcoin, monero};
use anyhow::{anyhow, bail, Context, Result};
@ -36,7 +35,7 @@ impl<T> Default for Channels<T> {
pub struct EventLoopHandle {
start_execution_setup: Sender<State0>,
done_execution_setup: Receiver<Result<State2>>,
recv_transfer_proof: Receiver<TransferProof>,
recv_transfer_proof: Receiver<transfer_proof::Request>,
conn_established: Receiver<PeerId>,
dial_alice: Sender<()>,
send_encrypted_signature: Sender<EncryptedSignature>,
@ -56,7 +55,7 @@ impl EventLoopHandle {
.ok_or_else(|| anyhow!("Failed to setup execution with Alice"))?
}
pub async fn recv_transfer_proof(&mut self) -> Result<TransferProof> {
pub async fn recv_transfer_proof(&mut self) -> Result<transfer_proof::Request> {
self.recv_transfer_proof
.recv()
.await
@ -122,7 +121,7 @@ pub struct EventLoop {
recv_spot_price: Sender<spot_price::Response>,
start_execution_setup: Receiver<State0>,
done_execution_setup: Sender<Result<State2>>,
recv_transfer_proof: Sender<TransferProof>,
recv_transfer_proof: Sender<transfer_proof::Request>,
dial_alice: Receiver<()>,
conn_established: Sender<PeerId>,
send_encrypted_signature: Receiver<EncryptedSignature>,
@ -212,10 +211,10 @@ impl EventLoop {
OutEvent::ExecutionSetupDone(res) => {
let _ = self.done_execution_setup.send(res.map(|state|*state)).await;
}
OutEvent::TransferProof{ msg, channel }=> {
OutEvent::TransferProofReceived{ msg, channel }=> {
let _ = self.recv_transfer_proof.send(*msg).await;
// Send back empty response so that the request/response protocol completes.
if let Err(error) = self.swarm.transfer_proof.send_ack(channel) {
if let Err(error) = self.swarm.transfer_proof.send_response(channel, ()) {
error!("Failed to send Transfer Proof ack: {:?}", error);
}
}

@ -1,85 +0,0 @@
use crate::network::request_response::{CborCodec, TransferProofProtocol, TIMEOUT};
use crate::protocol::alice::TransferProof;
use anyhow::{anyhow, Error, Result};
use libp2p::request_response::{
ProtocolSupport, RequestResponse, RequestResponseConfig, RequestResponseEvent,
RequestResponseMessage, ResponseChannel,
};
use libp2p::NetworkBehaviour;
use std::time::Duration;
use tracing::debug;
#[derive(Debug)]
pub enum OutEvent {
MsgReceived {
msg: TransferProof,
channel: ResponseChannel<()>,
},
AckSent,
Failure(Error),
}
/// A `NetworkBehaviour` that represents receiving the transfer proof from
/// Alice.
#[derive(NetworkBehaviour)]
#[behaviour(out_event = "OutEvent", event_process = false)]
#[allow(missing_debug_implementations)]
pub struct Behaviour {
rr: RequestResponse<CborCodec<TransferProofProtocol, TransferProof, ()>>,
}
impl Behaviour {
pub fn send_ack(&mut self, channel: ResponseChannel<()>) -> Result<()> {
self.rr
.send_response(channel, ())
.map_err(|err| anyhow!("Failed to ack transfer proof: {:?}", err))
}
}
impl Default for Behaviour {
fn default() -> Self {
let timeout = Duration::from_secs(TIMEOUT);
let mut config = RequestResponseConfig::default();
config.set_request_timeout(timeout);
Self {
rr: RequestResponse::new(
CborCodec::default(),
vec![(TransferProofProtocol, ProtocolSupport::Inbound)],
config,
),
}
}
}
impl From<RequestResponseEvent<TransferProof, ()>> for OutEvent {
fn from(event: RequestResponseEvent<TransferProof, ()>) -> Self {
match event {
RequestResponseEvent::Message {
peer,
message:
RequestResponseMessage::Request {
request, channel, ..
},
..
} => {
debug!("Received Transfer Proof from {}", peer);
OutEvent::MsgReceived {
msg: request,
channel,
}
}
RequestResponseEvent::Message {
message: RequestResponseMessage::Response { .. },
..
} => OutEvent::Failure(anyhow!("Bob should not get a Response")),
RequestResponseEvent::InboundFailure { error, .. } => {
OutEvent::Failure(anyhow!("Inbound failure: {:?}", error))
}
RequestResponseEvent::OutboundFailure { error, .. } => {
OutEvent::Failure(anyhow!("Outbound failure: {:?}", error))
}
RequestResponseEvent::ResponseSent { .. } => OutEvent::AckSent,
}
}
}
Loading…
Cancel
Save