Skip to content

Commit 4a06790

Browse files
committed
Add FundingTxBroadcastSafe event
The `FundingTxBroadcastSafe` event indicates that we have received `funding_signed` message from our counterparty and that you should broadcast the funding transaction. This event is only emitted if upon generating the funding transaction you call `ChannelManager::unsafe_manual_funding_transaction_generated` that will emit this event instead of `ChannelPending` event. `ChannelManager::unsafe_manual_funding_transaction_generated` wont check if the funding transaction is signed, those its unsafe. It is manual because you are responsibile on broadcasting the transaction once the event is received.
1 parent 737df0f commit 4a06790

File tree

5 files changed

+304
-6
lines changed

5 files changed

+304
-6
lines changed

lightning/src/events/mod.rs

Lines changed: 63 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -579,6 +579,37 @@ pub enum Event {
579579
/// [`UserConfig::manually_accept_inbound_channels`]: crate::util::config::UserConfig::manually_accept_inbound_channels
580580
user_channel_id: u128,
581581
},
582+
/// Used to indicate that the counterparty node has provided the signature(s) required to
583+
/// recover our funds in case they go offline.
584+
///
585+
/// It is safe (and your responsibility) to broadcast the funding transaction upon receiving this
586+
/// event.
587+
///
588+
/// This event is only emitted if you called
589+
/// [`ChannelManager::unsafe_manual_funding_transaction_generated`] instead of
590+
/// [`ChannelManager::funding_transaction_generated`].
591+
///
592+
/// [`ChannelManager::unsafe_manual_funding_transaction_generated`]: crate::ln::channelmanager::ChannelManager::unsafe_manual_funding_transaction_generated
593+
/// [`ChannelManager::funding_transaction_generated`]: crate::ln::channelmanager::ChannelManager::funding_transaction_generated
594+
FundingTxBroadcastSafe {
595+
/// The `channel_id` indicating which channel has reached this stage.
596+
channel_id: ChannelId,
597+
/// The `user_channel_id` value passed in to [`ChannelManager::create_channel`] for outbound
598+
/// channels, or to [`ChannelManager::accept_inbound_channel`] for inbound channels if
599+
/// [`UserConfig::manually_accept_inbound_channels`] config flag is set to true. Otherwise
600+
/// `user_channel_id` will be randomized for an inbound channel.
601+
///
602+
/// [`ChannelManager::create_channel`]: crate::ln::channelmanager::ChannelManager::create_channel
603+
/// [`ChannelManager::accept_inbound_channel`]: crate::ln::channelmanager::ChannelManager::accept_inbound_channel
604+
/// [`UserConfig::manually_accept_inbound_channels`]: crate::util::config::UserConfig::manually_accept_inbound_channels
605+
user_channel_id: u128,
606+
/// Channel funding transaction
607+
funding_tx: Transaction,
608+
/// The `node_id` of the channel counterparty.
609+
counterparty_node_id: PublicKey,
610+
/// The `temporary_channel_id` this channel used to be known by during channel establishment.
611+
former_temporary_channel_id: ChannelId,
612+
},
582613
/// Indicates that we've been offered a payment and it needs to be claimed via calling
583614
/// [`ChannelManager::claim_funds`] with the preimage given in [`PaymentPurpose`].
584615
///
@@ -1526,7 +1557,17 @@ impl Writeable for Event {
15261557
(0, payment_id, required),
15271558
(2, invoice, required),
15281559
(4, responder, option),
1529-
})
1560+
});
1561+
},
1562+
&Event::FundingTxBroadcastSafe { ref channel_id, ref user_channel_id, ref funding_tx, ref counterparty_node_id, ref former_temporary_channel_id} => {
1563+
43u8.write(writer)?;
1564+
write_tlv_fields!(writer, {
1565+
(0, channel_id, required),
1566+
(2, user_channel_id, required),
1567+
(4, funding_tx, required),
1568+
(6, counterparty_node_id, required),
1569+
(8, former_temporary_channel_id, required),
1570+
});
15301571
},
15311572
// Note that, going forward, all new events must only write data inside of
15321573
// `write_tlv_fields`. Versions 0.0.101+ will ignore odd-numbered events that write
@@ -1979,6 +2020,27 @@ impl MaybeReadable for Event {
19792020
};
19802021
f()
19812022
},
2023+
43u8 => {
2024+
let mut channel_id = RequiredWrapper(None);
2025+
let mut user_channel_id = RequiredWrapper(None);
2026+
let mut funding_tx = RequiredWrapper(None);
2027+
let mut counterparty_node_id = RequiredWrapper(None);
2028+
let mut former_temporary_channel_id = RequiredWrapper(None);
2029+
read_tlv_fields!(reader, {
2030+
(0, channel_id, required),
2031+
(2, user_channel_id, required),
2032+
(4, funding_tx, required),
2033+
(6, counterparty_node_id, required),
2034+
(8, former_temporary_channel_id, required)
2035+
});
2036+
Ok(Some(Event::FundingTxBroadcastSafe {
2037+
channel_id: channel_id.0.unwrap(),
2038+
user_channel_id: user_channel_id.0.unwrap(),
2039+
funding_tx: funding_tx.0.unwrap(),
2040+
counterparty_node_id: counterparty_node_id.0.unwrap(),
2041+
former_temporary_channel_id: former_temporary_channel_id.0.unwrap(),
2042+
}))
2043+
},
19822044
// Versions prior to 0.0.100 did not ignore odd types, instead returning InvalidValue.
19832045
// Version 0.0.100 failed to properly ignore odd types, possibly resulting in corrupt
19842046
// reads.

