mirror of
				https://github.com/comit-network/xmr-btc-swap.git
				synced 2025-10-30 14:39:12 -04:00 
			
		
		
		
	Implement swap recover function for Bob
This commit is contained in:
		
							parent
							
								
									28225f8643
								
							
						
					
					
						commit
						6db40dce2a
					
				
					 2 changed files with 105 additions and 13 deletions
				
			
		|  | @ -29,6 +29,7 @@ serde = { version = "1", features = ["derive"] } | |||
| serde_cbor = "0.11" | ||||
| serde_derive = "1.0" | ||||
| serde_json = "1" | ||||
| sha2 = "0.9" | ||||
| sled = "0.34" | ||||
| structopt = "0.3" | ||||
| tempfile = "3" | ||||
|  |  | |||
|  | @ -3,13 +3,15 @@ use crate::{ | |||
|     state::{Alice, Bob, Swap}, | ||||
| }; | ||||
| use anyhow::Result; | ||||
| use ecdsa_fun::{adaptor::Adaptor, nonce::Deterministic}; | ||||
| use futures::{ | ||||
|     future::{select, Either}, | ||||
|     pin_mut, | ||||
| }; | ||||
| use sha2::Sha256; | ||||
| use xmr_btc::bitcoin::{ | ||||
|     poll_until_block_height_is_gte, BroadcastSignedTransaction, TransactionBlockHeight, TxCancel, | ||||
|     TxPunish, TxRefund, WatchForRawTransaction, | ||||
|     TxPunish, TxRedeem, TxRefund, WatchForRawTransaction, | ||||
| }; | ||||
| 
 | ||||
