diff --git a/mm2src/coins/eth.rs b/mm2src/coins/eth.rs index 0fd259f40e..e31deae491 100644 --- a/mm2src/coins/eth.rs +++ b/mm2src/coins/eth.rs @@ -2545,7 +2545,7 @@ impl EthCoin { let mut from_block = search_from_block; loop { - let to_block = current_block.max(from_block + 1000); + let to_block = current_block.min(from_block + 1000); let spend_events = try_s!(self.spend_events(swap_contract_address, from_block, to_block).wait()); let found = spend_events.iter().find(|event| &event.data.0[..32] == id.as_slice()); diff --git a/mm2src/coins/qrc20.rs b/mm2src/coins/qrc20.rs index 8990d0517f..493a2465fc 100644 --- a/mm2src/coins/qrc20.rs +++ b/mm2src/coins/qrc20.rs @@ -505,7 +505,7 @@ impl UtxoCommonOps for Qrc20Coin { utxo_common::calc_interest_if_required(self, unsigned, data, my_script_pub).await } - fn p2sh_spending_tx( + async fn p2sh_spending_tx( &self, prev_transaction: UtxoTx, redeem_script: ScriptBytes, @@ -523,6 +523,7 @@ impl UtxoCommonOps for Qrc20Coin { sequence, lock_time, ) + .await } async fn ordered_mature_unspents<'a>( @@ -566,8 +567,8 @@ impl UtxoCommonOps for Qrc20Coin { utxo_common::increase_dynamic_fee_by_stage(self, dynamic_fee, stage) } - fn p2sh_tx_locktime(&self, htlc_locktime: u32) -> u32 { - utxo_common::p2sh_tx_locktime(&self.utxo.conf.ticker, htlc_locktime) + async fn p2sh_tx_locktime(&self, htlc_locktime: u32) -> Result> { + utxo_common::p2sh_tx_locktime(self, &self.utxo.conf.ticker, htlc_locktime).await } } diff --git a/mm2src/coins/utxo.rs b/mm2src/coins/utxo.rs index 6d76242018..e98a72cf33 100644 --- a/mm2src/coins/utxo.rs +++ b/mm2src/coins/utxo.rs @@ -501,7 +501,7 @@ pub trait UtxoCommonOps { my_script_pub: Bytes, ) -> UtxoRpcResult<(TransactionInputSigner, AdditionalTxData)>; - fn p2sh_spending_tx( + async fn p2sh_spending_tx( &self, prev_transaction: UtxoTx, redeem_script: Bytes, @@ -545,7 +545,7 @@ pub trait UtxoCommonOps { /// The method is used to predict a possible increase in dynamic fee. fn increase_dynamic_fee_by_stage(&self, dynamic_fee: u64, stage: &FeeApproxStage) -> u64; - fn p2sh_tx_locktime(&self, htlc_locktime: u32) -> u32; + async fn p2sh_tx_locktime(&self, htlc_locktime: u32) -> Result>; } #[async_trait] diff --git a/mm2src/coins/utxo/qtum.rs b/mm2src/coins/utxo/qtum.rs index f6ad4bf4c4..2c33ddf723 100644 --- a/mm2src/coins/utxo/qtum.rs +++ b/mm2src/coins/utxo/qtum.rs @@ -186,7 +186,7 @@ impl UtxoCommonOps for QtumCoin { utxo_common::calc_interest_if_required(self, unsigned, data, my_script_pub).await } - fn p2sh_spending_tx( + async fn p2sh_spending_tx( &self, prev_transaction: UtxoTx, redeem_script: Bytes, @@ -204,6 +204,7 @@ impl UtxoCommonOps for QtumCoin { sequence, lock_time, ) + .await } async fn ordered_mature_unspents<'a>( @@ -247,8 +248,8 @@ impl UtxoCommonOps for QtumCoin { utxo_common::increase_dynamic_fee_by_stage(self, dynamic_fee, stage) } - fn p2sh_tx_locktime(&self, htlc_locktime: u32) -> u32 { - utxo_common::p2sh_tx_locktime(&self.utxo_arc.conf.ticker, htlc_locktime) + async fn p2sh_tx_locktime(&self, htlc_locktime: u32) -> Result> { + utxo_common::p2sh_tx_locktime(self, &self.utxo_arc.conf.ticker, htlc_locktime).await } } @@ -430,7 +431,12 @@ impl SwapOps for QtumCoin { } fn can_refund_htlc(&self, locktime: u64) -> Box + Send + '_> { - utxo_common::can_refund_htlc(self, locktime) + Box::new( + utxo_common::can_refund_htlc(self, locktime) + .boxed() + .map_err(|e| ERRL!("{}", e)) + .compat(), + ) } fn negotiate_swap_contract_addr( diff --git a/mm2src/coins/utxo/utxo_common.rs b/mm2src/coins/utxo/utxo_common.rs index bee3f7f526..a5a5ceb560 100644 --- a/mm2src/coins/utxo/utxo_common.rs +++ b/mm2src/coins/utxo/utxo_common.rs @@ -532,7 +532,7 @@ where Ok((unsigned, data)) } -pub fn p2sh_spending_tx( +pub async fn p2sh_spending_tx( coin: &T, prev_transaction: UtxoTx, redeem_script: Bytes, @@ -544,7 +544,7 @@ pub fn p2sh_spending_tx( where T: AsRef + UtxoCommonOps, { - let lock_time = coin.p2sh_tx_locktime(lock_time); + let lock_time = try_s!(coin.p2sh_tx_locktime(lock_time).await); let n_time = if coin.as_ref().conf.is_pos { Some((now_ms() / 1000) as u32) } else { @@ -728,14 +728,17 @@ where value: prev_tx.outputs[0].value - fee, script_pubkey: Builder::build_p2pkh(&coin.as_ref().key_pair.public().address_hash()).to_bytes(), }; - let transaction = try_s!(coin.p2sh_spending_tx( - prev_tx, - redeem_script.into(), - vec![output], - script_data, - SEQUENCE_FINAL, - time_lock - )); + let transaction = try_s!( + coin.p2sh_spending_tx( + prev_tx, + redeem_script.into(), + vec![output], + script_data, + SEQUENCE_FINAL, + time_lock + ) + .await + ); let tx_fut = coin.as_ref().rpc_client.send_transaction(&transaction).compat(); try_s!(tx_fut.await); Ok(transaction.into()) @@ -771,14 +774,17 @@ where value: prev_tx.outputs[0].value - fee, script_pubkey: Builder::build_p2pkh(&coin.as_ref().key_pair.public().address_hash()).to_bytes(), }; - let transaction = try_s!(coin.p2sh_spending_tx( - prev_tx, - redeem_script.into(), - vec![output], - script_data, - SEQUENCE_FINAL, - time_lock - )); + let transaction = try_s!( + coin.p2sh_spending_tx( + prev_tx, + redeem_script.into(), + vec![output], + script_data, + SEQUENCE_FINAL, + time_lock + ) + .await + ); let tx_fut = coin.as_ref().rpc_client.send_transaction(&transaction).compat(); try_s!(tx_fut.await); Ok(transaction.into()) @@ -811,14 +817,17 @@ where value: prev_tx.outputs[0].value - fee, script_pubkey: Builder::build_p2pkh(&coin.as_ref().key_pair.public().address_hash()).to_bytes(), }; - let transaction = try_s!(coin.p2sh_spending_tx( - prev_tx, - redeem_script.into(), - vec![output], - script_data, - SEQUENCE_FINAL - 1, - time_lock, - )); + let transaction = try_s!( + coin.p2sh_spending_tx( + prev_tx, + redeem_script.into(), + vec![output], + script_data, + SEQUENCE_FINAL - 1, + time_lock, + ) + .await + ); let tx_fut = coin.as_ref().rpc_client.send_transaction(&transaction).compat(); try_s!(tx_fut.await); Ok(transaction.into()) @@ -851,14 +860,17 @@ where value: prev_tx.outputs[0].value - fee, script_pubkey: Builder::build_p2pkh(&coin.as_ref().key_pair.public().address_hash()).to_bytes(), }; - let transaction = try_s!(coin.p2sh_spending_tx( - prev_tx, - redeem_script.into(), - vec![output], - script_data, - SEQUENCE_FINAL - 1, - time_lock, - )); + let transaction = try_s!( + coin.p2sh_spending_tx( + prev_tx, + redeem_script.into(), + vec![output], + script_data, + SEQUENCE_FINAL - 1, + time_lock, + ) + .await + ); let tx_fut = coin.as_ref().rpc_client.send_transaction(&transaction).compat(); try_s!(tx_fut.await); Ok(transaction.into()) @@ -2636,39 +2648,37 @@ where } } -pub fn can_refund_htlc(coin: &T, locktime: u64) -> Box + Send + '_> +pub async fn can_refund_htlc(coin: &T, locktime: u64) -> Result> where T: UtxoCommonOps, { let now = now_ms() / 1000; if now < locktime { let to_wait = locktime - now + 1; - return Box::new(futures01::future::ok(CanRefundHtlc::HaveToWait(to_wait.max(3600)))); + return Ok(CanRefundHtlc::HaveToWait(to_wait.max(3600))); + } + + let mtp = coin.get_current_mtp().await?; + let locktime = coin.p2sh_tx_locktime(locktime as u32).await?; + + if locktime < mtp { + Ok(CanRefundHtlc::CanRefundNow) + } else { + let to_wait = (locktime - mtp + 1) as u64; + Ok(CanRefundHtlc::HaveToWait(to_wait.max(3600))) } - let locktime = coin.p2sh_tx_locktime(locktime as u32); - Box::new( - coin.get_current_mtp() - .compat() - .map(move |mtp| { - let mtp = mtp; - if locktime < mtp { - CanRefundHtlc::CanRefundNow - } else { - let to_wait = (locktime - mtp + 1) as u64; - CanRefundHtlc::HaveToWait(to_wait.max(3600)) - } - }) - .map_err(|e| ERRL!("{}", e)), - ) } -pub fn p2sh_tx_locktime(ticker: &str, htlc_locktime: u32) -> u32 { - let lock_time_by_now = if ticker == "KMD" { +pub async fn p2sh_tx_locktime(coin: &T, ticker: &str, htlc_locktime: u32) -> Result> +where + T: UtxoCommonOps, +{ + let lock_time = if ticker == "KMD" { (now_ms() / 1000) as u32 - 3600 + 2 * 777 } else { - (now_ms() / 1000) as u32 - 3600 + coin.get_current_mtp().await? - 1 }; - lock_time_by_now.max(htlc_locktime) + Ok(lock_time.max(htlc_locktime)) } #[test] diff --git a/mm2src/coins/utxo/utxo_standard.rs b/mm2src/coins/utxo/utxo_standard.rs index 89eba98dc3..3ef742eeb5 100644 --- a/mm2src/coins/utxo/utxo_standard.rs +++ b/mm2src/coins/utxo/utxo_standard.rs @@ -84,7 +84,7 @@ impl UtxoCommonOps for UtxoStandardCoin { utxo_common::calc_interest_if_required(self, unsigned, data, my_script_pub).await } - fn p2sh_spending_tx( + async fn p2sh_spending_tx( &self, prev_transaction: UtxoTx, redeem_script: Bytes, @@ -102,6 +102,7 @@ impl UtxoCommonOps for UtxoStandardCoin { sequence, lock_time, ) + .await } async fn ordered_mature_unspents<'a>( @@ -145,8 +146,8 @@ impl UtxoCommonOps for UtxoStandardCoin { utxo_common::increase_dynamic_fee_by_stage(self, dynamic_fee, stage) } - fn p2sh_tx_locktime(&self, htlc_locktime: u32) -> u32 { - utxo_common::p2sh_tx_locktime(&self.utxo_arc.conf.ticker, htlc_locktime) + async fn p2sh_tx_locktime(&self, htlc_locktime: u32) -> Result> { + utxo_common::p2sh_tx_locktime(self, &self.utxo_arc.conf.ticker, htlc_locktime).await } } @@ -328,7 +329,12 @@ impl SwapOps for UtxoStandardCoin { } fn can_refund_htlc(&self, locktime: u64) -> Box + Send + '_> { - utxo_common::can_refund_htlc(self, locktime) + Box::new( + utxo_common::can_refund_htlc(self, locktime) + .boxed() + .map_err(|e| ERRL!("{}", e)) + .compat(), + ) } fn negotiate_swap_contract_addr( diff --git a/mm2src/coins/utxo/utxo_tests.rs b/mm2src/coins/utxo/utxo_tests.rs index 60a1d31023..d5ebda18eb 100644 --- a/mm2src/coins/utxo/utxo_tests.rs +++ b/mm2src/coins/utxo/utxo_tests.rs @@ -2593,7 +2593,7 @@ fn send_and_refund_dex_fee() { value: 9000, script_pubkey: Builder::build_p2pkh(&keypair.public().address_hash()).into(), }; - let refund = p2sh_spending_tx( + let refund = block_on(p2sh_spending_tx( &coin, transaction, dex_fee_script.into(), @@ -2601,7 +2601,7 @@ fn send_and_refund_dex_fee() { script_data, SEQUENCE_FINAL - 1, lock_time, - ) + )) .unwrap(); let tx = serialize(&refund); @@ -2651,7 +2651,7 @@ fn send_and_redeem_dex_fee() { value: 9000, script_pubkey: Builder::build_p2pkh(&keypair.public().address_hash()).into(), }; - let refund = p2sh_spending_tx( + let refund = block_on(p2sh_spending_tx( &coin, transaction, dex_fee_script.into(), @@ -2659,7 +2659,7 @@ fn send_and_redeem_dex_fee() { script_data, SEQUENCE_FINAL, lock_time, - ) + )) .unwrap(); let tx = serialize(&refund);