Skip to content

Commit

Permalink
Add import_waiter for RpcBlockchain.
Browse files Browse the repository at this point in the history
Bitcoin Core rejects importing scriptPubKeys/descriptors when it is
still rescanning the wallet. We should wait until rescan completes
before importing again.
  • Loading branch information
evanlinjin committed Sep 1, 2022
1 parent 09e5e61 commit cafd917
Showing 1 changed file with 25 additions and 7 deletions.
32 changes: 25 additions & 7 deletions src/blockchain/rpc.rs
Original file line number Diff line number Diff line change
Expand Up @@ -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,
Expand Down Expand Up @@ -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
);
Expand Down Expand Up @@ -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();
Expand Down Expand Up @@ -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,
Expand All @@ -886,6 +888,8 @@ fn pagenated_import<'a, S>(
where
S: Iterator<Item = &'a Script> + Clone,
{
use bitcoincore_rpc::Error as CoreError;

(0_usize..)
.map(|page_index| {
scripts_iter
Expand All @@ -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))
})
}

Expand Down

0 comments on commit cafd917

Please sign in to comment.