From 777ce7b059c0e81cbb36813d9ad028f767985fdd Mon Sep 17 00:00:00 2001 From: Elias Rohrer Date: Thu, 6 Jun 2024 09:18:04 +0200 Subject: [PATCH 1/8] Make `confirmables` `Deref` .. the bindings branch needed a small patch as it doesn't support `dyn` traits. Here, we opt to use `Deref` in the hopes this works with bindings, rendering the patch unnecessary. --- lightning-transaction-sync/src/common.rs | 17 +++++++++++------ lightning-transaction-sync/src/electrum.rs | 12 ++++++++---- lightning-transaction-sync/src/esplora.rs | 21 +++++++++++++-------- 3 files changed, 32 insertions(+), 18 deletions(-) diff --git a/lightning-transaction-sync/src/common.rs b/lightning-transaction-sync/src/common.rs index c635f7385c6..d68ac95914e 100644 --- a/lightning-transaction-sync/src/common.rs +++ b/lightning-transaction-sync/src/common.rs @@ -4,6 +4,7 @@ use bitcoin::{Txid, BlockHash, Transaction, OutPoint}; use bitcoin::block::Header; use std::collections::{HashSet, HashMap}; +use std::ops::Deref; // Represents the current state. @@ -33,10 +34,12 @@ impl SyncState { pending_sync: false, } } - pub fn sync_unconfirmed_transactions( - &mut self, confirmables: &Vec<&(dyn Confirm + Sync + Send)>, + pub fn sync_unconfirmed_transactions( + &mut self, confirmables: &Vec, unconfirmed_txs: Vec, - ) { + ) + where C::Target: Confirm, + { for txid in unconfirmed_txs { for c in confirmables { c.transaction_unconfirmed(&txid); @@ -57,10 +60,12 @@ impl SyncState { } } - pub fn sync_confirmed_transactions( - &mut self, confirmables: &Vec<&(dyn Confirm + Sync + Send)>, + pub fn sync_confirmed_transactions( + &mut self, confirmables: &Vec, confirmed_txs: Vec - ) { + ) + where C::Target: Confirm, + { for ctx in confirmed_txs { for c in confirmables { c.transactions_confirmed( diff --git a/lightning-transaction-sync/src/electrum.rs b/lightning-transaction-sync/src/electrum.rs index d2cb7256fd0..4c809d40716 100644 --- a/lightning-transaction-sync/src/electrum.rs +++ b/lightning-transaction-sync/src/electrum.rs @@ -83,7 +83,9 @@ where /// [`ChainMonitor`]: lightning::chain::chainmonitor::ChainMonitor /// [`ChannelManager`]: lightning::ln::channelmanager::ChannelManager /// [`Filter`]: lightning::chain::Filter - pub fn sync(&self, confirmables: Vec<&(dyn Confirm + Sync + Send)>) -> Result<(), TxSyncError> { + pub fn sync(&self, confirmables: Vec) -> Result<(), TxSyncError> + where C::Target: Confirm + { // This lock makes sure we're syncing once at a time. let mut sync_state = self.sync_state.lock().unwrap(); @@ -378,9 +380,11 @@ where Ok(confirmed_txs) } - fn get_unconfirmed_transactions( - &self, confirmables: &Vec<&(dyn Confirm + Sync + Send)>, - ) -> Result, InternalError> { + fn get_unconfirmed_transactions( + &self, confirmables: &Vec, + ) -> Result, InternalError> + where C::Target: Confirm + { // Query the interface for relevant txids and check whether the relevant blocks are still // in the best chain, mark them unconfirmed otherwise let relevant_txids = confirmables diff --git a/lightning-transaction-sync/src/esplora.rs b/lightning-transaction-sync/src/esplora.rs index 2e35a150c55..82c49b9f9d2 100644 --- a/lightning-transaction-sync/src/esplora.rs +++ b/lightning-transaction-sync/src/esplora.rs @@ -84,7 +84,9 @@ where /// [`ChannelManager`]: lightning::ln::channelmanager::ChannelManager /// [`Filter`]: lightning::chain::Filter #[maybe_async] - pub fn sync(&self, confirmables: Vec<&(dyn Confirm + Sync + Send)>) -> Result<(), TxSyncError> { + pub fn sync(&self, confirmables: Vec) -> Result<(), TxSyncError> + where C::Target: Confirm + { // This lock makes sure we're syncing once at a time. #[cfg(not(feature = "async-interface"))] let mut sync_state = self.sync_state.lock().unwrap(); @@ -239,10 +241,11 @@ where } #[maybe_async] - fn sync_best_block_updated( - &self, confirmables: &Vec<&(dyn Confirm + Sync + Send)>, sync_state: &mut SyncState, tip_hash: &BlockHash, - ) -> Result<(), InternalError> { - + fn sync_best_block_updated( + &self, confirmables: &Vec, sync_state: &mut SyncState, tip_hash: &BlockHash, + ) -> Result<(), InternalError> + where C::Target: Confirm + { // Inform the interface of the new block. let tip_header = maybe_await!(self.client.get_header_by_hash(tip_hash))?; let tip_status = maybe_await!(self.client.get_block_status(&tip_hash))?; @@ -369,9 +372,11 @@ where } #[maybe_async] - fn get_unconfirmed_transactions( - &self, confirmables: &Vec<&(dyn Confirm + Sync + Send)>, - ) -> Result, InternalError> { + fn get_unconfirmed_transactions( + &self, confirmables: &Vec, + ) -> Result, InternalError> + where C::Target: Confirm + { // Query the interface for relevant txids and check whether the relevant blocks are still // in the best chain, mark them unconfirmed otherwise let relevant_txids = confirmables From 3ead26323ef6eaf4f1c19324876c44803f512dfa Mon Sep 17 00:00:00 2001 From: Elias Rohrer Date: Thu, 6 Jun 2024 09:21:15 +0200 Subject: [PATCH 2/8] `rustfmt`: Reformat `lightning-transaction-sync/src/common.rs` --- lightning-transaction-sync/src/common.rs | 55 +++++++++++------------- rustfmt_excluded_files | 1 - 2 files changed, 25 insertions(+), 31 deletions(-) diff --git a/lightning-transaction-sync/src/common.rs b/lightning-transaction-sync/src/common.rs index d68ac95914e..420d7d8a957 100644 --- a/lightning-transaction-sync/src/common.rs +++ b/lightning-transaction-sync/src/common.rs @@ -1,12 +1,11 @@ -use lightning::chain::{Confirm, WatchedOutput}; -use lightning::chain::channelmonitor::ANTI_REORG_DELAY; -use bitcoin::{Txid, BlockHash, Transaction, OutPoint}; use bitcoin::block::Header; +use bitcoin::{BlockHash, OutPoint, Transaction, Txid}; +use lightning::chain::channelmonitor::ANTI_REORG_DELAY; +use lightning::chain::{Confirm, WatchedOutput}; -use std::collections::{HashSet, HashMap}; +use std::collections::{HashMap, HashSet}; use std::ops::Deref; - // Represents the current state. pub(crate) struct SyncState { // Transactions that were previously processed, but must not be forgotten @@ -35,10 +34,9 @@ impl SyncState { } } pub fn sync_unconfirmed_transactions( - &mut self, confirmables: &Vec, - unconfirmed_txs: Vec, - ) - where C::Target: Confirm, + &mut self, confirmables: &Vec, unconfirmed_txs: Vec, + ) where + C::Target: Confirm, { for txid in unconfirmed_txs { for c in confirmables { @@ -49,22 +47,23 @@ impl SyncState { // If a previously-confirmed output spend is unconfirmed, re-add the watched output to // the tracking map. - self.outputs_spends_pending_threshold_conf.retain(|(conf_txid, _, prev_outpoint, output)| { - if txid == *conf_txid { - self.watched_outputs.insert(*prev_outpoint, output.clone()); - false - } else { - true - } - }) + self.outputs_spends_pending_threshold_conf.retain( + |(conf_txid, _, prev_outpoint, output)| { + if txid == *conf_txid { + self.watched_outputs.insert(*prev_outpoint, output.clone()); + false + } else { + true + } + }, + ) } } pub fn sync_confirmed_transactions( - &mut self, confirmables: &Vec, - confirmed_txs: Vec - ) - where C::Target: Confirm, + &mut self, confirmables: &Vec, confirmed_txs: Vec, + ) where + C::Target: Confirm, { for ctx in confirmed_txs { for c in confirmables { @@ -79,20 +78,19 @@ impl SyncState { for input in &ctx.tx.input { if let Some(output) = self.watched_outputs.remove(&input.previous_output) { - self.outputs_spends_pending_threshold_conf.push((ctx.tx.txid(), ctx.block_height, input.previous_output, output)); + let spent = (ctx.tx.txid(), ctx.block_height, input.previous_output, output); + self.outputs_spends_pending_threshold_conf.push(spent); } } } } pub fn prune_output_spends(&mut self, cur_height: u32) { - self.outputs_spends_pending_threshold_conf.retain(|(_, conf_height, _, _)| { - cur_height < conf_height + ANTI_REORG_DELAY - 1 - }); + self.outputs_spends_pending_threshold_conf + .retain(|(_, conf_height, _, _)| cur_height < conf_height + ANTI_REORG_DELAY - 1); } } - // A queue that is to be filled by `Filter` and drained during the next syncing round. pub(crate) struct FilterQueue { // Transactions that were registered via the `Filter` interface and have to be processed. @@ -103,10 +101,7 @@ pub(crate) struct FilterQueue { impl FilterQueue { pub fn new() -> Self { - Self { - transactions: HashSet::new(), - outputs: HashMap::new(), - } + Self { transactions: HashSet::new(), outputs: HashMap::new() } } // Processes the transaction and output queues and adds them to the given [`SyncState`]. diff --git a/rustfmt_excluded_files b/rustfmt_excluded_files index 36d85ef2061..8cc53a53075 100644 --- a/rustfmt_excluded_files +++ b/rustfmt_excluded_files @@ -159,7 +159,6 @@ ./lightning-rapid-gossip-sync/src/error.rs ./lightning-rapid-gossip-sync/src/lib.rs ./lightning-rapid-gossip-sync/src/processing.rs -./lightning-transaction-sync/src/common.rs ./lightning-transaction-sync/src/electrum.rs ./lightning-transaction-sync/src/error.rs ./lightning-transaction-sync/src/esplora.rs From 470085aa2f623d50392aa8ef31a2f9dc4639f993 Mon Sep 17 00:00:00 2001 From: Elias Rohrer Date: Thu, 6 Jun 2024 09:23:47 +0200 Subject: [PATCH 3/8] `rustfmt`: Reformat `lightning-transaction-sync/src/electrum.rs` --- lightning-transaction-sync/src/electrum.rs | 181 +++++++++++---------- rustfmt_excluded_files | 1 - 2 files changed, 98 insertions(+), 84 deletions(-) diff --git a/lightning-transaction-sync/src/electrum.rs b/lightning-transaction-sync/src/electrum.rs index 4c809d40716..8ba250f8460 100644 --- a/lightning-transaction-sync/src/electrum.rs +++ b/lightning-transaction-sync/src/electrum.rs @@ -1,24 +1,24 @@ -use crate::common::{ConfirmedTx, SyncState, FilterQueue}; -use crate::error::{TxSyncError, InternalError}; +use crate::common::{ConfirmedTx, FilterQueue, SyncState}; +use crate::error::{InternalError, TxSyncError}; use electrum_client::Client as ElectrumClient; use electrum_client::ElectrumApi; use electrum_client::GetMerkleRes; -use lightning::util::logger::Logger; -use lightning::{log_error, log_debug, log_trace}; use lightning::chain::WatchedOutput; use lightning::chain::{Confirm, Filter}; +use lightning::util::logger::Logger; +use lightning::{log_debug, log_error, log_trace}; -use bitcoin::{BlockHash, Script, Transaction, Txid}; use bitcoin::block::Header; use bitcoin::hash_types::TxMerkleNode; -use bitcoin::hashes::Hash; use bitcoin::hashes::sha256d::Hash as Sha256d; +use bitcoin::hashes::Hash; +use bitcoin::{BlockHash, Script, Transaction, Txid}; +use std::collections::HashSet; use std::ops::Deref; use std::sync::Mutex; -use std::collections::HashSet; use std::time::Instant; /// Synchronizes LDK with a given Electrum server. @@ -64,12 +64,7 @@ where let sync_state = Mutex::new(SyncState::new()); let queue = Mutex::new(FilterQueue::new()); - Ok(Self { - sync_state, - queue, - client, - logger, - }) + Ok(Self { sync_state, queue, client, logger }) } /// Synchronizes the given `confirmables` via their [`Confirm`] interface implementations. This @@ -84,7 +79,8 @@ where /// [`ChannelManager`]: lightning::ln::channelmanager::ChannelManager /// [`Filter`]: lightning::chain::Filter pub fn sync(&self, confirmables: Vec) -> Result<(), TxSyncError> - where C::Target: Confirm + where + C::Target: Confirm, { // This lock makes sure we're syncing once at a time. let mut sync_state = self.sync_state.lock().unwrap(); @@ -124,15 +120,15 @@ where num_unconfirmed += unconfirmed_txs.len(); sync_state.sync_unconfirmed_transactions( &confirmables, - unconfirmed_txs + unconfirmed_txs, ); - } + }, Ok(true) => { log_debug!(self.logger, "Encountered inconsistency during transaction sync, restarting."); sync_state.pending_sync = true; continue; - } + }, Err(err) => { // (Semi-)permanent failure, retry later. log_error!(self.logger, @@ -142,7 +138,7 @@ where ); sync_state.pending_sync = true; return Err(TxSyncError::from(err)); - } + }, } }, Err(err) => { @@ -154,7 +150,7 @@ where ); sync_state.pending_sync = true; return Err(TxSyncError::from(err)); - } + }, } // Update the best block. @@ -173,17 +169,15 @@ where match self.check_update_tip(&mut tip_header, &mut tip_height) { Ok(false) => { num_confirmed += confirmed_txs.len(); - sync_state.sync_confirmed_transactions( - &confirmables, - confirmed_txs - ); - } + sync_state + .sync_confirmed_transactions(&confirmables, confirmed_txs); + }, Ok(true) => { log_debug!(self.logger, "Encountered inconsistency during transaction sync, restarting."); sync_state.pending_sync = true; continue; - } + }, Err(err) => { // (Semi-)permanent failure, retry later. log_error!(self.logger, @@ -193,16 +187,18 @@ where ); sync_state.pending_sync = true; return Err(TxSyncError::from(err)); - } + }, } - } + }, Err(InternalError::Inconsistency) => { // Immediately restart syncing when we encounter any inconsistencies. - log_debug!(self.logger, - "Encountered inconsistency during transaction sync, restarting."); + log_debug!( + self.logger, + "Encountered inconsistency during transaction sync, restarting." + ); sync_state.pending_sync = true; continue; - } + }, Err(err) => { // (Semi-)permanent failure, retry later. log_error!(self.logger, @@ -212,27 +208,35 @@ where ); sync_state.pending_sync = true; return Err(TxSyncError::from(err)); - } + }, } sync_state.last_sync_hash = Some(tip_header.block_hash()); sync_state.pending_sync = false; } } #[cfg(feature = "time")] - log_debug!(self.logger, + log_debug!( + self.logger, "Finished transaction sync at tip {} in {}ms: {} confirmed, {} unconfirmed.", - tip_header.block_hash(), start_time.elapsed().as_millis(), num_confirmed, - num_unconfirmed); + tip_header.block_hash(), + start_time.elapsed().as_millis(), + num_confirmed, + num_unconfirmed + ); #[cfg(not(feature = "time"))] - log_debug!(self.logger, + log_debug!( + self.logger, "Finished transaction sync at tip {}: {} confirmed, {} unconfirmed.", - tip_header.block_hash(), num_confirmed, num_unconfirmed); + tip_header.block_hash(), + num_confirmed, + num_unconfirmed + ); Ok(()) } - fn check_update_tip(&self, cur_tip_header: &mut Header, cur_tip_height: &mut u32) - -> Result - { + fn check_update_tip( + &self, cur_tip_header: &mut Header, cur_tip_height: &mut u32, + ) -> Result { let check_notification = self.client.block_headers_subscribe()?; let check_tip_hash = check_notification.header.block_hash(); @@ -258,12 +262,12 @@ where fn get_confirmed_transactions( &self, sync_state: &SyncState, ) -> Result, InternalError> { - // First, check the confirmation status of registered transactions as well as the // status of dependent transactions of registered outputs. let mut confirmed_txs: Vec = Vec::new(); let mut watched_script_pubkeys = Vec::with_capacity( - sync_state.watched_transactions.len() + sync_state.watched_outputs.len()); + sync_state.watched_transactions.len() + sync_state.watched_outputs.len(), + ); let mut watched_txs = Vec::with_capacity(sync_state.watched_transactions.len()); for txid in &sync_state.watched_transactions { @@ -280,14 +284,14 @@ where log_error!(self.logger, "Failed due to retrieving invalid tx data."); return Err(InternalError::Failed); } - } + }, Err(electrum_client::Error::Protocol(_)) => { // We couldn't find the tx, do nothing. - } + }, Err(e) => { log_error!(self.logger, "Failed to look up transaction {}: {}.", txid, e); return Err(InternalError::Failed); - } + }, } } @@ -312,9 +316,9 @@ where if confirmed_txs.iter().any(|ctx| ctx.txid == **txid) { continue; } - let mut filtered_history = script_history.iter().filter(|h| h.tx_hash == **txid); - if let Some(history) = filtered_history.next() - { + let mut filtered_history = + script_history.iter().filter(|h| h.tx_hash == **txid); + if let Some(history) = filtered_history.next() { let prob_conf_height = history.height as u32; let confirmed_tx = self.get_confirmed_tx(tx, prob_conf_height)?; confirmed_txs.push(confirmed_tx); @@ -322,8 +326,8 @@ where debug_assert!(filtered_history.next().is_none()); } - for (watched_output, script_history) in sync_state.watched_outputs.values() - .zip(output_results) + for (watched_output, script_history) in + sync_state.watched_outputs.values().zip(output_results) { for possible_output_spend in script_history { if possible_output_spend.height <= 0 { @@ -339,8 +343,8 @@ where Ok(tx) => { let mut is_spend = false; for txin in &tx.input { - let watched_outpoint = watched_output.outpoint - .into_bitcoin_outpoint(); + let watched_outpoint = + watched_output.outpoint.into_bitcoin_outpoint(); if txin.previous_output == watched_outpoint { is_spend = true; break; @@ -354,21 +358,24 @@ where let prob_conf_height = possible_output_spend.height as u32; let confirmed_tx = self.get_confirmed_tx(&tx, prob_conf_height)?; confirmed_txs.push(confirmed_tx); - } + }, Err(e) => { - log_trace!(self.logger, + log_trace!( + self.logger, "Inconsistency: Tx {} was unconfirmed during syncing: {}", - txid, e); + txid, + e + ); return Err(InternalError::Inconsistency); - } + }, } } } - } + }, Err(e) => { log_error!(self.logger, "Failed to look up script histories: {}.", e); return Err(InternalError::Failed); - } + }, } // Sort all confirmed transactions first by block height, then by in-block @@ -383,7 +390,8 @@ where fn get_unconfirmed_transactions( &self, confirmables: &Vec, ) -> Result, InternalError> - where C::Target: Confirm + where + C::Target: Confirm, { // Query the interface for relevant txids and check whether the relevant blocks are still // in the best chain, mark them unconfirmed otherwise @@ -412,9 +420,9 @@ where Ok(unconfirmed_txs) } - fn get_confirmed_tx(&self, tx: &Transaction, prob_conf_height: u32) - -> Result - { + fn get_confirmed_tx( + &self, tx: &Transaction, prob_conf_height: u32, + ) -> Result { let txid = tx.txid(); match self.client.transaction_get_merkle(&txid, prob_conf_height as usize) { Ok(merkle_res) => { @@ -422,36 +430,47 @@ where match self.client.block_header(prob_conf_height as usize) { Ok(block_header) => { let pos = merkle_res.pos; - if !self.validate_merkle_proof(&txid, - &block_header.merkle_root, merkle_res)? - { - log_trace!(self.logger, + if !self.validate_merkle_proof( + &txid, + &block_header.merkle_root, + merkle_res, + )? { + log_trace!( + self.logger, "Inconsistency: Block {} was unconfirmed during syncing.", - block_header.block_hash()); + block_header.block_hash() + ); return Err(InternalError::Inconsistency); } let confirmed_tx = ConfirmedTx { tx: tx.clone(), txid, - block_header, block_height: prob_conf_height, + block_header, + block_height: prob_conf_height, pos, }; Ok(confirmed_tx) - } + }, Err(e) => { - log_error!(self.logger, + log_error!( + self.logger, "Failed to retrieve block header for height {}: {}.", - prob_conf_height, e); + prob_conf_height, + e + ); Err(InternalError::Failed) - } + }, } - } + }, Err(e) => { - log_trace!(self.logger, + log_trace!( + self.logger, "Inconsistency: Tx {} was unconfirmed during syncing: {}", - txid, e); + txid, + e + ); Err(InternalError::Inconsistency) - } + }, } } @@ -462,20 +481,16 @@ where &self.client } - fn validate_merkle_proof(&self, txid: &Txid, merkle_root: &TxMerkleNode, - merkle_res: GetMerkleRes) -> Result - { + fn validate_merkle_proof( + &self, txid: &Txid, merkle_root: &TxMerkleNode, merkle_res: GetMerkleRes, + ) -> Result { let mut index = merkle_res.pos; let mut cur = txid.to_raw_hash(); for mut bytes in merkle_res.merkle { bytes.reverse(); // unwrap() safety: `bytes` has len 32 so `from_slice` can never fail. let next_hash = Sha256d::from_slice(&bytes).unwrap(); - let (left, right) = if index % 2 == 0 { - (cur, next_hash) - } else { - (next_hash, cur) - }; + let (left, right) = if index % 2 == 0 { (cur, next_hash) } else { (next_hash, cur) }; let data = [&left[..], &right[..]].concat(); cur = Sha256d::hash(&data); diff --git a/rustfmt_excluded_files b/rustfmt_excluded_files index 8cc53a53075..d3f7dc8d930 100644 --- a/rustfmt_excluded_files +++ b/rustfmt_excluded_files @@ -159,7 +159,6 @@ ./lightning-rapid-gossip-sync/src/error.rs ./lightning-rapid-gossip-sync/src/lib.rs ./lightning-rapid-gossip-sync/src/processing.rs -./lightning-transaction-sync/src/electrum.rs ./lightning-transaction-sync/src/error.rs ./lightning-transaction-sync/src/esplora.rs ./lightning-transaction-sync/src/lib.rs From c5cd801f8781dd459b01e0221fd499f62922eb34 Mon Sep 17 00:00:00 2001 From: Elias Rohrer Date: Thu, 6 Jun 2024 09:25:18 +0200 Subject: [PATCH 4/8] `rustfmt`: Reformat `lightning-transaction-sync/src/esplora.rs` --- lightning-transaction-sync/src/esplora.rs | 128 +++++++++++++--------- rustfmt_excluded_files | 1 - 2 files changed, 76 insertions(+), 53 deletions(-) diff --git a/lightning-transaction-sync/src/esplora.rs b/lightning-transaction-sync/src/esplora.rs index 82c49b9f9d2..f176d535124 100644 --- a/lightning-transaction-sync/src/esplora.rs +++ b/lightning-transaction-sync/src/esplora.rs @@ -1,21 +1,21 @@ -use crate::error::{TxSyncError, InternalError}; -use crate::common::{SyncState, FilterQueue, ConfirmedTx}; +use crate::common::{ConfirmedTx, FilterQueue, SyncState}; +use crate::error::{InternalError, TxSyncError}; -use lightning::util::logger::Logger; -use lightning::{log_error, log_debug, log_trace}; use lightning::chain::WatchedOutput; use lightning::chain::{Confirm, Filter}; +use lightning::util::logger::Logger; +use lightning::{log_debug, log_error, log_trace}; use bitcoin::{BlockHash, Script, Txid}; -use esplora_client::Builder; -#[cfg(feature = "async-interface")] -use esplora_client::r#async::AsyncClient; #[cfg(not(feature = "async-interface"))] use esplora_client::blocking::BlockingClient; +#[cfg(feature = "async-interface")] +use esplora_client::r#async::AsyncClient; +use esplora_client::Builder; -use std::collections::HashSet; use core::ops::Deref; +use std::collections::HashSet; /// Synchronizes LDK with a given [`Esplora`] server. /// @@ -64,12 +64,7 @@ where pub fn from_client(client: EsploraClientType, logger: L) -> Self { let sync_state = MutexType::new(SyncState::new()); let queue = std::sync::Mutex::new(FilterQueue::new()); - Self { - sync_state, - queue, - client, - logger, - } + Self { sync_state, queue, client, logger } } /// Synchronizes the given `confirmables` via their [`Confirm`] interface implementations. This @@ -85,7 +80,8 @@ where /// [`Filter`]: lightning::chain::Filter #[maybe_async] pub fn sync(&self, confirmables: Vec) -> Result<(), TxSyncError> - where C::Target: Confirm + where + C::Target: Confirm, { // This lock makes sure we're syncing once at a time. #[cfg(not(feature = "async-interface"))] @@ -130,9 +126,9 @@ where num_unconfirmed += unconfirmed_txs.len(); sync_state.sync_unconfirmed_transactions( &confirmables, - unconfirmed_txs + unconfirmed_txs, ); - } + }, Err(err) => { // (Semi-)permanent failure, retry later. log_error!(self.logger, @@ -142,7 +138,7 @@ where ); sync_state.pending_sync = true; return Err(TxSyncError::from(err)); - } + }, } }, Err(err) => { @@ -154,17 +150,24 @@ where ); sync_state.pending_sync = true; return Err(TxSyncError::from(err)); - } + }, } - match maybe_await!(self.sync_best_block_updated(&confirmables, &mut sync_state, &tip_hash)) { - Ok(()) => {} + match maybe_await!(self.sync_best_block_updated( + &confirmables, + &mut sync_state, + &tip_hash + )) { + Ok(()) => {}, Err(InternalError::Inconsistency) => { // Immediately restart syncing when we encounter any inconsistencies. - log_debug!(self.logger, "Encountered inconsistency during transaction sync, restarting."); + log_debug!( + self.logger, + "Encountered inconsistency during transaction sync, restarting." + ); sync_state.pending_sync = true; continue; - } + }, Err(err) => { // (Semi-)permanent failure, retry later. log_error!(self.logger, @@ -174,7 +177,7 @@ where ); sync_state.pending_sync = true; return Err(TxSyncError::from(err)); - } + }, } } @@ -193,11 +196,9 @@ where continue; } num_confirmed += confirmed_txs.len(); - sync_state.sync_confirmed_transactions( - &confirmables, - confirmed_txs - ); - } + sync_state + .sync_confirmed_transactions(&confirmables, confirmed_txs); + }, Err(err) => { // (Semi-)permanent failure, retry later. log_error!(self.logger, @@ -207,15 +208,18 @@ where ); sync_state.pending_sync = true; return Err(TxSyncError::from(err)); - } + }, } - } + }, Err(InternalError::Inconsistency) => { // Immediately restart syncing when we encounter any inconsistencies. - log_debug!(self.logger, "Encountered inconsistency during transaction sync, restarting."); + log_debug!( + self.logger, + "Encountered inconsistency during transaction sync, restarting." + ); sync_state.pending_sync = true; continue; - } + }, Err(err) => { // (Semi-)permanent failure, retry later. log_error!(self.logger, @@ -225,18 +229,29 @@ where ); sync_state.pending_sync = true; return Err(TxSyncError::from(err)); - } + }, } sync_state.last_sync_hash = Some(tip_hash); sync_state.pending_sync = false; } } #[cfg(feature = "time")] - log_debug!(self.logger, "Finished transaction sync at tip {} in {}ms: {} confirmed, {} unconfirmed.", - tip_hash, start_time.elapsed().as_millis(), num_confirmed, num_unconfirmed); + log_debug!( + self.logger, + "Finished transaction sync at tip {} in {}ms: {} confirmed, {} unconfirmed.", + tip_hash, + start_time.elapsed().as_millis(), + num_confirmed, + num_unconfirmed + ); #[cfg(not(feature = "time"))] - log_debug!(self.logger, "Finished transaction sync at tip {}: {} confirmed, {} unconfirmed.", - tip_hash, num_confirmed, num_unconfirmed); + log_debug!( + self.logger, + "Finished transaction sync at tip {}: {} confirmed, {} unconfirmed.", + tip_hash, + num_confirmed, + num_unconfirmed + ); Ok(()) } @@ -244,7 +259,8 @@ where fn sync_best_block_updated( &self, confirmables: &Vec, sync_state: &mut SyncState, tip_hash: &BlockHash, ) -> Result<(), InternalError> - where C::Target: Confirm + where + C::Target: Confirm, { // Inform the interface of the new block. let tip_header = maybe_await!(self.client.get_header_by_hash(tip_hash))?; @@ -268,7 +284,6 @@ where fn get_confirmed_transactions( &self, sync_state: &SyncState, ) -> Result, InternalError> { - // First, check the confirmation status of registered transactions as well as the // status of dependent transactions of registered outputs. @@ -284,7 +299,8 @@ where } for (_, output) in &sync_state.watched_outputs { - if let Some(output_status) = maybe_await!(self.client + if let Some(output_status) = maybe_await!(self + .client .get_output_status(&output.outpoint.txid, output.outpoint.index as u64))? { if let Some(spending_txid) = output_status.txid { @@ -299,13 +315,11 @@ where } } - if let Some(confirmed_tx) = maybe_await!(self - .get_confirmed_tx( - spending_txid, - spending_tx_status.block_hash, - spending_tx_status.block_height, - ))? - { + if let Some(confirmed_tx) = maybe_await!(self.get_confirmed_tx( + spending_txid, + spending_tx_status.block_hash, + spending_tx_status.block_height, + ))? { confirmed_txs.push(confirmed_tx); } } @@ -331,7 +345,13 @@ where let block_hash = block_header.block_hash(); if let Some(expected_block_hash) = expected_block_hash { if expected_block_hash != block_hash { - log_trace!(self.logger, "Inconsistency: Tx {} expected in block {}, but is confirmed in {}", txid, expected_block_hash, block_hash); + log_trace!( + self.logger, + "Inconsistency: Tx {} expected in block {}, but is confirmed in {}", + txid, + expected_block_hash, + block_hash + ); return Err(InternalError::Inconsistency); } } @@ -363,7 +383,11 @@ where } else { // If any previously-confirmed block suddenly is no longer confirmed, we found // an inconsistency and should start over. - log_trace!(self.logger, "Inconsistency: Tx {} was unconfirmed during syncing.", txid); + log_trace!( + self.logger, + "Inconsistency: Tx {} was unconfirmed during syncing.", + txid + ); return Err(InternalError::Inconsistency); } } @@ -375,7 +399,8 @@ where fn get_unconfirmed_transactions( &self, confirmables: &Vec, ) -> Result, InternalError> - where C::Target: Confirm + where + C::Target: Confirm, { // Query the interface for relevant txids and check whether the relevant blocks are still // in the best chain, mark them unconfirmed otherwise @@ -422,7 +447,6 @@ type EsploraClientType = AsyncClient; #[cfg(not(feature = "async-interface"))] type EsploraClientType = BlockingClient; - impl Filter for EsploraSyncClient where L::Target: Logger, diff --git a/rustfmt_excluded_files b/rustfmt_excluded_files index d3f7dc8d930..bccaaf4ed43 100644 --- a/rustfmt_excluded_files +++ b/rustfmt_excluded_files @@ -160,7 +160,6 @@ ./lightning-rapid-gossip-sync/src/lib.rs ./lightning-rapid-gossip-sync/src/processing.rs ./lightning-transaction-sync/src/error.rs -./lightning-transaction-sync/src/esplora.rs ./lightning-transaction-sync/src/lib.rs ./lightning-transaction-sync/tests/integration_tests.rs ./lightning/src/blinded_path/message.rs From 915fe195ca3efff44109483b9140984e08e32de1 Mon Sep 17 00:00:00 2001 From: Elias Rohrer Date: Thu, 6 Jun 2024 09:26:08 +0200 Subject: [PATCH 5/8] `rustfmt`: Reformat `lightning-transaction-sync/src/error.rs` --- lightning-transaction-sync/src/error.rs | 2 +- rustfmt_excluded_files | 1 - 2 files changed, 1 insertion(+), 2 deletions(-) diff --git a/lightning-transaction-sync/src/error.rs b/lightning-transaction-sync/src/error.rs index d1f4a319e86..be59cb026b4 100644 --- a/lightning-transaction-sync/src/error.rs +++ b/lightning-transaction-sync/src/error.rs @@ -31,7 +31,7 @@ impl fmt::Display for InternalError { Self::Failed => write!(f, "Failed to conduct transaction sync."), Self::Inconsistency => { write!(f, "Encountered an inconsistency during transaction sync.") - } + }, } } } diff --git a/rustfmt_excluded_files b/rustfmt_excluded_files index bccaaf4ed43..0c33fd8e9e7 100644 --- a/rustfmt_excluded_files +++ b/rustfmt_excluded_files @@ -159,7 +159,6 @@ ./lightning-rapid-gossip-sync/src/error.rs ./lightning-rapid-gossip-sync/src/lib.rs ./lightning-rapid-gossip-sync/src/processing.rs -./lightning-transaction-sync/src/error.rs ./lightning-transaction-sync/src/lib.rs ./lightning-transaction-sync/tests/integration_tests.rs ./lightning/src/blinded_path/message.rs From 85a82045fe8191535505a31e4a3dd749ae61dbaa Mon Sep 17 00:00:00 2001 From: Elias Rohrer Date: Thu, 6 Jun 2024 09:26:35 +0200 Subject: [PATCH 6/8] `rustfmt`: Reformat `lightning-transaction-sync/src/lib.rs` --- lightning-transaction-sync/src/lib.rs | 6 ++---- rustfmt_excluded_files | 1 - 2 files changed, 2 insertions(+), 5 deletions(-) diff --git a/lightning-transaction-sync/src/lib.rs b/lightning-transaction-sync/src/lib.rs index 7bd4b4aee3f..96e0c0dfe9c 100644 --- a/lightning-transaction-sync/src/lib.rs +++ b/lightning-transaction-sync/src/lib.rs @@ -60,10 +60,8 @@ #![deny(rustdoc::broken_intra_doc_links)] #![deny(rustdoc::private_intra_doc_links)] - #![deny(missing_docs)] #![deny(unsafe_code)] - #![cfg_attr(docsrs, feature(doc_auto_cfg))] #[cfg(any(feature = "esplora-blocking", feature = "esplora-async"))] @@ -83,7 +81,7 @@ mod error; #[cfg(any(feature = "esplora-blocking", feature = "esplora-async", feature = "electrum"))] pub use error::TxSyncError; -#[cfg(any(feature = "esplora-blocking", feature = "esplora-async"))] -pub use esplora::EsploraSyncClient; #[cfg(feature = "electrum")] pub use electrum::ElectrumSyncClient; +#[cfg(any(feature = "esplora-blocking", feature = "esplora-async"))] +pub use esplora::EsploraSyncClient; diff --git a/rustfmt_excluded_files b/rustfmt_excluded_files index 0c33fd8e9e7..9a5c76eba18 100644 --- a/rustfmt_excluded_files +++ b/rustfmt_excluded_files @@ -159,7 +159,6 @@ ./lightning-rapid-gossip-sync/src/error.rs ./lightning-rapid-gossip-sync/src/lib.rs ./lightning-rapid-gossip-sync/src/processing.rs -./lightning-transaction-sync/src/lib.rs ./lightning-transaction-sync/tests/integration_tests.rs ./lightning/src/blinded_path/message.rs ./lightning/src/blinded_path/mod.rs From 21fee20a6d1e79a18a371e51e842da4b953ee070 Mon Sep 17 00:00:00 2001 From: Elias Rohrer Date: Fri, 7 Jun 2024 11:18:43 +0200 Subject: [PATCH 7/8] `rustfmt`: `lightning-transaction-sync/tests/integration_tests.rs` --- .../tests/integration_tests.rs | 88 +++++++++++++------ rustfmt_excluded_files | 1 - 2 files changed, 63 insertions(+), 26 deletions(-) diff --git a/lightning-transaction-sync/tests/integration_tests.rs b/lightning-transaction-sync/tests/integration_tests.rs index b1118e45776..b30594a717d 100644 --- a/lightning-transaction-sync/tests/integration_tests.rs +++ b/lightning-transaction-sync/tests/integration_tests.rs @@ -1,26 +1,29 @@ -#![cfg(all(not(target_os = "windows"), any(feature = "esplora-blocking", feature = "esplora-async", feature = "electrum")))] +#![cfg(all( + not(target_os = "windows"), + any(feature = "esplora-blocking", feature = "esplora-async", feature = "electrum") +))] -#[cfg(any(feature = "esplora-blocking", feature = "esplora-async"))] -use lightning_transaction_sync::EsploraSyncClient; -#[cfg(feature = "electrum")] -use lightning_transaction_sync::ElectrumSyncClient; -use lightning::chain::{Confirm, Filter, WatchedOutput}; use lightning::chain::transaction::{OutPoint, TransactionData}; +use lightning::chain::{Confirm, Filter, WatchedOutput}; use lightning::util::test_utils::TestLogger; +#[cfg(feature = "electrum")] +use lightning_transaction_sync::ElectrumSyncClient; +#[cfg(any(feature = "esplora-blocking", feature = "esplora-async"))] +use lightning_transaction_sync::EsploraSyncClient; -use electrsd::{bitcoind, bitcoind::BitcoinD, ElectrsD}; -use bitcoin::{Amount, Txid, BlockHash}; +use bdk_macros::maybe_await; use bitcoin::blockdata::block::Header; use bitcoin::blockdata::constants::genesis_block; use bitcoin::network::Network; -use electrsd::bitcoind::bitcoincore_rpc::bitcoincore_rpc_json::AddressType; +use bitcoin::{Amount, BlockHash, Txid}; use bitcoind::bitcoincore_rpc::RpcApi; -use bdk_macros::maybe_await; +use electrsd::bitcoind::bitcoincore_rpc::bitcoincore_rpc_json::AddressType; +use electrsd::{bitcoind, bitcoind::BitcoinD, ElectrsD}; +use std::collections::{HashMap, HashSet}; use std::env; use std::sync::Mutex; use std::time::Duration; -use std::collections::{HashMap, HashSet}; pub fn setup_bitcoind_and_electrsd() -> (BitcoinD, ElectrsD) { let bitcoind_exe = @@ -63,8 +66,11 @@ pub fn wait_for_block(electrsd: &ElectrsD, min_height: usize) { // it didn't. Since we can't proceed without subscribing, we try again after a delay // and panic if it still fails. std::thread::sleep(Duration::from_secs(1)); - electrsd.client.block_headers_subscribe_raw().expect("failed to subscribe to block headers") - } + electrsd + .client + .block_headers_subscribe_raw() + .expect("failed to subscribe to block headers") + }, }; loop { if header.height >= min_height { @@ -90,7 +96,7 @@ where None if delay.as_millis() < 512 => { delay = delay.mul_f32(2.0); tries += 1; - } + }, None if tries == 10 => panic!("Exceeded our maximum wait time."), None => tries += 1, } @@ -132,7 +138,8 @@ impl Confirm for TestConfirmable { let block_hash = header.block_hash(); self.confirmed_txs.lock().unwrap().insert(txid, (block_hash, height)); self.unconfirmed_txs.lock().unwrap().remove(&txid); - self.events.lock().unwrap().push(TestConfirmableEvent::Confirmed(txid, block_hash, height)); + let event = TestConfirmableEvent::Confirmed(txid, block_hash, height); + self.events.lock().unwrap().push(event); } } @@ -145,11 +152,13 @@ impl Confirm for TestConfirmable { fn best_block_updated(&self, header: &Header, height: u32) { let block_hash = header.block_hash(); *self.best_block.lock().unwrap() = (block_hash, height); - self.events.lock().unwrap().push(TestConfirmableEvent::BestBlockUpdated(block_hash, height)); + let event = TestConfirmableEvent::BestBlockUpdated(block_hash, height); + self.events.lock().unwrap().push(event); } fn get_relevant_txids(&self) -> Vec<(Txid, u32, Option)> { - self.confirmed_txs.lock().unwrap().iter().map(|(&txid, (hash, height))| (txid, *height, Some(*hash))).collect::>() + let lock = self.confirmed_txs.lock().unwrap(); + lock.iter().map(|(&txid, (hash, height))| (txid, *height, Some(*hash))).collect() } } @@ -165,12 +174,37 @@ macro_rules! test_syncing { assert_eq!(events.len(), 1); // Check registered confirmed transactions are marked confirmed - let new_address = $bitcoind.client.get_new_address(Some("test"), - Some(AddressType::Legacy)).unwrap().assume_checked(); - let txid = $bitcoind.client.send_to_address(&new_address, Amount::from_sat(5000), None, None, - None, None, None, None).unwrap(); - let second_txid = $bitcoind.client.send_to_address(&new_address, Amount::from_sat(5000), None, - None, None, None, None, None).unwrap(); + let new_address = $bitcoind + .client + .get_new_address(Some("test"), Some(AddressType::Legacy)) + .unwrap() + .assume_checked(); + let txid = $bitcoind + .client + .send_to_address( + &new_address, + Amount::from_sat(5000), + None, + None, + None, + None, + None, + None, + ) + .unwrap(); + let second_txid = $bitcoind + .client + .send_to_address( + &new_address, + Amount::from_sat(5000), + None, + None, + None, + None, + None, + None, + ) + .unwrap(); $tx_sync.register_tx(&txid, &new_address.payload().script_pubkey()); maybe_await!($tx_sync.sync(vec![&$confirmable])).unwrap(); @@ -193,13 +227,17 @@ macro_rules! test_syncing { let block_hash = tx_res.info.blockhash.unwrap(); let tx = tx_res.transaction().unwrap(); let prev_outpoint = tx.input.first().unwrap().previous_output; - let prev_tx = $bitcoind.client.get_transaction(&prev_outpoint.txid, None).unwrap().transaction() + let prev_tx = $bitcoind + .client + .get_transaction(&prev_outpoint.txid, None) + .unwrap() + .transaction() .unwrap(); let prev_script_pubkey = prev_tx.output[prev_outpoint.vout as usize].script_pubkey.clone(); let output = WatchedOutput { block_hash: Some(block_hash), outpoint: OutPoint { txid: prev_outpoint.txid, index: prev_outpoint.vout as u16 }, - script_pubkey: prev_script_pubkey + script_pubkey: prev_script_pubkey, }; $tx_sync.register_output(output); diff --git a/rustfmt_excluded_files b/rustfmt_excluded_files index 9a5c76eba18..30406f6519a 100644 --- a/rustfmt_excluded_files +++ b/rustfmt_excluded_files @@ -159,7 +159,6 @@ ./lightning-rapid-gossip-sync/src/error.rs ./lightning-rapid-gossip-sync/src/lib.rs ./lightning-rapid-gossip-sync/src/processing.rs -./lightning-transaction-sync/tests/integration_tests.rs ./lightning/src/blinded_path/message.rs ./lightning/src/blinded_path/mod.rs ./lightning/src/blinded_path/payment.rs From 43b41868bb9ac811564419954f2e49741dd7d9c9 Mon Sep 17 00:00:00 2001 From: Elias Rohrer Date: Thu, 6 Jun 2024 09:30:30 +0200 Subject: [PATCH 8/8] Pass our `edition` to `rustfmt` .. as it otherwise doesn't seem to pick up the right one when checkin integration tests. --- ci/rustfmt.sh | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/ci/rustfmt.sh b/ci/rustfmt.sh index a1fdf6bd7f3..1039429bc6a 100755 --- a/ci/rustfmt.sh +++ b/ci/rustfmt.sh @@ -15,5 +15,5 @@ TMP_FILE=$(mktemp) find . -name '*.rs' -type f |sort >$TMP_FILE for file in $(comm -23 $TMP_FILE rustfmt_excluded_files); do echo "Checking formatting of $file" - rustfmt $VERS --check $file + rustfmt $VERS --edition 2021 --check $file done