mirror of
https://github.com/comit-network/xmr-btc-swap.git
synced 2025-06-07 06:33:04 -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_cbor = "0.11"
|
||||||
serde_derive = "1.0"
|
serde_derive = "1.0"
|
||||||
serde_json = "1"
|
serde_json = "1"
|
||||||
|
sha2 = "0.9"
|
||||||
sled = "0.34"
|
sled = "0.34"
|
||||||
structopt = "0.3"
|
structopt = "0.3"
|
||||||
tempfile = "3"
|
tempfile = "3"
|
||||||
|
|
|
@ -3,13 +3,15 @@ use crate::{
|
||||||
state::{Alice, Bob, Swap},
|
state::{Alice, Bob, Swap},
|
||||||
};
|
};
|
||||||
use anyhow::Result;
|
use anyhow::Result;
|
||||||
|
use ecdsa_fun::{adaptor::Adaptor, nonce::Deterministic};
|
||||||
use futures::{
|
use futures::{
|
||||||
future::{select, Either},
|
future::{select, Either},
|
||||||
pin_mut,
|
pin_mut,
|
||||||
};
|
};
|
||||||
|
use sha2::Sha256;
|
||||||
use xmr_btc::bitcoin::{
|
use xmr_btc::bitcoin::{
|
||||||
poll_until_block_height_is_gte, BroadcastSignedTransaction, TransactionBlockHeight, TxCancel,
|
poll_until_block_height_is_gte, BroadcastSignedTransaction, TransactionBlockHeight, TxCancel,
|
||||||
TxPunish, TxRefund, WatchForRawTransaction,
|
TxPunish, TxRedeem, TxRefund, WatchForRawTransaction,
|
||||||
};
|
};
|
||||||
|
|
||||||
pub async fn recover(
|
pub async fn recover(
|
||||||
|
@ -29,7 +31,7 @@ pub async fn alice_recover(
|
||||||
state: Alice,
|
state: Alice,
|
||||||
) -> Result<()> {
|
) -> Result<()> {
|
||||||
match state {
|
match state {
|
||||||
Alice::Handshaken(_) | Alice::BtcLocked(_) | Alice::SwapComplete => Ok(()),
|
Alice::Handshaken(_) | Alice::BtcLocked(_) | Alice::SwapComplete => {}
|
||||||
Alice::XmrLocked(state) => {
|
Alice::XmrLocked(state) => {
|
||||||
let tx_cancel = TxCancel::new(
|
let tx_cancel = TxCancel::new(
|
||||||
&state.tx_lock,
|
&state.tx_lock,
|
||||||
|
@ -131,14 +133,11 @@ pub async fn alice_recover(
|
||||||
.await?;
|
.await?;
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
Ok(())
|
|
||||||
}
|
}
|
||||||
Alice::BtcRedeemable { redeem_tx, .. } => {
|
Alice::BtcRedeemable { redeem_tx, .. } => {
|
||||||
bitcoin_wallet
|
bitcoin_wallet
|
||||||
.broadcast_signed_transaction(redeem_tx)
|
.broadcast_signed_transaction(redeem_tx)
|
||||||
.await?;
|
.await?;
|
||||||
Ok(())
|
|
||||||
}
|
}
|
||||||
Alice::BtcPunishable(state) => {
|
Alice::BtcPunishable(state) => {
|
||||||
let tx_cancel = TxCancel::new(
|
let tx_cancel = TxCancel::new(
|
||||||
|
@ -162,8 +161,6 @@ pub async fn alice_recover(
|
||||||
bitcoin_wallet
|
bitcoin_wallet
|
||||||
.broadcast_signed_transaction(sig_tx_punish)
|
.broadcast_signed_transaction(sig_tx_punish)
|
||||||
.await?;
|
.await?;
|
||||||
|
|
||||||
Ok(())
|
|
||||||
}
|
}
|
||||||
Alice::BtcRefunded {
|
Alice::BtcRefunded {
|
||||||
view_key,
|
view_key,
|
||||||
|
@ -173,15 +170,109 @@ pub async fn alice_recover(
|
||||||
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?;
|
||||||
Ok(())
|
|
||||||
}
|
}
|
||||||
}
|
};
|
||||||
|
|
||||||
|
Ok(())
|
||||||
}
|
}
|
||||||
|
|
||||||
pub async fn bob_recover(
|
pub async fn bob_recover(
|
||||||
_bitcoin_wallet: crate::bitcoin::Wallet,
|
bitcoin_wallet: crate::bitcoin::Wallet,
|
||||||
_monero_wallet: crate::monero::Wallet,
|
monero_wallet: crate::monero::Wallet,
|
||||||
_state: Bob,
|
state: Bob,
|
||||||
) -> Result<()> {
|
) -> 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