Skip to content

Commit bf6a53e

Browse files
authored
Merge pull request #3275 from TheBlueMatt/2024-08-3259-followups
#3259 followups
2 parents a978076 + ea646ae commit bf6a53e

File tree

4 files changed

+63
-12
lines changed

4 files changed

+63
-12
lines changed

lightning/src/ln/channel.rs

+7
Original file line numberDiff line numberDiff line change
@@ -936,6 +936,7 @@ pub(crate) struct ShutdownResult {
936936
pub(crate) user_channel_id: u128,
937937
pub(crate) channel_capacity_satoshis: u64,
938938
pub(crate) counterparty_node_id: PublicKey,
939+
pub(crate) is_manual_broadcast: bool,
939940
pub(crate) unbroadcasted_funding_tx: Option<Transaction>,
940941
pub(crate) channel_funding_txo: Option<OutPoint>,
941942
}
@@ -3457,6 +3458,9 @@ impl<SP: Deref> ChannelContext<SP> where SP::Target: SignerProvider {
34573458

34583459
/// Returns the transaction if there is a pending funding transaction that is yet to be
34593460
/// broadcast.
3461+
///
3462+
/// Note that if [`Self::is_manual_broadcast`] is true the transaction will be a dummy
3463+
/// transaction.
34603464
pub fn unbroadcasted_funding(&self) -> Option<Transaction> {
34613465
self.if_unbroadcasted_funding(|| self.funding_transaction.clone())
34623466
}
@@ -3537,6 +3541,7 @@ impl<SP: Deref> ChannelContext<SP> where SP::Target: SignerProvider {
35373541
channel_capacity_satoshis: self.channel_value_satoshis,
35383542
counterparty_node_id: self.counterparty_node_id,
35393543
unbroadcasted_funding_tx,
3544+
is_manual_broadcast: self.is_manual_broadcast,
35403545
channel_funding_txo: self.get_funding_txo(),
35413546
}
35423547
}
@@ -6240,6 +6245,7 @@ impl<SP: Deref> Channel<SP> where
62406245
channel_capacity_satoshis: self.context.channel_value_satoshis,
62416246
counterparty_node_id: self.context.counterparty_node_id,
62426247
unbroadcasted_funding_tx: self.context.unbroadcasted_funding(),
6248+
is_manual_broadcast: self.context.is_manual_broadcast,
62436249
channel_funding_txo: self.context.get_funding_txo(),
62446250
};
62456251
let tx = self.build_signed_closing_transaction(&mut closing_tx, &msg.signature, &sig);
@@ -6272,6 +6278,7 @@ impl<SP: Deref> Channel<SP> where
62726278
channel_capacity_satoshis: self.context.channel_value_satoshis,
62736279
counterparty_node_id: self.context.counterparty_node_id,
62746280
unbroadcasted_funding_tx: self.context.unbroadcasted_funding(),
6281+
is_manual_broadcast: self.context.is_manual_broadcast,
62756282
channel_funding_txo: self.context.get_funding_txo(),
62766283
};
62776284
if closing_signed.is_some() {

lightning/src/ln/channelmanager.rs

+9-11
Original file line numberDiff line numberDiff line change
@@ -3510,7 +3510,6 @@ where
35103510
let _ = self.chain_monitor.update_channel(funding_txo, &monitor_update);
35113511
}
35123512
let mut shutdown_results = Vec::new();
3513-
let mut is_manual_broadcast = false;
35143513
if let Some(txid) = shutdown_res.unbroadcasted_batch_funding_txid {
35153514
let mut funding_batch_states = self.funding_batch_states.lock().unwrap();
35163515
let affected_channels = funding_batch_states.remove(&txid).into_iter().flatten();
@@ -3520,10 +3519,6 @@ where
35203519
if let Some(peer_state_mutex) = per_peer_state.get(&counterparty_node_id) {
35213520
let mut peer_state = peer_state_mutex.lock().unwrap();
35223521
if let Some(mut chan) = peer_state.channel_by_id.remove(&channel_id) {
3523-
// We override the previous value, so we could change from true -> false,
3524-
// but this is fine because if a channel has manual_broadcast set to false
3525-
// we should choose the safier condition.
3526-
is_manual_broadcast = chan.context().is_manual_broadcast();
35273522
update_maps_on_chan_removal!(self, &chan.context());
35283523
shutdown_results.push(chan.context_mut().force_shutdown(false, ClosureReason::FundingBatchClosure));
35293524
}
@@ -3547,12 +3542,15 @@ where
35473542
channel_funding_txo: shutdown_res.channel_funding_txo,
35483543
}, None));
35493544