| pub async fn recover( | ||||
|  | @ -29,7 +31,7 @@ pub async fn alice_recover( | |||
|     state: Alice, | ||||
| ) -> Result<()> { | ||||
|     match state { | ||||
|         Alice::Handshaken(_) | Alice::BtcLocked(_) | Alice::SwapComplete => Ok(()), | ||||
|         Alice::Handshaken(_) | Alice::BtcLocked(_) | Alice::SwapComplete => {} | ||||
|         Alice::XmrLocked(state) => { | ||||
|             let tx_cancel = TxCancel::new( | ||||
|                 &state.tx_lock, | ||||
|  | @ -131,14 +133,11 @@ pub async fn alice_recover( | |||
|                         .await?; | ||||
|                 } | ||||
|             }; | ||||
| 
 | ||||
|             Ok(()) | ||||
|         } | ||||
|         Alice::BtcRedeemable { redeem_tx, .. } => { | ||||
|             bitcoin_wallet | ||||
|                 .broadcast_signed_transaction(redeem_tx) | ||||
|                 .await?; | ||||
|             Ok(()) | ||||
|         } | ||||
|         Alice::BtcPunishable(state) => { | ||||
|             let tx_cancel = TxCancel::new( | ||||
|  | @ -162,8 +161,6 @@ pub async fn alice_recover( | |||
|             bitcoin_wallet | ||||
|                 .broadcast_signed_transaction(sig_tx_punish) | ||||
|                 .await?; | ||||
| 
 | ||||
|             Ok(()) | ||||
|         } | ||||
|         Alice::BtcRefunded { | ||||
|             view_key, | ||||
|  | @ -173,15 +170,109 @@ pub async fn alice_recover( | |||
|             monero_wallet | ||||
|                 .create_and_load_wallet_for_output(spend_key, view_key) | ||||
|                 .await?; | ||||
|             Ok(()) | ||||
|         } | ||||
|     } | ||||
|     }; | ||||
| 
 | ||||
|     Ok(()) | ||||
| } | ||||
| 
 | ||||
| pub async fn bob_recover( | ||||
|     _bitcoin_wallet: crate::bitcoin::Wallet, | ||||
|     _monero_wallet: crate::monero::Wallet, | ||||
|     _state: Bob, | ||||
|     bitcoin_wallet: crate::bitcoin::Wallet, | ||||
|     monero_wallet: crate::monero::Wallet, | ||||
|     state: Bob, | ||||
| ) -> Result<()> { | ||||
|     todo!() | ||||
|     match state { | ||||
|         Bob::Handshaken(_) | Bob::SwapComplete => {} | ||||
|         Bob::BtcLocked(state) | Bob::XmrLocked(state) | Bob::BtcRefundable(state) => { | ||||
|             let tx_cancel = TxCancel::new( | ||||
|                 &state.tx_lock, | ||||
|                 state.refund_timelock, | ||||
|                 state.A.clone(), | ||||
|                 state.b.public(), | ||||
|             ); | ||||
| 
 | ||||
|             // Ensure that TxCancel is on the blockchain
 | ||||
|             if bitcoin_wallet | ||||
|                 .0 | ||||
|                 .get_raw_transaction(tx_cancel.txid()) | ||||
|                 .await | ||||
|                 .is_err() | ||||
|             { | ||||
|                 let tx_lock_height = bitcoin_wallet | ||||
|                     .transaction_block_height(state.tx_lock.txid()) | ||||
|                     .await; | ||||
|                 poll_until_block_height_is_gte( | ||||
|                     &bitcoin_wallet, | ||||
|                     tx_lock_height + state.refund_timelock, | ||||
|                 ) | ||||
|                 .await; | ||||
| 
 | ||||
|                 let sig_a = state.tx_cancel_sig_a.clone(); | ||||
|                 let sig_b = state.b.sign(tx_cancel.digest()); | ||||
| 
 | ||||
|                 let tx_cancel = tx_cancel | ||||
|                     .clone() | ||||
|                     .add_signatures( | ||||
|                         &state.tx_lock, | ||||
|                         (state.A.clone(), sig_a), | ||||
|                         (state.b.public(), sig_b), | ||||
|                     ) | ||||
|                     .expect("sig_{a,b} to be valid signatures for tx_cancel"); | ||||
| 
 | ||||
|                 // TODO: We should not fail if the transaction is already on the blockchain
 | ||||
|                 bitcoin_wallet | ||||
|                     .broadcast_signed_transaction(tx_cancel) | ||||
|                     .await?; | ||||
|             } | ||||
| 
 | ||||
|             let tx_refund = TxRefund::new(&tx_cancel, &state.refund_address); | ||||
|             let signed_tx_refund = { | ||||
|                 let adaptor = Adaptor::<Sha256, Deterministic<Sha256>>::default(); | ||||
|                 let sig_a = adaptor | ||||
|                     .decrypt_signature(&state.s_b.into_secp256k1(), state.tx_refund_encsig.clone()); | ||||
|                 let sig_b = state.b.sign(tx_refund.digest()); | ||||
| 
 | ||||
|                 tx_refund | ||||
|                     .add_signatures( | ||||
|                         &tx_cancel, | ||||
|                         (state.A.clone(), sig_a), | ||||
|                         (state.b.public(), sig_b), | ||||
|                     ) | ||||
|                     .expect("sig_{a,b} to be valid signatures for tx_refund") | ||||
|             }; | ||||
| 
 | ||||
|             bitcoin_wallet | ||||
|                 .broadcast_signed_transaction(signed_tx_refund) | ||||
|                 .await?; | ||||
|         } | ||||
|         Bob::BtcRedeemed(state) => { | ||||
|             let tx_redeem = TxRedeem::new(&state.tx_lock, &state.redeem_address); | ||||
|             let tx_redeem_published = bitcoin_wallet | ||||
|                 .0 | ||||
|                 .get_raw_transaction(tx_redeem.txid()) | ||||
|                 .await?; | ||||
| 
 | ||||
|             let tx_redeem_encsig = state | ||||
|                 .b | ||||
|                 .encsign(state.S_a_bitcoin.clone(), tx_redeem.digest()); | ||||
|             let tx_redeem_sig = | ||||
|                 tx_redeem.extract_signature_by_key(tx_redeem_published, state.b.public())?; | ||||
| 
 | ||||
|             let s_a = | ||||
|                 xmr_btc::bitcoin::recover(state.S_a_bitcoin, tx_redeem_sig, tx_redeem_encsig)?; | ||||
|             let s_a = monero::PrivateKey::from_scalar( | ||||
|                 xmr_btc::monero::Scalar::from_bytes_mod_order(s_a.to_bytes()), | ||||
|             ); | ||||
| 
 | ||||
|             let s_b = monero::PrivateKey { | ||||
|                 scalar: state.s_b.into_ed25519(), | ||||
|             }; | ||||
| 
 | ||||
|             monero_wallet | ||||
|                 .create_and_load_wallet_for_output(s_a + s_b, state.v) | ||||
|                 .await?; | ||||
|         } | ||||
|     }; | ||||
| 
 | ||||
|     Ok(()) | ||||
| } | ||||
|  |  | |||
		Loading…
	
	Add table
		Add a link
		
	
		Reference in a new issue
	
	 Lucas Soriano del Pino
						Lucas Soriano del Pino