Skip to content

Commit 8e37448

Browse files
committed
Add ChannelMonitor::update_best_block
Expose a way for Electrum users to update the best block on a ChannelMonitor independently of confirming transactions.
1 parent 13a3340 commit 8e37448

File tree

2 files changed

+90
-11
lines changed

2 files changed

+90
-11
lines changed

lightning/src/chain/channelmonitor.rs

Lines changed: 86 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -1304,12 +1304,15 @@ impl<Signer: Sign> ChannelMonitor<Signer> {
13041304
header, height, broadcaster, fee_estimator, logger)
13051305
}
13061306

1307-
/// Processes transactions from a block with the given header and height, returning new outputs
1308-
/// to watch. See [`block_connected`] for details.
1307+
/// Processes transactions confirmed in a block with the given header and height, returning new
1308+
/// outputs to watch. See [`block_connected`] for details.
13091309
///
1310-
/// TODO: Expand docs.
1310+
/// Used instead of [`block_connected`] by clients that are notified of transactions rather than
1311+
/// blocks. May be called before or after [`update_best_block`] for transactions in the
1312+
/// corresponding block. See [`update_best_block`] for further calling expectations.
13111313
///
13121314
/// [`block_connected`]: Self::block_connected
1315+
/// [`update_best_block`]: Self::update_best_block
13131316
pub fn transactions_confirmed<B: Deref, F: Deref, L: Deref>(
13141317
&self,
13151318
header: &BlockHeader,
@@ -1327,6 +1330,35 @@ impl<Signer: Sign> ChannelMonitor<Signer> {
13271330
self.inner.lock().unwrap().transactions_confirmed(
13281331
header, txdata, height, broadcaster, fee_estimator, logger)
13291332
}
1333+
1334+
/// Updates the monitor with the current best chain tip, returning new outputs to watch. See
1335+
/// [`block_connected`] for details.
1336+
///
1337+
/// Used instead of [`block_connected`] by clients that are notified of transactions rather than
1338+
/// blocks. May be called before or after [`transactions_confirmed`] for the corresponding
1339+
/// block.
1340+
///
1341+
/// Must be called after new blocks become available for the most recent block. Intermediary
1342+
/// blocks, however, may be safely skipped.
1343+
///
1344+
/// [`block_connected`]: Self::block_connected
1345+
/// [`transactions_confirmed`]: Self::transactions_confirmed
1346+
pub fn update_best_block<B: Deref, F: Deref, L: Deref>(
1347+
&self,
1348+
header: &BlockHeader,
1349+
height: u32,
1350+
broadcaster: B,
1351+
fee_estimator: F,
1352+
logger: L,
1353+
) -> Vec<(Txid, Vec<(u32, TxOut)>)>
1354+
where
1355+
B::Target: BroadcasterInterface,
1356+
F::Target: FeeEstimator,
1357+
L::Target: Logger,
1358+
{
1359+
self.inner.lock().unwrap().update_best_block(
1360+
header, height, broadcaster, fee_estimator, logger)
1361+
}
13301362
}
13311363

