// Magical Bitcoin Library // Written in 2020 by // Alekos Filini // // Copyright (c) 2020 Magical Bitcoin // // Permission is hereby granted, free of charge, to any person obtaining a copy // of this software and associated documentation files (the "Software"), to deal // in the Software without restriction, including without limitation the rights // to use, copy, modify, merge, publish, distribute, sublicense, and/or sell // copies of the Software, and to permit persons to whom the Software is // furnished to do so, subject to the following conditions: // // The above copyright notice and this permission notice shall be included in all // copies or substantial portions of the Software. // // THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR // IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, // FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE // AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER // LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, // OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE // SOFTWARE. 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. #[maybe_async] pub trait ElectrumLikeSync { fn els_batch_script_get_history<'s, I: IntoIterator>( &self, scripts: I, ) -> Result>, Error>; fn els_batch_script_list_unspent<'s, I: IntoIterator>( &self, scripts: I, ) -> Result>, Error>; fn els_transaction_get(&self, txid: &Txid) -> Result; // Provided methods down here... fn electrum_like_setup( &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