Skip to content

Commit 6b14ade

Browse files
committed
Add rescan logic to ChainMonitor::block_connected
Electrum clients will only provide transaction data for outputs that have been explicitly registered. Hence, upon registering new outputs, recursively register any outputs to watch contained within dependent transactions from the same block.
1 parent 02b85fa commit 6b14ade

File tree

1 file changed

+19
-2
lines changed

1 file changed

+19
-2
lines changed

lightning/src/chain/chainmonitor.rs

Lines changed: 19 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -82,23 +82,40 @@ where C::Target: chain::Filter,
8282
/// descendants of such transactions. It is not necessary to re-fetch the block to obtain
8383
/// updated `txdata`.
8484
pub fn block_connected(&self, header: &BlockHeader, txdata: &TransactionData, height: u32) {
85+
let mut dependent_txdata = Vec::new();
8586
let monitors = self.monitors.read().unwrap();
8687
for monitor in monitors.values() {
8788
let mut txn_outputs = monitor.block_connected(header, txdata, height, &*self.broadcaster, &*self.fee_estimator, &*self.logger);
8889

90+
// Register any new outputs with the chain source for filtering, storing any dependent
91+
// transactions from within the block that previously had not been included in txdata.
8992
if let Some(ref chain_source) = self.chain_source {
9093
let block_hash = header.block_hash();
9194
for (txid, outputs) in txn_outputs.drain(..) {
9295
for (idx, output) in outputs.iter() {
93-
chain_source.register_output(WatchedOutput {
96+
// Register any new outputs with the chain source for filtering and recurse
97+
// if it indicates that there are dependent transactions within the block
98+
// that had not been previously included in txdata.
99+
let output = WatchedOutput {
94100
block_hash: Some(block_hash),
95101
outpoint: OutPoint { txid, index: *idx as u16 },
96102
script_pubkey: output.script_pubkey.clone(),
97-
});
103+
};
104+
if let Some(tx) = chain_source.register_output(output) {
105+
dependent_txdata.push(tx);
106+
}
98107
}
99108
}
100109
}
101110
}
111+
112+
// Recursively call for any dependent transactions that were identified by the chain source.
113+
if !dependent_txdata.is_empty() {
114+
dependent_txdata.sort_unstable_by_key(|(index, _tx)| *index);
115+
dependent_txdata.dedup_by_key(|(index, _tx)| *index);
116+
let txdata: Vec<_> = dependent_txdata.iter().map(|(index, tx)| (*index, tx)).collect();
117+
self.block_connected(header, &txdata, height);
118+
}
102119
}
103120

104121
/// Dispatches to per-channel monitors, which are responsible for updating their on-chain view

0 commit comments

Comments
 (0)