From cafd9177269ab4722eff1af347a0bee2c9d840eb Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=E5=BF=97=E5=AE=87?= Date: Thu, 11 Aug 2022 13:27:32 +0800 Subject: [PATCH] Add `import_waiter` for `RpcBlockchain`. Bitcoin Core rejects importing scriptPubKeys/descriptors when it is still rescanning the wallet. We should wait until rescan completes before importing again. --- src/blockchain/rpc.rs | 32 +++++++++++++++++++++++++------- 1 file changed, 25 insertions(+), 7 deletions(-) diff --git a/src/blockchain/rpc.rs b/src/blockchain/rpc.rs index 54126951bc..0372e07400 100644 --- a/src/blockchain/rpc.rs +++ b/src/blockchain/rpc.rs @@ -46,6 +46,7 @@ use bitcoincore_rpc::json::{ ImportMultiRequestScriptPubkey, ImportMultiRescanSince, ListTransactionResult, ListUnspentResultEntry, ScanningDetails, }; +use bitcoincore_rpc::jsonrpc::error::RpcError; use bitcoincore_rpc::jsonrpc::serde_json::{json, Value}; use bitcoincore_rpc::jsonrpc::{ self, simple_http::SimpleHttpTransport, Error as JsonRpcError, Request, Response, Transport, @@ -274,9 +275,9 @@ macro_rules! impl_inner { if io.kind() == std::io::ErrorKind::WouldBlock => { let attempt = $self.attempts.fetch_add(1, Ordering::Relaxed); - let delay = std::cmp::min(1000, 100 << attempt as u64); + let delay = std::cmp::min(5000, 100 << attempt as u64); - debug!( + warn!( "Got a WouldBlock error at attempt {}, sleeping for {}ms", attempt, delay ); @@ -543,7 +544,6 @@ impl<'a, D: BatchDatabase> DbState<'a, D> { scripts_iter, self.prog, )?; - // await_wallet_scan(client, self.params.poll_rate_sec, self.prog)?; // update import_params import_params.external_start_index = self.ext_spks.len(); @@ -874,6 +874,8 @@ where Ok(()) } +/// Import descriptors/scriptPubKeys in a pagenated manner, and wait for rescan to complete (if +/// import is successful or errored with code -4). fn pagenated_import<'a, S>( client: &Client, use_desc: bool, @@ -886,6 +888,8 @@ fn pagenated_import<'a, S>( where S: Iterator + Clone, { + use bitcoincore_rpc::Error as CoreError; + (0_usize..) .map(|page_index| { scripts_iter @@ -897,12 +901,26 @@ where }) .take_while(|scripts| !scripts.is_empty()) .try_for_each(|scripts| { - if use_desc { - import_descriptors(client, start_epoch, scripts.iter())?; + let result = if use_desc { + import_descriptors(client, start_epoch, scripts.iter()) } else { - import_multi(client, start_epoch, scripts.iter())?; + import_multi(client, start_epoch, scripts.iter()) + }; + + // On successful import, or unsuccessful with code -4, we wait until rescan is complete + // and return. Any other error will be returned immediately. + match result { + Err(Error::Rpc(CoreError::JsonRpc(JsonRpcError::Rpc(RpcError { + code: -4, + message, + .. + })))) => { + warn!("import return with code -4: \"{}\", waiting...", message); + Ok(()) + } + res => res, } - await_wallet_scan(client, poll_rate_sec, progress) + .and_then(|_| await_wallet_scan(client, poll_rate_sec, progress)) }) }