use std::cmp; use std::collections::{HashSet, VecDeque}; use std::convert::TryFrom; #[allow(unused_imports)] use log::{debug, error, info, trace}; use bitcoin::{Address, Network, OutPoint, Script, Transaction, Txid}; use super::*; use crate::database::{BatchDatabase, BatchOperations, DatabaseUtils}; use crate::error::Error; use crate::types::{ScriptType, TransactionDetails, UTXO}; use crate::wallet::utils::ChunksIterator; #[derive(Debug)] pub struct ELSGetHistoryRes { pub height: i32, pub tx_hash: Txid, } #[derive(Debug)] pub struct ELSListUnspentRes { pub height: usize, pub tx_hash: Txid, pub tx_pos: usize, } /// Implements the synchronization logic for an Electrum-like client. #[async_trait(?Send)] pub trait ElectrumLikeSync { async fn els_batch_script_get_history<'s, I: IntoIterator>( &mut self, scripts: I, ) -> Result>, Error>; async fn els_batch_script_list_unspent<'s, I: IntoIterator>( &mut self, scripts: I, ) -> Result>, Error>; async fn els_transaction_get(&mut self, txid: &Txid) -> Result; // Provided methods down here... async fn electrum_like_setup( &mut self, stop_gap: Option, database: &mut D, _progress_update: P, ) -> Result<(), Error> { // TODO: progress let stop_gap = stop_gap.unwrap_or(20); let batch_query_size = 20; // check unconfirmed tx, delete so they are retrieved later let mut del_batch = database.begin_batch(); for tx in database.iter_txs(false)? { if tx.height.is_none() { del_batch.del_tx(&tx.txid, false)?; } } database.commit_batch(del_batch)?; // maximum derivation index for a change address that we've seen during sync let mut change_max_deriv = 0; let mut already_checked: HashSet