fix (Bob): Check if Bitcoin redeem transaction was published before transitioning to CancelTimelockExpired

This commit is contained in:
pokkst 2023-08-12 22:20:54 -05:00 committed by binarybaron
parent 1930540c1f
commit 1f40ee739d
2 changed files with 38 additions and 0 deletions

View File

@ -489,6 +489,30 @@ pub struct State4 {
}
impl State4 {
pub async fn check_for_tx_redeem(
&self,
bitcoin_wallet: &bitcoin::Wallet,
) -> Result<State5> {
let tx_redeem =
bitcoin::TxRedeem::new(&self.tx_lock, &self.redeem_address, self.tx_redeem_fee);
let tx_redeem_encsig = self.b.encsign(self.S_a_bitcoin, tx_redeem.digest());
let tx_redeem_candidate = bitcoin_wallet.get_raw_transaction(tx_redeem.txid()).await?;
let tx_redeem_sig =
tx_redeem.extract_signature_by_key(tx_redeem_candidate, self.b.public())?;
let s_a = bitcoin::recover(self.S_a_bitcoin, tx_redeem_sig, tx_redeem_encsig)?;
let s_a = monero::private_key_from_secp256k1_scalar(s_a.into());
Ok(State5 {
s_a,
s_b: self.s_b,
v: self.v,
tx_lock: self.tx_lock.clone(),
monero_wallet_restore_blockheight: self.monero_wallet_restore_blockheight,
})
}
pub fn tx_redeem_encsig(&self) -> bitcoin::EncryptedSignature {
let tx_redeem =
bitcoin::TxRedeem::new(&self.tx_lock, &self.redeem_address, self.tx_redeem_fee);

View File

@ -183,6 +183,13 @@ async fn next_state(
}
}
BobState::XmrLocked(state) => {
// In case we send the encrypted signature to Alice, but she doesn't give us a confirmation
// We need to check if she still published the Bitcoin redeem transaction
// Otherwise we risk staying stuck in "XmrLocked"
if let Ok(state5) = state.check_for_tx_redeem(bitcoin_wallet).await {
return Ok(BobState::BtcRedeemed(state5));
}
let tx_lock_status = bitcoin_wallet.subscribe_to(state.tx_lock.clone()).await;
if let ExpiredTimelocks::None { .. } = state.expired_timelock(bitcoin_wallet).await? {
@ -207,6 +214,13 @@ async fn next_state(
}
}
BobState::EncSigSent(state) => {
// We need to make sure that Alice did not publish the redeem transaction while we were offline
// Even if the cancel timelock expired, if Alice published the redeem transaction while we were away we cannot miss it
// If we do we cannot refund and will never be able to leave the "CancelTimelockExpired" state
if let Ok(state5) = state.check_for_tx_redeem(bitcoin_wallet).await {
return Ok(BobState::BtcRedeemed(state5));
}
let tx_lock_status = bitcoin_wallet.subscribe_to(state.tx_lock.clone()).await;
if let ExpiredTimelocks::None { .. } = state.expired_timelock(bitcoin_wallet).await? {