lightning/src/ln/channel.rs

Lines changed: 51 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1419,6 +1419,9 @@ pub(super) struct ChannelContext<SP: Deref> where SP::Target: SignerProvider {
14191419
// We track whether we already emitted a `ChannelPending` event.
14201420
channel_pending_event_emitted: bool,
14211421

1422+
// We track whether we already emitted a `FundingTxBroadcastSafe` event.
1423+
funding_tx_broadcast_safe_event_emitted: bool,
1424+
14221425
// We track whether we already emitted a `ChannelReady` event.
14231426
channel_ready_event_emitted: bool,
14241427

@@ -1435,6 +1438,14 @@ pub(super) struct ChannelContext<SP: Deref> where SP::Target: SignerProvider {
14351438
/// If we can't release a [`ChannelMonitorUpdate`] until some external action completes, we
14361439
/// store it here and only release it to the `ChannelManager` once it asks for it.
14371440
blocked_monitor_updates: Vec<PendingChannelMonitorUpdate>,
1441+
1442+
/// Using this flag will prevent the funding transaction from being broadcasted
1443+
/// and will allow the user to manually broadcast it.
1444+
///
1445+
/// The funding transaction can be accessed through the [`Event::FundingTxBroadcastSafe`] event.
1446+
///
1447+
/// [`Event::FundingTxBroadcastSafe`]: crate::events::Event::FundingTxBroadcastSafe
1448+
is_manual_broadcast: bool,
14381449
}
14391450

14401451
impl<SP: Deref> ChannelContext<SP> where SP::Target: SignerProvider {
@@ -1758,6 +1769,7 @@ impl<SP: Deref> ChannelContext<SP> where SP::Target: SignerProvider {
17581769
outbound_scid_alias: 0,
17591770

17601771
channel_pending_event_emitted: false,
1772+
funding_tx_broadcast_safe_event_emitted: false,
17611773
channel_ready_event_emitted: false,
17621774

17631775
#[cfg(any(test, fuzzing))]
@@ -1769,6 +1781,8 @@ impl<SP: Deref> ChannelContext<SP> where SP::Target: SignerProvider {
17691781
local_initiated_shutdown: None,
17701782

17711783
blocked_monitor_updates: Vec::new(),
1784+
1785+
is_manual_broadcast: false,
17721786
};
17731787

17741788
Ok(channel_context)
@@ -1982,6 +1996,7 @@ impl<SP: Deref> ChannelContext<SP> where SP::Target: SignerProvider {
19821996
outbound_scid_alias,
19831997

19841998
channel_pending_event_emitted: false,
1999+
funding_tx_broadcast_safe_event_emitted: false,
19852000
channel_ready_event_emitted: false,
19862001

19872002
#[cfg(any(test, fuzzing))]
@@ -1992,6 +2007,7 @@ impl<SP: Deref> ChannelContext<SP> where SP::Target: SignerProvider {
19922007

19932008
blocked_monitor_updates: Vec::new(),
19942009
local_initiated_shutdown: None,
2010+
is_manual_broadcast: false,
19952011
})
19962012
}
19972013

@@ -2370,6 +2386,10 @@ impl<SP: Deref> ChannelContext<SP> where SP::Target: SignerProvider {
23702386
self.config.options.forwarding_fee_proportional_millionths
23712387
}
23722388

2389+
pub fn is_manual_broadcast(&self) -> bool {
2390+
self.is_manual_broadcast
2391+
}
2392+
23732393
pub fn get_cltv_expiry_delta(&self) -> u16 {
23742394
cmp::max(self.config.options.cltv_expiry_delta, MIN_CLTV_EXPIRY_DELTA)
23752395
}
@@ -2404,6 +2424,11 @@ impl<SP: Deref> ChannelContext<SP> where SP::Target: SignerProvider {
24042424
self.channel_pending_event_emitted
24052425
}
24062426

2427+
// Returns whether we already emitted a `FundingTxBroadcastSafe` event.
2428+
pub(crate) fn funding_tx_broadcast_safe_event_emitted(&self) -> bool {
2429+
self.funding_tx_broadcast_safe_event_emitted
2430+
}
2431+
24072432
// Remembers that we already emitted a `ChannelPending` event.
24082433
pub(crate) fn set_channel_pending_event_emitted(&mut self) {
24092434
self.channel_pending_event_emitted = true;
@@ -2419,6 +2444,11 @@ impl<SP: Deref> ChannelContext<SP> where SP::Target: SignerProvider {
24192444
self.channel_ready_event_emitted = true;
24202445
}
24212446

2447+
// Remembers that we already emitted a `FundingTxBroadcastSafe` event.
2448+
pub(crate) fn set_funding_tx_broadcast_safe_event_emitted(&mut self) {
2449+
self.funding_tx_broadcast_safe_event_emitted = true;
2450+
}
2451+
24222452
/// Tracks the number of ticks elapsed since the previous [`ChannelConfig`] was updated. Once
24232453
/// [`EXPIRE_PREV_CONFIG_TICKS`] is reached, the previous config is considered expired and will
24242454
/// no longer be considered when forwarding HTLCs.
@@ -2455,6 +2485,17 @@ impl<SP: Deref> ChannelContext<SP> where SP::Target: SignerProvider {
24552485
did_channel_update
24562486
}
24572487

2488+
/// Marking the channel as manual broadcast is used in order to prevent LDK from automatically
2489+
/// broadcasting the funding transaction.
2490+
///
2491+
/// This is useful if you wish to get hold of the funding transaction before it is broadcasted
2492+
/// via [`Event::FundingTxBroadcastSafe`] event.
2493+
///
2494+
/// [`Event::FundingTxBroadcastSafe`]: crate::events::Event::FundingTxBroadcastSafe
2495+
pub fn set_manual_broadcast(&mut self) {
2496+
self.is_manual_broadcast = true;
2497+
}
2498+
24582499
/// Returns true if funding_signed was sent/received and the
24592500
/// funding transaction has been broadcast if necessary.
24602501
pub fn is_funding_broadcast(&self) -> bool {
@@ -8705,6 +8746,7 @@ impl<SP: Deref> Writeable for Channel<SP> where SP::Target: SignerProvider {
87058746

87068747
let channel_pending_event_emitted = Some(self.context.channel_pending_event_emitted);
87078748
let channel_ready_event_emitted = Some(self.context.channel_ready_event_emitted);
8749+
let funding_tx_broadcast_safe_event_emitted = Some(self.context.funding_tx_broadcast_safe_event_emitted);
87088750

87098751
// `user_id` used to be a single u64 value. In order to remain backwards compatible with
87108752
// versions prior to 0.0.113, the u128 is serialized as two separate u64 values. Therefore,
@@ -8717,6 +8759,7 @@ impl<SP: Deref> Writeable for Channel<SP> where SP::Target: SignerProvider {
87178759
if !self.context.monitor_pending_update_adds.is_empty() {
87188760
monitor_pending_update_adds = Some(&self.context.monitor_pending_update_adds);
87198761
}
8762+
let is_manual_broadcast = Some(self.context.is_manual_broadcast);
87208763

87218764
// `current_point` will become optional when async signing is implemented.
87228765
let cur_holder_commitment_point = Some(self.context.holder_commitment_point.current_point());
@@ -8761,6 +8804,8 @@ impl<SP: Deref> Writeable for Channel<SP> where SP::Target: SignerProvider {
87618804
(45, cur_holder_commitment_point, option),
87628805
(47, next_holder_commitment_point, option),
87638806
(49, self.context.local_initiated_shutdown, option), // Added in 0.0.122
8807+
(51, is_manual_broadcast, option),
8808+
(53, funding_tx_broadcast_safe_event_emitted, option)
87648809
});
87658810

87668811
Ok(())
@@ -9049,6 +9094,7 @@ impl<'a, 'b, 'c, ES: Deref, SP: Deref> ReadableArgs<(&'a ES, &'b SP, u32, &'c Ch
90499094
let mut outbound_scid_alias = None;
90509095
let mut channel_pending_event_emitted = None;
90519096
let mut channel_ready_event_emitted = None;
9097+
let mut funding_tx_broadcast_safe_event_emitted = None;
90529098

90539099
let mut user_id_high_opt: Option<u64> = None;
90549100
let mut channel_keys_id: Option<[u8; 32]> = None;
@@ -9072,6 +9118,7 @@ impl<'a, 'b, 'c, ES: Deref, SP: Deref> ReadableArgs<(&'a ES, &'b SP, u32, &'c Ch
90729118

90739119
let mut cur_holder_commitment_point_opt: Option<PublicKey> = None;
90749120
let mut next_holder_commitment_point_opt: Option<PublicKey> = None;
9121+
let mut is_manual_broadcast = None;
90759122

90769123
read_tlv_fields!(reader, {
90779124
(0, announcement_sigs, option),
@@ -9106,6 +9153,8 @@ impl<'a, 'b, 'c, ES: Deref, SP: Deref> ReadableArgs<(&'a ES, &'b SP, u32, &'c Ch
91069153
(45, cur_holder_commitment_point_opt, option),
91079154
(47, next_holder_commitment_point_opt, option),
91089155
(49, local_initiated_shutdown, option),
9156+
(51, is_manual_broadcast, option),
9157+
(53, funding_tx_broadcast_safe_event_emitted, option),
91099158
});
91109159

91119160
let (channel_keys_id, holder_signer) = if let Some(channel_keys_id) = channel_keys_id {
@@ -9346,6 +9395,7 @@ impl<'a, 'b, 'c, ES: Deref, SP: Deref> ReadableArgs<(&'a ES, &'b SP, u32, &'c Ch
93469395
// Later in the ChannelManager deserialization phase we scan for channels and assign scid aliases if its missing
93479396
outbound_scid_alias: outbound_scid_alias.unwrap_or(0),
93489397

9398+
funding_tx_broadcast_safe_event_emitted: funding_tx_broadcast_safe_event_emitted.unwrap_or(false),
93499399
channel_pending_event_emitted: channel_pending_event_emitted.unwrap_or(true),
93509400
channel_ready_event_emitted: channel_ready_event_emitted.unwrap_or(true),
93519401

@@ -9358,6 +9408,7 @@ impl<'a, 'b, 'c, ES: Deref, SP: Deref> ReadableArgs<(&'a ES, &'b SP, u32, &'c Ch
93589408
local_initiated_shutdown,
93599409

93609410
blocked_monitor_updates: blocked_monitor_updates.unwrap(),
9411+
is_manual_broadcast: is_manual_broadcast.unwrap_or(false),
93619412
},
93629413
#[cfg(any(dual_funding, splicing))]
93639414
dual_funding_channel_context: None,

lightning/src/ln/channelmanager.rs

Lines changed: 73 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -2567,6 +2567,20 @@ macro_rules! send_channel_ready {
25672567
}
25682568
}}
25692569
}
2570+
macro_rules! emit_funding_tx_broadcast_safe_event {
2571+
($locked_events: expr, $channel: expr, $funding_tx: expr) => {
2572+
if !$channel.context.funding_tx_broadcast_safe_event_emitted() {
2573+
$locked_events.push_back((events::Event::FundingTxBroadcastSafe {
2574+
channel_id: $channel.context.channel_id(),
2575+
user_channel_id: $channel.context.get_user_id(),
2576+
funding_tx: $funding_tx,
2577+
counterparty_node_id: $channel.context.get_counterparty_node_id(),
2578+
former_temporary_channel_id: $channel.context.temporary_channel_id().expect("Unreachable: FundingTxBroadcastSafe event feature added to channel establishment process in LDK v0.124.0 where this should never be None."),
2579+
}, None));
2580+
$channel.context.set_funding_tx_broadcast_safe_event_emitted();
2581+
}
2582+
}
2583+
}
25702584

25712585
macro_rules! emit_channel_pending_event {
25722586
($locked_events: expr, $channel: expr) => {
@@ -4238,7 +4252,7 @@ where
42384252
/// which checks the correctness of the funding transaction given the associated channel.
42394253
fn funding_transaction_generated_intern<FundingOutput: FnMut(&OutboundV1Channel<SP>, &Transaction) -> Result<OutPoint, &'static str>>(
42404254
&self, temporary_channel_id: &ChannelId, counterparty_node_id: &PublicKey, funding_transaction: Transaction, is_batch_funding: bool,
4241-
mut find_funding_output: FundingOutput,
4255+
mut find_funding_output: FundingOutput, is_manual_broadcast: bool,
42424256
) -> Result<(), APIError> {
42434257
let per_peer_state = self.per_peer_state.read().unwrap();
42444258
let peer_state_mutex = per_peer_state.get(counterparty_node_id)
@@ -4302,6 +4316,9 @@ where
43024316
msg,
43034317
});
43044318
}
4319+
if is_manual_broadcast {
4320+
chan.context.set_manual_broadcast();
4321+
}
43054322
match peer_state.channel_by_id.entry(chan.context.channel_id()) {
43064323
hash_map::Entry::Occupied(_) => {
43074324
panic!("Generated duplicate funding txid?");
@@ -4333,7 +4350,7 @@ where
43334350
pub(crate) fn funding_transaction_generated_unchecked(&self, temporary_channel_id: &ChannelId, counterparty_node_id: &PublicKey, funding_transaction: Transaction, output_index: u16) -> Result<(), APIError> {
43344351
self.funding_transaction_generated_intern(temporary_channel_id, counterparty_node_id, funding_transaction, false, |_, tx| {
43354352
Ok(OutPoint { txid: tx.txid(), index: output_index })
4336-
})
4353+
}, false)
43374354
}
43384355

43394356
/// Call this upon creation of a funding transaction for the given channel.
@@ -4370,6 +4387,45 @@ where
43704387
self.batch_funding_transaction_generated(&[(temporary_channel_id, counterparty_node_id)], funding_transaction)
43714388
}
43724389

