diff --git a/swap/src/database/alice.rs b/swap/src/database/alice.rs index 9af07122..b76e1f85 100644 --- a/swap/src/database/alice.rs +++ b/swap/src/database/alice.rs @@ -30,27 +30,33 @@ pub enum Alice { }, XmrLockTransferProofSent { monero_wallet_restore_blockheight: BlockHeight, + transfer_proof: TransferProof, state3: alice::State3, }, EncSigLearned { monero_wallet_restore_blockheight: BlockHeight, + transfer_proof: TransferProof, encrypted_signature: EncryptedSignature, state3: alice::State3, }, CancelTimelockExpired { monero_wallet_restore_blockheight: BlockHeight, + transfer_proof: TransferProof, state3: alice::State3, }, BtcCancelled { monero_wallet_restore_blockheight: BlockHeight, + transfer_proof: TransferProof, state3: alice::State3, }, BtcPunishable { monero_wallet_restore_blockheight: BlockHeight, + transfer_proof: TransferProof, state3: alice::State3, }, BtcRefunded { monero_wallet_restore_blockheight: BlockHeight, + transfer_proof: TransferProof, state3: alice::State3, #[serde(with = "monero_private_key")] spend_key: monero::PrivateKey, @@ -95,52 +101,62 @@ impl From<&AliceState> for Alice { }, AliceState::XmrLockTransferProofSent { monero_wallet_restore_blockheight, + transfer_proof, state3, } => Alice::XmrLockTransferProofSent { monero_wallet_restore_blockheight: *monero_wallet_restore_blockheight, + transfer_proof: transfer_proof.clone(), state3: state3.as_ref().clone(), }, AliceState::EncSigLearned { monero_wallet_restore_blockheight, + transfer_proof, state3, encrypted_signature, } => Alice::EncSigLearned { monero_wallet_restore_blockheight: *monero_wallet_restore_blockheight, + transfer_proof: transfer_proof.clone(), state3: state3.as_ref().clone(), encrypted_signature: *encrypted_signature.clone(), }, AliceState::BtcRedeemed => Alice::Done(AliceEndState::BtcRedeemed), AliceState::BtcCancelled { monero_wallet_restore_blockheight, + transfer_proof, state3, - .. } => Alice::BtcCancelled { monero_wallet_restore_blockheight: *monero_wallet_restore_blockheight, + transfer_proof: transfer_proof.clone(), state3: state3.as_ref().clone(), }, AliceState::BtcRefunded { monero_wallet_restore_blockheight, + transfer_proof, spend_key, state3, } => Alice::BtcRefunded { monero_wallet_restore_blockheight: *monero_wallet_restore_blockheight, + transfer_proof: transfer_proof.clone(), spend_key: *spend_key, state3: state3.as_ref().clone(), }, AliceState::BtcPunishable { monero_wallet_restore_blockheight, + transfer_proof, state3, - .. } => Alice::BtcPunishable { monero_wallet_restore_blockheight: *monero_wallet_restore_blockheight, + transfer_proof: transfer_proof.clone(), state3: state3.as_ref().clone(), }, AliceState::XmrRefunded => Alice::Done(AliceEndState::XmrRefunded), AliceState::CancelTimelockExpired { monero_wallet_restore_blockheight, + transfer_proof, state3, } => Alice::CancelTimelockExpired { monero_wallet_restore_blockheight: *monero_wallet_restore_blockheight, + transfer_proof: transfer_proof.clone(), state3: state3.as_ref().clone(), }, AliceState::BtcPunished => Alice::Done(AliceEndState::BtcPunished), @@ -178,48 +194,60 @@ impl From for AliceState { }, Alice::XmrLockTransferProofSent { monero_wallet_restore_blockheight, + transfer_proof, state3, } => AliceState::XmrLockTransferProofSent { monero_wallet_restore_blockheight, + transfer_proof, state3: Box::new(state3), }, Alice::EncSigLearned { monero_wallet_restore_blockheight, + transfer_proof, state3: state, encrypted_signature, } => AliceState::EncSigLearned { monero_wallet_restore_blockheight, + transfer_proof, state3: Box::new(state), encrypted_signature: Box::new(encrypted_signature), }, Alice::CancelTimelockExpired { monero_wallet_restore_blockheight, + transfer_proof, state3, } => AliceState::CancelTimelockExpired { monero_wallet_restore_blockheight, + transfer_proof, state3: Box::new(state3), }, Alice::BtcCancelled { monero_wallet_restore_blockheight, + transfer_proof, state3, } => AliceState::BtcCancelled { monero_wallet_restore_blockheight, + transfer_proof, state3: Box::new(state3), }, Alice::BtcPunishable { monero_wallet_restore_blockheight, + transfer_proof, state3, } => AliceState::BtcPunishable { monero_wallet_restore_blockheight, + transfer_proof, state3: Box::new(state3), }, Alice::BtcRefunded { monero_wallet_restore_blockheight, - state3, + transfer_proof, spend_key, + state3, } => AliceState::BtcRefunded { monero_wallet_restore_blockheight, + transfer_proof, spend_key, state3: Box::new(state3), }, diff --git a/swap/src/protocol/alice/state.rs b/swap/src/protocol/alice/state.rs index d771b156..4a6194fb 100644 --- a/swap/src/protocol/alice/state.rs +++ b/swap/src/protocol/alice/state.rs @@ -34,30 +34,36 @@ pub enum AliceState { }, XmrLockTransferProofSent { monero_wallet_restore_blockheight: BlockHeight, + transfer_proof: TransferProof, state3: Box, }, EncSigLearned { monero_wallet_restore_blockheight: BlockHeight, + transfer_proof: TransferProof, encrypted_signature: Box, state3: Box, }, BtcRedeemed, BtcCancelled { monero_wallet_restore_blockheight: BlockHeight, + transfer_proof: TransferProof, state3: Box, }, BtcRefunded { monero_wallet_restore_blockheight: BlockHeight, + transfer_proof: TransferProof, spend_key: monero::PrivateKey, state3: Box, }, BtcPunishable { monero_wallet_restore_blockheight: BlockHeight, + transfer_proof: TransferProof, state3: Box, }, XmrRefunded, CancelTimelockExpired { monero_wallet_restore_blockheight: BlockHeight, + transfer_proof: TransferProof, state3: Box, }, BtcPunished, diff --git a/swap/src/protocol/alice/swap.rs b/swap/src/protocol/alice/swap.rs index 98333390..6bfc8af1 100644 --- a/swap/src/protocol/alice/swap.rs +++ b/swap/src/protocol/alice/swap.rs @@ -101,9 +101,9 @@ async fn next_state( .await?; AliceState::XmrLockTransactionSent { - state3, - transfer_proof, monero_wallet_restore_blockheight, + transfer_proof, + state3, } } _ => AliceState::SafelyAborted, @@ -120,47 +120,44 @@ async fn next_state( .await?; AliceState::XmrLocked { - state3, monero_wallet_restore_blockheight, transfer_proof, + state3, } } _ => AliceState::CancelTimelockExpired { - state3, monero_wallet_restore_blockheight, + transfer_proof, + state3, }, }, AliceState::XmrLocked { - state3, - transfer_proof, monero_wallet_restore_blockheight, + transfer_proof, + state3, } => match state3.expired_timelocks(bitcoin_wallet).await? { ExpiredTimelocks::None => { event_loop_handle .send_transfer_proof(transfer_proof.clone()) .await?; - // TODO: Handle this upon refund instead. - // Make sure that the balance of the created wallet is unlocked instead of - // watching for transfer. - monero_wallet - .watch_for_transfer(state3.lock_xmr_watch_request(transfer_proof, 10)) - .await?; - XmrLockTransferProofSent { - state3, monero_wallet_restore_blockheight, + transfer_proof, + state3, } } _ => AliceState::CancelTimelockExpired { - state3, monero_wallet_restore_blockheight, + transfer_proof, + state3, }, }, AliceState::XmrLockTransferProofSent { - state3, monero_wallet_restore_blockheight, + transfer_proof, + state3, } => { let tx_lock_status = bitcoin_wallet.subscribe_to(state3.tx_lock.clone()).await; @@ -168,32 +165,36 @@ async fn next_state( ExpiredTimelocks::None => { select! { _ = tx_lock_status.wait_until_confirmed_with(state3.cancel_timelock) => { - AliceState::CancelTimelockExpired { - state3, - monero_wallet_restore_blockheight, + AliceState::CancelTimelockExpired { + monero_wallet_restore_blockheight, + transfer_proof, + state3, } } enc_sig = event_loop_handle.recv_encrypted_signature() => { tracing::info!("Received encrypted signature"); AliceState::EncSigLearned { - state3, - encrypted_signature: Box::new(enc_sig?), monero_wallet_restore_blockheight, + transfer_proof, + encrypted_signature: Box::new(enc_sig?), + state3, } } } } _ => AliceState::CancelTimelockExpired { - state3, monero_wallet_restore_blockheight, + transfer_proof, + state3, }, } } AliceState::EncSigLearned { - state3, - encrypted_signature, monero_wallet_restore_blockheight, + transfer_proof, + encrypted_signature, + state3, } => match state3.expired_timelocks(bitcoin_wallet).await? { ExpiredTimelocks::None => { let tx_lock_status = bitcoin_wallet.subscribe_to(state3.tx_lock.clone()).await; @@ -212,8 +213,9 @@ async fn next_state( .await?; AliceState::CancelTimelockExpired { - state3, monero_wallet_restore_blockheight, + transfer_proof, + state3, } } }, @@ -224,20 +226,23 @@ async fn next_state( .await?; AliceState::CancelTimelockExpired { - state3, monero_wallet_restore_blockheight, + transfer_proof, + state3, } } } } _ => AliceState::CancelTimelockExpired { - state3, monero_wallet_restore_blockheight, + transfer_proof, + state3, }, }, AliceState::CancelTimelockExpired { - state3, monero_wallet_restore_blockheight, + transfer_proof, + state3, } => { let transaction = state3.signed_cancel_transaction()?; @@ -259,13 +264,15 @@ async fn next_state( } AliceState::BtcCancelled { - state3, monero_wallet_restore_blockheight, + transfer_proof, + state3, } } AliceState::BtcCancelled { - state3, monero_wallet_restore_blockheight, + transfer_proof, + state3, } => { let tx_refund_status = bitcoin_wallet.subscribe_to(state3.tx_refund()).await; let tx_cancel_status = bitcoin_wallet.subscribe_to(state3.tx_cancel()).await; @@ -278,26 +285,35 @@ async fn next_state( let spend_key = state3.extract_monero_private_key(published_refund_tx)?; AliceState::BtcRefunded { + monero_wallet_restore_blockheight, + transfer_proof, spend_key, state3, - monero_wallet_restore_blockheight, } } _ = tx_cancel_status.wait_until_confirmed_with(state3.punish_timelock) => { AliceState::BtcPunishable { - state3, monero_wallet_restore_blockheight, + transfer_proof, + state3, } } } } AliceState::BtcRefunded { + monero_wallet_restore_blockheight, + transfer_proof, spend_key, state3, - monero_wallet_restore_blockheight, } => { let view_key = state3.v; + // Ensure that the XMR to be refunded are spendable by awaiting 10 confirmations + // on the lock transaction + monero_wallet + .watch_for_transfer(state3.lock_xmr_watch_request(transfer_proof, 10)) + .await?; + monero_wallet .create_from(spend_key, view_key, monero_wallet_restore_blockheight) .await?; @@ -305,8 +321,9 @@ async fn next_state( AliceState::XmrRefunded } AliceState::BtcPunishable { - state3, monero_wallet_restore_blockheight, + transfer_proof, + state3, } => { let signed_tx_punish = state3.signed_punish_transaction()?; @@ -341,9 +358,10 @@ async fn next_state( let spend_key = state3.extract_monero_private_key(published_refund_tx)?; AliceState::BtcRefunded { + monero_wallet_restore_blockheight, + transfer_proof, spend_key, state3, - monero_wallet_restore_blockheight, } } }