/*! This models a how a sync happens where you have a server that you send your script pubkeys to and it returns associated transactions i.e. electrum. */ #![allow(dead_code)] use crate::{ database::{BatchDatabase, BatchOperations, DatabaseUtils}, error::MissingCachedScripts, wallet::time::Instant, BlockTime, Error, KeychainKind, LocalUtxo, TransactionDetails, }; use bitcoin::{OutPoint, Script, Transaction, TxOut, Txid}; use log::*; use std::collections::{BTreeMap, BTreeSet, HashMap, HashSet, VecDeque}; /// A request for on-chain information pub enum Request<'a, D: BatchDatabase> { /// A request for transactions related to script pubkeys. Script(ScriptReq<'a, D>), /// A request for confirmation times for some transactions. Conftime(ConftimeReq<'a, D>), /// A request for full transaction details of some transactions. Tx(TxReq<'a, D>), /// Requests are finished here's a batch database update to reflect data gathered. Finish(D::Batch), } /// starts a sync pub fn start(db: &D, stop_gap: usize) -> Result, Error> { use rand::seq::SliceRandom; let mut keychains = vec![KeychainKind::Internal, KeychainKind::External]; // shuffling improve privacy, the server doesn't know my first request is from my internal or external addresses keychains.shuffle(&mut rand::thread_rng()); let keychain = keychains.pop().unwrap(); let scripts_needed = db .iter_script_pubkeys(Some(keychain))? .into_iter() .collect::>(); let state = State::new(db); Ok(Request::Script(ScriptReq { state, initial_scripts_needed: scripts_needed.len(), scripts_needed, script_index: 0, stop_gap, keychain, next_keychains: keychains, })) } pub struct ScriptReq<'a, D: BatchDatabase> { state: State<'a, D>, script_index: usize, initial_scripts_needed: usize, // if this is 1, we assume the descriptor is not derivable scripts_needed: VecDeque