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.
This commit is contained in:
Thomas Eizinger 2021-03-18 12:27:08 +11:00
parent d682433ec9
commit 75aec95b0c
No known key found for this signature in database
GPG Key ID: 651AC83A6C6C8B96
4 changed files with 42 additions and 39 deletions

View File

@ -120,12 +120,13 @@ impl Wallet {
Ok(()) Ok(())
} }
pub async fn transfer( pub async fn transfer(&self, request: TransferRequest) -> Result<TransferProof> {
&self, let TransferRequest {
public_spend_key: PublicKey, public_spend_key,
public_view_key: PublicViewKey, public_view_key,
amount: Amount, amount,
) -> Result<TransferProof> { } = request;
let destination_address = let destination_address =
Address::standard(self.network, public_spend_key, public_view_key.into()); 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<Fut>( async fn wait_for_confirmations<Fut>(
txid: String, txid: String,
fetch_tx: impl Fn(String) -> Fut, fetch_tx: impl Fn(String) -> Fut,

View File

@ -2,6 +2,7 @@ use crate::bitcoin::{
current_epoch, CancelTimelock, ExpiredTimelocks, PunishTimelock, TxCancel, TxPunish, TxRefund, current_epoch, CancelTimelock, ExpiredTimelocks, PunishTimelock, TxCancel, TxPunish, TxRefund,
}; };
use crate::env::Config; use crate::env::Config;
use crate::monero::wallet::TransferRequest;
use crate::protocol::alice::{Message1, Message3}; use crate::protocol::alice::{Message1, Message3};
use crate::protocol::bob::{Message0, Message2, Message4}; use crate::protocol::bob::{Message0, Message2, Message4};
use crate::protocol::CROSS_CURVE_PROOF_SYSTEM; 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 { pub fn tx_cancel(&self) -> TxCancel {
TxCancel::new(&self.tx_lock, self.cancel_timelock, self.a.public(), self.B) TxCancel::new(&self.tx_lock, self.cancel_timelock, self.a.public(), self.B)
} }

View File

@ -1,35 +1,7 @@
use crate::bitcoin;
use crate::bitcoin::{CancelTimelock, PunishTimelock, TxCancel, TxLock, TxRefund}; 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}; 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( pub async fn publish_cancel_transaction(
tx_lock: TxLock, tx_lock: TxLock,
a: bitcoin::SecretKey, a: bitcoin::SecretKey,

View File

@ -6,9 +6,7 @@ use crate::env::Config;
use crate::monero_ext::ScalarExt; use crate::monero_ext::ScalarExt;
use crate::protocol::alice; use crate::protocol::alice;
use crate::protocol::alice::event_loop::EventLoopHandle; use crate::protocol::alice::event_loop::EventLoopHandle;
use crate::protocol::alice::steps::{ use crate::protocol::alice::steps::{publish_cancel_transaction, wait_for_bitcoin_refund};
lock_xmr, publish_cancel_transaction, wait_for_bitcoin_refund,
};
use crate::protocol::alice::AliceState; use crate::protocol::alice::AliceState;
use crate::{bitcoin, database, monero}; use crate::{bitcoin, database, monero};
use anyhow::{bail, Context, Result}; use anyhow::{bail, Context, Result};
@ -113,7 +111,18 @@ async fn run_until_internal(
// block 0 for scenarios where we create a refund wallet. // block 0 for scenarios where we create a refund wallet.
let monero_wallet_restore_blockheight = monero_wallet.block_height().await?; 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 { let state = AliceState::XmrLocked {
state3, state3,