Skip to content

Commit

Permalink
Switch to upstream rust-electrum-client, upgrade to v0.4.0
Browse files Browse the repository at this point in the history
It now has native support for setting the socket timeout,
implemented in bitcoindevkit/rust-electrum-client#27
  • Loading branch information
shesek committed Feb 27, 2021
1 parent 53a6f29 commit 51e2c21
Show file tree
Hide file tree
Showing 5 changed files with 17 additions and 52 deletions.
3 changes: 1 addition & 2 deletions subprojects/gdk_rust/Cargo.toml
Original file line number Diff line number Diff line change
Expand Up @@ -30,7 +30,7 @@ ureq = { version = "1.0.0", features = ["json"] }
[dev-dependencies]
tempdir = "0.3.7"
bitcoincore-rpc = { git="https://github.com/romanz/rust-bitcoincore-rpc", rev="637e895a0b73ffc21c8f62fa2c65b6fd1247785a" }
electrum-client = "0.3.0-beta.1"
electrum-client = "0.4.0-beta.1"
elements = { version = "0.13", features = ["serde-feature"] }

[profile.release]
Expand All @@ -42,4 +42,3 @@ incremental = false

[patch.crates-io]
bitcoin = { git = "https://github.com/shesek/rust-bitcoin", branch = "0.25.2-uint-serde", features = [ "use-serde" ] }
electrum-client = { git = "https://github.com/shesek/rust-electrum-client", branch = "202011-custom-ssl-stream" }
3 changes: 1 addition & 2 deletions subprojects/gdk_rust/gdk_electrum/Cargo.toml
Original file line number Diff line number Diff line change
Expand Up @@ -19,7 +19,7 @@ aes-gcm-siv = "0.5.0"
gdk-common = { path = "../gdk_common" }
libc = "0.2"
android_logger = { version = "0.8.6", optional = true }
electrum-client = "0.3.0-beta.1"
electrum-client = "0.4.0-beta.1"
chrono = "0.4.11"
ureq = { version = "1.0.0", features = ["json"] }
block-modes = "0.3.3"
Expand All @@ -34,4 +34,3 @@ elements = { version = "0.13", features = ["serde-feature"] }

[patch.crates-io]
bitcoin = { git = "https://github.com/shesek/rust-bitcoin", branch = "0.25.2-uint-serde", features = [ "use-serde" ] }
electrum-client = { git = "https://github.com/shesek/rust-electrum-client", branch = "202011-custom-ssl-stream" }
46 changes: 9 additions & 37 deletions subprojects/gdk_rust/gdk_electrum/src/interface.rs
Original file line number Diff line number Diff line change
Expand Up @@ -22,16 +22,13 @@ use crate::error::*;
use crate::store::*;

use bitcoin::util::bip143::SigHashCache;
use electrum_client::raw_client::RawClient;
use electrum_client::Client;
use electrum_client::{Client, ConfigBuilder};
use elements::confidential::{Asset, Nonce, Value};
use gdk_common::be::{self, *};
use std::cmp::Ordering;
use std::collections::{HashMap, HashSet};
use std::convert::TryInto;
use std::net::{TcpStream, ToSocketAddrs};
use std::str::FromStr;
use std::time::Duration;

