Skip to content

Commit 21939e9

Browse files
committed
Make the ChannelManager::block_connected API more electrum-friendly
See the similar commit that operates on `Channel`'s internal API for more details on the reasoning.
1 parent 68e8ad6 commit 21939e9

File tree

2 files changed

+57
-23
lines changed

2 files changed

+57
-23
lines changed

lightning/src/ln/channelmanager.rs

Lines changed: 55 additions & 21 deletions
Original file line numberDiff line numberDiff line change
@@ -3236,8 +3236,18 @@ where
32363236
L::Target: Logger,
32373237
{
32383238
fn block_connected(&self, block: &Block, height: u32) {
3239+
// This assertion should be enforced in tests, however we have a number of tests that
3240+
// were written before this requirement and do not meet it.
3241+
#[cfg(not(test))]
3242+
{
3243+
assert_eq!(*self.last_block_hash.read().unwrap(), block.header.prev_blockhash,
3244+
"Blocks must be connected in chain-order - the connected header must build on the last connected header");
3245+
assert_eq!(self.latest_block_height.load(Ordering::Acquire) as u64, height as u64 - 1,
3246+
"Blocks must be connected in chain-order - the connected header must build on the last connected header");
3247+
}
32393248
let txdata: Vec<_> = block.txdata.iter().enumerate().collect();
3240-
ChannelManager::block_connected(self, &block.header, &txdata, height);
3249+
self.transactions_confirmed(&block.header, height, &txdata);
3250+
self.update_best_block(&block.header, height);
32413251
}
32423252

32433253
fn block_disconnected(&self, header: &BlockHeader, _height: u32) {
@@ -3252,27 +3262,12 @@ impl<Signer: Sign, M: Deref, T: Deref, K: Deref, F: Deref, L: Deref> ChannelMana
32523262
F::Target: FeeEstimator,
32533263
L::Target: Logger,
32543264
{
3255-
/// Updates channel state based on transactions seen in a connected block.
3256-
pub fn block_connected(&self, header: &BlockHeader, txdata: &TransactionData, height: u32) {
3265+
///asdf
3266+
fn do_block_event<FN: Fn(&mut Channel<Signer>) -> Result<(Option<msgs::FundingLocked>, Vec<(HTLCSource, PaymentHash)>), msgs::ErrorMessage>>
3267+
(&self, height: u32, f: FN) {
32573268
// Note that we MUST NOT end up calling methods on self.chain_monitor here - we're called
32583269
// during initialization prior to the chain_monitor being fully configured in some cases.
32593270
// See the docs for `ChannelManagerReadArgs` for more.
3260-
let block_hash = header.block_hash();
3261-
log_trace!(self.logger, "Block {} at height {} connected", block_hash, height);
3262-
3263-
let _persistence_guard = PersistenceNotifierGuard::new(&self.total_consistency_lock, &self.persistence_notifier);
3264-
3265-
// This assertion should be enforced in tests, however we have a number of tests that
3266-
// were written before this requirement and do not meet it.
3267-
#[cfg(not(test))]
3268-
{
3269-
assert_eq!(*self.last_block_hash.read().unwrap(), header.prev_blockhash,
3270-
"Blocks must be connected in chain-order - the connected header must build on the last connected header");
3271-
assert_eq!(self.latest_block_height.load(Ordering::Acquire) as u64, height as u64 - 1,
3272-
"Blocks must be connected in chain-order - the connected header must build on the last connected header");
3273-
}
3274-
self.latest_block_height.store(height as usize, Ordering::Release);
3275-
*self.last_block_hash.write().unwrap() = block_hash;
32763271

32773272
let mut failed_channels = Vec::new();
32783273
let mut timed_out_htlcs = Vec::new();
@@ -3282,8 +3277,7 @@ impl<Signer: Sign, M: Deref, T: Deref, K: Deref, F: Deref, L: Deref> ChannelMana
32823277
let short_to_id = &mut channel_state.short_to_id;
32833278
let pending_msg_events = &mut channel_state.pending_msg_events;
32843279
channel_state.by_id.retain(|_, channel| {
3285-
let res = channel.transactions_confirmed(&block_hash, height, txdata, &self.logger)
3286-
.and_then(|_| channel.update_best_block(height, header.time));
3280+
let res = f(channel);
32873281
if let Ok((chan_res, mut timed_out_pending_htlcs)) = res {
32883282
for (source, payment_hash) in timed_out_pending_htlcs.drain(..) {
32893283
let chan_update = self.get_channel_update(&channel).map(|u| u.encode_with_len()).unwrap(); // Cannot add/recv HTLCs before we have a short_id so unwrap is safe
@@ -3353,6 +3347,46 @@ impl<Signer: Sign, M: Deref, T: Deref, K: Deref, F: Deref, L: Deref> ChannelMana
33533347
for (source, payment_hash, reason) in timed_out_htlcs.drain(..) {
33543348
self.fail_htlc_backwards_internal(self.channel_state.lock().unwrap(), source, &payment_hash, reason);
33553349
}
3350+
}
3351+
3352+
/// Updates channel state to take note of transactions which were confirmed in the given block
3353+
/// at the given height.
3354+
///
3355+
/// Note that you must still call update_best_block with the block information here.
3356+
///
3357+
/// XXX: Note that in the case that a transaction which was provided via this method is
3358+
/// reorganized out of the best chain, the only current way to correctly handle the any
3359+
/// associated channel force-closure is to walk the chain back from the current tip with
3360+
/// repeated `block_disconnected` calls, followed by an `update_best_block` call.
3361+
pub fn transactions_confirmed(&self, header: &BlockHeader, height: u32, txdata: &TransactionData) {
3362+
// Note that we MUST NOT end up calling methods on self.chain_monitor here - we're called
3363+
// during initialization prior to the chain_monitor being fully configured in some cases.
3364+
// See the docs for `ChannelManagerReadArgs` for more.
3365+
3366+
let block_hash = header.block_hash();
3367+
log_trace!(self.logger, "{} transactions included in block {} at height {} provided", txdata.len(), block_hash, height);
3368+
3369+
let _persistence_guard = PersistenceNotifierGuard::new(&self.total_consistency_lock, &self.persistence_notifier);
3370+
self.do_block_event(height, |channel| channel.transactions_confirmed(&block_hash, height, txdata, &self.logger).map(|a| (a, Vec::new())));
3371+
}
3372+
3373+
/// Updates channel state with the current best blockchain tip. You should attempt to call this
3374+
/// quickly after a new block becomes available, however it does not need to be called for each
3375+
/// new block.
3376+
pub fn update_best_block(&self, header: &BlockHeader, height: u32) {
3377+
// Note that we MUST NOT end up calling methods on self.chain_monitor here - we're called
3378+
// during initialization prior to the chain_monitor being fully configured in some cases.
3379+
// See the docs for `ChannelManagerReadArgs` for more.
3380+
3381+
let block_hash = header.block_hash();
3382+
log_trace!(self.logger, "Block {} at height {} connected", block_hash, height);
3383+
3384+
let _persistence_guard = PersistenceNotifierGuard::new(&self.total_consistency_lock, &self.persistence_notifier);
3385+
3386+
self.latest_block_height.store(height as usize, Ordering::Release);
3387+
*self.last_block_hash.write().unwrap() = block_hash;
3388+
3389+
self.do_block_event(height, |channel| channel.update_best_block(height, header.time));
33563390

33573391
loop {
33583392
// Update last_node_announcement_serial to be the max of its current value and the

lightning/src/ln/functional_test_utils.rs

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -10,7 +10,7 @@
1010
//! A bunch of useful utilities for building networks of nodes and exchanging messages between
1111
//! nodes for functional tests.
1212
13-
use chain::Watch;
13+
use chain::{Listen, Watch};
1414
use chain::channelmonitor::ChannelMonitor;
1515
use chain::transaction::OutPoint;
1616
use ln::channelmanager::{ChainParameters, ChannelManager, ChannelManagerReadArgs, RAACommitmentOrder, PaymentPreimage, PaymentHash, PaymentSecret, PaymentSendFailure};
@@ -110,7 +110,7 @@ pub fn connect_blocks<'a, 'b, 'c, 'd>(node: &'a Node<'b, 'c, 'd>, depth: u32, he
110110
pub fn connect_block<'a, 'b, 'c, 'd>(node: &'a Node<'b, 'c, 'd>, block: &Block, height: u32) {
111111
let txdata: Vec<_> = block.txdata.iter().enumerate().collect();
112112
node.chain_monitor.chain_monitor.block_connected(&block.header, &txdata, height);
113-
node.node.block_connected(&block.header, &txdata, height);
113+
node.node.block_connected(&block, height);
114114
node.node.test_process_background_events();
115115
*node.last_block.lock().unwrap() = (block.header.block_hash(), height);
116116
node.blocks.lock().unwrap().push((block.header, height));

0 commit comments

Comments
 (0)