wip: Segregate negotation and execution setup from swap execution

This commit is contained in:
Franck Royer 2021-02-04 17:14:26 +11:00
parent 5a2f82478a
commit 815ef90c9f
No known key found for this signature in database
GPG Key ID: A82ED75A8DFC50A4
6 changed files with 40 additions and 140 deletions

View File

@ -14,10 +14,6 @@ use serde::{Deserialize, Serialize};
#[derive(Clone, Debug, Deserialize, Serialize, PartialEq)]
pub enum Alice {
Started {
amounts: SwapAmounts,
state0: alice::State0,
},
Negotiated {
state3: alice::State3,
#[serde(with = "crate::serde_peer_id")]
bob_peer_id: PeerId,
@ -54,11 +50,11 @@ pub enum AliceEndState {
impl From<&AliceState> for Alice {
fn from(alice_state: &AliceState) -> Self {
match alice_state {
AliceState::Negotiated {
AliceState::Started {
state3,
bob_peer_id,
..
} => Alice::Negotiated {
} => Alice::Started {
state3: state3.as_ref().clone(),
bob_peer_id: *bob_peer_id,
},
@ -93,10 +89,6 @@ impl From<&AliceState> for Alice {
}
AliceState::BtcPunished => Alice::Done(AliceEndState::BtcPunished),
AliceState::SafelyAborted => Alice::Done(AliceEndState::SafelyAborted),
AliceState::Started { amounts, state0 } => Alice::Started {
amounts: *amounts,
state0: state0.clone(),
},
}
}
}
@ -104,11 +96,10 @@ impl From<&AliceState> for Alice {
impl From<Alice> for AliceState {
fn from(db_state: Alice) -> Self {
match db_state {
Alice::Started { amounts, state0 } => AliceState::Started { amounts, state0 },
Alice::Negotiated {
Alice::Started {
state3,
bob_peer_id,
} => AliceState::Negotiated {
} => AliceState::Started {
bob_peer_id,
amounts: SwapAmounts {
btc: state3.btc,
@ -186,7 +177,6 @@ impl Display for Alice {
fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
match self {
Alice::Started { .. } => write!(f, "Started"),
Alice::Negotiated { .. } => f.write_str("Negotiated"),
Alice::BtcLocked { .. } => f.write_str("Bitcoin locked"),
Alice::XmrLocked(_) => f.write_str("Monero locked"),
Alice::CancelTimelockExpired(_) => f.write_str("Cancel timelock is expired"),

View File

@ -17,7 +17,6 @@ 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;
@ -69,7 +68,11 @@ pub struct Builder {
enum InitParams {
None,
New { swap_amounts: SwapAmounts },
New {
swap_amounts: SwapAmounts,
bob_peer_id: PeerId,
state3: Box<State3>,
},
}
impl Builder {
@ -99,19 +102,34 @@ impl Builder {
}
}
pub fn with_init_params(self, swap_amounts: SwapAmounts) -> Self {
pub fn with_init_params(
self,
swap_amounts: SwapAmounts,
bob_peer_id: PeerId,
state3: State3,
) -> Self {
Self {
init_params: InitParams::New { swap_amounts },
init_params: InitParams::New {
swap_amounts,
bob_peer_id,
state3: Box::new(state3),
},
..self
}
}
pub async fn build(self) -> Result<(Swap, EventLoop)> {
match self.init_params {
InitParams::New { swap_amounts } => {
let initial_state = self
.make_initial_state(swap_amounts.btc, swap_amounts.xmr)
.await?;
InitParams::New {
swap_amounts,
bob_peer_id,
ref state3,
} => {
let initial_state = AliceState::Started {
bob_peer_id,
amounts: swap_amounts,
state3: state3.clone(),
};
let (event_loop, event_loop_handle) = self.init_event_loop()?;
@ -170,31 +188,6 @@ impl Builder {
self.listen_address.clone()
}
async fn make_initial_state(
&self,
btc_to_swap: bitcoin::Amount,
xmr_to_swap: monero::Amount,
) -> Result<AliceState> {
let rng = &mut OsRng;
let amounts = SwapAmounts {
btc: btc_to_swap,
xmr: xmr_to_swap,
};
let state0 = State0::new(
amounts.btc,
amounts.xmr,
self.execution_params.bitcoin_cancel_timelock,
self.execution_params.bitcoin_punish_timelock,
self.bitcoin_wallet.as_ref(),
rng,
)
.await?;
Ok(AliceState::Started { amounts, state0 })
}
fn init_event_loop(&self) -> Result<(EventLoop, EventLoopHandle)> {
let alice_behaviour = Behaviour::default();
let alice_transport = build(self.identity.clone())?;

View File

@ -10,7 +10,7 @@ use libp2p::{
core::Multiaddr, futures::FutureExt, request_response::ResponseChannel, PeerId, Swarm,
};
use tokio::sync::mpsc::{Receiver, Sender};
use tracing::{error, trace};
use tracing::{debug, error, trace};
#[allow(missing_debug_implementations)]
pub struct Channels<T> {
@ -36,7 +36,6 @@ pub struct EventLoopHandle {
done_execution_setup: Receiver<Result<State3>>,
recv_encrypted_signature: Receiver<EncryptedSignature>,
request: Receiver<crate::protocol::alice::swap_response::OutEvent>,
conn_established: Receiver<PeerId>,
send_swap_response: Sender<(ResponseChannel<Response>, SwapResponse)>,
start_execution_setup: Sender<(PeerId, State0)>,
send_transfer_proof: Sender<(PeerId, TransferProof)>,
@ -44,13 +43,6 @@ pub struct EventLoopHandle {
}
impl EventLoopHandle {
pub async fn recv_conn_established(&mut self) -> Result<PeerId> {
self.conn_established
.recv()
.await
.ok_or_else(|| anyhow!("Failed to receive connection established from Bob"))
}
pub async fn execution_setup(&mut self, bob_peer_id: PeerId, state0: State0) -> Result<State3> {
let _ = self
.start_execution_setup
@ -109,7 +101,6 @@ pub struct EventLoop {
done_execution_setup: Sender<Result<State3>>,
recv_encrypted_signature: Sender<EncryptedSignature>,
request: Sender<crate::protocol::alice::swap_response::OutEvent>,
conn_established: Sender<PeerId>,
send_swap_response: Receiver<(ResponseChannel<Response>, SwapResponse)>,
send_transfer_proof: Receiver<(PeerId, TransferProof)>,
recv_transfer_proof_ack: Sender<()>,
@ -135,7 +126,6 @@ impl EventLoop {
let done_execution_setup = Channels::new();
let recv_encrypted_signature = Channels::new();
let request = Channels::new();
let conn_established = Channels::new();
let send_swap_response = Channels::new();
let send_transfer_proof = Channels::new();
let recv_transfer_proof_ack = Channels::new();
@ -146,7 +136,6 @@ impl EventLoop {
done_execution_setup: done_execution_setup.sender,
recv_encrypted_signature: recv_encrypted_signature.sender,
request: request.sender,
conn_established: conn_established.sender,
send_swap_response: send_swap_response.receiver,
send_transfer_proof: send_transfer_proof.receiver,
recv_transfer_proof_ack: recv_transfer_proof_ack.sender,
@ -157,7 +146,6 @@ impl EventLoop {
done_execution_setup: done_execution_setup.receiver,
recv_encrypted_signature: recv_encrypted_signature.receiver,
request: request.receiver,
conn_established: conn_established.receiver,
send_swap_response: send_swap_response.sender,
send_transfer_proof: send_transfer_proof.sender,
recv_transfer_proof_ack: recv_transfer_proof_ack.receiver,
@ -171,8 +159,8 @@ impl EventLoop {
tokio::select! {
swarm_event = self.swarm.next().fuse() => {
match swarm_event {
OutEvent::ConnectionEstablished(alice) => {
let _ = self.conn_established.send(alice).await;
OutEvent::ConnectionEstablished(bob_peer_id) => {
debug!("Connection established with {}", bob_peer_id)
}
OutEvent::ExecutionSetupDone(res) => {
let _ = self.done_execution_setup.send(res.map(|state|*state)).await;

View File

@ -24,10 +24,6 @@ use std::fmt;
#[derive(Debug)]
pub enum AliceState {
Started {
amounts: SwapAmounts,
state0: State0,
},
Negotiated {
bob_peer_id: PeerId,
amounts: SwapAmounts,
state3: Box<State3>,
@ -69,7 +65,6 @@ impl fmt::Display for AliceState {
fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
match self {
AliceState::Started { .. } => write!(f, "started"),
AliceState::Negotiated { .. } => write!(f, "negotiated"),
AliceState::BtcLocked { .. } => write!(f, "btc is locked"),
AliceState::XmrLocked { .. } => write!(f, "xmr is locked"),
AliceState::EncSigLearned { .. } => write!(f, "encrypted signature is learned"),

View File

@ -12,7 +12,7 @@ use crate::{
monero::Transfer,
protocol::{
alice,
alice::{event_loop::EventLoopHandle, SwapResponse, TransferProof},
alice::{event_loop::EventLoopHandle, TransferProof},
SwapAmounts,
},
};
@ -26,43 +26,7 @@ use libp2p::PeerId;
use sha2::Sha256;
use std::sync::Arc;
use tokio::time::timeout;
use tracing::{info, trace};
pub async fn negotiate(
state0: alice::State0,
xmr_amount: monero::Amount,
event_loop_handle: &mut EventLoopHandle,
execution_params: ExecutionParams,
) -> Result<(PeerId, alice::State3)> {
trace!("Starting negotiate");
// todo: we can move this out, we dont need to timeout here
let bob_peer_id = timeout(
execution_params.bob_time_to_act,
event_loop_handle.recv_conn_established(),
)
.await
.context("Failed to receive dial connection from Bob")??;
let event = timeout(
execution_params.bob_time_to_act,
event_loop_handle.recv_request(),
)
.await
.context("Failed to receive swap request from Bob")??;
event_loop_handle
.send_swap_response(event.channel, SwapResponse { xmr_amount })
.await?;
let state3 = timeout(
execution_params.bob_time_to_act,
event_loop_handle.execution_setup(bob_peer_id, state0),
)
.await??;
Ok((bob_peer_id, state3))
}
use tracing::info;
// TODO(Franck): Use helper functions from xmr-btc instead of re-writing them
// here

View File

@ -17,10 +17,10 @@ use crate::{
event_loop::EventLoopHandle,
steps::{
build_bitcoin_punish_transaction, build_bitcoin_redeem_transaction,
extract_monero_private_key, lock_xmr, negotiate,
publish_bitcoin_punish_transaction, publish_bitcoin_redeem_transaction,
publish_cancel_transaction, wait_for_bitcoin_encrypted_signature,
wait_for_bitcoin_refund, wait_for_locked_bitcoin,
extract_monero_private_key, lock_xmr, publish_bitcoin_punish_transaction,
publish_bitcoin_redeem_transaction, publish_cancel_transaction,
wait_for_bitcoin_encrypted_signature, wait_for_bitcoin_refund,
wait_for_locked_bitcoin,
},
AliceState,
},
@ -91,37 +91,7 @@ async fn run_until_internal(
Ok(state)
} else {
match state {
AliceState::Started { amounts, state0 } => {
let (bob_peer_id, state3) = negotiate(
state0,
amounts.xmr,
&mut event_loop_handle,
execution_params,
)
.await?;
let state = AliceState::Negotiated {
bob_peer_id,
amounts,
state3: Box::new(state3),
};
let db_state = (&state).into();
db.insert_latest_state(swap_id, database::Swap::Alice(db_state))
.await?;
run_until_internal(
state,
is_target_state,
event_loop_handle,
bitcoin_wallet,
monero_wallet,
execution_params,
swap_id,
db,
)
.await
}
AliceState::Negotiated {
AliceState::Started {
state3,
bob_peer_id,
amounts,