You signed in with another tab or window. Reload to refresh your session.You signed out in another tab or window. Reload to refresh your session.You switched accounts on another tab or window. Reload to refresh your session.Dismiss alert
bail!("Waiting for Bitcoin redeem transaction to be in mempool failed with {}! The redeem transaction was published, but it is not ensured that the transaction was included! You're screwed.", e)
281
+
} => {
282
+
match state3.expired_timelocks(bitcoin_wallet).await? {
283
+
ExpiredTimelocks::None{ .. } => {
284
+
let tx_lock_status = bitcoin_wallet.subscribe_to(state3.tx_lock.clone()).await;
285
+
match state3.signed_redeem_transaction(*encrypted_signature){
286
+
Ok(tx) => {
287
+
// We will retry indefinitely to publish the redeem transaction, until the cancel timelock expires
288
+
// We might not be able to publish the redeem transaction on the first try due to any number of reasons
289
+
let backoff = backoff::ExponentialBackoffBuilder::new()
290
+
.with_max_elapsed_time(None)
291
+
.with_max_interval(Duration::from_secs(60))
292
+
.build();
293
+
294
+
match backoff::future::retry_notify(backoff.clone(), || async{
295
+
// If the cancel timelock is expired, we do not need to publish anymore
296
+
// We cannot use a tokio::select! here because this is not cancellation safe
297
+
if !matches!(
298
+
state3.expired_timelocks(bitcoin_wallet).await?,
299
+
ExpiredTimelocks::None{ .. }
300
+
){
301
+
returnOk(None);
321
302
}
322
-
},
323
-
324
-
// Cancel timelock expired before we could publish the redeem transaction
325
-
Ok(None) => {
326
-
tracing::error!("We were unable to publish the redeem transaction before the timelock expired.");
327
303
328
-
AliceState::CancelTimelockExpired{
329
-
monero_wallet_restore_blockheight,
330
-
transfer_proof,
331
-
state3,
304
+
bitcoin_wallet
305
+
.broadcast(tx.clone(),"redeem")
306
+
.await
307
+
.map(Some)
308
+
.map_err(backoff::Error::transient)
309
+
}, |e,wait_time:Duration| {
310
+
tracing::warn!(
311
+
swap_id = %swap_id,
312
+
error = ?e,
313
+
"Failed to broadcast Bitcoin redeem transaction. We will retry in {} seconds",
314
+
wait_time.as_secs_f64()
315
+
)
316
+
})
317
+
.await
318
+
{
319
+
// We successfully published the redeem transaction
320
+
// We wait until we see the transaction in the mempool before transitioning to the next state
321
+
Ok(Some((_, subscription))) => match subscription.wait_until_seen().await{
// We extract the txid and the hex representation of the transaction
325
+
// this'll allow the user to manually re-publish the transaction
326
+
let txid = tx.txid();
327
+
let tx_hex = serialize_hex(&tx);
328
+
329
+
bail!("Waiting for Bitcoin redeem transaction to be in mempool failed with {}! The redeem transaction was published, but it is not ensured that the transaction was included! You might be screwed. You can try to manually re-publish the transaction (TxID: {}, Tx Hex: {})", e, txid, tx_hex)
330
+
}
331
+
},
332
+
333
+
// Cancel timelock expired before we could publish the redeem transaction
334
+
Ok(None) => {
335
+
tracing::error!("We were unable to publish the redeem transaction before the timelock expired.");
336
+
337
+
AliceState::CancelTimelockExpired{
338
+
monero_wallet_restore_blockheight,
339
+
transfer_proof,
340
+
state3,
341
+
}
332
342
}
333
-
}
334
343
335
-
// We should never reach this because we retry indefinitely
336
-
Err(error) => {
337
-
unreachable!(
338
-
"We construct the backoff without a max_elapsed_time. We should never error while retrying to publish the redeem transaction: {:#}",
339
-
error
340
-
)
344
+
// We should never reach this because we retry indefinitely
345
+
Err(error) => {
346
+
unreachable!(
347
+
"We construct the backoff without a max_elapsed_time. We should never error while retrying to publish the redeem transaction: {:#}",
348
+
error
349
+
)
350
+
}
341
351
}
342
352
}
343
-
}
344
-
Err(error) => {
345
-
tracing::error!("Failed to construct redeem transaction: {:#}", error);
let subscription = bitcoin_wallet.subscribe_to(state3.tx_redeem()).await;
371
381
@@ -456,6 +466,9 @@ where
456
466
transfer_proof,
457
467
state3,
458
468
} => {
469
+
// TODO: We should retry indefinitely here until we find the refund transaction
470
+
// TODO: If we crash while we are waiting for the punish_tx to be confirmed (punish_btc waits until confirmation), we will remain in this state forever because we will attempt to re-publish the punish transaction
471
+
// as soon as we restart which will fail because it has already been included
459
472
let punish = state3.punish_btc(bitcoin_wallet).await;
460
473
461
474
match punish {
@@ -474,7 +487,8 @@ where
474
487
475
488
let published_refund_tx = bitcoin_wallet
476
489
.get_raw_transaction(state3.tx_refund().txid())
477
-
.await?;
490
+
.await
491
+
.context("Failed to fetch refund transaction after assuming it was included because the punish transaction failed")?;
478
492
479
493
let spend_key = state3.extract_monero_private_key(published_refund_tx)?;
0 commit comments