pub struct WalletCtx {
pub secp: Secp256k1<All>,
Expand All @@ -52,41 +49,19 @@ pub enum ElectrumUrl {

impl ElectrumUrl {
pub fn build_client(&self) -> Result<Client, Error> {
match self {
ElectrumUrl::Tls(url, validate) => {
let client = RawClient::new_ssl(url.as_str(), *validate)?;
Ok(Client::SSL(client))
}
ElectrumUrl::Plaintext(url) => {
let client = RawClient::new(&url)?;
Ok(Client::TCP(client))
}
}
self.build_config(ConfigBuilder::new())
}

pub fn build_client_timeout(&self, timeouts: Timeouts) -> Result<Client, Error> {
let (connect_timeout, read_timeout, write_timeout) = timeouts;

let make_stream = |url: &str| -> Result<TcpStream, Error> {
let mut addrs = url.to_socket_addrs()?;
// connect_timeout only works with a single socket address
let addr = addrs.next().ok_or_else(|| Error::AddrParse(url.into()))?;

let stream = TcpStream::connect_timeout(&addr, connect_timeout)?;
stream.set_read_timeout(Some(read_timeout))?;
stream.set_write_timeout(Some(write_timeout))?;
Ok(stream)
};

match self {
pub fn build_config(&self, config: ConfigBuilder) -> Result<Client, Error> {
let (url, config) = match self {
ElectrumUrl::Tls(url, validate) => {
let stream = make_stream(&url)?;
let client = RawClient::new_ssl_from_stream(url.as_str(), *validate, stream)?;
Ok(Client::SSL(client))
(format!("tls://{}", url), config.validate_domain(*validate))
}
ElectrumUrl::Plaintext(url) => Ok(Client::TCP(make_stream(url)?.into())),
}
ElectrumUrl::Plaintext(url) => (format!("tcp://{}", url), config),
};
Ok(Client::from_config(&url, config.build())?)
}

pub fn url(&self) -> &str {
match self {
ElectrumUrl::Tls(url, _) => url,
Expand All @@ -95,9 +70,6 @@ impl ElectrumUrl {
}
}

/// Timeouts for connect, read and write
pub type Timeouts = (Duration, Duration, Duration);

// Parse the standard <host>:<port>:<t|s> string format,
// with an optional non-standard `:noverify` suffix to skip tls validation
impl FromStr for ElectrumUrl {
Expand Down
13 changes: 4 additions & 9 deletions subprojects/gdk_rust/gdk_electrum/src/spv.rs
Original file line number Diff line number Diff line change
Expand Up @@ -2,29 +2,24 @@ use log::warn;
use rand::seq::SliceRandom;
use serde::{Deserialize, Serialize};
use std::str::FromStr;
use std::time::Duration;

use bitcoin::blockdata::constants::{max_target, DIFFCHANGE_INTERVAL, DIFFCHANGE_TIMESPAN};
use bitcoin::BlockHash;
use bitcoin::{util::uint::Uint256, util::BitArray, BlockHeader};
use electrum_client::{Client as ElectrumClient, ElectrumApi};
use electrum_client::{Client as ElectrumClient, ConfigBuilder, ElectrumApi};

use gdk_common::network::Network;

use crate::error::Error;
use crate::headers::bitcoin::HeadersChain;
use crate::interface::{ElectrumUrl, Timeouts};
use crate::interface::ElectrumUrl;

const INIT_CHUNK_SIZE: u32 = 5;
const MAX_CHUNK_SIZE: u32 = 200;
const MAX_FORK_DEPTH: u32 = DIFFCHANGE_INTERVAL * 3;
const SERVERS_PER_ROUND: usize = 3;

const TIMEOUTS: Timeouts = (
Duration::from_secs(2), // connect timeout
Duration::from_secs(4), // read timeout
Duration::from_secs(2), // write timeout
);
const TIMEOUT: u8 = 3; // connect, read and write timeout

#[derive(Debug)]
pub struct SpvCrossValidator {
Expand Down Expand Up @@ -145,7 +140,7 @@ pub fn spv_cross_validate(
local_tip_hash: &BlockHash,
server_url: &ElectrumUrl,
) -> Result<CrossValidationResult, CrossValidationError> {
let client = server_url.build_client_timeout(TIMEOUTS)?;
let client = server_url.build_config(ConfigBuilder::new().timeout(TIMEOUT)?)?;
let remote_tip = client.block_headers_subscribe()?;
let remote_tip_hash = remote_tip.header.block_hash();
let remote_tip_height = remote_tip.height as u32;
Expand Down
4 changes: 2 additions & 2 deletions subprojects/gdk_rust/tests/test_session.rs
Original file line number Diff line number Diff line change
Expand Up @@ -183,7 +183,7 @@ pub fn setup(
let electrs_header = loop {
assert!(i > 0, "1 minute without updates");
i -= 1;
match RawClient::new(&electrs_url) {
match RawClient::new(&electrs_url, None) {
Ok(c) => {
let header = c.block_headers_subscribe_raw().unwrap();
if header.height == 101 {
Expand All @@ -196,7 +196,7 @@ pub fn setup(
}
thread::sleep(Duration::from_millis(500));
};
let electrs = RawClient::new(&electrs_url).unwrap();
let electrs = RawClient::new(&electrs_url, None).unwrap();
info!("done creating electrs client");

let mut network = Network::default();
Expand Down

0 comments on commit 51e2c21

Please sign in to comment.