Save state for Bob at specific points in the swap

This commit is contained in:
rishflab 2020-11-02 16:00:10 +11:00
parent 5cb2f451d0
commit ea08778b2f
6 changed files with 82 additions and 7 deletions

View File

@ -19,7 +19,7 @@ genawaiter = "0.99.1"
libp2p = { version = "0.29", default-features = false, features = ["tcp-tokio", "yamux", "mplex", "dns", "noise", "request-response"] } libp2p = { version = "0.29", default-features = false, features = ["tcp-tokio", "yamux", "mplex", "dns", "noise", "request-response"] }
libp2p-tokio-socks5 = "0.4" libp2p-tokio-socks5 = "0.4"
log = { version = "0.4", features = ["serde"] } log = { version = "0.4", features = ["serde"] }
monero = "0.9" monero = { version = "0.9", features = ["serde_support"] }
monero-harness = { path = "../monero-harness" } monero-harness = { path = "../monero-harness" }
rand = "0.7" rand = "0.7"
reqwest = { version = "0.10", default-features = false, features = ["socks"] } reqwest = { version = "0.10", default-features = false, features = ["socks"] }

View File

@ -31,6 +31,7 @@ use crate::{
transport::SwapTransport, transport::SwapTransport,
TokioExecutor, TokioExecutor,
}, },
storage::Database,
SwapAmounts, PUNISH_TIMELOCK, REFUND_TIMELOCK, SwapAmounts, PUNISH_TIMELOCK, REFUND_TIMELOCK,
}; };
use xmr_btc::{ use xmr_btc::{
@ -43,6 +44,7 @@ use xmr_btc::{
pub async fn swap( pub async fn swap(
bitcoin_wallet: Arc<bitcoin::Wallet>, bitcoin_wallet: Arc<bitcoin::Wallet>,
monero_wallet: Arc<monero::Wallet>, monero_wallet: Arc<monero::Wallet>,
_db: Database<crate::storage::Alice>,
listen: Multiaddr, listen: Multiaddr,
transport: SwapTransport, transport: SwapTransport,
behaviour: Alice, behaviour: Alice,

View File

@ -22,14 +22,14 @@ mod message3;
use self::{amounts::*, message0::*, message1::*, message2::*, message3::*}; use self::{amounts::*, message0::*, message1::*, message2::*, message3::*};
use crate::{ use crate::{
bitcoin, bitcoin::{self, TX_LOCK_MINE_TIMEOUT},
bitcoin::TX_LOCK_MINE_TIMEOUT,
monero, monero,
network::{ network::{
peer_tracker::{self, PeerTracker}, peer_tracker::{self, PeerTracker},
transport::SwapTransport, transport::SwapTransport,
TokioExecutor, TokioExecutor,
}, },
storage::{self, Database},
Cmd, Rsp, SwapAmounts, PUNISH_TIMELOCK, REFUND_TIMELOCK, Cmd, Rsp, SwapAmounts, PUNISH_TIMELOCK, REFUND_TIMELOCK,
}; };
use xmr_btc::{ use xmr_btc::{
@ -43,6 +43,7 @@ use xmr_btc::{
pub async fn swap( pub async fn swap(
bitcoin_wallet: Arc<bitcoin::Wallet>, bitcoin_wallet: Arc<bitcoin::Wallet>,
monero_wallet: Arc<monero::Wallet>, monero_wallet: Arc<monero::Wallet>,
db: Database<storage::Bob>,
btc: u64, btc: u64,
addr: Multiaddr, addr: Multiaddr,
mut cmd_tx: Sender<Cmd>, mut cmd_tx: Sender<Cmd>,
@ -141,6 +142,9 @@ pub async fn swap(
other => panic!("unexpected event: {:?}", other), other => panic!("unexpected event: {:?}", other),
}; };
db.insert_latest_state(&storage::Bob::Handshaken(state2.clone()))
.await?;
swarm.send_message2(alice.clone(), state2.next_message()); swarm.send_message2(alice.clone(), state2.next_message());
info!("Handshake complete"); info!("Handshake complete");
@ -151,7 +155,7 @@ pub async fn swap(
network.clone(), network.clone(),
monero_wallet.clone(), monero_wallet.clone(),
bitcoin_wallet.clone(), bitcoin_wallet.clone(),
state2, state2.clone(),
TX_LOCK_MINE_TIMEOUT, TX_LOCK_MINE_TIMEOUT,
); );
@ -166,8 +170,17 @@ pub async fn swap(
let _ = bitcoin_wallet let _ = bitcoin_wallet
.broadcast_signed_transaction(signed_tx_lock) .broadcast_signed_transaction(signed_tx_lock)
.await?; .await?;
db.insert_latest_state(&storage::Bob::BtcLocked(state2.clone()))
.await?;
} }
GeneratorState::Yielded(bob::Action::SendBtcRedeemEncsig(tx_redeem_encsig)) => { 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?;
let mut guard = network.as_ref().lock().await; let mut guard = network.as_ref().lock().await;
guard.0.send_message3(alice.clone(), tx_redeem_encsig); guard.0.send_message3(alice.clone(), tx_redeem_encsig);
info!("Sent Bitcoin redeem encsig"); info!("Sent Bitcoin redeem encsig");
@ -185,21 +198,41 @@ pub async fn swap(
spend_key, spend_key,
view_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?;
monero_wallet monero_wallet
.create_and_load_wallet_for_output(spend_key, view_key) .create_and_load_wallet_for_output(spend_key, view_key)
.await?; .await?;
} }
GeneratorState::Yielded(bob::Action::CancelBtc(tx_cancel)) => { GeneratorState::Yielded(bob::Action::CancelBtc(tx_cancel)) => {
db.insert_latest_state(&storage::Bob::BtcRefundable(state2.clone()))
.await?;
let _ = bitcoin_wallet let _ = bitcoin_wallet
.broadcast_signed_transaction(tx_cancel) .broadcast_signed_transaction(tx_cancel)
.await?; .await?;
db.insert_latest_state(&storage::Bob::BtcRefundable(state2.clone()))
.await?;
} }
GeneratorState::Yielded(bob::Action::RefundBtc(tx_refund)) => { GeneratorState::Yielded(bob::Action::RefundBtc(tx_refund)) => {
db.insert_latest_state(&storage::Bob::BtcRefundable(state2.clone()))
.await?;
let _ = bitcoin_wallet let _ = bitcoin_wallet
.broadcast_signed_transaction(tx_refund) .broadcast_signed_transaction(tx_refund)
.await?; .await?;
} }
GeneratorState::Complete(()) => return Ok(()), GeneratorState::Complete(()) => {
db.insert_latest_state(&storage::Bob::SwapComplete).await?;
return Ok(());
}
} }
} }
} }

View File

@ -27,6 +27,7 @@ use swap::{
network::transport::{build, build_tor, SwapTransport}, network::transport::{build, build_tor, SwapTransport},
Cmd, Rsp, SwapAmounts, Cmd, Rsp, SwapAmounts,
}; };
use tempfile::tempdir;
use tracing::info; use tracing::info;
mod cli; mod cli;
@ -80,9 +81,12 @@ async fn main() -> Result<()> {
let monero_wallet = Arc::new(monero::Wallet::new(monerod_url)); let monero_wallet = Arc::new(monero::Wallet::new(monerod_url));
let db = Database::open(db_dir.path()).unwrap();
swap_as_alice( swap_as_alice(
bitcoin_wallet, bitcoin_wallet,
monero_wallet, monero_wallet,
db
listen_addr, listen_addr,
transport, transport,
behaviour, behaviour,
@ -113,9 +117,12 @@ async fn main() -> Result<()> {
let monero_wallet = Arc::new(monero::Wallet::new(monerod_url)); let monero_wallet = Arc::new(monero::Wallet::new(monerod_url));
let db = Database::open(db_dir.path()).unwrap();
swap_as_bob( swap_as_bob(
bitcoin_wallet, bitcoin_wallet,
monero_wallet, monero_wallet,
db
satoshis, satoshis,
alice_addr, alice_addr,
transport, transport,
@ -149,6 +156,7 @@ async fn create_tor_service(
async fn swap_as_alice( async fn swap_as_alice(
bitcoin_wallet: Arc<swap::bitcoin::Wallet>, bitcoin_wallet: Arc<swap::bitcoin::Wallet>,
monero_wallet: Arc<swap::monero::Wallet>, monero_wallet: Arc<swap::monero::Wallet>,
db: Database<storage::Alice>,
addr: Multiaddr, addr: Multiaddr,
transport: SwapTransport, transport: SwapTransport,
behaviour: Alice, behaviour: Alice,
@ -159,6 +167,7 @@ async fn swap_as_alice(
async fn swap_as_bob( async fn swap_as_bob(
bitcoin_wallet: Arc<swap::bitcoin::Wallet>, bitcoin_wallet: Arc<swap::bitcoin::Wallet>,
monero_wallet: Arc<swap::monero::Wallet>, monero_wallet: Arc<swap::monero::Wallet>,
db: Database<storage::Bob>,
sats: u64, sats: u64,
alice: Multiaddr, alice: Multiaddr,
transport: SwapTransport, transport: SwapTransport,
@ -169,6 +178,7 @@ async fn swap_as_bob(
tokio::spawn(bob::swap( tokio::spawn(bob::swap(
bitcoin_wallet, bitcoin_wallet,
monero_wallet, monero_wallet,
db,
sats, sats,
alice, alice,
cmd_tx, cmd_tx,

View File

@ -1,6 +1,36 @@
use anyhow::{anyhow, Context, Result}; use anyhow::{anyhow, Context, Result};
use serde::{de::DeserializeOwned, Serialize}; use serde::{de::DeserializeOwned, Deserialize, Serialize};
use std::path::Path; 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,
}
#[allow(clippy::large_enum_variant)]
#[derive(Clone, Debug, Deserialize, Serialize)]
pub enum Alice {
Handshaken(alice::State3),
BtcLocked(alice::State3),
XmrLocked(alice::State3),
ReceivedEncSig {
state: alice::State3,
enc_sig: EncryptedSignature,
},
BtcCancelled(alice::State3),
BtcRefunded {
state: alice::State3,
#[serde(with = "monero_private_key")]
s_b: monero::PrivateKey,
},
SwapComplete,
}
pub struct Database<T> pub struct Database<T>
where where

View File

@ -495,7 +495,7 @@ impl State1 {
} }
} }
#[derive(Debug, Deserialize, Serialize)] #[derive(Debug, Clone, Deserialize, Serialize)]
pub struct State2 { pub struct State2 {
pub A: bitcoin::PublicKey, pub A: bitcoin::PublicKey,
pub b: bitcoin::SecretKey, pub b: bitcoin::SecretKey,