From 7e986fd904cd0c00b3a30da8623fb2d1fc6c1f9d Mon Sep 17 00:00:00 2001 From: Steve Myers Date: Thu, 15 Jul 2021 10:55:49 -0700 Subject: [PATCH] Add stop_gap param to electrum and esplora blockchain configs --- src/blockchain/any.rs | 6 ++-- src/blockchain/electrum.rs | 34 +++++++++++++--------- src/blockchain/esplora.rs | 58 ++++++++++++++++++++++---------------- 3 files changed, 59 insertions(+), 39 deletions(-) diff --git a/src/blockchain/any.rs b/src/blockchain/any.rs index 21913c92..9ab53861 100644 --- a/src/blockchain/any.rs +++ b/src/blockchain/any.rs @@ -188,7 +188,8 @@ impl_from!(compact_filters::CompactFiltersBlockchain, AnyBlockchain, CompactFilt /// r#"{ /// "type" : "electrum", /// "url" : "ssl://electrum.blockstream.info:50002", -/// "retry": 2 +/// "retry": 2, +/// "stop_gap": 20 /// }"#, /// ) /// .unwrap(); @@ -198,7 +199,8 @@ impl_from!(compact_filters::CompactFiltersBlockchain, AnyBlockchain, CompactFilt /// url: "ssl://electrum.blockstream.info:50002".into(), /// retry: 2, /// socks5: None, -/// timeout: None +/// timeout: None, +/// stop_gap: 20, /// }) /// ); /// # } diff --git a/src/blockchain/electrum.rs b/src/blockchain/electrum.rs index cba210a9..df9e72b1 100644 --- a/src/blockchain/electrum.rs +++ b/src/blockchain/electrum.rs @@ -43,11 +43,17 @@ use crate::FeeRate; /// /// ## Example /// See the [`blockchain::electrum`](crate::blockchain::electrum) module for a usage example. -pub struct ElectrumBlockchain(Client); +pub struct ElectrumBlockchain { + client: Client, + stop_gap: usize, +} impl std::convert::From for ElectrumBlockchain { fn from(client: Client) -> Self { - ElectrumBlockchain(client) + ElectrumBlockchain { + client, + stop_gap: 20, + } } } @@ -64,34 +70,34 @@ impl Blockchain for ElectrumBlockchain { fn setup( &self, - stop_gap: Option, + _stop_gap: Option, database: &mut D, progress_update: P, ) -> Result<(), Error> { - self.0 - .electrum_like_setup(stop_gap, database, progress_update) + self.client + .electrum_like_setup(Some(self.stop_gap), database, progress_update) } fn get_tx(&self, txid: &Txid) -> Result, Error> { - Ok(self.0.transaction_get(txid).map(Option::Some)?) + Ok(self.client.transaction_get(txid).map(Option::Some)?) } fn broadcast(&self, tx: &Transaction) -> Result<(), Error> { - Ok(self.0.transaction_broadcast(tx).map(|_| ())?) + Ok(self.client.transaction_broadcast(tx).map(|_| ())?) } fn get_height(&self) -> Result { // TODO: unsubscribe when added to the client, or is there a better call to use here? Ok(self - .0 + .client .block_headers_subscribe() .map(|data| data.height as u32)?) } fn estimate_fee(&self, target: usize) -> Result { Ok(FeeRate::from_btc_per_kvb( - self.0.estimate_fee(target)? as f32 + self.client.estimate_fee(target)? as f32 )) } } @@ -149,6 +155,8 @@ pub struct ElectrumBlockchainConfig { pub retry: u8, /// Request timeout (seconds) pub timeout: Option, + /// Stop searching addresses for transactions after finding an unused gap of this length + pub stop_gap: usize, } impl ConfigurableBlockchain for ElectrumBlockchain { @@ -162,10 +170,10 @@ impl ConfigurableBlockchain for ElectrumBlockchain { .socks5(socks5)? .build(); - Ok(ElectrumBlockchain(Client::from_config( - config.url.as_str(), - electrum_config, - )?)) + Ok(ElectrumBlockchain { + client: Client::from_config(config.url.as_str(), electrum_config)?, + stop_gap: config.stop_gap, + }) } } diff --git a/src/blockchain/esplora.rs b/src/blockchain/esplora.rs index 7f49fd83..7de7ad8c 100644 --- a/src/blockchain/esplora.rs +++ b/src/blockchain/esplora.rs @@ -25,27 +25,25 @@ use std::collections::{HashMap, HashSet}; use std::fmt; -use futures::stream::{self, FuturesOrdered, StreamExt, TryStreamExt}; - -#[allow(unused_imports)] -use log::{debug, error, info, trace}; - -use serde::Deserialize; - -use reqwest::{Client, StatusCode}; - use bitcoin::consensus::{self, deserialize, serialize}; use bitcoin::hashes::hex::{FromHex, ToHex}; use bitcoin::hashes::{sha256, Hash}; use bitcoin::{BlockHash, BlockHeader, Script, Transaction, Txid}; +use futures::stream::{self, FuturesOrdered, StreamExt, TryStreamExt}; +#[allow(unused_imports)] +use log::{debug, error, info, trace}; +use reqwest::{Client, StatusCode}; +use serde::Deserialize; -use self::utils::{ElectrumLikeSync, ElsGetHistoryRes}; -use super::*; use crate::database::BatchDatabase; use crate::error::Error; use crate::wallet::utils::ChunksIterator; use crate::FeeRate; +use super::*; + +use self::utils::{ElectrumLikeSync, ElsGetHistoryRes}; + const DEFAULT_CONCURRENT_REQUESTS: u8 = 4; #[derive(Debug)] @@ -62,22 +60,31 @@ struct UrlClient { /// ## Example /// See the [`blockchain::esplora`](crate::blockchain::esplora) module for a usage example. #[derive(Debug)] -pub struct EsploraBlockchain(UrlClient); +pub struct EsploraBlockchain { + url_client: UrlClient, + stop_gap: usize, +} impl std::convert::From for EsploraBlockchain { fn from(url_client: UrlClient) -> Self { - EsploraBlockchain(url_client) + EsploraBlockchain { + url_client, + stop_gap: 20, + } } } impl EsploraBlockchain { /// Create a new instance of the client from a base URL - pub fn new(base_url: &str, concurrency: Option) -> Self { - EsploraBlockchain(UrlClient { - url: base_url.to_string(), - client: Client::new(), - concurrency: concurrency.unwrap_or(DEFAULT_CONCURRENT_REQUESTS), - }) + pub fn new(base_url: &str, concurrency: Option, stop_gap: usize) -> Self { + EsploraBlockchain { + url_client: UrlClient { + url: base_url.to_string(), + client: Client::new(), + concurrency: concurrency.unwrap_or(DEFAULT_CONCURRENT_REQUESTS), + }, + stop_gap, + } } } @@ -100,24 +107,24 @@ impl Blockchain for EsploraBlockchain { progress_update: P, ) -> Result<(), Error> { maybe_await!(self - .0 + .url_client .electrum_like_setup(stop_gap, database, progress_update)) } fn get_tx(&self, txid: &Txid) -> Result, Error> { - Ok(await_or_block!(self.0._get_tx(txid))?) + Ok(await_or_block!(self.url_client._get_tx(txid))?) } fn broadcast(&self, tx: &Transaction) -> Result<(), Error> { - Ok(await_or_block!(self.0._broadcast(tx))?) + Ok(await_or_block!(self.url_client._broadcast(tx))?) } fn get_height(&self) -> Result { - Ok(await_or_block!(self.0._get_height())?) + Ok(await_or_block!(self.url_client._get_height())?) } fn estimate_fee(&self, target: usize) -> Result { - let estimates = await_or_block!(self.0._get_fee_estimates())?; + let estimates = await_or_block!(self.url_client._get_fee_estimates())?; let fee_val = estimates .into_iter() @@ -369,6 +376,8 @@ pub struct EsploraBlockchainConfig { pub base_url: String, /// Number of parallel requests sent to the esplora service (default: 4) pub concurrency: Option, + /// Stop searching addresses for transactions after finding an unused gap of this length + pub stop_gap: usize, } impl ConfigurableBlockchain for EsploraBlockchain { @@ -378,6 +387,7 @@ impl ConfigurableBlockchain for EsploraBlockchain { Ok(EsploraBlockchain::new( config.base_url.as_str(), config.concurrency, + config.stop_gap, )) } }