13321364
impl<Signer: Sign> ChannelMonitorImpl<Signer> {
@@ -2028,10 +2060,40 @@ impl<Signer: Sign> ChannelMonitorImpl<Signer> {
20282060
F::Target: FeeEstimator,
20292061
L::Target: Logger,
20302062
{
2031-
self.best_block = BestBlock::new(header.block_hash(), height);
2063+
let block_hash = header.block_hash();
2064+
log_trace!(logger, "New best block {} at height {}", block_hash, height);
2065+
self.best_block = BestBlock::new(block_hash, height);
2066+
20322067
self.transactions_confirmed(header, txdata, height, broadcaster, fee_estimator, logger)
20332068
}
20342069

2070+
fn update_best_block<B: Deref, F: Deref, L: Deref>(
2071+
&mut self,
2072+
header: &BlockHeader,
2073+
height: u32,
2074+
broadcaster: B,
2075+
fee_estimator: F,
2076+
logger: L,
2077+
) -> Vec<(Txid, Vec<(u32, TxOut)>)>
2078+
where
2079+
B::Target: BroadcasterInterface,
2080+
F::Target: FeeEstimator,
2081+
L::Target: Logger,
2082+
{
2083+
let block_hash = header.block_hash();
2084+
log_trace!(logger, "New best block {} at height {}", block_hash, height);
2085+
2086+
if height > self.best_block.height() {
2087+
self.best_block = BestBlock::new(block_hash, height);
2088+
self.block_confirmed(height, vec![], vec![], vec![], broadcaster, fee_estimator, logger)
2089+
} else {
2090+
self.best_block = BestBlock::new(block_hash, height);
2091+
self.onchain_events_waiting_threshold_conf.retain(|ref entry| entry.height <= height);
2092+
self.onchain_tx_handler.block_disconnected(height + 1, broadcaster, fee_estimator, logger);
2093+
Vec::new()
2094+
}
2095+
}
2096+
20352097
fn transactions_confirmed<B: Deref, F: Deref, L: Deref>(
20362098
&mut self,
20372099
header: &BlockHeader,
@@ -2100,11 +2162,28 @@ impl<Signer: Sign> ChannelMonitorImpl<Signer> {
21002162

21012163
self.is_paying_spendable_output(&tx, height, &logger);
21022164
}
2165+
2166+
self.block_confirmed(height, txn_matched, watch_outputs, claimable_outpoints, broadcaster, fee_estimator, logger)
2167+
}
2168+
2169+
fn block_confirmed<B: Deref, F: Deref, L: Deref>(
2170+
&mut self,
2171+
height: u32,
2172+
txn_matched: Vec<&Transaction>,
2173+
mut watch_outputs: Vec<(Txid, Vec<(u32, TxOut)>)>,
2174+
mut claimable_outpoints: Vec<ClaimRequest>,
2175+
broadcaster: B,
2176+
fee_estimator: F,
2177+
logger: L,
2178+
) -> Vec<(Txid, Vec<(u32, TxOut)>)>
2179+
where
2180+
B::Target: BroadcasterInterface,
2181+
F::Target: FeeEstimator,
2182+
L::Target: Logger,
2183+
{
21032184
let should_broadcast = self.would_broadcast_at_height(height, &logger);
21042185
if should_broadcast {
21052186
claimable_outpoints.push(ClaimRequest { absolute_timelock: height, aggregable: false, outpoint: BitcoinOutPoint { txid: self.funding_info.0.txid.clone(), vout: self.funding_info.0.index as u32 }, witness_data: InputMaterial::Funding { funding_redeemscript: self.funding_redeemscript.clone() }});
2106-
}
2107-
if should_broadcast {
21082187
self.pending_monitor_events.push(MonitorEvent::CommitmentTxBroadcasted(self.funding_info.0));
21092188
let commitment_tx = self.onchain_tx_handler.get_fully_signed_holder_tx(&self.funding_redeemscript);
21102189
self.holder_tx_signed = true;
@@ -2211,7 +2290,7 @@ impl<Signer: Sign> ChannelMonitorImpl<Signer> {
22112290
//We may discard:
22122291
//- htlc update there as failure-trigger tx (revoked commitment tx, non-revoked commitment tx, HTLC-timeout tx) has been disconnected
22132292
//- maturing spendable output has transaction paying us has been disconnected
2214-
self.onchain_events_waiting_threshold_conf.retain(|ref entry| entry.height != height);
2293+
self.onchain_events_waiting_threshold_conf.retain(|ref entry| entry.height < height);
22152294

22162295
self.onchain_tx_handler.block_disconnected(height, broadcaster, fee_estimator, logger);
22172296

lightning/src/ln/onchaintx.rs

Lines changed: 4 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -848,8 +848,8 @@ impl<ChannelSigner: Sign> OnchainTxHandler<ChannelSigner> {
848848

849849
// Check if any pending claim request must be rescheduled
850850
for (first_claim_txid, ref claim_data) in self.pending_claim_requests.iter() {
851-
if let Some(h) = claim_data.height_timer {
852-
if h == height {
851+
if let Some(height_timer) = claim_data.height_timer {
852+
if height >= height_timer {
853853
bump_candidates.insert(*first_claim_txid, (*claim_data).clone());
854854
}
855855
}
@@ -878,7 +878,7 @@ impl<ChannelSigner: Sign> OnchainTxHandler<ChannelSigner> {
878878
let onchain_events_waiting_threshold_conf =
879879
self.onchain_events_waiting_threshold_conf.drain(..).collect::<Vec<_>>();
880880
for entry in onchain_events_waiting_threshold_conf {
881-
if entry.height == height {
881+
if entry.height >= height {
882882
//- our claim tx on a commitment tx output
883883
//- resurect outpoint back in its claimable set and regenerate tx
884884
match entry.event {
@@ -912,7 +912,7 @@ impl<ChannelSigner: Sign> OnchainTxHandler<ChannelSigner> {
912912
// right now if one of the outpoint get disconnected, just erase whole pending claim request.
913913
let mut remove_request = Vec::new();
914914
self.claimable_outpoints.retain(|_, ref v|
915-
if v.1 == height {
915+
if v.1 >= height {
916916
remove_request.push(v.0.clone());
917917
false
918918
} else { true });

0 commit comments

Comments
 (0)