Skip to content

Commit

Permalink
Hotfix MTP retrieval in electrum mode for QTUM and ZER coins #966 (#975)
Browse files Browse the repository at this point in the history
* WIP. Got conflicting block header version between BTC/DOGE/QTUM.

* Add coin_variant to serialization::Reader.
  • Loading branch information
artemii235 authored Jun 10, 2021
1 parent 1512af8 commit 8bf6ed3
Show file tree
Hide file tree
Showing 9 changed files with 585 additions and 43 deletions.
7 changes: 4 additions & 3 deletions mm2src/coins/qrc20.rs
Original file line number Diff line number Diff line change
Expand Up @@ -38,8 +38,7 @@ use rpc::v1::types::{Bytes as BytesJson, Transaction as RpcTransaction, H160 as
use script::{Builder as ScriptBuilder, Opcode, Script, TransactionInputSigner};
use script_pubkey::generate_contract_call_script_pubkey;
use serde_json::{self as json, Value as Json};
use serialization::deserialize;
use serialization::serialize;
use serialization::{deserialize, serialize, CoinVariant};
use std::ops::{Deref, Neg};
#[cfg(not(target_arch = "wasm32"))] use std::path::PathBuf;
use std::str::FromStr;
Expand Down Expand Up @@ -480,7 +479,9 @@ impl UtxoCommonOps for Qrc20Coin {
utxo_common::address_from_str(&self.utxo.conf, address)
}

async fn get_current_mtp(&self) -> UtxoRpcResult<u32> { utxo_common::get_current_mtp(&self.utxo).await }
async fn get_current_mtp(&self) -> UtxoRpcResult<u32> {
utxo_common::get_current_mtp(&self.utxo, CoinVariant::Qtum).await
}

fn is_unspent_mature(&self, output: &RpcTransaction) -> bool { self.is_qtum_unspent_mature(output) }

Expand Down
5 changes: 4 additions & 1 deletion mm2src/coins/utxo/qtum.rs
Original file line number Diff line number Diff line change
Expand Up @@ -5,6 +5,7 @@ use common::mm_metrics::MetricsArc;
use common::mm_number::MmNumber;
use ethereum_types::H160;
use futures::{FutureExt, TryFutureExt};
use serialization::CoinVariant;

pub const QTUM_STANDARD_DUST: u64 = 1000;

Expand Down Expand Up @@ -166,7 +167,9 @@ impl UtxoCommonOps for QtumCoin {
utxo_common::address_from_str(&self.utxo_arc.conf, address)
}

async fn get_current_mtp(&self) -> UtxoRpcResult<u32> { utxo_common::get_current_mtp(&self.utxo_arc).await }
async fn get_current_mtp(&self) -> UtxoRpcResult<u32> {
utxo_common::get_current_mtp(&self.utxo_arc, CoinVariant::Qtum).await
}

fn is_unspent_mature(&self, output: &RpcTransaction) -> bool { self.is_qtum_unspent_mature(output) }

Expand Down
25 changes: 20 additions & 5 deletions mm2src/coins/utxo/rpc_clients.rs
Original file line number Diff line number Diff line change
Expand Up @@ -31,7 +31,7 @@ use keys::Address;
use rpc::v1::types::{Bytes as BytesJson, Transaction as RpcTransaction, H256 as H256Json};
use script::Builder;
use serde_json::{self as json, Value as Json};
use serialization::{deserialize, serialize, CompactInteger, Reader};
use serialization::{deserialize, serialize, CoinVariant, CompactInteger, Reader};
use sha2::{Digest, Sha256};
use std::collections::hash_map::{Entry, HashMap};
use std::fmt;
Expand Down Expand Up @@ -245,7 +245,12 @@ pub trait UtxoRpcClientOps: fmt::Debug + Send + Sync + 'static {
) -> Box<dyn Future<Item = Option<UtxoTx>, Error = String> + Send>;

/// Get median time past for `count` blocks in the past including `starting_block`
fn get_median_time_past(&self, starting_block: u64, count: NonZeroU64) -> UtxoRpcFut<u32>;
fn get_median_time_past(
&self,
starting_block: u64,
count: NonZeroU64,
coin_variant: CoinVariant,
) -> UtxoRpcFut<u32>;
}

#[derive(Clone, Deserialize, Debug)]
Expand Down Expand Up @@ -660,7 +665,12 @@ impl UtxoRpcClientOps for NativeClient {
Box::new(fut.boxed().compat())
}

fn get_median_time_past(&self, starting_block: u64, count: NonZeroU64) -> UtxoRpcFut<u32> {
fn get_median_time_past(
&self,
starting_block: u64,
count: NonZeroU64,
_coin_variant: CoinVariant,
) -> UtxoRpcFut<u32> {
let selfi = self.clone();
let fut = async move {
let starting_block_hash = selfi.get_block_hash(starting_block).compat().await?;
Expand Down Expand Up @@ -1575,7 +1585,12 @@ impl UtxoRpcClientOps for ElectrumClient {
Box::new(fut.boxed().compat())
}

fn get_median_time_past(&self, starting_block: u64, count: NonZeroU64) -> UtxoRpcFut<u32> {
fn get_median_time_past(
&self,
starting_block: u64,
count: NonZeroU64,
coin_variant: CoinVariant,
) -> UtxoRpcFut<u32> {
let from = if starting_block <= count.get() {
0
} else {
Expand All @@ -1591,7 +1606,7 @@ impl UtxoRpcClientOps for ElectrumClient {
let len = CompactInteger::from(res.count);
let mut serialized = serialize(&len).take();
serialized.extend(res.hex.0.into_iter());
let mut reader = Reader::new(serialized.as_slice());
let mut reader = Reader::new_with_coin_variant(serialized.as_slice(), coin_variant);
let headers = reader.read_list::<BlockHeader>()?;
let mut timestamps: Vec<_> = headers.into_iter().map(|block| block.time).collect();
// can unwrap because count is non zero
Expand Down
6 changes: 3 additions & 3 deletions mm2src/coins/utxo/utxo_common.rs
Original file line number Diff line number Diff line change
Expand Up @@ -22,7 +22,7 @@ use script::{Builder, Opcode, Script, ScriptAddress, SignatureVersion, Transacti
UnsignedTransactionInput};
use secp256k1::{PublicKey, Signature};
use serde_json::{self as json};
use serialization::{deserialize, serialize};
use serialization::{deserialize, serialize, CoinVariant};
use std::cmp::Ordering;
use std::collections::hash_map::{Entry, HashMap};
use std::str::FromStr;
Expand Down Expand Up @@ -253,10 +253,10 @@ pub fn address_from_str(conf: &UtxoCoinConf, address: &str) -> Result<Address, S
}
}

pub async fn get_current_mtp(coin: &UtxoCoinFields) -> UtxoRpcResult<u32> {
pub async fn get_current_mtp(coin: &UtxoCoinFields, coin_variant: CoinVariant) -> UtxoRpcResult<u32> {
let current_block = coin.rpc_client.get_block_count().compat().await?;
coin.rpc_client
.get_median_time_past(current_block, coin.conf.mtp_block_count)
.get_median_time_past(current_block, coin.conf.mtp_block_count, coin_variant)
.compat()
.await
}
Expand Down
5 changes: 4 additions & 1 deletion mm2src/coins/utxo/utxo_standard.rs
Original file line number Diff line number Diff line change
Expand Up @@ -4,6 +4,7 @@ use crate::{CanRefundHtlc, CoinBalance, NegotiateSwapContractAddrErr, SwapOps, T
use common::mm_metrics::MetricsArc;
use common::mm_number::MmNumber;
use futures::{FutureExt, TryFutureExt};
use serialization::CoinVariant;

#[derive(Clone, Debug)]
pub struct UtxoStandardCoin {
Expand Down Expand Up @@ -58,7 +59,9 @@ impl UtxoCommonOps for UtxoStandardCoin {
utxo_common::address_from_str(&self.utxo_arc.conf, address)
}

async fn get_current_mtp(&self) -> UtxoRpcResult<u32> { utxo_common::get_current_mtp(&self.utxo_arc).await }
async fn get_current_mtp(&self) -> UtxoRpcResult<u32> {
utxo_common::get_current_mtp(&self.utxo_arc, CoinVariant::Standard).await
}

fn is_unspent_mature(&self, output: &RpcTransaction) -> bool {
utxo_common::is_unspent_mature(self.utxo_arc.conf.mature_confirmations, output)
Expand Down
57 changes: 47 additions & 10 deletions mm2src/coins/utxo/utxo_tests.rs
Original file line number Diff line number Diff line change
Expand Up @@ -16,7 +16,7 @@ use futures::future::join_all;
use mocktopus::mocking::*;
use rpc::v1::types::H256 as H256Json;
use script::Opcode;
use serialization::deserialize;
use serialization::{deserialize, CoinVariant};
use std::thread;
use std::time::Duration;

Expand Down Expand Up @@ -1016,7 +1016,7 @@ fn test_get_median_time_past_from_electrum_kmd() {
]);

let mtp = client
.get_median_time_past(1773390, KMD_MTP_BLOCK_COUNT)
.get_median_time_past(1773390, KMD_MTP_BLOCK_COUNT, CoinVariant::Standard)
.wait()
.unwrap();
// the MTP is block time of 1773385 in this case
Expand All @@ -1031,7 +1031,10 @@ fn test_get_median_time_past_from_electrum_btc() {
"electrum3.cipig.net:10000",
]);

let mtp = client.get_median_time_past(632858, KMD_MTP_BLOCK_COUNT).wait().unwrap();
let mtp = client
.get_median_time_past(632858, KMD_MTP_BLOCK_COUNT, CoinVariant::Standard)
.wait()
.unwrap();
assert_eq!(1591173041, mtp);
}

Expand All @@ -1055,7 +1058,10 @@ fn test_get_median_time_past_from_native_has_median_in_get_block() {
)
});

let mtp = client.get_median_time_past(632858, KMD_MTP_BLOCK_COUNT).wait().unwrap();
let mtp = client
.get_median_time_past(632858, KMD_MTP_BLOCK_COUNT, CoinVariant::Standard)
.wait()
.unwrap();
assert_eq!(1591173041, mtp);
}

Expand Down Expand Up @@ -1098,7 +1104,10 @@ fn test_get_median_time_past_from_native_does_not_have_median_in_get_block() {
MockResult::Return(Box::new(futures01::future::ok(block)))
});

let mtp = client.get_median_time_past(632858, KMD_MTP_BLOCK_COUNT).wait().unwrap();
let mtp = client
.get_median_time_past(632858, KMD_MTP_BLOCK_COUNT, CoinVariant::Standard)
.wait()
.unwrap();
assert_eq!(1591173041, mtp);
}

Expand Down Expand Up @@ -2389,7 +2398,7 @@ fn doge_mtp() {
"electrum3.cipig.net:10060",
]);
let mtp = electrum
.get_median_time_past(3631820, NonZeroU64::new(11).unwrap())
.get_median_time_past(3631820, NonZeroU64::new(11).unwrap(), CoinVariant::Standard)
.wait()
.unwrap();
assert_eq!(mtp, 1614849084);
Expand All @@ -2403,7 +2412,7 @@ fn firo_mtp() {
"electrumx03.firo.org:50001",
]);
let mtp = electrum
.get_median_time_past(356730, NonZeroU64::new(11).unwrap())
.get_median_time_past(356730, NonZeroU64::new(11).unwrap(), CoinVariant::Standard)
.wait()
.unwrap();
assert_eq!(mtp, 1616492629);
Expand All @@ -2413,7 +2422,7 @@ fn firo_mtp() {
fn verus_mtp() {
let electrum = electrum_client_for_test(&["el0.verus.io:17485", "el1.verus.io:17485", "el2.verus.io:17485"]);
let mtp = electrum
.get_median_time_past(1480113, NonZeroU64::new(11).unwrap())
.get_median_time_past(1480113, NonZeroU64::new(11).unwrap(), CoinVariant::Standard)
.wait()
.unwrap();
assert_eq!(mtp, 1618579909);
Expand Down Expand Up @@ -2533,7 +2542,7 @@ fn sys_mtp() {
"electrum3.cipig.net:10064",
]);
let mtp = electrum
.get_median_time_past(1006678, NonZeroU64::new(11).unwrap())
.get_median_time_past(1006678, NonZeroU64::new(11).unwrap(), CoinVariant::Standard)
.wait()
.unwrap();
assert_eq!(mtp, 1620019628);
Expand All @@ -2547,12 +2556,40 @@ fn btc_mtp() {
"electrum3.cipig.net:10000",
]);
let mtp = electrum
.get_median_time_past(681659, NonZeroU64::new(11).unwrap())
.get_median_time_past(681659, NonZeroU64::new(11).unwrap(), CoinVariant::Standard)
.wait()
.unwrap();
assert_eq!(mtp, 1620019527);
}

#[test]
fn qtum_mtp() {
let electrum = electrum_client_for_test(&[
"electrum1.cipig.net:10050",
"electrum2.cipig.net:10050",
"electrum3.cipig.net:10050",
]);
let mtp = electrum
.get_median_time_past(681659, NonZeroU64::new(11).unwrap(), CoinVariant::Qtum)
.wait()
.unwrap();
assert_eq!(mtp, 1598854128);
}

#[test]
fn zer_mtp() {
let electrum = electrum_client_for_test(&[
"electrum1.cipig.net:10065",
"electrum2.cipig.net:10065",
"electrum3.cipig.net:10065",
]);
let mtp = electrum
.get_median_time_past(1130915, NonZeroU64::new(11).unwrap(), CoinVariant::Standard)
.wait()
.unwrap();
assert_eq!(mtp, 1623240214);
}

#[test]
#[ignore]
fn send_and_refund_dex_fee() {
Expand Down
Loading

0 comments on commit 8bf6ed3

Please sign in to comment.