X-Git-Url: http://git.bitcoin.ninja/index.cgi?a=blobdiff_plain;f=lightning-transaction-sync%2Fsrc%2Fcommon.rs;h=420d7d8a9575f8672ce3111a52d000270c141a4e;hb=c5cd801f8781dd459b01e0221fd499f62922eb34;hp=45f18afb99bb07632c9590c1bc4e97c686dcab90;hpb=a0183d7ef1bdf95eb009b1c85849585e3faa0217;p=rust-lightning diff --git a/lightning-transaction-sync/src/common.rs b/lightning-transaction-sync/src/common.rs index 45f18afb..420d7d8a 100644 --- a/lightning-transaction-sync/src/common.rs +++ b/lightning-transaction-sync/src/common.rs @@ -1,9 +1,10 @@ -use lightning::chain::WatchedOutput; -use bitcoin::{Txid, BlockHash, Transaction, OutPoint}; -use bitcoin::blockdata::block::Header; - -use std::collections::{HashSet, HashMap}; +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::{HashMap, HashSet}; +use std::ops::Deref; // Represents the current state. pub(crate) struct SyncState { @@ -13,6 +14,9 @@ pub(crate) struct SyncState { // Outputs that were previously processed, but must not be forgotten yet as // as we still need to monitor any spends on-chain. pub watched_outputs: HashMap, + // Outputs for which we previously saw a spend on-chain but kept around until the spends reach + // sufficient depth. + pub outputs_spends_pending_threshold_conf: Vec<(Txid, u32, OutPoint, WatchedOutput)>, // The tip hash observed during our last sync. pub last_sync_hash: Option, // Indicates whether we need to resync, e.g., after encountering an error. @@ -24,12 +28,68 @@ impl SyncState { Self { watched_transactions: HashSet::new(), watched_outputs: HashMap::new(), + outputs_spends_pending_threshold_conf: Vec::new(), last_sync_hash: None, pending_sync: false, } } -} + 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); + } + + self.watched_transactions.insert(txid); + + // 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 + } + }, + ) + } + } + 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( + &ctx.block_header, + &[(ctx.pos, &ctx.tx)], + ctx.block_height, + ); + } + + self.watched_transactions.remove(&ctx.tx.txid()); + + for input in &ctx.tx.input { + if let Some(output) = self.watched_outputs.remove(&input.previous_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); + } +} // A queue that is to be filled by `Filter` and drained during the next syncing round. pub(crate) struct FilterQueue { @@ -41,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`]. @@ -68,8 +125,10 @@ impl FilterQueue { } } +#[derive(Debug)] pub(crate) struct ConfirmedTx { pub tx: Transaction, + pub txid: Txid, pub block_header: Header, pub block_height: u32, pub pos: usize,