Skip to content

Commit 9a845bb

Browse files
authored
Merge pull request lightningdevkit#4182 from TheBlueMatt/2025-10-4109-followups
Minor bugfixes and test improvements to lightningdevkit#4109
2 parents 17f7858 + e1a4259 commit 9a845bb

File tree

3 files changed

+167
-179
lines changed

3 files changed

+167
-179
lines changed

lightning/src/chain/channelmonitor.rs

Lines changed: 22 additions & 14 deletions
Original file line numberDiff line numberDiff line change
@@ -3933,6 +3933,7 @@ impl<Signer: EcdsaChannelSigner> ChannelMonitorImpl<Signer> {
39333933
#[rustfmt::skip]
39343934
fn generate_claimable_outpoints_and_watch_outputs(
39353935
&mut self, generate_monitor_event_with_reason: Option<ClosureReason>,
3936+
require_funding_seen: bool,
39363937
) -> (Vec<PackageTemplate>, Vec<TransactionOutputs>) {
39373938
let funding = get_confirmed_funding_scope!(self);
39383939
let holder_commitment_tx = &funding.current_holder_commitment_tx;
@@ -3960,6 +3961,13 @@ impl<Signer: EcdsaChannelSigner> ChannelMonitorImpl<Signer> {
39603961
// in the claim that is queued to OnchainTxHandler. We set holder_tx_signed here to reject
39613962
// new channel updates.
39623963
self.holder_tx_signed = true;
3964+
3965+
// In manual-broadcast mode, if we have not yet observed the funding transaction on-chain,
3966+
// return empty vectors rather than triggering a broadcast.
3967+
if require_funding_seen && self.is_manual_broadcast && !self.funding_seen_onchain {
3968+
return (Vec::new(), Vec::new());
3969+
}
3970+
39633971
let mut watch_outputs = Vec::new();
39643972
// In CSV anchor channels, we can't broadcast our HTLC transactions while the commitment transaction is
39653973
// unconfirmed.
@@ -3985,13 +3993,7 @@ impl<Signer: EcdsaChannelSigner> ChannelMonitorImpl<Signer> {
39853993
}
39863994
claimable_outpoints.append(&mut new_outpoints);
39873995
}
3988-
// In manual-broadcast mode, if we have not yet observed the funding transaction on-chain,
3989-
// return empty vectors.
3990-
if self.is_manual_broadcast && !self.funding_seen_onchain {
3991-
return (Vec::new(), Vec::new());
3992-
} else {
3993-
(claimable_outpoints, watch_outputs)
3994-
}
3996+
(claimable_outpoints, watch_outputs)
39953997
}
39963998

39973999
#[rustfmt::skip]
@@ -4004,7 +4006,8 @@ impl<Signer: EcdsaChannelSigner> ChannelMonitorImpl<Signer> {
40044006
///
40054007
/// [`ChannelMonitor::broadcast_latest_holder_commitment_txn`]: crate::chain::channelmonitor::ChannelMonitor::broadcast_latest_holder_commitment_txn
40064008
pub(crate) fn queue_latest_holder_commitment_txn_for_broadcast<B: Deref, F: Deref, L: Deref>(
4007-
&mut self, broadcaster: &B, fee_estimator: &LowerBoundedFeeEstimator<F>, logger: &WithChannelMonitor<L>, require_funding_seen: bool,
4009+
&mut self, broadcaster: &B, fee_estimator: &LowerBoundedFeeEstimator<F>, logger: &WithChannelMonitor<L>,
4010+
require_funding_seen: bool,
40084011
)
40094012
where
40104013
B::Target: BroadcasterInterface,
@@ -4015,7 +4018,8 @@ impl<Signer: EcdsaChannelSigner> ChannelMonitorImpl<Signer> {
40154018
broadcasted_latest_txn: Some(true),
40164019
message: "ChannelMonitor-initiated commitment transaction broadcast".to_owned(),
40174020
};
4018-
let (claimable_outpoints, _) = self.generate_claimable_outpoints_and_watch_outputs(Some(reason));
4021+
let (claimable_outpoints, _) =
4022+
self.generate_claimable_outpoints_and_watch_outputs(Some(reason), require_funding_seen);
40194023
// In manual-broadcast mode, if `require_funding_seen` is true and we have not yet observed
40204024
// the funding transaction on-chain, do not queue any transactions.
40214025
if require_funding_seen && self.is_manual_broadcast && !self.funding_seen_onchain {
@@ -5618,7 +5622,7 @@ impl<Signer: EcdsaChannelSigner> ChannelMonitorImpl<Signer> {
56185622

56195623
if should_broadcast_commitment {
56205624
let (mut claimables, mut outputs) =
5621-
self.generate_claimable_outpoints_and_watch_outputs(None);
5625+
self.generate_claimable_outpoints_and_watch_outputs(None, false);
56225626
claimable_outpoints.append(&mut claimables);
56235627
watch_outputs.append(&mut outputs);
56245628
}
@@ -5660,9 +5664,13 @@ impl<Signer: EcdsaChannelSigner> ChannelMonitorImpl<Signer> {
56605664
if let Some(payment_hash) = should_broadcast {
56615665
let reason = ClosureReason::HTLCsTimedOut { payment_hash: Some(payment_hash) };
56625666
let (mut new_outpoints, mut new_outputs) =
5663-
self.generate_claimable_outpoints_and_watch_outputs(Some(reason));
5664-
claimable_outpoints.append(&mut new_outpoints);
5665-
watch_outputs.append(&mut new_outputs);
5667+
self.generate_claimable_outpoints_and_watch_outputs(Some(reason), false);
5668+
if !self.is_manual_broadcast || self.funding_seen_onchain {
5669+
claimable_outpoints.append(&mut new_outpoints);
5670+
watch_outputs.append(&mut new_outputs);
5671+
} else {
5672+
log_info!(logger, "Not broadcasting holder commitment for manual-broadcast channel before funding appears on-chain");
5673+
}
56665674
}
56675675
}
56685676

@@ -5969,7 +5977,7 @@ impl<Signer: EcdsaChannelSigner> ChannelMonitorImpl<Signer> {
59695977
/// Filters a block's `txdata` for transactions spending watched outputs or for any child
59705978
/// transactions thereof.
59715979
#[rustfmt::skip]
5972-
fn filter_block<'a>(&mut self, txdata: &TransactionData<'a>) -> Vec<&'a Transaction> {
5980+
fn filter_block<'a>(&self, txdata: &TransactionData<'a>) -> Vec<&'a Transaction> {
59735981
let mut matched_txn = new_hash_set();
59745982
txdata.iter().filter(|&&(_, tx)| {
59755983
let mut matches = self.spends_watched_output(tx);

lightning/src/ln/functional_test_utils.rs

Lines changed: 75 additions & 12 deletions
Original file line numberDiff line numberDiff line change
@@ -1576,14 +1576,10 @@ pub fn open_zero_conf_channel<'a, 'b, 'c, 'd>(
15761576
open_zero_conf_channel_with_value(initiator, receiver, initiator_config, 100_000, 10_001)
15771577
}
15781578

1579-
// Receiver must have been initialized with manually_accept_inbound_channels set to true.
1580-
pub fn open_zero_conf_channel_with_value<'a, 'b, 'c, 'd>(
1579+
pub fn exchange_open_accept_zero_conf_chan<'a, 'b, 'c, 'd>(
15811580
initiator: &'a Node<'b, 'c, 'd>, receiver: &'a Node<'b, 'c, 'd>,
15821581
initiator_config: Option<UserConfig>, channel_value_sat: u64, push_msat: u64,
1583-
) -> (bitcoin::Transaction, ChannelId) {
1584-
let initiator_channels = initiator.node.list_usable_channels().len();
1585-
let receiver_channels = receiver.node.list_usable_channels().len();
1586-
1582+
) -> ChannelId {
15871583
let receiver_node_id = receiver.node.get_our_node_id();
15881584
let initiator_node_id = initiator.node.get_our_node_id();
15891585

@@ -1617,6 +1613,28 @@ pub fn open_zero_conf_channel_with_value<'a, 'b, 'c, 'd>(
16171613
assert_eq!(accept_channel.common_fields.minimum_depth, 0);
16181614
initiator.node.handle_accept_channel(receiver_node_id, &accept_channel);
16191615

1616+
accept_channel.common_fields.temporary_channel_id
1617+
}
1618+
1619+
// Receiver must have been initialized with manually_accept_inbound_channels set to true.
1620+
pub fn open_zero_conf_channel_with_value<'a, 'b, 'c, 'd>(
1621+
initiator: &'a Node<'b, 'c, 'd>, receiver: &'a Node<'b, 'c, 'd>,
1622+
initiator_config: Option<UserConfig>, channel_value_sat: u64, push_msat: u64,
1623+
) -> (bitcoin::Transaction, ChannelId) {
1624+
let initiator_channels = initiator.node.list_usable_channels().len();
1625+
let receiver_channels = receiver.node.list_usable_channels().len();
1626+
1627+
let receiver_node_id = receiver.node.get_our_node_id();
1628+
let initiator_node_id = initiator.node.get_our_node_id();
1629+
1630+
exchange_open_accept_zero_conf_chan(
1631+
initiator,
1632+
receiver,
1633+
initiator_config,
1634+
channel_value_sat,
1635+
push_msat,
1636+
);
1637+
16201638
let (temporary_channel_id, tx, _) =
16211639
create_funding_transaction(&initiator, &receiver_node_id, channel_value_sat, 42);
16221640
initiator
@@ -1806,14 +1824,18 @@ pub fn create_chan_between_nodes_with_value_a<'a, 'b, 'c: 'd, 'd>(
18061824

18071825
pub fn create_channel_manual_funding<'a, 'b, 'c: 'd, 'd>(
18081826
nodes: &'a Vec<Node<'b, 'c, 'd>>, initiator: usize, counterparty: usize, channel_value: u64,
1809-
push_msat: u64,
1827+
push_msat: u64, zero_conf: bool,
18101828
) -> (ChannelId, Transaction, OutPoint) {
18111829
let node_a = &nodes[initiator];
18121830
let node_b = &nodes[counterparty];
18131831
let node_a_id = node_a.node.get_our_node_id();
18141832
let node_b_id = node_b.node.get_our_node_id();
18151833

1816-
let temp_channel_id = exchange_open_accept_chan(node_a, node_b, channel_value, push_msat);
1834+
let temp_channel_id = if zero_conf {
1835+
exchange_open_accept_zero_conf_chan(node_a, node_b, None, channel_value, push_msat)
1836+
} else {
1837+
exchange_open_accept_chan(node_a, node_b, channel_value, push_msat)
1838+
};
18171839

18181840
let (funding_temp_id, funding_tx, funding_outpoint) =
18191841
create_funding_transaction(node_a, &node_b_id, channel_value, 42);
@@ -1834,12 +1856,39 @@ pub fn create_channel_manual_funding<'a, 'b, 'c: 'd, 'd>(
18341856
check_added_monitors!(node_b, 1);
18351857
let channel_id_b = expect_channel_pending_event(node_b, &node_a_id);
18361858

1837-
let funding_signed = get_event_msg!(node_b, MessageSendEvent::SendFundingSigned, node_a_id);
1838-
node_a.node.handle_funding_signed(node_b_id, &funding_signed);
1839-
check_added_monitors!(node_a, 1);
1859+
if zero_conf {
1860+
let bs_signed_locked = node_b.node.get_and_clear_pending_msg_events();
1861+
assert_eq!(bs_signed_locked.len(), 2);
1862+
match &bs_signed_locked[0] {
1863+
MessageSendEvent::SendFundingSigned { node_id, msg } => {
1864+
assert_eq!(*node_id, node_a_id);
1865+
node_a.node.handle_funding_signed(node_b_id, &msg);
1866+
check_added_monitors(node_a, 1);
1867+
1868+
assert!(node_a.tx_broadcaster.txn_broadcast().is_empty());
1869+
1870+
let as_channel_ready =
1871+
get_event_msg!(node_a, MessageSendEvent::SendChannelReady, node_b_id);
1872+
node_b.node.handle_channel_ready(node_a_id, &as_channel_ready);
1873+
expect_channel_ready_event(node_b, &node_a_id);
1874+
},
1875+
_ => panic!("Unexpected event"),
1876+
}
1877+
match &bs_signed_locked[1] {
1878+
MessageSendEvent::SendChannelReady { node_id, msg } => {
1879+
assert_eq!(*node_id, node_a_id);
1880+
node_a.node.handle_channel_ready(node_b_id, &msg);
1881+
},
1882+
_ => panic!("Unexpected event"),
1883+
}
1884+
} else {
1885+
let funding_signed = get_event_msg!(node_b, MessageSendEvent::SendFundingSigned, node_a_id);
1886+
node_a.node.handle_funding_signed(node_b_id, &funding_signed);
1887+
check_added_monitors(node_a, 1)
1888+
}
18401889

18411890
let events = node_a.node.get_and_clear_pending_events();
1842-
assert_eq!(events.len(), 2);
1891+
assert_eq!(events.len(), if zero_conf { 3 } else { 2 });
18431892
let funding_txid = funding_tx.compute_txid();
18441893
let mut channel_id = None;
18451894
for event in events {
@@ -1853,6 +1902,10 @@ pub fn create_channel_manual_funding<'a, 'b, 'c: 'd, 'd>(
18531902
assert_eq!(counterparty_node_id, node_b_id);
18541903
channel_id = Some(pending_id);
18551904
},
1905+
Event::ChannelReady { channel_id: pending_id, counterparty_node_id, .. } => {
1906+
assert_eq!(counterparty_node_id, node_b_id);
1907+
channel_id = Some(pending_id);
1908+
},
18561909
_ => panic!("Unexpected event"),
18571910
}
18581911
}
@@ -1861,6 +1914,16 @@ pub fn create_channel_manual_funding<'a, 'b, 'c: 'd, 'd>(
18611914

18621915
assert!(node_a.tx_broadcaster.txn_broadcasted.lock().unwrap().is_empty());
18631916

1917+
if zero_conf {
1918+
let as_channel_update =
1919+
get_event_msg!(node_a, MessageSendEvent::SendChannelUpdate, node_b_id);
1920+
let bs_channel_update =
1921+
get_event_msg!(node_b, MessageSendEvent::SendChannelUpdate, node_a_id);
1922+
1923+
node_a.node.handle_channel_update(node_b_id, &bs_channel_update);
1924+
node_b.node.handle_channel_update(node_a_id, &as_channel_update);
1925+
}
1926+
18641927
(channel_id, funding_tx, funding_outpoint)
18651928
}
18661929

0 commit comments

Comments
 (0)