From 934ddb366a8e472f3bf40f9abda3dac8652817e6 Mon Sep 17 00:00:00 2001 From: Lucas Soriano del Pino Date: Mon, 2 Nov 2020 17:14:56 +1100 Subject: [PATCH] Save state for Alice at specific points in the swap --- swap/src/alice.rs | 38 ++++++++++++++++++++++++++++++++++---- swap/src/bob.rs | 11 ----------- swap/src/storage.rs | 33 ++++++++++++++++++--------------- 3 files changed, 52 insertions(+), 30 deletions(-) diff --git a/swap/src/alice.rs b/swap/src/alice.rs index 136f045f..10092169 100644 --- a/swap/src/alice.rs +++ b/swap/src/alice.rs @@ -31,7 +31,7 @@ use crate::{ transport::SwapTransport, TokioExecutor, }, - storage::Database, + storage::{self, Database}, SwapAmounts, PUNISH_TIMELOCK, REFUND_TIMELOCK, }; use xmr_btc::{ @@ -44,7 +44,7 @@ use xmr_btc::{ pub async fn swap( bitcoin_wallet: Arc, monero_wallet: Arc, - _db: Database, + db: Database, listen: Multiaddr, transport: SwapTransport, behaviour: Alice, @@ -175,6 +175,9 @@ pub async fn swap( other => panic!("Unexpected event: {:?}", other), }; + db.insert_latest_state(&storage::Alice::Handshaken(state3.clone())) + .await?; + info!("Handshake complete, we now have State3 for Alice."); let network = Arc::new(Mutex::new(Network { @@ -185,7 +188,7 @@ pub async fn swap( let mut action_generator = action_generator( network.clone(), bitcoin_wallet.clone(), - state3, + state3.clone(), TX_LOCK_MINE_TIMEOUT, ); @@ -200,33 +203,60 @@ pub async fn swap( public_spend_key, public_view_key, }) => { + db.insert_latest_state(&storage::Alice::BtcLocked(state3.clone())) + .await?; + let (transfer_proof, _) = monero_wallet .transfer(public_spend_key, public_view_key, amount) .await?; + db.insert_latest_state(&storage::Alice::XmrLocked(state3.clone())) + .await?; + let mut guard = network.as_ref().lock().await; guard.send_message2(transfer_proof).await; info!("Sent transfer proof"); } GeneratorState::Yielded(Action::RedeemBtc(tx)) => { + db.insert_latest_state(&storage::Alice::BtcRedeemable { + state: state3.clone(), + redeem_tx: tx.clone(), + }) + .await?; + let _ = bitcoin_wallet.broadcast_signed_transaction(tx).await?; } GeneratorState::Yielded(Action::CancelBtc(tx)) => { let _ = bitcoin_wallet.broadcast_signed_transaction(tx).await?; } GeneratorState::Yielded(Action::PunishBtc(tx)) => { + db.insert_latest_state(&storage::Alice::BtcPunishable(state3.clone())) + .await?; + let _ = bitcoin_wallet.broadcast_signed_transaction(tx).await?; } GeneratorState::Yielded(Action::CreateMoneroWalletForOutput { spend_key, view_key, }) => { + db.insert_latest_state(&storage::Alice::BtcRefunded { + state: state3.clone(), + spend_key, + view_key, + }) + .await?; + monero_wallet .create_and_load_wallet_for_output(spend_key, view_key) .await?; } - GeneratorState::Complete(()) => return Ok(()), + GeneratorState::Complete(()) => { + db.insert_latest_state(&storage::Alice::SwapComplete) + .await?; + + return Ok(()); + } } } } diff --git a/swap/src/bob.rs b/swap/src/bob.rs index b1296c7c..c72831f2 100644 --- a/swap/src/bob.rs +++ b/swap/src/bob.rs @@ -174,10 +174,6 @@ pub async fn swap( .await?; } GeneratorState::Yielded(bob::Action::SendBtcRedeemEncsig(tx_redeem_encsig)) => { - // FIXME: We _know_ that this action is only yielded if the monero has been - // locked. This only works because we know that this is the case, but it may be - // cleaner to save the state inside an implementation of `watch_for_transfer` or - // modify the library code to make this easier db.insert_latest_state(&storage::Bob::XmrLocked(state2.clone())) .await?; @@ -198,10 +194,6 @@ pub async fn swap( spend_key, view_key, }) => { - // FIXME: We _know_ that this action is only yielded if the bitcoin has been - // redeemed. This only works because we know that this is the case, but it may - // be cleaner to save the state inside an implementation of `watch_for_transfer` - // or modify the library code to make this easier db.insert_latest_state(&storage::Bob::BtcRedeemed(state2.clone())) .await?; @@ -216,9 +208,6 @@ pub async fn swap( let _ = bitcoin_wallet .broadcast_signed_transaction(tx_cancel) .await?; - - db.insert_latest_state(&storage::Bob::BtcRefundable(state2.clone())) - .await?; } GeneratorState::Yielded(bob::Action::RefundBtc(tx_refund)) => { db.insert_latest_state(&storage::Bob::BtcRefundable(state2.clone())) diff --git a/swap/src/storage.rs b/swap/src/storage.rs index 7c9942e4..21541858 100644 --- a/swap/src/storage.rs +++ b/swap/src/storage.rs @@ -1,17 +1,7 @@ use anyhow::{anyhow, Context, Result}; use serde::{de::DeserializeOwned, Deserialize, Serialize}; use std::path::Path; -use xmr_btc::{alice, bitcoin::EncryptedSignature, bob, serde::monero_private_key}; - -#[derive(Clone, Debug, Deserialize, Serialize)] -pub enum Bob { - Handshaken(bob::State2), - BtcLocked(bob::State2), - XmrLocked(bob::State2), - BtcRedeemed(bob::State2), - BtcRefundable(bob::State2), - SwapComplete, -} +use xmr_btc::{alice, bob, monero, serde::monero_private_key}; #[allow(clippy::large_enum_variant)] #[derive(Clone, Debug, Deserialize, Serialize)] @@ -19,19 +9,30 @@ pub enum Alice { Handshaken(alice::State3), BtcLocked(alice::State3), XmrLocked(alice::State3), - ReceivedEncSig { + BtcRedeemable { state: alice::State3, - enc_sig: EncryptedSignature, + redeem_tx: bitcoin::Transaction, }, - BtcCancelled(alice::State3), + BtcPunishable(alice::State3), BtcRefunded { state: alice::State3, #[serde(with = "monero_private_key")] - s_b: monero::PrivateKey, + spend_key: monero::PrivateKey, + view_key: monero::PrivateViewKey, }, SwapComplete, } +#[derive(Clone, Debug, Deserialize, Serialize)] +pub enum Bob { + Handshaken(bob::State2), + BtcLocked(bob::State2), + XmrLocked(bob::State2), + BtcRedeemed(bob::State2), + BtcRefundable(bob::State2), + SwapComplete, +} + pub struct Database where T: Serialize + DeserializeOwned, @@ -57,6 +58,8 @@ where }) } + // TODO: Add method to update state + pub async fn insert_latest_state(&self, state: &T) -> Result<()> { let key = serialize(&Self::LAST_STATE_KEY)?; let new_value = serialize(&state).context("Could not serialize new state value")?;