Skip to content

Commit

Permalink
Use MTP in p2sh_tx_locktime #951
Browse files Browse the repository at this point in the history
Also fix the block range in EthCoin::search_for_swap_tx_spend #947
  • Loading branch information
artemii235 committed May 28, 2021
1 parent 534973c commit b5e202b
Show file tree
Hide file tree
Showing 7 changed files with 96 additions and 73 deletions.
2 changes: 1 addition & 1 deletion mm2src/coins/eth.rs
Original file line number Diff line number Diff line change
Expand Up @@ -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());
Expand Down
7 changes: 4 additions & 3 deletions mm2src/coins/qrc20.rs
Original file line number Diff line number Diff line change
Expand Up @@ -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,
Expand All @@ -523,6 +523,7 @@ impl UtxoCommonOps for Qrc20Coin {
sequence,
lock_time,
)
.await
}

async fn ordered_mature_unspents<'a>(
Expand Down Expand Up @@ -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<u32, MmError<UtxoRpcError>> {
utxo_common::p2sh_tx_locktime(self, &self.utxo.conf.ticker, htlc_locktime).await
}
}

Expand Down
4 changes: 2 additions & 2 deletions mm2src/coins/utxo.rs
Original file line number Diff line number Diff line change
Expand Up @@ -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,
Expand Down Expand Up @@ -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<u32, MmError<UtxoRpcError>>;
}

#[async_trait]
Expand Down
14 changes: 10 additions & 4 deletions mm2src/coins/utxo/qtum.rs
Original file line number Diff line number Diff line change
Expand Up @@ -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,
Expand All @@ -204,6 +204,7 @@ impl UtxoCommonOps for QtumCoin {
sequence,
lock_time,
)
.await
}

async fn ordered_mature_unspents<'a>(
Expand Down Expand Up @@ -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<u32, MmError<UtxoRpcError>> {
utxo_common::p2sh_tx_locktime(self, &self.utxo_arc.conf.ticker, htlc_locktime).await
}
}

Expand Down Expand Up @@ -430,7 +431,12 @@ impl SwapOps for QtumCoin {
}

fn can_refund_htlc(&self, locktime: u64) -> Box<dyn Future<Item = CanRefundHtlc, Error = String> + 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(
Expand Down
120 changes: 65 additions & 55 deletions mm2src/coins/utxo/utxo_common.rs
Original file line number Diff line number Diff line change
Expand Up @@ -532,7 +532,7 @@ where
Ok((unsigned, data))
}

pub fn p2sh_spending_tx<T>(
pub async fn p2sh_spending_tx<T>(
coin: &T,
prev_transaction: UtxoTx,
redeem_script: Bytes,
Expand All @@ -544,7 +544,7 @@ pub fn p2sh_spending_tx<T>(
where
T: AsRef<UtxoCoinFields> + 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 {
Expand Down Expand Up @@ -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())
Expand Down Expand Up @@ -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())
Expand Down Expand Up @@ -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())
Expand Down Expand Up @@ -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())
Expand Down Expand Up @@ -2636,39 +2648,37 @@ where
}
}

pub fn can_refund_htlc<T>(coin: &T, locktime: u64) -> Box<dyn Future<Item = CanRefundHtlc, Error = String> + Send + '_>
pub async fn can_refund_htlc<T>(coin: &T, locktime: u64) -> Result<CanRefundHtlc, MmError<UtxoRpcError>>
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<T>(coin: &T, ticker: &str, htlc_locktime: u32) -> Result<u32, MmError<UtxoRpcError>>
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]
Expand Down
14 changes: 10 additions & 4 deletions mm2src/coins/utxo/utxo_standard.rs
Original file line number Diff line number Diff line change
Expand Up @@ -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,
Expand All @@ -102,6 +102,7 @@ impl UtxoCommonOps for UtxoStandardCoin {
sequence,
lock_time,
)
.await
}

async fn ordered_mature_unspents<'a>(
Expand Down Expand Up @@ -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<u32, MmError<UtxoRpcError>> {
utxo_common::p2sh_tx_locktime(self, &self.utxo_arc.conf.ticker, htlc_locktime).await
}
}

Expand Down Expand Up @@ -328,7 +329,12 @@ impl SwapOps for UtxoStandardCoin {
}

fn can_refund_htlc(&self, locktime: u64) -> Box<dyn Future<Item = CanRefundHtlc, Error = String> + 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(
Expand Down
8 changes: 4 additions & 4 deletions mm2src/coins/utxo/utxo_tests.rs
Original file line number Diff line number Diff line change
Expand Up @@ -2593,15 +2593,15 @@ 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(),
vec![output],
script_data,
SEQUENCE_FINAL - 1,
lock_time,
)
))
.unwrap();

let tx = serialize(&refund);
Expand Down Expand Up @@ -2651,15 +2651,15 @@ 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(),
vec![output],
script_data,
SEQUENCE_FINAL,
lock_time,
)
))
.unwrap();

let tx = serialize(&refund);
Expand Down

0 comments on commit b5e202b

Please sign in to comment.