bitcoind: add a 'noreply' client

The query we are going to use to rescan, 'importdescriptors' will block
until the rescan is finished. Stopping the connection through a timeout
immediately after triggering the rescan is a workaround to make it
asynchronous.

Eventually we should probably use 'rescanblockchain' but then it
wouldn't update the timestamps of the descriptors in the watchonly
wallet...
This commit is contained in:
Antoine Poinsot 2022-11-09 17:40:59 +01:00
parent 45d601282f
commit c32f714a2e
No known key found for this signature in database
GPG Key ID: E13FC145CD3F4304

View File

@ -54,6 +54,20 @@ impl BitcoindError {
_ => false,
}
}
/// Is it a timeout of any kind?
pub fn is_timeout(&self) -> bool {
match self {
BitcoindError::Server(jsonrpc::Error::Transport(ref e)) => {
match e.downcast_ref::<simple_http::Error>() {
Some(simple_http::Error::Timeout) => true,
Some(simple_http::Error::SocketError(e)) => e.kind() == io::ErrorKind::TimedOut,
_ => false,
}
}
_ => false,
}
}
}
impl std::fmt::Display for BitcoindError {
@ -116,7 +130,11 @@ impl From<simple_http::Error> for BitcoindError {
}
pub struct BitcoinD {
/// Client for generalistic calls.
node_client: Client,
/// A client that will disregard responses to the queries it makes.
sendonly_client: Client,
/// A client for calls related to the wallet.
watchonly_client: Client,
watchonly_wallet_path: String,
/// How many times we'll retry upon failure to send a request.
@ -183,12 +201,21 @@ impl BitcoinD {
.url(&watchonly_url)
.map_err(BitcoindError::from)?
.timeout(Duration::from_secs(RPC_SOCKET_TIMEOUT))
.cookie_auth(cookie_string.clone())
.build(),
);
let sendonly_client = Client::with_transport(
SimpleHttpTransport::builder()
.url(&watchonly_url)
.map_err(BitcoindError::from)?
.timeout(Duration::from_secs(1))
.cookie_auth(cookie_string)
.build(),
);
Ok(BitcoinD {
node_client,
sendonly_client,
watchonly_client,
watchonly_wallet_path,
retries: 0,
@ -258,9 +285,14 @@ impl BitcoinD {
})
}
fn make_node_request(&self, method: &str, params: &[Box<serde_json::value::RawValue>]) -> Json {
self.make_request(&self.node_client, method, params)
.expect("We must not fail to make a request for more than a minute")
// Make a request for which you don't expect a response. This is achieved by setting a very low
// timeout on the connection, and will panic on any other error than a timeout.
fn make_noreply_request(&self, method: &str, params: &[Box<serde_json::value::RawValue>]) {
if let Err(e) = self.make_request(&self.sendonly_client, method, params) {
if !e.is_timeout() {
panic!("{}", e);
}
}
}
fn make_fallible_node_request(
@ -271,6 +303,11 @@ impl BitcoinD {
self.make_request(&self.node_client, method, params)
}
fn make_node_request(&self, method: &str, params: &[Box<serde_json::value::RawValue>]) -> Json {
self.make_request(&self.sendonly_client, method, params)
.expect("We must not fail to make a request for more than a minute")
}
fn make_wallet_request(
&self,
method: &str,