mirror of
https://github.com/comit-network/xmr-btc-swap.git
synced 2025-11-28 19:50:20 -05:00
feat(asb): Retry tx_early_refund and give up eventually (#412)
This commit is contained in:
parent
7b194f0499
commit
26eaf06ecf
2 changed files with 54 additions and 9 deletions
|
|
@ -8,6 +8,7 @@ and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0
|
|||
## [Unreleased]
|
||||
|
||||
- GUI: Improved peer discovery: We can now connect to multiple rendezvous points at once. We also cache peers we have previously connected to locally and will attempt to connect to them again in the future, even if they aren't registered with a rendezvous point anymore.
|
||||
- ASB: We now retry for 6 hours to broadcast the early refund transaction. After that, we give up and Bob will have to wait for the timelock to expire then refund himself. If we detect that Bob has cancelled the swap, we will abort the swap on our side and let Bob refund himself.
|
||||
|
||||
## [2.0.3] - 2025-06-12
|
||||
|
||||
|
|
|
|||
|
|
@ -203,17 +203,61 @@ where
|
|||
let tx_early_refund = tx_early_refund?;
|
||||
let tx_early_refund_txid = tx_early_refund.compute_txid();
|
||||
|
||||
// Broadcast the early refund transaction
|
||||
let (_, _) = bitcoin_wallet
|
||||
.broadcast(tx_early_refund, "early_refund")
|
||||
.await?;
|
||||
// Bob might cancel the swap and refund for himself. We won't need to early refund anymore.
|
||||
let tx_cancel_status = bitcoin_wallet.subscribe_to(state3.tx_cancel()).await;
|
||||
|
||||
tracing::info!(
|
||||
%tx_early_refund_txid,
|
||||
"Refunded Bitcoin early for Bob"
|
||||
);
|
||||
let backoff = backoff::ExponentialBackoffBuilder::new()
|
||||
// We give up after 6 hours
|
||||
// (Most likely Bob the a Replace-by-Fee on the tx_lock transaction)
|
||||
.with_max_elapsed_time(Some(Duration::from_secs(6 * 60 * 60)))
|
||||
// We wait a while between retries
|
||||
.with_max_interval(Duration::from_secs(10 * 60))
|
||||
.build();
|
||||
|
||||
AliceState::BtcEarlyRefunded(state3)
|
||||
// Concurrently retry to broadcast the early refund transaction
|
||||
// and wait for the cancel transaction to be broadcasted.
|
||||
tokio::select! {
|
||||
// If Bob cancels the swap, he can refund himself.
|
||||
// Nothing for us to do anymore.
|
||||
result = tx_cancel_status.wait_until_seen() => {
|
||||
result?;
|
||||
AliceState::SafelyAborted
|
||||
}
|
||||
|
||||
// Retry repeatedly to broadcast tx_early_refund
|
||||
result = async {
|
||||
backoff::future::retry_notify(backoff, || async {
|
||||
bitcoin_wallet.broadcast(tx_early_refund.clone(), "early_refund").await.map_err(backoff::Error::transient)
|
||||
}, |e, wait_time: Duration| {
|
||||
tracing::warn!(
|
||||
%tx_early_refund_txid,
|
||||
error = ?e,
|
||||
"Failed to broadcast early refund transaction. We will retry in {} seconds",
|
||||
wait_time.as_secs()
|
||||
)
|
||||
})
|
||||
.await
|
||||
} => {
|
||||
match result {
|
||||
Ok((_txid, _subscription)) => {
|
||||
tracing::info!(
|
||||
%tx_early_refund_txid,
|
||||
"Refunded Bitcoin early for Bob"
|
||||
);
|
||||
|
||||
AliceState::BtcEarlyRefunded(state3)
|
||||
}
|
||||
Err(e) => {
|
||||
tracing::error!(
|
||||
%tx_early_refund_txid,
|
||||
error = ?e,
|
||||
"Failed to broadcast early refund transaction after retries exhausted. Bob will have to wait for the timelock to expire then refund himself."
|
||||
);
|
||||
AliceState::SafelyAborted
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
} else {
|
||||
// We do not have Bob's signature for the early refund transaction
|
||||
// Therefore we cannot do an early refund.
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue