Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
4 changes: 2 additions & 2 deletions mm2src/coins/qrc20.rs
Original file line number Diff line number Diff line change
Expand Up @@ -59,7 +59,7 @@ use rpc::v1::types::{
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, serialize, CoinVariant};
use serialization::{deserialize, serialize};
use std::collections::{HashMap, HashSet};
use std::convert::TryInto;
use std::num::TryFromIntError;
Expand Down Expand Up @@ -731,7 +731,7 @@ impl UtxoCommonOps for Qrc20Coin {
}

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

fn is_unspent_mature(&self, output: &RpcTransaction) -> bool {
Expand Down
6 changes: 5 additions & 1 deletion mm2src/coins/utxo.rs
Original file line number Diff line number Diff line change
Expand Up @@ -83,7 +83,9 @@ use rpc::v1::types::{Bytes as BytesJson, Transaction as RpcTransaction, H256 as
use script::{Builder, Script, SignatureVersion, TransactionInputSigner};
use secp256k1::Signature as SecpSignature;
use serde_json::{self as json, Value as Json};
use serialization::{deserialize, serialize, serialize_with_flags, Error as SerError, SERIALIZE_TRANSACTION_WITNESS};
use serialization::{
deserialize, serialize, serialize_with_flags, ChainVariant, Error as SerError, SERIALIZE_TRANSACTION_WITNESS,
};
use spv_validation::conf::SPVConf;
use spv_validation::helpers_validation::SPVError;
use spv_validation::storage::BlockHeaderStorageError;
Expand Down Expand Up @@ -626,6 +628,8 @@ pub struct UtxoCoinConf {
pub derivation_path: Option<HDPathToCoin>,
/// The average time in seconds needed to mine a new block for this coin.
pub avg_blocktime: Option<u64>,
/// How to interpret block headers for this coin (BTC, Qtum, RVN, etc.).
pub chain_variant: ChainVariant,
}

pub struct UtxoCoinFields {
Expand Down
5 changes: 2 additions & 3 deletions mm2src/coins/utxo/bch.rs
Original file line number Diff line number Diff line change
Expand Up @@ -42,7 +42,7 @@ use mm2_metrics::MetricsArc;
use mm2_number::MmNumber;
use rpc::v1::types::H264 as H264Json;
use serde_json::{self as json, Value as Json};
use serialization::{deserialize, CoinVariant};
use serialization::deserialize;
use std::sync::MutexGuard;

pub type BchUnspentMap = HashMap<Address, BchUnspents>;
Expand Down Expand Up @@ -825,8 +825,7 @@ impl UtxoCommonOps for BchCoin {
}

async fn get_current_mtp(&self) -> UtxoRpcResult<u32> {
// BCH uses the same coin variant as BTC for block header deserialization
utxo_common::get_current_mtp(&self.utxo_arc, CoinVariant::BTC).await
utxo_common::get_current_mtp(&self.utxo_arc).await
}

fn is_unspent_mature(&self, output: &RpcTransaction) -> bool {
Expand Down
3 changes: 1 addition & 2 deletions mm2src/coins/utxo/qtum.rs
Original file line number Diff line number Diff line change
Expand Up @@ -50,7 +50,6 @@ use mm2_metrics::MetricsArc;
use mm2_number::MmNumber;
use rpc::v1::types::H264 as H264Json;
use serde::Serialize;
use serialization::CoinVariant;
use utxo_signer::UtxoSignerOps;

#[derive(Debug, Display)]
Expand Down Expand Up @@ -438,7 +437,7 @@ impl UtxoCommonOps for QtumCoin {
}

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

fn is_unspent_mature(&self, output: &RpcTransaction) -> bool {
Expand Down
34 changes: 21 additions & 13 deletions mm2src/coins/utxo/rpc_clients.rs
Original file line number Diff line number Diff line change
Expand Up @@ -22,7 +22,7 @@ use mm2_err_handle::prelude::*;
use mm2_number::{BigDecimal, MmNumber};
use rpc::v1::types::{Bytes as BytesJson, Transaction as RpcTransaction, H256 as H256Json};
use script::Script;
use serialization::{deserialize, serialize, serialize_with_flags, CoinVariant, SERIALIZE_TRANSACTION_WITNESS};
use serialization::{deserialize, serialize, serialize_with_flags, ChainVariant, SERIALIZE_TRANSACTION_WITNESS};

use std::collections::HashMap;
use std::fmt;
Expand Down Expand Up @@ -193,6 +193,15 @@ impl UtxoRpcClientEnum {
UtxoRpcClientEnum::Electrum(_) => false,
}
}

/// Returns how block headers/transactions should be interpreted for this client.
/// Delegates to the underlying concrete client, which stores the configured ChainVariant.
pub fn chain_variant(&self) -> ChainVariant {
match self {
UtxoRpcClientEnum::Native(ref c) => c.chain_variant(),
UtxoRpcClientEnum::Electrum(ref c) => c.chain_variant(),
}
}
}

/// Generic unspent info required to build transactions, we need this separate type because native
Expand Down Expand Up @@ -389,12 +398,7 @@ pub trait UtxoRpcClientOps: fmt::Debug + Send + Sync + 'static {
) -> Box<dyn Future<Item = Option<SpentOutputInfo>, 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,
coin_variant: CoinVariant,
) -> UtxoRpcFut<u32>;
fn get_median_time_past(&self, starting_block: u64, count: NonZeroU64) -> UtxoRpcFut<u32>;

/// Returns block time in seconds since epoch (Jan 1 1970 GMT).
async fn get_block_timestamp(&self, height: u64) -> Result<u64, MmError<GetBlockHeaderError>>;
Expand Down Expand Up @@ -692,6 +696,7 @@ impl<K: Clone + Eq + std::hash::Hash, V: Clone> ConcurrentRequestMap<K, V> {
pub struct NativeClientImpl {
/// Name of coin the rpc client is intended to work with
pub coin_ticker: String,
pub chain_variant: ChainVariant,
/// The uri to send requests to
pub uri: String,
/// Value of Authorization header, e.g. "Basic base64(user:password)"
Expand All @@ -707,6 +712,7 @@ impl Default for NativeClientImpl {
fn default() -> Self {
NativeClientImpl {
coin_ticker: "TEST".to_string(),
chain_variant: ChainVariant::Standard,
uri: "".to_string(),
auth: "".to_string(),
event_handlers: vec![],
Expand All @@ -730,6 +736,9 @@ pub trait UtxoJsonRpcClientInfo: JsonRpcClient {
/// Name of coin the rpc client is intended to work with
fn coin_name(&self) -> &str;

/// How to interpret headers/transactions for the coin.
fn chain_variant(&self) -> ChainVariant;

/// Generate client info from coin name
fn client_info(&self) -> String {
format!("coin: {}", self.coin_name())
Expand All @@ -740,6 +749,10 @@ impl UtxoJsonRpcClientInfo for NativeClientImpl {
fn coin_name(&self) -> &str {
self.coin_ticker.as_str()
}

fn chain_variant(&self) -> ChainVariant {
self.chain_variant
}
}

impl JsonRpcClient for NativeClientImpl {
Expand Down Expand Up @@ -992,12 +1005,7 @@ impl UtxoRpcClientOps for NativeClient {
Box::new(fut.boxed().compat())
}

fn get_median_time_past(
&self,
starting_block: u64,
count: NonZeroU64,
_coin_variant: CoinVariant,
) -> UtxoRpcFut<u32> {
fn get_median_time_past(&self, starting_block: u64, count: NonZeroU64) -> UtxoRpcFut<u32> {
let selfi = self.clone();
let fut = async move {
let starting_block_hash = selfi.get_block_hash(starting_block).compat().await?;
Expand Down
34 changes: 23 additions & 11 deletions mm2src/coins/utxo/rpc_clients/electrum_rpc/client.rs
Original file line number Diff line number Diff line change
Expand Up @@ -36,7 +36,7 @@ use mm2_number::BigDecimal;
use mocktopus::macros::*;
use rpc::v1::types::{Bytes as BytesJson, Transaction as RpcTransaction, H256 as H256Json};
use serialization::{
deserialize, serialize, serialize_with_flags, CoinVariant, CompactInteger, Reader, SERIALIZE_TRANSACTION_WITNESS,
deserialize, serialize, serialize_with_flags, ChainVariant, CompactInteger, Reader, SERIALIZE_TRANSACTION_WITNESS,
};
use spv_validation::helpers_validation::SPVError;
use spv_validation::storage::BlockHeaderStorageOps;
Expand Down Expand Up @@ -84,6 +84,7 @@ pub struct ElectrumClientSettings {
pub struct ElectrumClientImpl {
client_name: String,
coin_ticker: String,
chain_variant: ChainVariant,
pub connection_manager: ConnectionManager,
next_id: AtomicU64,
negotiate_version: bool,
Expand Down Expand Up @@ -112,6 +113,7 @@ impl ElectrumClientImpl {
streaming_manager: StreamingManager,
abortable_system: AbortableQueue,
mut event_handlers: Vec<Box<SharableRpcTransportEventHandler>>,
chain_variant: ChainVariant,
) -> Result<ElectrumClientImpl, String> {
let connection_manager = ConnectionManager::try_new(
client_settings.servers,
Expand All @@ -127,6 +129,7 @@ impl ElectrumClientImpl {
Ok(ElectrumClientImpl {
client_name: client_settings.client_name,
coin_ticker: client_settings.coin_ticker,
chain_variant,
connection_manager,
next_id: 0.into(),
negotiate_version: client_settings.negotiate_version,
Expand All @@ -148,13 +151,15 @@ impl ElectrumClientImpl {
streaming_manager: StreamingManager,
abortable_system: AbortableQueue,
event_handlers: Vec<Box<SharableRpcTransportEventHandler>>,
chain_variant: ChainVariant,
) -> Result<Arc<ElectrumClientImpl>, String> {
let client_impl = Arc::new(ElectrumClientImpl::try_new(
client_settings,
block_headers_storage,
streaming_manager,
abortable_system,
event_handlers,
chain_variant,
)?);
// Initialize the connection manager.
client_impl
Expand Down Expand Up @@ -227,6 +232,10 @@ impl ElectrumClientImpl {
&self.block_headers_storage
}

pub fn chain_variant(&self) -> ChainVariant {
self.chain_variant
}

pub fn weak_spawner(&self) -> WeakSpawner {
self.abortable_system.weak_spawner()
}
Expand All @@ -239,6 +248,7 @@ impl ElectrumClientImpl {
abortable_system: AbortableQueue,
event_handlers: Vec<Box<SharableRpcTransportEventHandler>>,
protocol_version: OrdRange<f32>,
chain_variant: ChainVariant,
) -> Result<Arc<ElectrumClientImpl>, String> {
let client_impl = Arc::new(ElectrumClientImpl {
protocol_version,
Expand All @@ -248,6 +258,7 @@ impl ElectrumClientImpl {
streaming_manager,
abortable_system,
event_handlers,
chain_variant,
)?
});
// Initialize the connection manager.
Expand All @@ -274,6 +285,10 @@ impl UtxoJsonRpcClientInfo for ElectrumClient {
fn coin_name(&self) -> &str {
self.coin_ticker.as_str()
}

fn chain_variant(&self) -> ChainVariant {
self.chain_variant
}
}

impl JsonRpcClient for ElectrumClient {
Expand Down Expand Up @@ -316,13 +331,15 @@ impl ElectrumClient {
block_headers_storage: BlockHeaderStorage,
streaming_manager: StreamingManager,
abortable_system: AbortableQueue,
chain_variant: ChainVariant,
) -> Result<ElectrumClient, String> {
let client = ElectrumClient(ElectrumClientImpl::try_new_arc(
client_settings,
block_headers_storage,
streaming_manager,
abortable_system,
event_handlers,
chain_variant,
)?);

Ok(client)
Expand Down Expand Up @@ -752,7 +769,7 @@ impl ElectrumClient {
from_height: u64,
to_height: u64,
) -> UtxoRpcFut<(HashMap<u64, BlockHeader>, Vec<BlockHeader>)> {
let coin_name = self.coin_ticker.clone();
let chain_variant = self.chain_variant;
if from_height == 0 || to_height < from_height {
return Box::new(futures01::future::err(
UtxoRpcError::Internal("Invalid values for from/to parameters".to_string()).into(),
Expand All @@ -774,8 +791,7 @@ impl ElectrumClient {
let mut serialized = serialize(&len).take();
serialized.extend(headers.hex.0);
drop_mutability!(serialized);
let mut reader =
Reader::new_with_coin_variant(serialized.as_slice(), coin_name.as_str().into());
let mut reader = Reader::new_with_chain_variant(serialized.as_slice(), chain_variant);
let maybe_block_headers = reader.read_list::<BlockHeader>();
let block_headers = match maybe_block_headers {
Ok(headers) => headers,
Expand Down Expand Up @@ -1089,19 +1105,15 @@ impl UtxoRpcClientOps for ElectrumClient {
Box::new(fut.boxed().compat())
}

fn get_median_time_past(
&self,
starting_block: u64,
count: NonZeroU64,
coin_variant: CoinVariant,
) -> UtxoRpcFut<u32> {
fn get_median_time_past(&self, starting_block: u64, count: NonZeroU64) -> UtxoRpcFut<u32> {
let from = if starting_block <= count.get() {
0
} else {
starting_block - count.get() + 1
};

let coin_name = self.coin_ticker.clone();
let chain_variant = self.chain_variant;
let requested_count = count.get();

Box::new(
Expand All @@ -1115,7 +1127,7 @@ impl UtxoRpcClientOps for ElectrumClient {
let len = CompactInteger::from(res_count);
let mut serialized = serialize(&len).take();
serialized.extend(res.hex.0);
let mut reader = Reader::new_with_coin_variant(serialized.as_slice(), coin_variant);
let mut reader = Reader::new_with_chain_variant(serialized.as_slice(), chain_variant);

let headers = reader.read_list::<BlockHeader>().map_to_mm(|e| UtxoRpcError::InvalidResponse(format!(
"blockchain.block.headers: failed to parse list of {} headers (coin={}, from={}, requested_count={}): {}",
Expand Down
Loading
Loading