From 75aec95b0ce29ceeb0b61fd2f115f69375f0e228 Mon Sep 17 00:00:00 2001 From: Thomas Eizinger Date: Thu, 18 Mar 2021 12:27:08 +1100 Subject: [PATCH] Introduce monero::TransferRequest This allows us to move critical crypto logic onto `State3` which holds all the necessary data which consequently allows us to get rid of `lock_xmr` altogether by inlining it into the swap function. The reduced indirection improves readability. --- swap/src/monero/wallet.rs | 20 ++++++++++++++------ swap/src/protocol/alice/state.rs | 14 ++++++++++++++ swap/src/protocol/alice/steps.rs | 30 +----------------------------- swap/src/protocol/alice/swap.rs | 17 +++++++++++++---- 4 files changed, 42 insertions(+), 39 deletions(-) diff --git a/swap/src/monero/wallet.rs b/swap/src/monero/wallet.rs index 764235c9..61894b99 100644 --- a/swap/src/monero/wallet.rs +++ b/swap/src/monero/wallet.rs @@ -120,12 +120,13 @@ impl Wallet { Ok(()) } - pub async fn transfer( - &self, - public_spend_key: PublicKey, - public_view_key: PublicViewKey, - amount: Amount, - ) -> Result { + pub async fn transfer(&self, request: TransferRequest) -> Result { + let TransferRequest { + public_spend_key, + public_view_key, + amount, + } = request; + let destination_address = Address::standard(self.network, public_spend_key, public_view_key.into()); @@ -222,6 +223,13 @@ impl Wallet { } } +#[derive(Debug)] +pub struct TransferRequest { + pub public_spend_key: PublicKey, + pub public_view_key: PublicViewKey, + pub amount: Amount, +} + async fn wait_for_confirmations( txid: String, fetch_tx: impl Fn(String) -> Fut, diff --git a/swap/src/protocol/alice/state.rs b/swap/src/protocol/alice/state.rs index e961a13b..bc443f03 100644 --- a/swap/src/protocol/alice/state.rs +++ b/swap/src/protocol/alice/state.rs @@ -2,6 +2,7 @@ use crate::bitcoin::{ current_epoch, CancelTimelock, ExpiredTimelocks, PunishTimelock, TxCancel, TxPunish, TxRefund, }; use crate::env::Config; +use crate::monero::wallet::TransferRequest; use crate::protocol::alice::{Message1, Message3}; use crate::protocol::bob::{Message0, Message2, Message4}; use crate::protocol::CROSS_CURVE_PROOF_SYSTEM; @@ -343,6 +344,19 @@ impl State3 { )) } + pub fn lock_xmr_transfer_request(&self) -> TransferRequest { + let S_a = monero::PublicKey::from_private_key(&monero::PrivateKey { scalar: self.s_a }); + + let public_spend_key = S_a + self.S_b_monero; + let public_view_key = self.v.public(); + + TransferRequest { + public_spend_key, + public_view_key, + amount: self.xmr, + } + } + pub fn tx_cancel(&self) -> TxCancel { TxCancel::new(&self.tx_lock, self.cancel_timelock, self.a.public(), self.B) } diff --git a/swap/src/protocol/alice/steps.rs b/swap/src/protocol/alice/steps.rs index e6d900f4..85075f8d 100644 --- a/swap/src/protocol/alice/steps.rs +++ b/swap/src/protocol/alice/steps.rs @@ -1,35 +1,7 @@ +use crate::bitcoin; use crate::bitcoin::{CancelTimelock, PunishTimelock, TxCancel, TxLock, TxRefund}; -use crate::protocol::alice; -use crate::protocol::alice::event_loop::EventLoopHandle; -use crate::{bitcoin, monero}; use anyhow::{bail, Result}; -pub async fn lock_xmr( - state3: alice::State3, - event_loop_handle: &mut EventLoopHandle, - monero_wallet: &monero::Wallet, -) -> Result<()> { - let S_a = monero::PublicKey::from_private_key(&monero::PrivateKey { scalar: state3.s_a }); - - let public_spend_key = S_a + state3.S_b_monero; - let public_view_key = state3.v.public(); - - let transfer_proof = monero_wallet - .transfer(public_spend_key, public_view_key, state3.xmr) - .await?; - - // TODO(Franck): Wait for Monero to be confirmed once - // Waiting for XMR confirmations should not be done in here, but in a separate - // state! We have to record that Alice has already sent the transaction. - // Otherwise Alice might publish the lock tx twice! - - event_loop_handle - .send_transfer_proof(transfer_proof) - .await?; - - Ok(()) -} - pub async fn publish_cancel_transaction( tx_lock: TxLock, a: bitcoin::SecretKey, diff --git a/swap/src/protocol/alice/swap.rs b/swap/src/protocol/alice/swap.rs index fcd5885f..52c6ae92 100644 --- a/swap/src/protocol/alice/swap.rs +++ b/swap/src/protocol/alice/swap.rs @@ -6,9 +6,7 @@ use crate::env::Config; use crate::monero_ext::ScalarExt; use crate::protocol::alice; use crate::protocol::alice::event_loop::EventLoopHandle; -use crate::protocol::alice::steps::{ - lock_xmr, publish_cancel_transaction, wait_for_bitcoin_refund, -}; +use crate::protocol::alice::steps::{publish_cancel_transaction, wait_for_bitcoin_refund}; use crate::protocol::alice::AliceState; use crate::{bitcoin, database, monero}; use anyhow::{bail, Context, Result}; @@ -113,7 +111,18 @@ async fn run_until_internal( // block 0 for scenarios where we create a refund wallet. let monero_wallet_restore_blockheight = monero_wallet.block_height().await?; - lock_xmr(*state3.clone(), &mut event_loop_handle, &monero_wallet).await?; + let transfer_proof = monero_wallet + .transfer(state3.lock_xmr_transfer_request()) + .await?; + + // TODO(Franck): Wait for Monero to be confirmed once + // Waiting for XMR confirmations should not be done in here, but in a separate + // state! We have to record that Alice has already sent the transaction. + // Otherwise Alice might publish the lock tx twice! + + event_loop_handle + .send_transfer_proof(transfer_proof) + .await?; let state = AliceState::XmrLocked { state3,