diff --git a/vault/src/issue.rs b/vault/src/issue.rs index 4d9ee5d4b..ccb9b7dee 100644 --- a/vault/src/issue.rs +++ b/vault/src/issue.rs @@ -144,7 +144,84 @@ impl RescanStatus { } } -pub async fn add_keys_from_past_issue_request( +pub async fn add_keys_from_past_issue_request_old( + bitcoin_core: &DynBitcoinCoreApi, + btc_parachain: &InterBtcParachain, + db: &DatabaseConfig, +) -> Result<(), Error> { + let account_id = btc_parachain.get_account_id(); + let mut scanning_status = RescanStatus::get(&account_id, db)?; + tracing::info!("Scanning: {scanning_status:?}"); + + let issue_requests = btc_parachain.get_vault_issue_requests(account_id.clone()).await?; + + for (issue_id, request) in issue_requests.clone().into_iter() { + if let Err(e) = add_new_deposit_key(bitcoin_core, issue_id, request.btc_public_key).await { + tracing::error!("Failed to add deposit key #{}: {}", issue_id, e.to_string()); + } + } + + // read height only _after_ the last add_new_deposit_key. If a new block arrives + // while we rescan, bitcoin core will correctly recognize addressed associated with the + // privkey + let btc_end_height = bitcoin_core.get_block_count().await? as usize; + let btc_pruned_start_height = bitcoin_core.get_pruned_height().await? as usize; + + let issues = issue_requests.clone().into_iter().map(|(_key, issue)| issue).collect(); + scanning_status.update(issues, btc_end_height); + + // use electrs to scan the portion that is not scannable by bitcoin core + if let Some((start, end)) = scanning_status.prune(btc_pruned_start_height) { + tracing::info!( + "Also checking electrs for issue requests between {} and {}...", + start, + end + ); + bitcoin_core + .rescan_electrs_for_addresses( + issue_requests + .into_iter() + .filter_map(|(_, request)| { + // only import if BEFORE current pruning height + if (request.btc_height as usize) < btc_pruned_start_height { + Some(request.btc_address.to_address(bitcoin_core.network()).ok()?) + } else { + None + } + }) + .collect(), + ) + .await?; + } + + // save progress s.t. we don't rescan pruned range again if we crash now + scanning_status.store(account_id, db)?; + + let mut chunk_size = 1; + // rescan the blockchain in chunks, so that we can save progress. The code below + // aims to have each chunk take about 10 seconds (arbitrarily chosen value). + while let Some((chunk_start, chunk_end)) = scanning_status.process_blocks(chunk_size) { + tracing::info!("Rescanning bitcoin chain from {} to {}...", chunk_start, chunk_end); + + let start_time = Instant::now(); + + bitcoin_core.rescan_blockchain(chunk_start, chunk_end).await?; + + // with the code below the rescan time should remain between 5 and 20 seconds + // after the first couple of rounds. + if start_time.elapsed() < Duration::from_secs(10) { + chunk_size = chunk_size.saturating_mul(2); + } else { + chunk_size = (chunk_size.checked_div(2).ok_or(Error::ArithmeticUnderflow)?).max(1); + } + + scanning_status.store(account_id, db)?; + } + + Ok(()) +} + +pub async fn add_keys_from_past_issue_request_new( bitcoin_core: &DynBitcoinCoreApi, btc_parachain: &InterBtcParachain, db: &DatabaseConfig, diff --git a/vault/src/system.rs b/vault/src/system.rs index 0e14d9754..96f386a62 100644 --- a/vault/src/system.rs +++ b/vault/src/system.rs @@ -455,6 +455,7 @@ impl VaultIdManager { pub struct VaultService { btc_parachain: InterBtcParachain, btc_rpc_master_wallet: DynBitcoinCoreApi, + btc_rpc_shared_wallet: DynBitcoinCoreApi, btc_rpc_shared_wallet_v2: DynBitcoinCoreApi, config: VaultServiceConfig, monitoring_config: MonitoringConfig, @@ -567,6 +568,7 @@ impl VaultService { Self { btc_parachain: btc_parachain.clone(), btc_rpc_master_wallet: btc_rpc_master_wallet.clone(), + btc_rpc_shared_wallet: btc_rpc_shared_wallet.clone(), btc_rpc_shared_wallet_v2: btc_rpc_shared_wallet_v2.clone(), config, monitoring_config, @@ -689,10 +691,17 @@ impl VaultService { // purposefully _after_ maybe_register_vault and _before_ other calls self.vault_id_manager.fetch_vault_ids().await?; - self.vault_id_manager.sweep_shared_wallet().await?; tracing::info!("Adding keys from past issues..."); - issue::add_keys_from_past_issue_request( + issue::add_keys_from_past_issue_request_old( + &self.btc_rpc_shared_wallet, + &self.btc_parachain, + &self.vault_id_manager.db, + ) + .await?; + + self.vault_id_manager.sweep_shared_wallet().await?; + issue::add_keys_from_past_issue_request_new( &self.btc_rpc_shared_wallet_v2, &self.btc_parachain, &self.vault_id_manager.db,