Connection timeout (#765)

This commit is contained in:
ardocrat
2026-07-05 21:21:53 +02:00
committed by GitHub
parent 547675dcab
commit 876ee1c277
14 changed files with 181 additions and 106 deletions
+7 -3
View File
@@ -140,7 +140,7 @@ where
///
/// // A NodeClient must first be created to handle communication between
/// // the wallet and the node.
/// let node_client = HTTPNodeClient::new(&wallet_config.check_node_api_http_addr, None).unwrap();
/// let node_client = HTTPNodeClient::new(&wallet_config.check_node_api_http_addr, None, wallet_config.api_request_timeout()).unwrap();
///
/// // impls::DefaultWalletImpl is provided for convenience in instantiating the wallet
/// // It contains the LMDBBackend, DefaultLCProvider (lifecycle) and ExtKeychain used
@@ -506,8 +506,12 @@ macro_rules! doctest_helper_setup_doc_env_foreign {
wallet_config.data_file_dir = dir.to_owned();
let pw = ZeroingString::from("");
let node_client =
HTTPNodeClient::new(&wallet_config.check_node_api_http_addr, None).unwrap();
let node_client = HTTPNodeClient::new(
&wallet_config.check_node_api_http_addr,
None,
wallet_config.api_request_timeout(),
)
.unwrap();
let mut wallet =
Box::new(DefaultWalletImpl::<HTTPNodeClient>::new(node_client.clone()).unwrap())
as Box<
+7 -3
View File
@@ -147,7 +147,7 @@ where
///
/// // A NodeClient must first be created to handle communication between
/// // the wallet and the node.
/// let node_client = HTTPNodeClient::new(&wallet_config.check_node_api_http_addr, None).unwrap();
/// let node_client = HTTPNodeClient::new(&wallet_config.check_node_api_http_addr, None, wallet_config.api_request_timeout()).unwrap();
///
/// // impls::DefaultWalletImpl is provided for convenience in instantiating the wallet
/// // It contains the WalletBackend, DefaultLCProvider (lifecycle) and ExtKeychain used
@@ -2610,8 +2610,12 @@ macro_rules! doctest_helper_setup_doc_env {
wallet_config.data_file_dir = dir.to_owned();
let pw = ZeroingString::from("");
let node_client =
HTTPNodeClient::new(&wallet_config.check_node_api_http_addr, None).unwrap();
let node_client = HTTPNodeClient::new(
&wallet_config.check_node_api_http_addr,
None,
wallet_config.api_request_timeout(),
)
.unwrap();
let mut wallet =
Box::new(DefaultWalletImpl::<HTTPNodeClient>::new(node_client.clone()).unwrap())
as Box<
+23
View File
@@ -70,6 +70,13 @@ fn comments() -> HashMap<String, String> {
"check_node_api_http_addr".to_string(),
"
#where the wallet should find a running node
"
.to_string(),
);
retval.insert(
"node_api_request_timeout_secs".to_string(),
"
#total timeout for requests to node API
"
.to_string(),
);
@@ -252,6 +259,22 @@ fn comments() -> HashMap<String, String> {
.to_string(),
);
retval.insert(
"request_timeout_secs".to_string(),
"
#Tor request timeout in seconds
"
.to_string(),
);
retval.insert(
"bootstrap_timeout_secs".to_string(),
"
#Tor bootstrap timeout in seconds
"
.to_string(),
);
retval.insert(
"[tor.bridge]".to_string(),
"
+47 -3
View File
@@ -14,12 +14,12 @@
//! Public types for config modules
use crate::core::global::ChainTypes;
use crate::util::logger::LoggingConfig;
use std::fmt;
use std::io;
use std::path::PathBuf;
use crate::core::global::ChainTypes;
use crate::util::logger::LoggingConfig;
use std::time::Duration;
/// Command-line wallet configuration
#[derive(Debug, Clone, Serialize, Deserialize, PartialEq)]
@@ -37,6 +37,8 @@ pub struct WalletConfig {
/// The api address of a running server node against which transaction inputs
/// will be checked during send
pub check_node_api_http_addr: String,
/// Request timeout for requests to node API.
pub node_api_request_timeout_secs: Option<u64>,
/// Whether to include foreign API endpoints on the Owner API
pub owner_api_include_foreign: Option<bool>,
/// The directory in which wallet files are stored
@@ -65,6 +67,7 @@ impl Default for WalletConfig {
api_secret_path: Some(".owner_api_secret".to_string()),
node_api_secret_path: Some(".foreign_api_secret".to_string()),
check_node_api_http_addr: "http://127.0.0.1:3413".to_string(),
node_api_request_timeout_secs: Some(Self::NODE_API_REQUEST_TIMEOUT_SECS),
owner_api_include_foreign: Some(false),
data_file_dir: ".".to_string(),
no_commit_cache: Some(false),
@@ -77,6 +80,9 @@ impl Default for WalletConfig {
}
impl WalletConfig {
/// Default Node API request timeout in seconds.
pub const NODE_API_REQUEST_TIMEOUT_SECS: u64 = 60;
/// API Listen address
pub fn api_listen_addr(&self) -> String {
format!("127.0.0.1:{}", self.api_listen_port)
@@ -108,6 +114,15 @@ impl WalletConfig {
self.accept_fee_base
.unwrap_or_else(|| WalletConfig::default_accept_fee_base())
}
/// Node API requests timeout.
pub fn api_request_timeout(&self) -> Duration {
Duration::from_secs(
self.node_api_request_timeout_secs
.filter(|s| *s > 0)
.unwrap_or(Self::NODE_API_REQUEST_TIMEOUT_SECS),
)
}
}
/// Error type wrapping config errors.
#[derive(Debug)]
@@ -172,6 +187,10 @@ pub struct TorConfig {
pub socks_proxy_addr: String,
/// Send configuration directory
pub send_config_dir: String,
/// Total timeout for request in seconds.
pub request_timeout_secs: Option<u64>,
/// Timeout for bootstrap in seconds.
pub bootstrap_timeout_secs: Option<u64>,
/// Tor bridge config
#[serde(default)]
pub bridge: TorBridgeConfig,
@@ -188,6 +207,8 @@ impl Default for TorConfig {
use_tor_listener: true,
socks_proxy_addr: "127.0.0.1:59050".to_owned(),
send_config_dir: ".".into(),
request_timeout_secs: Some(Self::REQUEST_TIMEOUT_SECS),
bootstrap_timeout_secs: Some(Self::BOOTSTRAP_TIMEOUT_SECS),
bridge: TorBridgeConfig::default(),
proxy: TorProxyConfig::default(),
}
@@ -195,6 +216,11 @@ impl Default for TorConfig {
}
impl TorConfig {
/// Tor request timeout in seconds.
const REQUEST_TIMEOUT_SECS: u64 = 60;
/// Tor bootstrap timeout in seconds.
const BOOTSTRAP_TIMEOUT_SECS: u64 = 60;
/// Check if attempt to send over Tor is needed using provided possible argument at priority.
pub fn send_tor(&self, skip_arg: Option<bool>) -> bool {
if let Some(skip_tor) = skip_arg {
@@ -202,6 +228,24 @@ impl TorConfig {
}
!self.skip_send_attempt.unwrap_or(false)
}
/// Request timeout.
pub fn request_timeout(&self) -> Duration {
Duration::from_secs(
self.request_timeout_secs
.filter(|s| *s > 0)
.unwrap_or(Self::REQUEST_TIMEOUT_SECS),
)
}
/// Bootstrap timeout.
pub fn bootstrap_timeout(&self) -> Duration {
Duration::from_secs(
self.bootstrap_timeout_secs
.filter(|s| *s > 0)
.unwrap_or(Self::BOOTSTRAP_TIMEOUT_SECS),
)
}
}
/// Tor Bridge Config
+1 -1
View File
@@ -22,6 +22,7 @@ use crate::error::Error;
use crate::impls::PathToSlatepack;
use crate::impls::SlateGetter as _;
use crate::keychain;
use crate::libwallet::api_impl::types::update_tx_slate_state;
use crate::libwallet::{
self, InitTxArgs, IssueInvoiceTxArgs, NodeClient, PaymentProof, Slate, SlateState, Slatepack,
SlatepackAddress, Slatepacker, SlatepackerArgs, WalletLCProvider,
@@ -40,7 +41,6 @@ use std::sync::Arc;
use std::thread;
use std::time::Duration;
use uuid::Uuid;
use grin_wallet_libwallet::api_impl::types::update_tx_slate_state;
fn show_recovery_phrase(phrase: ZeroingString) {
println!("Your recovery phrase is:");
+7 -16
View File
@@ -25,7 +25,6 @@ use crate::util::secp::key::SecretKey;
use crate::util::{from_hex, static_secp_instance, to_base64, Mutex};
use futures::channel::oneshot;
use grin_wallet_api::JsonId;
use grin_wallet_config::types::{TorBridgeConfig, TorProxyConfig};
use grin_wallet_util::OnionV3Address;
use hyper::body;
use hyper::header::HeaderValue;
@@ -88,18 +87,16 @@ fn init_tor_listener(
sec_key: SecretKey,
tor_dir: String,
addr: &str,
bridge: TorBridgeConfig,
tor_proxy: TorProxyConfig,
tor_config: TorConfig,
) -> Result<Tor, Error> {
info!("Starting external Tor Process listener.");
let mut process = tor_process::TorProcess::new();
let tor_timeout = tor_config.bootstrap_timeout().as_secs();
let mut hm_tor_bridge: HashMap<String, String> = HashMap::new();
let mut tor_timeout = 20;
if bridge.bridge_line.is_some() {
tor_timeout = 40;
let bridge_config = tor_bridge::TorBridge::try_from(bridge)
if tor_config.bridge.bridge_line.is_some() {
let bridge_config = tor_bridge::TorBridge::try_from(tor_config.bridge)
.map_err(|e| Error::TorConfig(format!("{}", e).into()))?;
hm_tor_bridge = bridge_config
.to_hashmap()
@@ -107,8 +104,8 @@ fn init_tor_listener(
}
let mut hm_tor_poxy: HashMap<String, String> = HashMap::new();
if tor_proxy.transport.is_some() || tor_proxy.allowed_port.is_some() {
let proxy_config = tor_proxy::TorProxy::try_from(tor_proxy)
if tor_config.proxy.transport.is_some() || tor_config.proxy.allowed_port.is_some() {
let proxy_config = tor_proxy::TorProxy::try_from(tor_config.proxy)
.map_err(|e| Error::TorConfig(format!("{}", e).into()))?;
hm_tor_poxy = proxy_config
.to_hashmap()
@@ -323,13 +320,7 @@ where
let res = if use_integrated {
start_tor_service(sec_key, &tor_dir, addr, tor_config.clone())
} else {
init_tor_listener(
sec_key,
tor_dir,
addr,
tor_config.bridge.clone(),
tor_config.proxy.clone(),
)
init_tor_listener(sec_key, tor_dir, addr, tor_config)
};
match res {
Ok(service) => {
+12 -12
View File
@@ -12,15 +12,6 @@
// See the License for the specific language governing permissions and
// limitations under the License.
use grin_wallet_config::TorConfig;
use serde::Serialize;
use serde_json::{json, Value};
use std::collections::HashMap;
use std::convert::TryFrom;
use std::net::SocketAddr;
use std::path::PathBuf;
use std::sync::Arc;
use crate::client_utils::{Client, ClientError};
use crate::libwallet::slate_versions::{SlateVersion, VersionedSlate};
use crate::libwallet::{Error, Slate};
@@ -30,6 +21,14 @@ use crate::tor::process::TorProcess;
use crate::tor::proxy::TorProxy;
use crate::tor::{config as tor_config, Tor};
use crate::SlateSender;
use grin_wallet_config::TorConfig;
use serde::Serialize;
use serde_json::{json, Value};
use std::collections::HashMap;
use std::convert::TryFrom;
use std::net::SocketAddr;
use std::path::PathBuf;
use std::sync::Arc;
#[derive(Clone)]
pub struct TorSlateSender {
@@ -104,7 +103,7 @@ impl TorSlateSender {
path.push("torrc");
tor.torrc_path(path.to_str().unwrap())
.working_dir(tor_dir.to_str().unwrap())
.timeout(20)
.timeout(config.bootstrap_timeout().as_secs())
.completion_percent(100)
.launch()
.map_err(|e| Error::TorProcess(format!("{:?}", e)))?;
@@ -183,14 +182,15 @@ impl TorSlateSender {
SocketAddr::V4(self.config.socks_proxy_addr.parse().map_err(|_| {
ClientError::Internal("Socks proxy address is not set".to_string())
})?);
let client = Client::with_proxy(socks_proxy_addr, "socks5h://")
let timeout = self.config.request_timeout();
let client = Client::with_proxy(socks_proxy_addr, "socks5h://", timeout)
.map_err(|_| ClientError::Internal("Unable to create http client".into()))?;
let req = client.create_post_request(url, None, &input)?;
let res = client.send_request(req)?;
res
} else {
if let Some(client) = &self.tor.client {
tor_post(client.clone(), &input, url)
tor_post(client.clone(), &self.config, &input, url)
.map_err(|e| ClientError::RequestError(format!("{:?}", e)))?
} else {
return Err(ClientError::Internal("Tor is not configured".to_string()));
+10 -6
View File
@@ -52,22 +52,26 @@ pub struct Client {
impl Client {
/// New client
pub fn new() -> Result<Self, Error> {
Self::build(None)
pub fn new(request_timeout: Duration) -> Result<Self, Error> {
Self::build(None, request_timeout)
}
pub fn with_proxy(socks_proxy_addr: SocketAddr, scheme: &'static str) -> Result<Self, Error> {
Self::build(Some((socks_proxy_addr, scheme)))
pub fn with_proxy(
socks_proxy_addr: SocketAddr,
scheme: &'static str,
request_timeout: Duration,
) -> Result<Self, Error> {
Self::build(Some((socks_proxy_addr, scheme)), request_timeout)
}
fn build(proxy: Option<(SocketAddr, &str)>) -> Result<Self, Error> {
fn build(proxy: Option<(SocketAddr, &str)>, request_timeout: Duration) -> Result<Self, Error> {
let mut headers = HeaderMap::new();
headers.insert(USER_AGENT, HeaderValue::from_static("grin-client"));
headers.insert(ACCEPT, HeaderValue::from_static("application/json"));
headers.insert(CONTENT_TYPE, HeaderValue::from_static("application/json"));
let mut builder = ClientBuilder::new()
.timeout(Duration::from_secs(20))
.timeout(request_timeout)
.use_rustls_tls()
.default_headers(headers);
+28 -26
View File
@@ -14,7 +14,9 @@
//! Client functions, implementations of the NodeClient trait
use super::resp_types::*;
use crate::api::{self, LocatedTxKernel, OutputListing, OutputPrintable};
use crate::client_utils::json_rpc::*;
use crate::client_utils::{Client, RUNTIME};
use crate::core::core::{Transaction, TxKernel};
use crate::libwallet;
@@ -26,9 +28,7 @@ use futures::TryStreamExt;
use std::collections::HashMap;
use std::env;
use std::net::SocketAddr;
use super::resp_types::*;
use crate::client_utils::json_rpc::*;
use std::time::Duration;
const ENDPOINT: &str = "/v2/foreign";
@@ -45,8 +45,9 @@ impl HTTPNodeClient {
pub fn new(
node_url: &str,
node_api_secret: Option<String>,
request_timeout: Duration,
) -> Result<HTTPNodeClient, libwallet::Error> {
Self::new_proxy(node_url, node_api_secret, None)
Self::new_proxy(node_url, node_api_secret, None, request_timeout)
}
/// Create a new client with proxy
@@ -54,16 +55,17 @@ impl HTTPNodeClient {
node_url: &str,
node_api_secret: Option<String>,
proxy: Option<(SocketAddr, &'static str)>,
request_timeout: Duration,
) -> Result<HTTPNodeClient, libwallet::Error> {
let client = if let Some((a, s)) = proxy {
Client::with_proxy(a, s)
Client::with_proxy(a, s, request_timeout)
} else {
Client::new()
Client::new(request_timeout)
};
Ok(HTTPNodeClient {
client: client.map_err(|_| libwallet::Error::Node)?,
node_url: node_url.to_owned(),
node_api_secret: node_api_secret,
node_api_secret,
node_version_info: None,
})
}
@@ -107,18 +109,25 @@ impl NodeClient for HTTPNodeClient {
fn node_url(&self) -> &str {
&self.node_url
}
fn node_api_secret(&self) -> Option<String> {
self.node_api_secret.clone()
}
fn set_node_url(&mut self, node_url: &str) {
self.node_url = node_url.to_owned();
}
fn node_api_secret(&self) -> Option<String> {
self.node_api_secret.clone()
}
fn set_node_api_secret(&mut self, node_api_secret: Option<String>) {
self.node_api_secret = node_api_secret;
}
/// Posts a transaction to a grin node
fn post_tx(&self, tx: &Transaction, fluff: bool) -> Result<(), libwallet::Error> {
let params = json!([tx, fluff]);
self.send_json_request::<serde_json::Value>("push_transaction", &params)?;
Ok(())
}
fn get_version_info(&mut self) -> Option<NodeVersionInfo> {
if let Some(v) = self.node_version_info.as_ref() {
return Some(v.clone());
@@ -135,30 +144,23 @@ impl NodeClient for HTTPNodeClient {
// If node isn't available, allow offline functions
// unfortunately have to parse string due to error structure
let err_string = format!("{}", e);
if err_string.contains("404") {
return Some(NodeVersionInfo {
return if err_string.contains("404") {
Some(NodeVersionInfo {
node_version: "1.0.0".into(),
block_header_version: 1,
verified: Some(false),
});
})
} else {
error!("Unable to contact Node to get version info: {}, check your node is running", e);
warn!("Warning: a) Node is offline, or b) 'node_api_secret_path' in 'grin-wallet.toml' is set incorrectly");
return None;
}
None
};
}
};
self.node_version_info = Some(retval.clone());
Some(retval)
}
/// Posts a transaction to a grin node
fn post_tx(&self, tx: &Transaction, fluff: bool) -> Result<(), libwallet::Error> {
let params = json!([tx, fluff]);
self.send_json_request::<serde_json::Value>("push_transaction", &params)?;
Ok(())
}
/// Return the chain tip from a given node
fn get_chain_tip(&self) -> Result<(u64, String), libwallet::Error> {
let result = self.send_json_request::<GetTipResp>("get_tip", &serde_json::Value::Null)?;
@@ -222,7 +224,7 @@ impl NodeClient for HTTPNodeClient {
.collect();
// going to leave this here even though we're moving
// to the json RPC api to keep the functionality of
// to the JSON RPC api to keep the functionality of
// parallelizing larger requests. Will raise default
// from 200 to 500, however
let chunk_default = 500;
@@ -420,8 +422,8 @@ mod tests {
}
}
// Wallet will "push" a transaction to node, serializing the transaction as json.
// We are testing the json structure is what we expect here.
// Wallet will "push" a transaction to node, serializing the transaction as JSON.
// We are testing the JSON structure is what we expect here.
#[test]
fn test_transaction_json_ser_deser() {
let tx1 = tx1i1o_v2_compatible();
+19 -19
View File
@@ -160,12 +160,10 @@ pub fn start_tor_client(tor_dir: &str, config: TorConfig) -> Result<Tor, Error>
})
}
/// Tor request timeout in milliseconds.
const REQUEST_TIMEOUT_MS: u64 = 60000;
/// Make POST request with provided client.
pub fn tor_post<IN>(
client: Arc<TorClient<TokioNativeTlsRuntime>>,
tor_config: &TorConfig,
input: &IN,
url: &str,
) -> Result<String, Error>
@@ -183,12 +181,13 @@ where
Some(h) => h,
}
.to_string();
let timeout = tor_config.request_timeout();
let res: Result<String, Error> = thread::spawn(move || {
let c = client.clone();
client.runtime().block_on(async move {
let res = c
.runtime()
.timeout(Duration::from_millis(REQUEST_TIMEOUT_MS), async {
.timeout(timeout, async {
let stream = c
.connect((host, url.port_u16().unwrap_or(80)))
.await
@@ -238,21 +237,18 @@ where
res
}
/// Client Bootstrap timeout in milliseconds.
const BOOTSTRAP_TIMEOUT_MS: u64 = 60000;
/// Create Tor client.
fn init_client(
state_path: &PathBuf,
cache_path: &PathBuf,
config: TorConfig,
tor_config: TorConfig,
reuse_client: bool,
) -> Result<(Arc<TorClient<TokioNativeTlsRuntime>>, TorClientConfig), Error> {
let mut builder = TorClientConfigBuilder::from_directories(&state_path, cache_path);
builder.address_filter().allow_onion_addrs(true);
// Configure bridge.
if let Some(bridge_line) = config.bridge.bridge_line {
if let Some(bridge_line) = tor_config.bridge.bridge_line.as_ref() {
let bridge: BridgeConfigBuilder = bridge_line
.parse()
.map_err(|e| Error::TorConfig(format!("{:?}", e)))?;
@@ -266,7 +262,11 @@ fn init_client(
}
Some(t) => {
// Now configure bridge transport. (Requires the "pt-client" feature)
let bin_path = config.bridge.bridge_bin_path.unwrap_or(t.to_owned());
let bin_path = tor_config
.bridge
.bridge_bin_path
.clone()
.unwrap_or(t.to_owned());
let mut transport = TransportConfigBuilder::default();
transport
.protocols(vec![t
@@ -294,7 +294,7 @@ fn init_client(
*cached_client_config = None;
}
}
let res = launch_client(config.clone());
let res = launch_client(config.clone(), &tor_config);
return match res {
Ok(client) => {
cached_client_config.replace((client.clone(), config.clone()));
@@ -304,7 +304,7 @@ fn init_client(
};
}
let res = launch_client(config.clone());
let res = launch_client(config.clone(), &tor_config);
match res {
Ok(client) => Ok((client, config)),
Err(e) => Err(e),
@@ -312,13 +312,17 @@ fn init_client(
}
/// Launch tor client from provided configuration.
fn launch_client(config: TorClientConfig) -> Result<Arc<TorClient<TokioNativeTlsRuntime>>, Error> {
fn launch_client(
client_config: TorClientConfig,
tor_config: &TorConfig,
) -> Result<Arc<TorClient<TokioNativeTlsRuntime>>, Error> {
let r = runtime()?;
let client = TorClient::with_runtime(r)
.config(config)
.config(client_config)
.create_unbootstrapped()
.map_err(|e| Error::TorProcess(format!("{:?}", e)))?;
let c = client.clone();
let timeout = tor_config.bootstrap_timeout();
let res = client.runtime().block_on(async move {
let bootstrap = async || {
return match c.bootstrap().await {
@@ -339,11 +343,7 @@ fn launch_client(config: TorClientConfig) -> Result<Arc<TorClient<TokioNativeTls
Err(e) => Err(e),
};
};
match c
.runtime()
.timeout(Duration::from_millis(BOOTSTRAP_TIMEOUT_MS), bootstrap())
.await
{
match c.runtime().timeout(timeout, bootstrap()).await {
Ok(r) => match r {
Err(e) => Err(Error::TorProcess(format!("{:?}", e))),
Ok(_) => Ok(c),
+12 -11
View File
@@ -51,13 +51,13 @@ extern crate timer;
use regex::Regex;
use std::fs::{self, File};
use std::io;
use std::io::Write;
use std::io::{BufRead, BufReader};
use std::path::{Path, MAIN_SEPARATOR};
use std::process::{Child, ChildStdout, Command, Stdio};
use std::sync::mpsc::channel;
use std::thread;
use std::{cmp, io};
use sysinfo::{Process, ProcessExt, System, SystemExt};
#[cfg(windows)]
@@ -83,7 +83,7 @@ pub struct TorProcess {
args: Vec<String>,
torrc_path: Option<String>,
completion_percent: u8,
timeout: u32,
timeout: u64,
working_dir: Option<String>,
pub stdout: Option<BufReader<ChildStdout>>,
pub process: Option<Child>,
@@ -96,8 +96,8 @@ impl TorProcess {
tor_cmd: TOR_EXE_NAME.to_string(),
args: vec![],
torrc_path: None,
completion_percent: 100 as u8,
timeout: 0 as u32,
completion_percent: 100,
timeout: 0,
working_dir: None,
stdout: None,
process: None,
@@ -137,7 +137,7 @@ impl TorProcess {
self
}
pub fn timeout(&mut self, timeout: u32) -> &mut Self {
pub fn timeout(&mut self, timeout: u64) -> &mut Self {
self.timeout = timeout;
self
}
@@ -198,10 +198,11 @@ impl TorProcess {
let stdout_timeout_tx = stdout_tx.clone();
let timer = timer::Timer::new();
let _guard =
timer.schedule_with_delay(chrono::Duration::seconds(self.timeout as i64), move || {
stdout_timeout_tx.send(Err(Error::Timeout)).unwrap_or(());
});
// Keep this below chrono's DateTime range used by timer.
let timeout = chrono::Duration::seconds(cmp::min(self.timeout, u32::MAX as u64) as i64);
let _guard = timer.schedule_with_delay(timeout, move || {
stdout_timeout_tx.send(Err(Error::Timeout)).unwrap_or(());
});
let stdout_thread = thread::spawn(move || {
stdout_tx
.send(Self::parse_tor_stdout(stdout, completion_percent))
@@ -225,8 +226,8 @@ impl TorProcess {
mut stdout: BufReader<ChildStdout>,
completion_perc: u8,
) -> Result<BufReader<ChildStdout>, Error> {
let re_bootstrap = Regex::new(r"^\[notice\] Bootstrapped (?P<perc>[0-9]+)%(.*): ")
.map_err(Error::Regex)?;
let re_bootstrap =
Regex::new(r"^\[notice] Bootstrapped (?P<perc>[0-9]+)%(.*): ").map_err(Error::Regex)?;
let timestamp_len = "May 16 02:50:08.792".len();
let mut warnings = Vec::new();
+3 -3
View File
@@ -281,7 +281,7 @@ impl LocalServerContainer {
let _ = fs::create_dir_all(self.wallet_config.clone().data_file_dir);
let r = wallet::WalletSeed::init_file(&self.wallet_config, 32, None, "");
let client_n = HTTPNodeClient::new(&self.wallet_config.check_node_api_http_addr, None);
let client_n = HTTPNodeClient::new(&self.wallet_config.check_node_api_http_addr, None, std::time::Duration::from_secs(60));
if let Err(_e) = r {
//panic!("Error initializing wallet seed: {}", e);
@@ -354,7 +354,7 @@ impl LocalServerContainer {
let keychain: keychain::ExtKeychain = wallet_seed
.derive_keychain(false)
.expect("Failed to derive keychain from seed file and passphrase.");
let client_n = HTTPNodeClient::new(&config.check_node_api_http_addr, None);
let client_n = HTTPNodeClient::new(&config.check_node_api_http_addr, None, std::time::Duration::from_secs(60));
let mut wallet = LMDBBackend::new(config.clone(), "", client_n)
.unwrap_or_else(|e| panic!("Error creating wallet: {:?} Config: {:?}", e, config));
wallet.keychain = Some(keychain);
@@ -382,7 +382,7 @@ impl LocalServerContainer {
.derive_keychain(false)
.expect("Failed to derive keychain from seed file and passphrase.");
let client_n = HTTPNodeClient::new(&config.check_node_api_http_addr, None);
let client_n = HTTPNodeClient::new(&config.check_node_api_http_addr, None, std::time::Duration::from_secs(60));
let client_w = HTTPWalletCommAdapter::new();
let max_outputs = 500;
+2 -2
View File
@@ -908,7 +908,7 @@ fn replicate_tx_fluff_failure() {
// Create Wallet 1 (Mining Input) and start it listening
// Wallet 1 post to another node, just for fun
let client1 = HTTPNodeClient::new("http://127.0.0.1:23003", None);
let client1 = HTTPNodeClient::new("http://127.0.0.1:23003", None, std::time::Duration::from_secs(60));
let client1_w = HTTPWalletCommAdapter::new();
let wallet1 = create_wallet("target/tmp/tx_fluff/wallet1", client1.clone());
let _wallet1_handle = thread::spawn(move || {
@@ -917,7 +917,7 @@ fn replicate_tx_fluff_failure() {
});
// Create Wallet 2 (Recipient) and launch
let client2 = HTTPNodeClient::new("http://127.0.0.1:23001", None);
let client2 = HTTPNodeClient::new("http://127.0.0.1:23001", None, std::time::Duration::from_secs(60));
let wallet2 = create_wallet("target/tmp/tx_fluff/wallet2", client2.clone());
let _wallet2_handle = thread::spawn(move || {
controller::foreign_listener(wallet2, "127.0.0.1:33001", None)
+3 -1
View File
@@ -161,6 +161,8 @@ fn real_main() -> i32 {
global::init_global_accept_fee_base(config.members.as_ref().unwrap().wallet.accept_fee_base());
let wallet_config = config.clone().members.unwrap().wallet;
let node_client = HTTPNodeClient::new(&wallet_config.check_node_api_http_addr, None).unwrap();
let timeout = wallet_config.api_request_timeout();
let node_client =
HTTPNodeClient::new(&wallet_config.check_node_api_http_addr, None, timeout).unwrap();
cmd::wallet_command(&args, config, node_client)
}