Skip to content

Commit

Permalink
Add FundingSigned event
Browse files Browse the repository at this point in the history
  If `manually_broadcast_outbound_channels` is set, LDK will emit this
  event after the counterparty node send the `FundingSigned` msg without
  broadcasting the funding transaction.
  • Loading branch information
jbesraa committed Apr 25, 2024
1 parent 94801c7 commit 999fc5a
Show file tree
Hide file tree
Showing 5 changed files with 239 additions and 3 deletions.
44 changes: 44 additions & 0 deletions lightning/src/events/mod.rs
Original file line number Diff line number Diff line change
Expand Up @@ -497,6 +497,27 @@ impl_writeable_tlv_based_enum!(PaymentFailureReason,
/// written as it makes no sense to respond to it after reconnecting to peers).
#[derive(Clone, Debug, PartialEq, Eq)]
pub enum Event {
/// Used to indicate that the counterparty node has sent `FundingSigned` msg but we are yet to
/// broadcast the funding transaction.
///
/// After you receive this event, you should broadcast the funding transaction and then call
//// [`ChannelManager::funding_transaction_broadcasted`]. <-- not implemtened yet
/// // should we have some timeout for this?
//// [`ChannelManager::funding_transaction_broadcasted`]: crate::ln::channelmanager::ChannelManager::funding_transaction_broadcasted
FundingSigned {
/// The `channel_id` indicating which channel has completed the `FundingSigned` stage.
channel_id: ChannelId,
/// The `user_channel_id` value passed in to [`ChannelManager::create_channel`] for outbound
/// channels, or to [`ChannelManager::accept_inbound_channel`] for inbound channels if
/// [`UserConfig::manually_accept_inbound_channels`] config flag is set to true. Otherwise
/// `user_channel_id` will be randomized for an inbound channel. This may be zero for objects
/// serialized with LDK versions prior to 0.0.113.
///
/// [`ChannelManager::create_channel`]: crate::ln::channelmanager::ChannelManager::create_channel
/// [`ChannelManager::accept_inbound_channel`]: crate::ln::channelmanager::ChannelManager::accept_inbound_channel
/// [`UserConfig::manually_accept_inbound_channels`]: crate::util::config::UserConfig::manually_accept_inbound_channels
user_channel_id: u128,
},
/// Used to indicate that the client should generate a funding transaction with the given
/// parameters and then call [`ChannelManager::funding_transaction_generated`].
/// Generated in [`ChannelManager`] message handling.
Expand Down Expand Up @@ -1404,6 +1425,13 @@ impl Writeable for Event {
35u8.write(writer)?;
// Never write ConnectionNeeded events as buffered onion messages aren't serialized.
},
&Event::FundingSigned { ref channel_id, ref user_channel_id } => {
37u8.write(writer)?;
write_tlv_fields!(writer, {
(0, channel_id, required),
(2, user_channel_id, required),
});
},
// Note that, going forward, all new events must only write data inside of
// `write_tlv_fields`. Versions 0.0.101+ will ignore odd-numbered events that write
// data via `write_tlv_fields`.
Expand Down Expand Up @@ -1814,6 +1842,22 @@ impl MaybeReadable for Event {
},
// Note that we do not write a length-prefixed TLV for ConnectionNeeded events.
35u8 => Ok(None),
37u8 => {
let mut f = || {
let mut channel_id = ChannelId::new_zero();
let mut user_channel_id: u128 = 0;
read_tlv_fields!(reader, {
(0, channel_id, required),
(2, user_channel_id, required),
});

Ok(Some(Event::FundingSigned {
channel_id,
user_channel_id,
}))
};
f()
},
// Versions prior to 0.0.100 did not ignore odd types, instead returning InvalidValue.
// Version 0.0.100 failed to properly ignore odd types, possibly resulting in corrupt
// reads.
Expand Down
147 changes: 144 additions & 3 deletions lightning/src/ln/channel.rs
Original file line number Diff line number Diff line change
Expand Up @@ -646,6 +646,7 @@ mod state_flags {
pub const LOCAL_SHUTDOWN_SENT: u32 = 1 << 11;
pub const SHUTDOWN_COMPLETE: u32 = 1 << 12;
pub const WAITING_FOR_BATCH: u32 = 1 << 13;
pub const FUNDING_SIGNED: u32 = 1 << 14;
}

define_state_flags!(
Expand Down Expand Up @@ -681,6 +682,10 @@ define_state_flags!(
define_state_flags!(
"Flags that only apply to [`ChannelState::AwaitingChannelReady`].",
FUNDED_STATE, AwaitingChannelReadyFlags, [
("Indicates we sent them a `funding_created` message and received `funding_signed` message \
but the broadcasting is manually handled.",
FUNDING_SIGNED, state_flags::FUNDING_SIGNED,
is_funding_signed, set_funding_signed, clear_funding_signed),
("Indicates they sent us a `channel_ready` message. Once both `THEIR_CHANNEL_READY` and \
`OUR_CHANNEL_READY` are set, our state moves on to `ChannelReady`.",
THEIR_CHANNEL_READY, state_flags::THEIR_CHANNEL_READY,
Expand Down Expand Up @@ -835,6 +840,7 @@ impl ChannelState {
impl_state_flag!(is_their_channel_ready, set_their_channel_ready, clear_their_channel_ready, AwaitingChannelReady);
impl_state_flag!(is_waiting_for_batch, set_waiting_for_batch, clear_waiting_for_batch, AwaitingChannelReady);
impl_state_flag!(is_awaiting_remote_revoke, set_awaiting_remote_revoke, clear_awaiting_remote_revoke, ChannelReady);
impl_state_flag!(is_funding_signed, set_funding_signed, clear_funding_signed, AwaitingChannelReady);
}

pub const INITIAL_COMMITMENT_NUMBER: u64 = (1 << 48) - 1;
Expand Down Expand Up @@ -1524,6 +1530,9 @@ pub(super) struct ChannelContext<SP: Deref> where SP::Target: SignerProvider {

// We track whether we already emitted a `ChannelPending` event.
channel_pending_event_emitted: bool,

// We track whether we already emitted a `FundingSigned` event.
funding_signed_event_emitted: bool,

// We track whether we already emitted a `ChannelReady` event.
channel_ready_event_emitted: bool,
Expand Down Expand Up @@ -1871,6 +1880,7 @@ impl<SP: Deref> ChannelContext<SP> where SP::Target: SignerProvider {
outbound_scid_alias: 0,

channel_pending_event_emitted: false,
funding_signed_event_emitted: false,
channel_ready_event_emitted: false,

#[cfg(any(test, fuzzing))]
Expand Down Expand Up @@ -2094,6 +2104,7 @@ impl<SP: Deref> ChannelContext<SP> where SP::Target: SignerProvider {
outbound_scid_alias,

channel_pending_event_emitted: false,
funding_signed_event_emitted: false,
channel_ready_event_emitted: false,

#[cfg(any(test, fuzzing))]
Expand Down Expand Up @@ -2378,6 +2389,13 @@ impl<SP: Deref> ChannelContext<SP> where SP::Target: SignerProvider {
self.is_funding_broadcast() && !self.channel_pending_event_emitted
}

// Checks whether we should emit a `FundingSigned` event.
pub(crate) fn should_emit_funding_signed_event(&self) -> bool {
!self.is_funding_broadcast()
&& self.manually_broadcast_outbound_channels.is_some()
&& !self.funding_signed_event_emitted
}

// Returns whether we already emitted a `ChannelPending` event.
pub(crate) fn channel_pending_event_emitted(&self) -> bool {
self.channel_pending_event_emitted
Expand All @@ -2398,6 +2416,11 @@ impl<SP: Deref> ChannelContext<SP> where SP::Target: SignerProvider {
self.channel_ready_event_emitted = true;
}

// Remembers that we already emitted a `FundingSigned` event.
pub(crate) fn set_funding_signed_event_emitted(&mut self) {
self.funding_signed_event_emitted = true;
}

/// Tracks the number of ticks elapsed since the previous [`ChannelConfig`] was updated. Once
/// [`EXPIRE_PREV_CONFIG_TICKS`] is reached, the previous config is considered expired and will
/// no longer be considered when forwarding HTLCs.
Expand Down Expand Up @@ -2439,6 +2462,7 @@ impl<SP: Deref> ChannelContext<SP> where SP::Target: SignerProvider {
pub fn is_funding_broadcast(&self) -> bool {
!self.channel_state.is_pre_funded_state() &&
!matches!(self.channel_state, ChannelState::AwaitingChannelReady(flags) if flags.is_set(AwaitingChannelReadyFlags::WAITING_FOR_BATCH))
&& !matches!(self.channel_state, ChannelState::AwaitingChannelReady(flags) if flags.is_set(AwaitingChannelReadyFlags::FUNDING_SIGNED))
}

/// Transaction nomenclature is somewhat confusing here as there are many different cases - a
Expand Down Expand Up @@ -3284,7 +3308,8 @@ impl<SP: Deref> ChannelContext<SP> where SP::Target: SignerProvider {
match self.channel_state {
ChannelState::FundingNegotiated => f(),
ChannelState::AwaitingChannelReady(flags) =>
if flags.is_set(AwaitingChannelReadyFlags::WAITING_FOR_BATCH) ||
if flags.is_set(AwaitingChannelReadyFlags::FUNDING_SIGNED) ||
flags.is_set(AwaitingChannelReadyFlags::WAITING_FOR_BATCH) ||
flags.is_set(FundedStateFlags::MONITOR_UPDATE_IN_PROGRESS.into())
{
f()
Expand Down Expand Up @@ -4057,6 +4082,7 @@ impl<SP: Deref> Channel<SP> where
/// Handles a channel_ready message from our peer. If we've already sent our channel_ready
/// and the channel is now usable (and public), this may generate an announcement_signatures to
/// reply with.
/// MAYBE SHOULD FIX HERE;
pub fn channel_ready<NS: Deref, L: Deref>(
&mut self, msg: &msgs::ChannelReady, node_signer: &NS, chain_hash: ChainHash,
user_config: &UserConfig, best_block: &BestBlock, logger: &L
Expand Down Expand Up @@ -5185,6 +5211,12 @@ impl<SP: Deref> Channel<SP> where
} else { None };
// That said, if the funding transaction is already confirmed (ie we're active with a
// minimum_depth over 0) don't bother re-broadcasting the confirmed funding tx.

if matches!(
self.context.channel_state
,ChannelState::AwaitingChannelReady(flag) if flag.is_set(AwaitingChannelReadyFlags::FUNDING_SIGNED)) {
funding_broadcastable = None;
}
if matches!(self.context.channel_state, ChannelState::ChannelReady(_)) && self.context.minimum_depth != Some(0) {
funding_broadcastable = None;
}
Expand Down Expand Up @@ -6280,7 +6312,9 @@ impl<SP: Deref> Channel<SP> where
if !self.is_awaiting_monitor_update() { return false; }
if matches!(
self.context.channel_state, ChannelState::AwaitingChannelReady(flags)
if flags.clone().clear(AwaitingChannelReadyFlags::THEIR_CHANNEL_READY | FundedStateFlags::PEER_DISCONNECTED | FundedStateFlags::MONITOR_UPDATE_IN_PROGRESS | AwaitingChannelReadyFlags::WAITING_FOR_BATCH).is_empty()
if flags.clone().clear(AwaitingChannelReadyFlags::THEIR_CHANNEL_READY |
FundedStateFlags::PEER_DISCONNECTED | FundedStateFlags::MONITOR_UPDATE_IN_PROGRESS
| AwaitingChannelReadyFlags::WAITING_FOR_BATCH | AwaitingChannelReadyFlags::FUNDING_SIGNED).is_empty()
) {
// If we're not a 0conf channel, we'll be waiting on a monitor update with only
// AwaitingChannelReady set, though our peer could have sent their channel_ready.
Expand Down Expand Up @@ -7709,7 +7743,9 @@ impl<SP: Deref> OutboundV1Channel<SP> where SP::Target: SignerProvider {
counterparty_initial_commitment_tx.to_countersignatory_value_sat(), logger);

assert!(!self.context.channel_state.is_monitor_update_in_progress()); // We have no had any monitor(s) yet to fail update!
if self.context.is_batch_funding() {
if self.context.get_manually_broadcast_outbound_channels().is_some() {
self.context.channel_state = ChannelState::AwaitingChannelReady(AwaitingChannelReadyFlags::FUNDING_SIGNED);
} else if self.context.is_batch_funding() {
self.context.channel_state = ChannelState::AwaitingChannelReady(AwaitingChannelReadyFlags::WAITING_FOR_BATCH);
} else {
self.context.channel_state = ChannelState::AwaitingChannelReady(AwaitingChannelReadyFlags::new());
Expand Down Expand Up @@ -8693,6 +8729,7 @@ impl<SP: Deref> Writeable for Channel<SP> where SP::Target: SignerProvider {

let channel_pending_event_emitted = Some(self.context.channel_pending_event_emitted);
let channel_ready_event_emitted = Some(self.context.channel_ready_event_emitted);
let funding_signed_event_emitted = Some(self.context.funding_signed_event_emitted);

// `user_id` used to be a single u64 value. In order to remain backwards compatible with
// versions prior to 0.0.113, the u128 is serialized as two separate u64 values. Therefore,
Expand Down Expand Up @@ -8744,6 +8781,8 @@ impl<SP: Deref> Writeable for Channel<SP> where SP::Target: SignerProvider {
(43, malformed_htlcs, optional_vec), // Added in 0.0.119
// 45 and 47 are reserved for async signing
(49, self.context.local_initiated_shutdown, option), // Added in 0.0.122
(51, self.context.manually_broadcast_outbound_channels, option),
(53, funding_signed_event_emitted, option)
});

Ok(())
Expand Down Expand Up @@ -9032,6 +9071,7 @@ impl<'a, 'b, 'c, ES: Deref, SP: Deref> ReadableArgs<(&'a ES, &'b SP, u32, &'c Ch
let mut outbound_scid_alias = None;
let mut channel_pending_event_emitted = None;
let mut channel_ready_event_emitted = None;
let mut funding_signed_event_emitted = None;

let mut user_id_high_opt: Option<u64> = None;
let mut channel_keys_id: Option<[u8; 32]> = None;
Expand Down Expand Up @@ -9087,6 +9127,7 @@ impl<'a, 'b, 'c, ES: Deref, SP: Deref> ReadableArgs<(&'a ES, &'b SP, u32, &'c Ch
// 45 and 47 are reserved for async signing
(49, local_initiated_shutdown, option),
(51, manually_broadcast_outbound_channels, option),
(53, funding_signed_event_emitted, option),
});

let (channel_keys_id, holder_signer) = if let Some(channel_keys_id) = channel_keys_id {
Expand Down Expand Up @@ -9310,6 +9351,7 @@ impl<'a, 'b, 'c, ES: Deref, SP: Deref> ReadableArgs<(&'a ES, &'b SP, u32, &'c Ch
outbound_scid_alias: outbound_scid_alias.unwrap_or(0),

channel_pending_event_emitted: channel_pending_event_emitted.unwrap_or(true),
funding_signed_event_emitted: funding_signed_event_emitted.unwrap_or(true),
channel_ready_event_emitted: channel_ready_event_emitted.unwrap_or(true),

#[cfg(any(test, fuzzing))]
Expand Down Expand Up @@ -10972,6 +11014,105 @@ mod tests {
assert!(res.is_err());
}

#[test]
fn test_funding_signed_event() {
let feeest = LowerBoundedFeeEstimator::new(&TestFeeEstimator{fee_est: 15000});
let logger = test_utils::TestLogger::new();
let secp_ctx = Secp256k1::new();
let seed = [42; 32];
let network = Network::Testnet;
let best_block = BestBlock::from_network(network);
let chain_hash = ChainHash::using_genesis_block(network);
let keys_provider = test_utils::TestKeysInterface::new(&seed, network);

let mut config = UserConfig::default();
config.manually_broadcast_outbound_channels = true;
let node_b_node_id = PublicKey::from_secret_key(&secp_ctx, &SecretKey::from_slice(&[42; 32]).unwrap());
let mut node_a_chan = OutboundV1Channel::<&TestKeysInterface>::new(
&feeest,
&&keys_provider,
&&keys_provider,
node_b_node_id,
&channelmanager::provided_init_features(&config),
10000000,
100000,
42,
&config,
0,
42,
None
).unwrap();

let open_channel_msg = node_a_chan.get_open_channel(ChainHash::using_genesis_block(network));
let node_b_node_id = PublicKey::from_secret_key(&secp_ctx, &SecretKey::from_slice(&[7; 32]).unwrap());
let mut node_b_chan = InboundV1Channel::<&TestKeysInterface>::new(
&feeest,
&&keys_provider,
&&keys_provider,
node_b_node_id,
&channelmanager::provided_channel_type_features(&config),
&channelmanager::provided_init_features(&config),
&open_channel_msg,
7,
&config,
0,
&&logger,
true,
).unwrap();

let accept_channel_msg = node_b_chan.accept_inbound_channel();
node_a_chan.accept_channel(
&accept_channel_msg,
&config.channel_handshake_limits,
&channelmanager::provided_init_features(&config),
).unwrap();

let output_script = node_a_chan.context.get_funding_redeemscript();
let tx = Transaction {
version: 1,
lock_time: LockTime::ZERO,
input: Vec::new(),
output: vec![
TxOut {
value: 10000000, script_pubkey: output_script.clone(),
},
TxOut {
value: 10000000, script_pubkey: Builder::new().into_script(),
},
]};
let funding_outpoint = OutPoint{ txid: tx.txid(), index: 0 };
let funding_created_msg = node_a_chan.get_funding_created(
tx.clone(), funding_outpoint, false, &&logger,
).map_err(|_| ()).unwrap();
let (mut node_b_chan, funding_signed_msg, _) = node_b_chan.funding_created(
&funding_created_msg.unwrap(),
best_block,
&&keys_provider,
&&logger,
).map_err(|_| ()).unwrap();
let _ = node_b_chan.monitor_updating_restored(
&&logger,
&&keys_provider,
chain_hash,
&config,
0,
);
let res = node_a_chan.funding_signed(
&funding_signed_msg.unwrap(), best_block, &&keys_provider, &&logger,
);
let (mut node_a_chan, _) = if let Ok(res) = res { res } else { panic!(); };
let node_a_updates = node_a_chan.monitor_updating_restored(
&&logger,
&&keys_provider,
chain_hash,
&config,
0,
);
assert!(node_a_updates.channel_ready.is_none());
assert!(node_a_updates.funding_broadcastable.is_none());
assert_eq!(node_a_chan.context.channel_state, ChannelState::AwaitingChannelReady(AwaitingChannelReadyFlags::FUNDING_SIGNED));
}

#[test]
fn test_waiting_for_batch() {
let feeest = LowerBoundedFeeEstimator::new(&TestFeeEstimator{fee_est: 15000});
Expand Down
12 changes: 12 additions & 0 deletions lightning/src/ln/channelmanager.rs
Original file line number Diff line number Diff line change
Expand Up @@ -2864,6 +2864,17 @@ macro_rules! send_channel_ready {
}
}}
}
macro_rules! emit_funding_signed_event {
($locked_events: expr, $channel: expr) => {
if $channel.context.should_emit_funding_signed_event() {
$locked_events.push_back((events::Event::FundingSigned {
channel_id: $channel.context.channel_id(),
user_channel_id: $channel.context.get_user_id(),
}, None));
$channel.context.set_funding_signed_event_emitted();
}
}
}

macro_rules! emit_channel_pending_event {
($locked_events: expr, $channel: expr) => {
Expand Down Expand Up @@ -6840,6 +6851,7 @@ where
{
let mut pending_events = self.pending_events.lock().unwrap();
emit_channel_pending_event!(pending_events, channel);
emit_funding_signed_event!(pending_events, channel);
emit_channel_ready_event!(pending_events, channel);
}

Expand Down
12 changes: 12 additions & 0 deletions lightning/src/ln/functional_test_utils.rs
Original file line number Diff line number Diff line change
Expand Up @@ -2339,6 +2339,18 @@ pub fn expect_channel_pending_event<'a, 'b, 'c, 'd>(node: &'a Node<'b, 'c, 'd>,
}
}

#[cfg(any(test, ldk_bench, feature = "_test_utils"))]
pub fn expect_funding_signed_event<'a, 'b, 'c, 'd>(node: &'a Node<'b, 'c, 'd>) -> ChannelId {
let events = node.node.get_and_clear_pending_events();
assert_eq!(events.len(), 1);
match &events[0] {
crate::events::Event::FundingSigned { channel_id, .. } => {
*channel_id
},
_ => panic!("Unexpected event"),
}
}

#[cfg(any(test, ldk_bench, feature = "_test_utils"))]
pub fn expect_channel_ready_event<'a, 'b, 'c, 'd>(node: &'a Node<'b, 'c, 'd>, expected_counterparty_node_id: &PublicKey) {
let events = node.node.get_and_clear_pending_events();
Expand Down

0 comments on commit 999fc5a

Please sign in to comment.