Make bitcoin::WatchForRawTransaction infallible

And trigger refund if Alice's redeem transaction takes too long.
pull/12/head
Lucas Soriano del Pino 4 years ago
parent ba3011a9c9
commit df4ffb65c9

@ -356,7 +356,7 @@ impl State3 {
tracing::info!("watching for lock btc with txid: {}", self.tx_lock.txid());
let tx = bitcoin_wallet
.watch_for_raw_transaction(self.tx_lock.txid())
.await?;
.await;
tracing::info!("tx lock seen with txid: {}", tx.txid());
@ -554,7 +554,7 @@ impl State5 {
let tx_refund_candidate = bitcoin_wallet
.watch_for_raw_transaction(tx_refund.txid())
.await?;
.await;
let tx_refund_sig =
tx_refund.extract_signature_by_key(tx_refund_candidate, self.a.public())?;

@ -189,7 +189,7 @@ pub trait BroadcastSignedTransaction {
#[async_trait]
pub trait WatchForRawTransaction {
async fn watch_for_raw_transaction(&self, txid: Txid) -> Result<Transaction>;
async fn watch_for_raw_transaction(&self, txid: Txid) -> Transaction;
}
pub fn recover(S: PublicKey, sig: Signature, encsig: EncryptedSignature) -> Result<SecretKey> {

@ -472,7 +472,7 @@ impl State4 {
let tx_redeem_candidate = bitcoin_wallet
.watch_for_raw_transaction(tx_redeem.txid())
.await?;
.await;
let tx_redeem_sig =
tx_redeem.extract_signature_by_key(tx_redeem_candidate, self.b.public())?;

@ -53,7 +53,10 @@ pub mod transport;
use async_trait::async_trait;
use ecdsa_fun::{adaptor::Adaptor, nonce::Deterministic};
use futures::future::Either;
use futures::{
future::{select, Either},
FutureExt,
};
use genawaiter::sync::{Gen, GenBoxed};
use sha2::Sha256;
@ -133,7 +136,8 @@ where
let swap_result: Result<(), SwapFailed> = async {
co.yield_(Action::LockBitcoin(tx_lock.clone())).await;
let poll_until_expiry = poll_until_bitcoin_time(bitcoin_ledger, refund_timelock);
let poll_until_expiry =
poll_until_bitcoin_time(bitcoin_ledger, refund_timelock).shared();
futures::pin_mut!(poll_until_expiry);
// the source of this could be the database, this layer doesn't care
@ -144,7 +148,7 @@ where
));
let S = S_a_monero + S_b_monero;
match futures::future::select(
match select(
monero_ledger.watch_for_transfer(
S,
v.public(),
@ -152,7 +156,7 @@ where
xmr,
monero::MIN_CONFIRMATIONS,
),
poll_until_expiry,
poll_until_expiry.clone(),
)
.await
{
@ -167,10 +171,15 @@ where
co.yield_(Action::SendBitcoinRedeemEncsig(tx_redeem_encsig.clone()))
.await;
let tx_redeem_published = bitcoin_ledger
.watch_for_raw_transaction(tx_redeem.txid())
.await
.expect("TODO: implementor of this trait must make it infallible by retrying");
let tx_redeem_published = match select(
bitcoin_ledger.watch_for_raw_transaction(tx_redeem.txid()),
poll_until_expiry,
)
.await
{
Either::Left((tx, _)) => tx,
Either::Right(_) => return Err(SwapFailed::TimelockReached),
};
// NOTE: If any of this fails, Bob will never be able to take the monero.
// Therefore, there is no way to handle these errors other than aborting

@ -112,13 +112,14 @@ impl BroadcastSignedTransaction for Wallet {
#[async_trait]
impl WatchForRawTransaction for Wallet {
async fn watch_for_raw_transaction(&self, txid: Txid) -> Result<Transaction> {
loop {
if let Ok(tx) = self.0.get_raw_transaction(txid).await {
return Ok(tx);
}
time::delay_for(Duration::from_millis(200)).await;
}
async fn watch_for_raw_transaction(&self, txid: Txid) -> Transaction {
(|| async { Ok(self.0.get_raw_transaction(txid).await?) })
.retry(ExponentialBackoff {
max_elapsed_time: None,
..Default::default()
})
.await
.expect("transient errors to be retried")
}
}

Loading…
Cancel
Save