Add stop_gap param to electrum and esplora blockchain configs

This commit is contained in:
Steve Myers 2021-07-15 10:55:49 -07:00
parent 77379e9262
commit 7e986fd904
No known key found for this signature in database
GPG Key ID: 8105A46B22C2D051
3 changed files with 59 additions and 39 deletions

View File

@ -188,7 +188,8 @@ impl_from!(compact_filters::CompactFiltersBlockchain, AnyBlockchain, CompactFilt
/// r#"{ /// r#"{
/// "type" : "electrum", /// "type" : "electrum",
/// "url" : "ssl://electrum.blockstream.info:50002", /// "url" : "ssl://electrum.blockstream.info:50002",
/// "retry": 2 /// "retry": 2,
/// "stop_gap": 20
/// }"#, /// }"#,
/// ) /// )
/// .unwrap(); /// .unwrap();
@ -198,7 +199,8 @@ impl_from!(compact_filters::CompactFiltersBlockchain, AnyBlockchain, CompactFilt
/// url: "ssl://electrum.blockstream.info:50002".into(), /// url: "ssl://electrum.blockstream.info:50002".into(),
/// retry: 2, /// retry: 2,
/// socks5: None, /// socks5: None,
/// timeout: None /// timeout: None,
/// stop_gap: 20,
/// }) /// })
/// ); /// );
/// # } /// # }

View File

@ -43,11 +43,17 @@ use crate::FeeRate;
/// ///
/// ## Example /// ## Example
/// See the [`blockchain::electrum`](crate::blockchain::electrum) module for a usage 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<Client> for ElectrumBlockchain { impl std::convert::From<Client> for ElectrumBlockchain {
fn from(client: Client) -> Self { fn from(client: Client) -> Self {
ElectrumBlockchain(client) ElectrumBlockchain {
client,
stop_gap: 20,
}
} }
} }
@ -64,34 +70,34 @@ impl Blockchain for ElectrumBlockchain {
fn setup<D: BatchDatabase, P: Progress>( fn setup<D: BatchDatabase, P: Progress>(
&self, &self,
stop_gap: Option<usize>, _stop_gap: Option<usize>,
database: &mut D, database: &mut D,
progress_update: P, progress_update: P,
) -> Result<(), Error> { ) -> Result<(), Error> {
self.0 self.client
.electrum_like_setup(stop_gap, database, progress_update) .electrum_like_setup(Some(self.stop_gap), database, progress_update)
} }
fn get_tx(&self, txid: &Txid) -> Result<Option<Transaction>, Error> { fn get_tx(&self, txid: &Txid) -> Result<Option<Transaction>, 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> { 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<u32, Error> { fn get_height(&self) -> Result<u32, Error> {
// TODO: unsubscribe when added to the client, or is there a better call to use here? // TODO: unsubscribe when added to the client, or is there a better call to use here?
Ok(self Ok(self
.0 .client
.block_headers_subscribe() .block_headers_subscribe()
.map(|data| data.height as u32)?) .map(|data| data.height as u32)?)
} }
fn estimate_fee(&self, target: usize) -> Result<FeeRate, Error> { fn estimate_fee(&self, target: usize) -> Result<FeeRate, Error> {
Ok(FeeRate::from_btc_per_kvb( 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, pub retry: u8,
/// Request timeout (seconds) /// Request timeout (seconds)
pub timeout: Option<u8>, pub timeout: Option<u8>,
/// Stop searching addresses for transactions after finding an unused gap of this length
pub stop_gap: usize,
} }
impl ConfigurableBlockchain for ElectrumBlockchain { impl ConfigurableBlockchain for ElectrumBlockchain {
@ -162,10 +170,10 @@ impl ConfigurableBlockchain for ElectrumBlockchain {
.socks5(socks5)? .socks5(socks5)?
.build(); .build();
Ok(ElectrumBlockchain(Client::from_config( Ok(ElectrumBlockchain {
config.url.as_str(), client: Client::from_config(config.url.as_str(), electrum_config)?,
electrum_config, stop_gap: config.stop_gap,
)?)) })
} }
} }

View File

@ -25,27 +25,25 @@
use std::collections::{HashMap, HashSet}; use std::collections::{HashMap, HashSet};
use std::fmt; 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::consensus::{self, deserialize, serialize};
use bitcoin::hashes::hex::{FromHex, ToHex}; use bitcoin::hashes::hex::{FromHex, ToHex};
use bitcoin::hashes::{sha256, Hash}; use bitcoin::hashes::{sha256, Hash};
use bitcoin::{BlockHash, BlockHeader, Script, Transaction, Txid}; 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::database::BatchDatabase;
use crate::error::Error; use crate::error::Error;
use crate::wallet::utils::ChunksIterator; use crate::wallet::utils::ChunksIterator;
use crate::FeeRate; use crate::FeeRate;
use super::*;
use self::utils::{ElectrumLikeSync, ElsGetHistoryRes};
const DEFAULT_CONCURRENT_REQUESTS: u8 = 4; const DEFAULT_CONCURRENT_REQUESTS: u8 = 4;
#[derive(Debug)] #[derive(Debug)]
@ -62,22 +60,31 @@ struct UrlClient {
/// ## Example /// ## Example
/// See the [`blockchain::esplora`](crate::blockchain::esplora) module for a usage example. /// See the [`blockchain::esplora`](crate::blockchain::esplora) module for a usage example.
#[derive(Debug)] #[derive(Debug)]
pub struct EsploraBlockchain(UrlClient); pub struct EsploraBlockchain {
url_client: UrlClient,
stop_gap: usize,
}
impl std::convert::From<UrlClient> for EsploraBlockchain { impl std::convert::From<UrlClient> for EsploraBlockchain {
fn from(url_client: UrlClient) -> Self { fn from(url_client: UrlClient) -> Self {
EsploraBlockchain(url_client) EsploraBlockchain {
url_client,
stop_gap: 20,
}
} }
} }
impl EsploraBlockchain { impl EsploraBlockchain {
/// Create a new instance of the client from a base URL /// Create a new instance of the client from a base URL
pub fn new(base_url: &str, concurrency: Option<u8>) -> Self { pub fn new(base_url: &str, concurrency: Option<u8>, stop_gap: usize) -> Self {
EsploraBlockchain(UrlClient { EsploraBlockchain {
url_client: UrlClient {
url: base_url.to_string(), url: base_url.to_string(),
client: Client::new(), client: Client::new(),
concurrency: concurrency.unwrap_or(DEFAULT_CONCURRENT_REQUESTS), concurrency: concurrency.unwrap_or(DEFAULT_CONCURRENT_REQUESTS),
}) },
stop_gap,
}
} }
} }
@ -100,24 +107,24 @@ impl Blockchain for EsploraBlockchain {
progress_update: P, progress_update: P,
) -> Result<(), Error> { ) -> Result<(), Error> {
maybe_await!(self maybe_await!(self
.0 .url_client
.electrum_like_setup(stop_gap, database, progress_update)) .electrum_like_setup(stop_gap, database, progress_update))
} }
fn get_tx(&self, txid: &Txid) -> Result<Option<Transaction>, Error> { fn get_tx(&self, txid: &Txid) -> Result<Option<Transaction>, 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> { 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<u32, Error> { fn get_height(&self) -> Result<u32, Error> {
Ok(await_or_block!(self.0._get_height())?) Ok(await_or_block!(self.url_client._get_height())?)
} }
fn estimate_fee(&self, target: usize) -> Result<FeeRate, Error> { fn estimate_fee(&self, target: usize) -> Result<FeeRate, Error> {
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 let fee_val = estimates
.into_iter() .into_iter()
@ -369,6 +376,8 @@ pub struct EsploraBlockchainConfig {
pub base_url: String, pub base_url: String,
/// Number of parallel requests sent to the esplora service (default: 4) /// Number of parallel requests sent to the esplora service (default: 4)
pub concurrency: Option<u8>, pub concurrency: Option<u8>,
/// Stop searching addresses for transactions after finding an unused gap of this length
pub stop_gap: usize,
} }
impl ConfigurableBlockchain for EsploraBlockchain { impl ConfigurableBlockchain for EsploraBlockchain {
@ -378,6 +387,7 @@ impl ConfigurableBlockchain for EsploraBlockchain {
Ok(EsploraBlockchain::new( Ok(EsploraBlockchain::new(
config.base_url.as_str(), config.base_url.as_str(),
config.concurrency, config.concurrency,
config.stop_gap,
)) ))
} }
} }