4390+
4391+
/// Unsafe: This method does not check the validatiy of the provided output. It is the
4392+
/// caller's responsibility to ensure that.
4393+
///
4394+
/// For a safer method, please refer to [`ChannelManager::funding_transaction_generated`].
4395+
///
4396+
/// Call this in response to a [`Event::FundingGenerationReady`] event.
4397+
///
4398+
/// Note that if this method is called successfully, the funding transaction won't be
4399+
/// broadcasted and you are expected to broadcast it manually when receiving the
4400+
/// [`Event::FundingTxBroadcastSafe`] event.
4401+
///
4402+
/// Returns an [`APIError::APIMisuseError`] if no output was found which matches the parameters
4403+
/// in [`Event::FundingGenerationReady`].
4404+
///
4405+
/// Returns [`APIError::ChannelUnavailable`] if a funding transaction has already been provided
4406+
/// for the channel or if the channel has been closed as indicated by [`Event::ChannelClosed`].
4407+
///
4408+
/// May panic if the output found in the funding transaction is duplicative with some other
4409+
/// channel (note that this should be trivially prevented by using unique funding transaction
4410+
/// keys per-channel).
4411+
///
4412+
/// Note to keep the miner incentives aligned in moving the blockchain forward, we recommend
4413+
/// the wallet software generating the funding transaction to apply anti-fee sniping as
4414+
/// implemented by Bitcoin Core wallet. See <https://bitcoinops.org/en/topics/fee-sniping/> for
4415+
/// more details.
4416+
///
4417+
/// [`Event::FundingGenerationReady`]: crate::events::Event::FundingGenerationReady
4418+
/// [`Event::FundingTxBroadcastSafe`]: crate::events::Event::FundingTxBroadcastSafe
4419+
/// [`Event::ChannelClosed`]: crate::events::Event::ChannelClosed
4420+
/// [`ChannelManager::funding_transaction_generated`]: crate::ln::channelmanager::ChannelManager::funding_transaction_generated
4421+
pub fn unsafe_manual_funding_transaction_generated(&self, temporary_channel_id: &ChannelId, counterparty_node_id: &PublicKey, funding_transaction: Transaction) -> Result<(), APIError> {
4422+
let _persistence_guard = PersistenceNotifierGuard::notify_on_drop(self);
4423+
4424+
let temporary_channels = &[(temporary_channel_id, counterparty_node_id)];
4425+
return self.batch_funding_transaction_generated_intern(temporary_channels, funding_transaction, true);
4426+
4427+
}
4428+
43734429
/// Call this upon creation of a batch funding transaction for the given channels.
43744430
///
43754431
/// Return values are identical to [`Self::funding_transaction_generated`], respective to
@@ -4393,6 +4449,11 @@ where
43934449
}
43944450
}
43954451
}
4452+
result.and(self.batch_funding_transaction_generated_intern(temporary_channels, funding_transaction, false))
4453+
}
4454+
4455+
fn batch_funding_transaction_generated_intern(&self, temporary_channels: &[(&ChannelId, &PublicKey)], funding_transaction: Transaction, is_manual_broadcast: bool) -> Result<(), APIError> {
4456+
let mut result = Ok(());
43964457
if funding_transaction.output.len() > u16::max_value() as usize {
43974458
result = result.and(Err(APIError::APIMisuseError {
43984459
err: "Transaction had more than 2^16 outputs, which is not supported".to_owned()
@@ -4460,7 +4521,8 @@ where
44604521
funding_batch_state.push((ChannelId::v1_from_funding_outpoint(outpoint), *counterparty_node_id, false));
44614522
}
44624523
Ok(outpoint)
4463-
})
4524+
},
4525+
is_manual_broadcast)
44644526
);
44654527
}
44664528
if let Err(ref e) = result {
@@ -6596,8 +6658,14 @@ where
65966658
}
65976659

65986660
if let Some(tx) = funding_broadcastable {
6599-
log_info!(logger, "Broadcasting funding transaction with txid {}", tx.txid());
6600-
self.tx_broadcaster.broadcast_transactions(&[&tx]);
6661+
if channel.context.is_manual_broadcast() {
6662+
log_info!(logger, "Not broadcasting funding transaction with txid {} as it is manually managed", tx.txid());
6663+
let mut pending_events = self.pending_events.lock().unwrap();
6664+
emit_funding_tx_broadcast_safe_event!(pending_events, channel, tx);
6665+
} else {
6666+
log_info!(logger, "Broadcasting funding transaction with txid {}", tx.txid());
6667+
self.tx_broadcaster.broadcast_transactions(&[&tx]);
6668+
}
66016669
}
66026670

66036671
{

0 commit comments

Comments
 (0)