diff --git a/src/blockchain/rpc.rs b/src/blockchain/rpc.rs index f711452bf..914d03759 100644 --- a/src/blockchain/rpc.rs +++ b/src/blockchain/rpc.rs @@ -40,14 +40,14 @@ use crate::error::MissingCachedScripts; use crate::{BlockTime, Error, FeeRate, KeychainKind, LocalUtxo, TransactionDetails}; use bitcoin::Script; use bitcoincore_rpc::json::{ - GetTransactionResult, GetTransactionResultDetailCategory, ImportMultiOptions, - ImportMultiRequest, ImportMultiRequestScriptPubkey, ImportMultiRescanSince, - ListTransactionResult, ScanningDetails, + GetTransactionResultDetailCategory, ImportMultiOptions, ImportMultiRequest, + ImportMultiRequestScriptPubkey, ImportMultiRescanSince, ListTransactionResult, + ListUnspentResultEntry, ScanningDetails, }; use bitcoincore_rpc::jsonrpc::serde_json::{json, Value}; use bitcoincore_rpc::Auth as RpcAuth; use bitcoincore_rpc::{Client, RpcApi}; -use log::debug; +use log::{debug, info}; use serde::{Deserialize, Serialize}; use std::collections::{HashMap, HashSet}; use std::path::PathBuf; @@ -93,6 +93,8 @@ pub struct RpcSyncParams { pub start_script_count: usize, /// Time in unix seconds in which initial sync will start scanning from (0 to start from genesis). pub start_time: u64, + /// Forces every sync to use `start_time` as import timestamp. + pub force_start_time: bool, /// RPC poll rate (in seconds) to get state updates. pub poll_rate_sec: u64, } @@ -102,6 +104,7 @@ impl Default for RpcSyncParams { Self { start_script_count: 100, start_time: 0, + force_start_time: false, poll_rate_sec: 3, } } @@ -180,54 +183,15 @@ impl GetBlockHash for RpcBlockchain { } impl WalletSync for RpcBlockchain { - fn wallet_setup( - &self, - db: &mut D, - progress_update: Box, - ) -> Result<(), Error> { - let db_scripts = db.iter_script_pubkeys(None)?; - - // this is a hack to check whether the scripts are coming from a derivable descriptor - // we assume for non-derivable descriptors, the initial script count is always 1 - let is_derivable = db_scripts.len() > 1; - - // ensure db scripts meet start script count requirements - if is_derivable && db_scripts.len() < self.sync_params.start_script_count { - return Err(Error::MissingCachedScripts(MissingCachedScripts { - last_count: db_scripts.len(), - missing_count: self.sync_params.start_script_count - db_scripts.len(), - })); - } - - // this tells Core wallet where to sync from for imported scripts - let start_epoch = db - .get_sync_time()? - .map_or(self.sync_params.start_time, |st| st.block_time.timestamp); - - // import all scripts from db into Core wallet - if self.is_descriptors { - import_descriptors(&self.client, start_epoch, db_scripts.iter())?; - } else { - import_multi(&self.client, start_epoch, db_scripts.iter())?; - } - - // await sync (TODO: Maybe make this async) - await_wallet_scan( - &self.client, - self.sync_params.poll_rate_sec, - &*progress_update, - )?; - - // begin db batch updates - let mut db_batch = db.begin_batch(); - - // update batch: obtain db state then update state with core txids - DbState::from_db(db)? - .update_state(&self.client, db)? - .update_batch::(&mut db_batch)?; + fn wallet_setup(&self, db: &mut D, prog: Box) -> Result<(), Error> + where + D: BatchDatabase, + { + let batch = DbState::new(db, &self.sync_params, &*prog)? + .sync_with_core(&self.client, self.is_descriptors)? + .as_db_batch()?; - // apply batch updates to db - db.commit_batch(db_batch) + db.commit_batch(batch) } } @@ -322,7 +286,13 @@ fn list_wallet_dir(client: &Client) -> Result, Error> { } /// Represents the state of the [`crate::database::Database`]. -struct DbState { +struct DbState<'a, D> { + db: &'a D, + params: &'a RpcSyncParams, + prog: &'a dyn Progress, + + ext_spks: Vec