3550-
let funding_info = if is_manual_broadcast {
3551-
shutdown_res.channel_funding_txo.map(|outpoint| FundingInfo::OutPoint{ outpoint })
3552-
} else {
3553-
shutdown_res.unbroadcasted_funding_tx.map(|transaction| FundingInfo::Tx{ transaction })
3554-
};
3555-
if let Some(funding_info) = funding_info {
3545+
if let Some(transaction) = shutdown_res.unbroadcasted_funding_tx {
3546+
let funding_info = if shutdown_res.is_manual_broadcast {
3547+
FundingInfo::OutPoint {
3548+
outpoint: shutdown_res.channel_funding_txo
3549+
.expect("We had an unbroadcasted funding tx, so should also have had a funding outpoint"),
3550+
}
3551+
} else {
3552+
FundingInfo::Tx{ transaction }
3553+
};
35563554
pending_events.push_back((events::Event::DiscardFunding {
35573555
channel_id: shutdown_res.channel_id, funding_info
35583556
}, None));

lightning/src/ln/functional_tests.rs

+43-1
Original file line numberDiff line numberDiff line change
@@ -18,7 +18,7 @@ use crate::chain::channelmonitor;
1818
use crate::chain::channelmonitor::{CLOSED_CHANNEL_UPDATE_ID, CLTV_CLAIM_BUFFER, LATENCY_GRACE_PERIOD_BLOCKS, ANTI_REORG_DELAY};
1919
use crate::chain::transaction::OutPoint;
2020
use crate::sign::{ecdsa::EcdsaChannelSigner, EntropySource, OutputSpender, SignerProvider};
21-
use crate::events::{Event, MessageSendEvent, MessageSendEventsProvider, PathFailure, PaymentPurpose, ClosureReason, HTLCDestination, PaymentFailureReason};
21+
use crate::events::{Event, FundingInfo, MessageSendEvent, MessageSendEventsProvider, PathFailure, PaymentPurpose, ClosureReason, HTLCDestination, PaymentFailureReason};
2222
use crate::ln::types::{ChannelId, PaymentPreimage, PaymentSecret, PaymentHash};
2323
use crate::ln::channel::{CONCURRENT_INBOUND_HTLC_FEE_BUFFER, FEE_SPIKE_BUFFER_FEE_INCREASE_MULTIPLE, MIN_AFFORDABLE_HTLC_COUNT, get_holder_selected_channel_reserve_satoshis, OutboundV1Channel, InboundV1Channel, COINBASE_MATURITY, ChannelPhase};
2424
use crate::ln::channelmanager::{self, PaymentId, RAACommitmentOrder, PaymentSendFailure, RecipientOnionFields, BREAKDOWN_TIMEOUT, ENABLE_GOSSIP_TICKS, DISABLE_GOSSIP_TICKS, MIN_CLTV_EXPIRY_DELTA};
@@ -11209,6 +11209,48 @@ fn test_accept_inbound_channel_errors_queued() {
1120911209
open_channel_msg.common_fields.temporary_channel_id);
1121011210
}
1121111211

11212+
#[test]
11213+
fn test_manual_funding_abandon() {
11214+
let mut cfg = UserConfig::default();
11215+
cfg.channel_handshake_config.minimum_depth = 1;
11216+
let chanmon_cfgs = create_chanmon_cfgs(2);
11217+
let node_cfgs = create_node_cfgs(2, &chanmon_cfgs);
11218+
let node_chanmgrs = create_node_chanmgrs(2, &node_cfgs, &[Some(cfg), Some(cfg)]);
11219+
let nodes = create_network(2, &node_cfgs, &node_chanmgrs);
11220+
11221+
assert!(nodes[0].node.create_channel(nodes[1].node.get_our_node_id(), 100_000, 0, 42, None, None).is_ok());
11222+
let open_channel = get_event_msg!(nodes[0], MessageSendEvent::SendOpenChannel, nodes[1].node.get_our_node_id());
11223+
11224+
nodes[1].node.handle_open_channel(&nodes[0].node.get_our_node_id(), &open_channel);
11225+
let accept_channel = get_event_msg!(nodes[1], MessageSendEvent::SendAcceptChannel, nodes[0].node.get_our_node_id());
11226+
11227+
nodes[0].node.handle_accept_channel(&nodes[1].node.get_our_node_id(), &accept_channel);
11228+
let (temporary_channel_id, _tx, funding_outpoint) = create_funding_transaction(&nodes[0], &nodes[1].node.get_our_node_id(), 100_000, 42);
11229+
nodes[0].node.unsafe_manual_funding_transaction_generated(temporary_channel_id, nodes[1].node.get_our_node_id(), funding_outpoint).unwrap();
11230+
check_added_monitors!(nodes[0], 0);
11231+
11232+
let funding_created = get_event_msg!(nodes[0], MessageSendEvent::SendFundingCreated, nodes[1].node.get_our_node_id());
11233+
nodes[1].node.handle_funding_created(&nodes[0].node.get_our_node_id(), &funding_created);
11234+
check_added_monitors!(nodes[1], 1);
11235+
expect_channel_pending_event(&nodes[1], &nodes[0].node.get_our_node_id());
11236+
11237+
let funding_signed = get_event_msg!(nodes[1], MessageSendEvent::SendFundingSigned, nodes[0].node.get_our_node_id());
11238+
let err = msgs::ErrorMessage { channel_id: funding_signed.channel_id, data: "".to_string() };
11239+
nodes[0].node.handle_error(&nodes[1].node.get_our_node_id(), &err);
11240+
11241+
let close_events = nodes[0].node.get_and_clear_pending_events();
11242+
assert_eq!(close_events.len(), 2);
11243+
assert!(close_events.iter().any(|ev| matches!(ev, Event::ChannelClosed { .. })));
11244+
assert!(close_events.iter().any(|ev| match ev {
11245+
Event::DiscardFunding { channel_id, funding_info: FundingInfo::OutPoint { outpoint } } => {
11246+
assert_eq!(*channel_id, err.channel_id);
11247+
assert_eq!(*outpoint, funding_outpoint);
11248+
true
11249+
}
11250+
_ => false,
11251+
}));
11252+
}
11253+
1121211254
#[test]
1121311255
fn test_funding_signed_event() {
1121411256
let mut cfg = UserConfig::default();
+4
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,4 @@
1+
# Backwards Compatibility
2+
* Downgrading after using `ChannelManager`'s
3+
`unsafe_manual_funding_transaction_generated` may cause deserialization of
4+
`ChannelManager` to fail with an `Err` (#3259).

0 commit comments

Comments
 (0)