mirror of
https://github.com/comit-network/xmr-btc-swap.git
synced 2024-10-01 01:45:40 -04:00
Save Alice states in db
This commit is contained in:
parent
238f6a989d
commit
64b021daf4
@ -10,11 +10,15 @@ use crate::{
|
|||||||
wait_for_bitcoin_encrypted_signature, wait_for_bitcoin_refund, wait_for_locked_bitcoin,
|
wait_for_bitcoin_encrypted_signature, wait_for_bitcoin_refund, wait_for_locked_bitcoin,
|
||||||
},
|
},
|
||||||
},
|
},
|
||||||
|
bitcoin,
|
||||||
bitcoin::EncryptedSignature,
|
bitcoin::EncryptedSignature,
|
||||||
network::request_response::AliceToBob,
|
network::request_response::AliceToBob,
|
||||||
|
state,
|
||||||
|
state::{Alice, Swap},
|
||||||
|
storage::Database,
|
||||||
SwapAmounts,
|
SwapAmounts,
|
||||||
};
|
};
|
||||||
use anyhow::Result;
|
use anyhow::{bail, Result};
|
||||||
use async_recursion::async_recursion;
|
use async_recursion::async_recursion;
|
||||||
use futures::{
|
use futures::{
|
||||||
future::{select, Either},
|
future::{select, Either},
|
||||||
@ -22,8 +26,13 @@ use futures::{
|
|||||||
};
|
};
|
||||||
use libp2p::request_response::ResponseChannel;
|
use libp2p::request_response::ResponseChannel;
|
||||||
use rand::{CryptoRng, RngCore};
|
use rand::{CryptoRng, RngCore};
|
||||||
use std::{fmt, sync::Arc};
|
use std::{
|
||||||
|
convert::{TryFrom, TryInto},
|
||||||
|
fmt,
|
||||||
|
sync::Arc,
|
||||||
|
};
|
||||||
use tracing::info;
|
use tracing::info;
|
||||||
|
use uuid::Uuid;
|
||||||
use xmr_btc::{
|
use xmr_btc::{
|
||||||
alice::{State0, State3},
|
alice::{State0, State3},
|
||||||
bitcoin::{TransactionBlockHeight, TxCancel, TxRefund, WatchForRawTransaction},
|
bitcoin::{TransactionBlockHeight, TxCancel, TxRefund, WatchForRawTransaction},
|
||||||
@ -102,12 +111,124 @@ impl fmt::Display for AliceState {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
impl TryFrom<&AliceState> for state::Swap {
|
||||||
|
type Error = anyhow::Error;
|
||||||
|
|
||||||
|
fn try_from(alice_state: &AliceState) -> Result<Self> {
|
||||||
|
use state::{Alice::*, Swap::Alice};
|
||||||
|
|
||||||
|
let state = match alice_state {
|
||||||
|
AliceState::Started { .. } => bail!("Does not support storing `Started state."),
|
||||||
|
AliceState::Negotiated { state3, .. } => Negotiated(state3.clone()),
|
||||||
|
AliceState::BtcLocked { state3, .. } => BtcLocked(state3.clone()),
|
||||||
|
AliceState::XmrLocked { state3 } => XmrLocked(state3.clone()),
|
||||||
|
AliceState::EncSignLearned {
|
||||||
|
state3,
|
||||||
|
encrypted_signature,
|
||||||
|
} => EncSignLearned {
|
||||||
|
state: state3.clone(),
|
||||||
|
encrypted_signature: encrypted_signature.clone(),
|
||||||
|
},
|
||||||
|
AliceState::BtcRedeemed => SwapComplete,
|
||||||
|
AliceState::BtcCancelled { state3, .. } => BtcCancelled(state3.clone()),
|
||||||
|
AliceState::BtcRefunded { .. } => SwapComplete,
|
||||||
|
AliceState::BtcPunishable { state3, .. } => BtcPunishable(state3.clone()),
|
||||||
|
AliceState::XmrRefunded => SwapComplete,
|
||||||
|
// TODO(Franck): it may be more efficient to store the fact that we already want to
|
||||||
|
// abort
|
||||||
|
AliceState::Cancelling { state3 } => XmrLocked(state3.clone()),
|
||||||
|
AliceState::Punished => SwapComplete,
|
||||||
|
AliceState::SafelyAborted => SwapComplete,
|
||||||
|
};
|
||||||
|
|
||||||
|
Ok(Alice(state))
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
impl TryFrom<state::Swap> for AliceState {
|
||||||
|
type Error = anyhow::Error;
|
||||||
|
|
||||||
|
fn try_from(db_state: Swap) -> Result<Self, Self::Error> {
|
||||||
|
use AliceState::*;
|
||||||
|
if let Swap::Alice(state) = db_state {
|
||||||
|
let alice_state = match state {
|
||||||
|
Alice::Negotiated(state3) => Negotiated {
|
||||||
|
channel: None,
|
||||||
|
amounts: SwapAmounts {
|
||||||
|
btc: state3.btc,
|
||||||
|
xmr: state3.xmr,
|
||||||
|
},
|
||||||
|
state3,
|
||||||
|
},
|
||||||
|
Alice::BtcLocked(state3) => BtcLocked {
|
||||||
|
channel: None,
|
||||||
|
amounts: SwapAmounts {
|
||||||
|
btc: state3.btc,
|
||||||
|
xmr: state3.xmr,
|
||||||
|
},
|
||||||
|
state3,
|
||||||
|
},
|
||||||
|
Alice::XmrLocked(state3) => XmrLocked { state3 },
|
||||||
|
Alice::BtcRedeemable { .. } => bail!("BtcRedeemable state is unexpected"),
|
||||||
|
Alice::EncSignLearned {
|
||||||
|
state,
|
||||||
|
encrypted_signature,
|
||||||
|
} => EncSignLearned {
|
||||||
|
state3: state,
|
||||||
|
encrypted_signature,
|
||||||
|
},
|
||||||
|
Alice::BtcCancelled(state) => {
|
||||||
|
let tx_cancel = bitcoin::TxCancel::new(
|
||||||
|
&state.tx_lock,
|
||||||
|
state.refund_timelock,
|
||||||
|
state.a.public(),
|
||||||
|
state.B,
|
||||||
|
);
|
||||||
|
|
||||||
|
BtcCancelled {
|
||||||
|
state3: state,
|
||||||
|
tx_cancel,
|
||||||
|
}
|
||||||
|
}
|
||||||
|
Alice::BtcPunishable(state) => {
|
||||||
|
let tx_cancel = bitcoin::TxCancel::new(
|
||||||
|
&state.tx_lock,
|
||||||
|
state.refund_timelock,
|
||||||
|
state.a.public(),
|
||||||
|
state.B,
|
||||||
|
);
|
||||||
|
let tx_refund = bitcoin::TxRefund::new(&tx_cancel, &state.refund_address);
|
||||||
|
BtcPunishable {
|
||||||
|
tx_refund,
|
||||||
|
state3: state,
|
||||||
|
}
|
||||||
|
}
|
||||||
|
Alice::BtcRefunded {
|
||||||
|
state, spend_key, ..
|
||||||
|
} => BtcRefunded {
|
||||||
|
spend_key,
|
||||||
|
state3: state,
|
||||||
|
},
|
||||||
|
Alice::SwapComplete => {
|
||||||
|
// TODO(Franck): Better fine grain
|
||||||
|
AliceState::SafelyAborted
|
||||||
|
}
|
||||||
|
};
|
||||||
|
Ok(alice_state)
|
||||||
|
} else {
|
||||||
|
bail!("Alice swap state expected.")
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
pub async fn swap(
|
pub async fn swap(
|
||||||
state: AliceState,
|
state: AliceState,
|
||||||
event_loop_handle: EventLoopHandle,
|
event_loop_handle: EventLoopHandle,
|
||||||
bitcoin_wallet: Arc<crate::bitcoin::Wallet>,
|
bitcoin_wallet: Arc<crate::bitcoin::Wallet>,
|
||||||
monero_wallet: Arc<crate::monero::Wallet>,
|
monero_wallet: Arc<crate::monero::Wallet>,
|
||||||
config: Config,
|
config: Config,
|
||||||
|
swap_id: Uuid,
|
||||||
|
db: Database,
|
||||||
) -> Result<(AliceState, EventLoopHandle)> {
|
) -> Result<(AliceState, EventLoopHandle)> {
|
||||||
run_until(
|
run_until(
|
||||||
state,
|
state,
|
||||||
@ -116,6 +237,8 @@ pub async fn swap(
|
|||||||
bitcoin_wallet,
|
bitcoin_wallet,
|
||||||
monero_wallet,
|
monero_wallet,
|
||||||
config,
|
config,
|
||||||
|
swap_id,
|
||||||
|
db,
|
||||||
)
|
)
|
||||||
.await
|
.await
|
||||||
}
|
}
|
||||||
@ -139,6 +262,7 @@ pub fn is_xmr_locked(state: &AliceState) -> bool {
|
|||||||
|
|
||||||
// State machine driver for swap execution
|
// State machine driver for swap execution
|
||||||
#[async_recursion]
|
#[async_recursion]
|
||||||
|
#[allow(clippy::too_many_arguments)]
|
||||||
pub async fn run_until(
|
pub async fn run_until(
|
||||||
state: AliceState,
|
state: AliceState,
|
||||||
is_target_state: fn(&AliceState) -> bool,
|
is_target_state: fn(&AliceState) -> bool,
|
||||||
@ -146,6 +270,8 @@ pub async fn run_until(
|
|||||||
bitcoin_wallet: Arc<crate::bitcoin::Wallet>,
|
bitcoin_wallet: Arc<crate::bitcoin::Wallet>,
|
||||||
monero_wallet: Arc<crate::monero::Wallet>,
|
monero_wallet: Arc<crate::monero::Wallet>,
|
||||||
config: Config,
|
config: Config,
|
||||||
|
swap_id: Uuid,
|
||||||
|
db: Database,
|
||||||
) -> Result<(AliceState, EventLoopHandle)> {
|
) -> Result<(AliceState, EventLoopHandle)> {
|
||||||
info!("Current state:{}", state);
|
info!("Current state:{}", state);
|
||||||
if is_target_state(&state) {
|
if is_target_state(&state) {
|
||||||
@ -156,17 +282,23 @@ pub async fn run_until(
|
|||||||
let (channel, state3) =
|
let (channel, state3) =
|
||||||
negotiate(state0, amounts, &mut event_loop_handle, config).await?;
|
negotiate(state0, amounts, &mut event_loop_handle, config).await?;
|
||||||
|
|
||||||
|
let state = AliceState::Negotiated {
|
||||||
|
channel: Some(channel),
|
||||||
|
amounts,
|
||||||
|
state3,
|
||||||
|
};
|
||||||
|
|
||||||
|
let db_state = (&state).try_into()?;
|
||||||
|
db.insert_latest_state(swap_id, db_state).await?;
|
||||||
run_until(
|
run_until(
|
||||||
AliceState::Negotiated {
|
state,
|
||||||
channel: Some(channel),
|
|
||||||
amounts,
|
|
||||||
state3,
|
|
||||||
},
|
|
||||||
is_target_state,
|
is_target_state,
|
||||||
event_loop_handle,
|
event_loop_handle,
|
||||||
bitcoin_wallet,
|
bitcoin_wallet,
|
||||||
monero_wallet,
|
monero_wallet,
|
||||||
config,
|
config,
|
||||||
|
swap_id,
|
||||||
|
db,
|
||||||
)
|
)
|
||||||
.await
|
.await
|
||||||
}
|
}
|
||||||
@ -175,7 +307,7 @@ pub async fn run_until(
|
|||||||
channel,
|
channel,
|
||||||
amounts,
|
amounts,
|
||||||
} => {
|
} => {
|
||||||
match channel {
|
let state = match channel {
|
||||||
Some(channel) => {
|
Some(channel) => {
|
||||||
let _ = wait_for_locked_bitcoin(
|
let _ = wait_for_locked_bitcoin(
|
||||||
state3.tx_lock.txid(),
|
state3.tx_lock.txid(),
|
||||||
@ -184,128 +316,113 @@ pub async fn run_until(
|
|||||||
)
|
)
|
||||||
.await?;
|
.await?;
|
||||||
|
|
||||||
run_until(
|
AliceState::BtcLocked {
|
||||||
AliceState::BtcLocked {
|
channel: Some(channel),
|
||||||
channel: Some(channel),
|
amounts,
|
||||||
amounts,
|
state3,
|
||||||
state3,
|
}
|
||||||
},
|
|
||||||
is_target_state,
|
|
||||||
event_loop_handle,
|
|
||||||
bitcoin_wallet,
|
|
||||||
monero_wallet,
|
|
||||||
config,
|
|
||||||
)
|
|
||||||
.await
|
|
||||||
}
|
}
|
||||||
None => {
|
None => {
|
||||||
tracing::info!("Cannot resume swap from negotiated state, aborting");
|
tracing::info!("Cannot resume swap from negotiated state, aborting");
|
||||||
|
|
||||||
// Alice did not lock Xmr yet
|
// Alice did not lock Xmr yet
|
||||||
run_until(
|
AliceState::SafelyAborted
|
||||||
AliceState::SafelyAborted,
|
|
||||||
is_target_state,
|
|
||||||
event_loop_handle,
|
|
||||||
bitcoin_wallet,
|
|
||||||
monero_wallet,
|
|
||||||
config,
|
|
||||||
)
|
|
||||||
.await
|
|
||||||
}
|
}
|
||||||
}
|
};
|
||||||
|
|
||||||
|
let db_state = (&state).try_into()?;
|
||||||
|
db.insert_latest_state(swap_id, db_state).await?;
|
||||||
|
run_until(
|
||||||
|
state,
|
||||||
|
is_target_state,
|
||||||
|
event_loop_handle,
|
||||||
|
bitcoin_wallet,
|
||||||
|
monero_wallet,
|
||||||
|
config,
|
||||||
|
swap_id,
|
||||||
|
db,
|
||||||
|
)
|
||||||
|
.await
|
||||||
}
|
}
|
||||||
AliceState::BtcLocked {
|
AliceState::BtcLocked {
|
||||||
channel,
|
channel,
|
||||||
amounts,
|
amounts,
|
||||||
state3,
|
state3,
|
||||||
} => match channel {
|
} => {
|
||||||
Some(channel) => {
|
let state = match channel {
|
||||||
lock_xmr(
|
Some(channel) => {
|
||||||
channel,
|
lock_xmr(
|
||||||
amounts,
|
channel,
|
||||||
state3.clone(),
|
amounts,
|
||||||
&mut event_loop_handle,
|
state3.clone(),
|
||||||
monero_wallet.clone(),
|
&mut event_loop_handle,
|
||||||
)
|
monero_wallet.clone(),
|
||||||
.await?;
|
)
|
||||||
|
.await?;
|
||||||
|
|
||||||
run_until(
|
AliceState::XmrLocked { state3 }
|
||||||
AliceState::XmrLocked { state3 },
|
}
|
||||||
is_target_state,
|
None => {
|
||||||
event_loop_handle,
|
tracing::info!("Cannot resume swap from BTC locked state, aborting");
|
||||||
bitcoin_wallet,
|
|
||||||
monero_wallet,
|
|
||||||
config,
|
|
||||||
)
|
|
||||||
.await
|
|
||||||
}
|
|
||||||
None => {
|
|
||||||
tracing::info!("Cannot resume swap from BTC locked state, aborting");
|
|
||||||
|
|
||||||
// Alice did not lock Xmr yet
|
// Alice did not lock Xmr yet
|
||||||
run_until(
|
AliceState::SafelyAborted
|
||||||
AliceState::SafelyAborted,
|
}
|
||||||
is_target_state,
|
};
|
||||||
event_loop_handle,
|
|
||||||
bitcoin_wallet,
|
let db_state = (&state).try_into()?;
|
||||||
monero_wallet,
|
db.insert_latest_state(swap_id, db_state).await?;
|
||||||
config,
|
run_until(
|
||||||
)
|
state,
|
||||||
.await
|
is_target_state,
|
||||||
}
|
event_loop_handle,
|
||||||
},
|
bitcoin_wallet,
|
||||||
|
monero_wallet,
|
||||||
|
config,
|
||||||
|
swap_id,
|
||||||
|
db,
|
||||||
|
)
|
||||||
|
.await
|
||||||
|
}
|
||||||
AliceState::XmrLocked { state3 } => {
|
AliceState::XmrLocked { state3 } => {
|
||||||
// todo: match statement and wait for t1 can probably be expressed more cleanly
|
// todo: match statement and wait for t1 can probably be expressed more cleanly
|
||||||
match state3.current_epoch(bitcoin_wallet.as_ref()).await? {
|
let state = match state3.current_epoch(bitcoin_wallet.as_ref()).await? {
|
||||||
Epoch::T0 => {
|
Epoch::T0 => {
|
||||||
let wait_for_enc_sig = wait_for_bitcoin_encrypted_signature(
|
let wait_for_enc_sig = wait_for_bitcoin_encrypted_signature(
|
||||||
&mut event_loop_handle,
|
&mut event_loop_handle,
|
||||||
config.monero_max_finality_time,
|
config.monero_max_finality_time,
|
||||||
);
|
);
|
||||||
let t1_timeout = state3.wait_for_t1(bitcoin_wallet.as_ref());
|
let state3_clone = state3.clone();
|
||||||
|
let t1_timeout = state3_clone.wait_for_t1(bitcoin_wallet.as_ref());
|
||||||
|
|
||||||
tokio::select! {
|
pin_mut!(wait_for_enc_sig);
|
||||||
_ = t1_timeout => {
|
pin_mut!(t1_timeout);
|
||||||
run_until(
|
|
||||||
AliceState::Cancelling { state3 },
|
match select(t1_timeout, wait_for_enc_sig).await {
|
||||||
is_target_state,
|
Either::Left(_) => AliceState::Cancelling { state3 },
|
||||||
event_loop_handle,
|
Either::Right((enc_sig, _)) => AliceState::EncSignLearned {
|
||||||
bitcoin_wallet,
|
state3,
|
||||||
monero_wallet,
|
encrypted_signature: enc_sig?,
|
||||||
config,
|
},
|
||||||
)
|
|
||||||
.await
|
|
||||||
}
|
|
||||||
enc_sig = wait_for_enc_sig => {
|
|
||||||
run_until(
|
|
||||||
AliceState::EncSignLearned {
|
|
||||||
state3,
|
|
||||||
encrypted_signature: enc_sig?,
|
|
||||||
},
|
|
||||||
is_target_state,
|
|
||||||
event_loop_handle,
|
|
||||||
bitcoin_wallet,
|
|
||||||
monero_wallet,
|
|
||||||
config,
|
|
||||||
)
|
|
||||||
.await
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
_ => {
|
_ => AliceState::Cancelling { state3 },
|
||||||
run_until(
|
};
|
||||||
AliceState::Cancelling { state3 },
|
|
||||||
is_target_state,
|
|
||||||
event_loop_handle,
|
|
||||||
bitcoin_wallet,
|
|
||||||
monero_wallet,
|
|
||||||
config,
|
|
||||||
)
|
|
||||||
.await
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
|
let db_state = (&state).try_into()?;
|
||||||
|
db.insert_latest_state(swap_id, db_state).await?;
|
||||||
|
run_until(
|
||||||
|
state,
|
||||||
|
is_target_state,
|
||||||
|
event_loop_handle,
|
||||||
|
bitcoin_wallet.clone(),
|
||||||
|
monero_wallet,
|
||||||
|
config,
|
||||||
|
swap_id,
|
||||||
|
db,
|
||||||
|
)
|
||||||
|
.await
|
||||||
|
}
|
||||||
AliceState::EncSignLearned {
|
AliceState::EncSignLearned {
|
||||||
state3,
|
state3,
|
||||||
encrypted_signature,
|
encrypted_signature,
|
||||||
@ -320,13 +437,18 @@ pub async fn run_until(
|
|||||||
) {
|
) {
|
||||||
Ok(tx) => tx,
|
Ok(tx) => tx,
|
||||||
Err(_) => {
|
Err(_) => {
|
||||||
|
let state = AliceState::Cancelling { state3 };
|
||||||
|
let db_state = (&state).try_into()?;
|
||||||
|
db.insert_latest_state(swap_id, db_state).await?;
|
||||||
return run_until(
|
return run_until(
|
||||||
AliceState::Cancelling { state3 },
|
state,
|
||||||
is_target_state,
|
is_target_state,
|
||||||
event_loop_handle,
|
event_loop_handle,
|
||||||
bitcoin_wallet,
|
bitcoin_wallet,
|
||||||
monero_wallet,
|
monero_wallet,
|
||||||
config,
|
config,
|
||||||
|
swap_id,
|
||||||
|
db,
|
||||||
)
|
)
|
||||||
.await;
|
.await;
|
||||||
}
|
}
|
||||||
@ -342,13 +464,18 @@ pub async fn run_until(
|
|||||||
)
|
)
|
||||||
.await?;
|
.await?;
|
||||||
|
|
||||||
|
let state = AliceState::BtcRedeemed;
|
||||||
|
let db_state = (&state).try_into()?;
|
||||||
|
db.insert_latest_state(swap_id, db_state).await?;
|
||||||
run_until(
|
run_until(
|
||||||
AliceState::BtcRedeemed,
|
state,
|
||||||
is_target_state,
|
is_target_state,
|
||||||
event_loop_handle,
|
event_loop_handle,
|
||||||
bitcoin_wallet,
|
bitcoin_wallet,
|
||||||
monero_wallet,
|
monero_wallet,
|
||||||
config,
|
config,
|
||||||
|
swap_id,
|
||||||
|
db,
|
||||||
)
|
)
|
||||||
.await
|
.await
|
||||||
}
|
}
|
||||||
@ -363,13 +490,18 @@ pub async fn run_until(
|
|||||||
)
|
)
|
||||||
.await?;
|
.await?;
|
||||||
|
|
||||||
|
let state = AliceState::BtcCancelled { state3, tx_cancel };
|
||||||
|
let db_state = (&state).try_into()?;
|
||||||
|
db.insert_latest_state(swap_id, db_state).await?;
|
||||||
run_until(
|
run_until(
|
||||||
AliceState::BtcCancelled { state3, tx_cancel },
|
state,
|
||||||
is_target_state,
|
is_target_state,
|
||||||
event_loop_handle,
|
event_loop_handle,
|
||||||
bitcoin_wallet,
|
bitcoin_wallet,
|
||||||
monero_wallet,
|
monero_wallet,
|
||||||
config,
|
config,
|
||||||
|
swap_id,
|
||||||
|
db,
|
||||||
)
|
)
|
||||||
.await
|
.await
|
||||||
}
|
}
|
||||||
@ -390,13 +522,17 @@ pub async fn run_until(
|
|||||||
// TODO(Franck): Review error handling
|
// TODO(Franck): Review error handling
|
||||||
match published_refund_tx {
|
match published_refund_tx {
|
||||||
None => {
|
None => {
|
||||||
run_until(
|
let state = AliceState::BtcPunishable { tx_refund, state3 };
|
||||||
AliceState::BtcPunishable { tx_refund, state3 },
|
let db_state = (&state).try_into()?;
|
||||||
is_target_state,
|
db.insert_latest_state(swap_id, db_state).await?;
|
||||||
|
swap(
|
||||||
|
state,
|
||||||
event_loop_handle,
|
event_loop_handle,
|
||||||
bitcoin_wallet.clone(),
|
bitcoin_wallet.clone(),
|
||||||
monero_wallet,
|
monero_wallet,
|
||||||
config,
|
config,
|
||||||
|
swap_id,
|
||||||
|
db,
|
||||||
)
|
)
|
||||||
.await
|
.await
|
||||||
}
|
}
|
||||||
@ -409,13 +545,18 @@ pub async fn run_until(
|
|||||||
state3.S_b_bitcoin,
|
state3.S_b_bitcoin,
|
||||||
)?;
|
)?;
|
||||||
|
|
||||||
|
let state = AliceState::BtcRefunded { spend_key, state3 };
|
||||||
|
let db_state = (&state).try_into()?;
|
||||||
|
db.insert_latest_state(swap_id, db_state).await?;
|
||||||
run_until(
|
run_until(
|
||||||
AliceState::BtcRefunded { spend_key, state3 },
|
state,
|
||||||
is_target_state,
|
is_target_state,
|
||||||
event_loop_handle,
|
event_loop_handle,
|
||||||
bitcoin_wallet.clone(),
|
bitcoin_wallet.clone(),
|
||||||
monero_wallet,
|
monero_wallet,
|
||||||
config,
|
config,
|
||||||
|
swap_id,
|
||||||
|
db,
|
||||||
)
|
)
|
||||||
.await
|
.await
|
||||||
}
|
}
|
||||||
@ -428,7 +569,10 @@ pub async fn run_until(
|
|||||||
.create_and_load_wallet_for_output(spend_key, view_key)
|
.create_and_load_wallet_for_output(spend_key, view_key)
|
||||||
.await?;
|
.await?;
|
||||||
|
|
||||||
Ok((AliceState::XmrRefunded, event_loop_handle))
|
let state = AliceState::XmrRefunded;
|
||||||
|
let db_state = (&state).try_into()?;
|
||||||
|
db.insert_latest_state(swap_id, db_state).await?;
|
||||||
|
Ok((state, event_loop_handle))
|
||||||
}
|
}
|
||||||
AliceState::BtcPunishable { tx_refund, state3 } => {
|
AliceState::BtcPunishable { tx_refund, state3 } => {
|
||||||
let signed_tx_punish = build_bitcoin_punish_transaction(
|
let signed_tx_punish = build_bitcoin_punish_transaction(
|
||||||
@ -454,13 +598,18 @@ pub async fn run_until(
|
|||||||
|
|
||||||
match select(punish_tx_finalised, refund_tx_seen).await {
|
match select(punish_tx_finalised, refund_tx_seen).await {
|
||||||
Either::Left(_) => {
|
Either::Left(_) => {
|
||||||
|
let state = AliceState::Punished;
|
||||||
|
let db_state = (&state).try_into()?;
|
||||||
|
db.insert_latest_state(swap_id, db_state).await?;
|
||||||
run_until(
|
run_until(
|
||||||
AliceState::Punished,
|
state,
|
||||||
is_target_state,
|
is_target_state,
|
||||||
event_loop_handle,
|
event_loop_handle,
|
||||||
bitcoin_wallet.clone(),
|
bitcoin_wallet.clone(),
|
||||||
monero_wallet,
|
monero_wallet,
|
||||||
config,
|
config,
|
||||||
|
swap_id,
|
||||||
|
db,
|
||||||
)
|
)
|
||||||
.await
|
.await
|
||||||
}
|
}
|
||||||
@ -472,14 +621,18 @@ pub async fn run_until(
|
|||||||
state3.a.clone(),
|
state3.a.clone(),
|
||||||
state3.S_b_bitcoin,
|
state3.S_b_bitcoin,
|
||||||
)?;
|
)?;
|
||||||
|
let state = AliceState::BtcRefunded { spend_key, state3 };
|
||||||
|
let db_state = (&state).try_into()?;
|
||||||
|
db.insert_latest_state(swap_id, db_state).await?;
|
||||||
run_until(
|
run_until(
|
||||||
AliceState::BtcRefunded { spend_key, state3 },
|
state,
|
||||||
is_target_state,
|
is_target_state,
|
||||||
event_loop_handle,
|
event_loop_handle,
|
||||||
bitcoin_wallet.clone(),
|
bitcoin_wallet.clone(),
|
||||||
monero_wallet,
|
monero_wallet,
|
||||||
config,
|
config,
|
||||||
|
swap_id,
|
||||||
|
db,
|
||||||
)
|
)
|
||||||
.await
|
.await
|
||||||
}
|
}
|
||||||
|
@ -117,12 +117,17 @@ async fn main() -> Result<()> {
|
|||||||
let (mut event_loop, handle) =
|
let (mut event_loop, handle) =
|
||||||
alice::event_loop::EventLoop::new(alice_transport, alice_behaviour, listen_addr)?;
|
alice::event_loop::EventLoop::new(alice_transport, alice_behaviour, listen_addr)?;
|
||||||
|
|
||||||
|
let swap_id = Uuid::new_v4();
|
||||||
|
info!("Swap id: {}", swap_id);
|
||||||
|
|
||||||
let swap = alice::swap::swap(
|
let swap = alice::swap::swap(
|
||||||
alice_state,
|
alice_state,
|
||||||
handle,
|
handle,
|
||||||
bitcoin_wallet.clone(),
|
bitcoin_wallet.clone(),
|
||||||
monero_wallet.clone(),
|
monero_wallet.clone(),
|
||||||
config,
|
config,
|
||||||
|
swap_id,
|
||||||
|
db,
|
||||||
);
|
);
|
||||||
|
|
||||||
let _event_loop = tokio::spawn(async move { event_loop.run().await });
|
let _event_loop = tokio::spawn(async move { event_loop.run().await });
|
||||||
|
@ -157,6 +157,8 @@ pub async fn alice_recover(
|
|||||||
}
|
}
|
||||||
};
|
};
|
||||||
}
|
}
|
||||||
|
Alice::EncSignLearned { .. } => unimplemented!("recover method is deprecated"),
|
||||||
|
Alice::BtcCancelled { .. } => unimplemented!("recover method is deprecated"),
|
||||||
Alice::BtcRedeemable { redeem_tx, state } => {
|
Alice::BtcRedeemable { redeem_tx, state } => {
|
||||||
info!("Have the means to redeem the Bitcoin");
|
info!("Have the means to redeem the Bitcoin");
|
||||||
|
|
||||||
|
@ -1,6 +1,6 @@
|
|||||||
use serde::{Deserialize, Serialize};
|
use serde::{Deserialize, Serialize};
|
||||||
use std::fmt::Display;
|
use std::fmt::Display;
|
||||||
use xmr_btc::{alice, bob, monero, serde::monero_private_key};
|
use xmr_btc::{alice, bitcoin::EncryptedSignature, bob, monero, serde::monero_private_key};
|
||||||
|
|
||||||
#[allow(clippy::large_enum_variant)]
|
#[allow(clippy::large_enum_variant)]
|
||||||
#[derive(Clone, Debug, Deserialize, Serialize, PartialEq)]
|
#[derive(Clone, Debug, Deserialize, Serialize, PartialEq)]
|
||||||
@ -15,10 +15,16 @@ pub enum Alice {
|
|||||||
Negotiated(alice::State3),
|
Negotiated(alice::State3),
|
||||||
BtcLocked(alice::State3),
|
BtcLocked(alice::State3),
|
||||||
XmrLocked(alice::State3),
|
XmrLocked(alice::State3),
|
||||||
|
// TODO(Franck): Delete this state as it is not used in alice::swap
|
||||||
BtcRedeemable {
|
BtcRedeemable {
|
||||||
state: alice::State3,
|
state: alice::State3,
|
||||||
redeem_tx: bitcoin::Transaction,
|
redeem_tx: bitcoin::Transaction,
|
||||||
},
|
},
|
||||||
|
EncSignLearned {
|
||||||
|
state: alice::State3,
|
||||||
|
encrypted_signature: EncryptedSignature,
|
||||||
|
},
|
||||||
|
BtcCancelled(alice::State3),
|
||||||
BtcPunishable(alice::State3),
|
BtcPunishable(alice::State3),
|
||||||
BtcRefunded {
|
BtcRefunded {
|
||||||
state: alice::State3,
|
state: alice::State3,
|
||||||
@ -67,9 +73,11 @@ impl Display for Alice {
|
|||||||
Alice::BtcLocked(_) => f.write_str("Bitcoin locked"),
|
Alice::BtcLocked(_) => f.write_str("Bitcoin locked"),
|
||||||
Alice::XmrLocked(_) => f.write_str("Monero locked"),
|
Alice::XmrLocked(_) => f.write_str("Monero locked"),
|
||||||
Alice::BtcRedeemable { .. } => f.write_str("Bitcoin redeemable"),
|
Alice::BtcRedeemable { .. } => f.write_str("Bitcoin redeemable"),
|
||||||
|
Alice::BtcCancelled(_) => f.write_str("Bitcoin cancel transaction published"),
|
||||||
Alice::BtcPunishable(_) => f.write_str("Bitcoin punishable"),
|
Alice::BtcPunishable(_) => f.write_str("Bitcoin punishable"),
|
||||||
Alice::BtcRefunded { .. } => f.write_str("Monero refundable"),
|
Alice::BtcRefunded { .. } => f.write_str("Monero refundable"),
|
||||||
Alice::SwapComplete => f.write_str("Swap complete"),
|
Alice::SwapComplete => f.write_str("Swap complete"),
|
||||||
|
Alice::EncSignLearned { .. } => f.write_str("Encrypted signature learned"),
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -77,12 +77,17 @@ async fn happy_path() {
|
|||||||
)
|
)
|
||||||
.await;
|
.await;
|
||||||
|
|
||||||
|
let alice_db_datadir = tempdir().unwrap();
|
||||||
|
let alice_db = Database::open(alice_db_datadir.path()).unwrap();
|
||||||
|
|
||||||
let alice_swap_fut = alice::swap::swap(
|
let alice_swap_fut = alice::swap::swap(
|
||||||
alice_state,
|
alice_state,
|
||||||
alice_swarm_handle,
|
alice_swarm_handle,
|
||||||
alice_btc_wallet.clone(),
|
alice_btc_wallet.clone(),
|
||||||
alice_xmr_wallet.clone(),
|
alice_xmr_wallet.clone(),
|
||||||
config,
|
config,
|
||||||
|
Uuid::new_v4(),
|
||||||
|
alice_db,
|
||||||
);
|
);
|
||||||
|
|
||||||
let _alice_swarm_fut = tokio::spawn(async move { alice_swarm_driver.run().await });
|
let _alice_swarm_fut = tokio::spawn(async move { alice_swarm_driver.run().await });
|
||||||
@ -188,12 +193,17 @@ async fn alice_punishes_if_bob_never_acts_after_fund() {
|
|||||||
|
|
||||||
let _bob_swarm_fut = tokio::spawn(async move { bob_swarm_driver.run().await });
|
let _bob_swarm_fut = tokio::spawn(async move { bob_swarm_driver.run().await });
|
||||||
|
|
||||||
|
let alice_db_datadir = tempdir().unwrap();
|
||||||
|
let alice_db = Database::open(alice_db_datadir.path()).unwrap();
|
||||||
|
|
||||||
let alice_fut = alice::swap::swap(
|
let alice_fut = alice::swap::swap(
|
||||||
alice_state,
|
alice_state,
|
||||||
alice_swarm_handle,
|
alice_swarm_handle,
|
||||||
alice_btc_wallet.clone(),
|
alice_btc_wallet.clone(),
|
||||||
alice_xmr_wallet.clone(),
|
alice_xmr_wallet.clone(),
|
||||||
Config::regtest(),
|
Config::regtest(),
|
||||||
|
Uuid::new_v4(),
|
||||||
|
alice_db,
|
||||||
);
|
);
|
||||||
|
|
||||||
let _alice_swarm_fut = tokio::spawn(async move { alice_swarm.run().await });
|
let _alice_swarm_fut = tokio::spawn(async move { alice_swarm.run().await });
|
||||||
@ -311,6 +321,8 @@ async fn both_refund() {
|
|||||||
alice_btc_wallet.clone(),
|
alice_btc_wallet.clone(),
|
||||||
alice_xmr_wallet.clone(),
|
alice_xmr_wallet.clone(),
|
||||||
Config::regtest(),
|
Config::regtest(),
|
||||||
|
todo!(),
|
||||||
|
todo!(),
|
||||||
);
|
);
|
||||||
|
|
||||||
tokio::spawn(async move { alice_swarm_driver.run().await });
|
tokio::spawn(async move { alice_swarm_driver.run().await });
|
||||||
@ -331,6 +343,8 @@ async fn both_refund() {
|
|||||||
alice_btc_wallet.clone(),
|
alice_btc_wallet.clone(),
|
||||||
alice_xmr_wallet.clone(),
|
alice_xmr_wallet.clone(),
|
||||||
Config::regtest(),
|
Config::regtest(),
|
||||||
|
todo!(),
|
||||||
|
todo!(),
|
||||||
)
|
)
|
||||||
.await
|
.await
|
||||||
.unwrap();
|
.unwrap();
|
||||||
@ -408,8 +422,8 @@ async fn init_alice(
|
|||||||
xmr: xmr_to_swap,
|
xmr: xmr_to_swap,
|
||||||
};
|
};
|
||||||
|
|
||||||
|
let rng = &mut OsRng;
|
||||||
let (alice_state, alice_behaviour) = {
|
let (alice_state, alice_behaviour) = {
|
||||||
let rng = &mut OsRng;
|
|
||||||
let a = bitcoin::SecretKey::new_random(rng);
|
let a = bitcoin::SecretKey::new_random(rng);
|
||||||
let s_a = cross_curve_dleq::Scalar::random(rng);
|
let s_a = cross_curve_dleq::Scalar::random(rng);
|
||||||
let v_a = xmr_btc::monero::PrivateViewKey::new_random(rng);
|
let v_a = xmr_btc::monero::PrivateViewKey::new_random(rng);
|
||||||
|
Loading…
Reference in New Issue
Block a user