Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Implement V2 channel establishment #2302

Draft
wants to merge 6 commits into
base: main
Choose a base branch
from
Draft
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
93 changes: 88 additions & 5 deletions lightning/src/events/mod.rs
Original file line number Diff line number Diff line change
Expand Up @@ -538,6 +538,18 @@ impl_writeable_tlv_based_enum!(PaymentFailureReason,
(10, UnexpectedError) => {}, ;
);

/// Used to indicate the kind of funding for this channel by the channel acceptor (us).
///
/// Allows the differentiation between a request for a dual-funded and non-dual-funded channel.
#[derive(Clone, Debug, PartialEq, Eq)]
pub enum InboundChannelFunds {
/// For a non-dual-funded channel, the `push_msat` value from the channel initiator to us.
PushMsat(u64),
/// Indicates the open request is for a dual funded channel and we may choose to contribute
/// funds to the channel.
DualFunded,
}

/// An Event which you should probably take some action in response to.
///
/// Note that while Writeable and Readable are implemented for Event, you probably shouldn't use
Expand Down Expand Up @@ -1143,14 +1155,28 @@ pub enum Event {
},
/// Indicates a request to open a new channel by a peer.
///
/// To accept the request, call [`ChannelManager::accept_inbound_channel`]. To reject the request,
/// call [`ChannelManager::force_close_without_broadcasting_txn`]. Note that a ['ChannelClosed`]
/// event will _not_ be triggered if the channel is rejected.
/// If `acceptor_funds` is `InboundChannelFunds::DualFunded`, this indicates that the peer wishes to
/// open a dual-funded channel. In this case you can choose whether to contribute funds or not.
/// Otherwise, `acceptor_funds` will be `InboundChannelFunds::PushMsats`, indicating the `push_msats`
/// value for a non-dual-funded channel.
///
/// To accept the request (and in the case of a dual-funded channel, not contribute funds),
/// call [`ChannelManager::accept_inbound_channel`].
// TODO(dual_funding): Make this a doc comment when dual-funding fully released.
// To accept the request and contribute funds for a dual-funded channel,
// call [`ChannelManager::accept_inbound_channel_with_contribution`].
/// To reject the request, call [`ChannelManager::force_close_without_broadcasting_txn`].
/// Note that a ['ChannelClosed`] event will _not_ be triggered if the channel is rejected.
///
/// The event is only triggered when a new open channel request is received and the
/// [`UserConfig::manually_accept_inbound_channels`] config flag is set to true.
/// Note that if you wish to be able to contribute funds to dual-funded open channel requests,
/// [`UserConfig::manually_accept_inbound_channels`] MUST be set to true so that you may
/// provide funding inputs when choosing to contribute to the channel capacity.
///
/// [`ChannelManager::accept_inbound_channel`]: crate::ln::channelmanager::ChannelManager::accept_inbound_channel
// TODO(dual_funding): Make this a doc comment when dual-funding fully released.
// [`ChannelManager::accept_inbound_channel_with_contribution`]: crate::ln::channelmanager::ChannelManager::accept_inbound_channel_with_contribution
/// [`ChannelManager::force_close_without_broadcasting_txn`]: crate::ln::channelmanager::ChannelManager::force_close_without_broadcasting_txn
/// [`UserConfig::manually_accept_inbound_channels`]: crate::util::config::UserConfig::manually_accept_inbound_channels
OpenChannelRequest {
Expand All @@ -1176,7 +1202,7 @@ pub enum Event {
/// The channel value of the requested channel.
funding_satoshis: u64,
/// Our starting balance in the channel if the request is accepted, in milli-satoshi.
push_msat: u64,
acceptor_funds: InboundChannelFunds,
Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

What's the plan for landing this? We have public API changes (and associated documentation) here, but most of the logic is still cfg-flagged. Its not the end of the world but definitely a bit awkward...Does it make sense to land v2 establishment without the ability to fund the opening transaction so we can avoid all public API changes and then land the ability to negotiate in a separate PR? That would also neatly split this PR, though it would be some work to split it apart, I think?

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

So, first being allowed to accept V2 channels without contributing (and then introducing the public API in the next PR for contributing)?

It's not too much work, and it does seem safer to land that a bit earlier than everything here.

Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Do you plan on doing this in a new PR and rebasing this one or just doing it in this one?

Copy link
Contributor Author

@dunxen dunxen Jun 18, 2024

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I'm thinking new PR to slim this one down. Then I'll rebase this one.

EDIT: The split seems to be going smoothly for now.

/// The features that this channel will operate with. If you reject the channel, a
/// well-behaved counterparty may automatically re-attempt the channel with a new set of
/// feature flags.
Expand Down Expand Up @@ -1244,7 +1270,56 @@ pub enum Event {
/// The node id of the peer we just connected to, who advertises support for
/// onion messages.
peer_node_id: PublicKey,
}
},
#[cfg(any(dual_funding, splicing))]
/// Indicates that a transaction constructed via interactive transaction construction for a
/// dual-funded (V2) channel is ready to be signed by the client. This event will only be triggered
/// if at least one input was contributed by the holder.
///
/// The transaction contains all inputs provided by both parties when the channel was
/// created/accepted along with the channel's funding output and a change output if applicable.
///
/// No part of the transaction should be changed before signing as the content of the transaction
/// has already been negotiated with the counterparty.
///
/// Each signature MUST use the SIGHASH_ALL flag to avoid invalidation of initial commitment and
/// hence possible loss of funds.
///
/// After signing, call [`ChannelManager::funding_transaction_signed`] with the (partially) signed
/// funding transaction.
///
/// Generated in [`ChannelManager`] message handling.
///
/// [`ChannelManager`]: crate::ln::channelmanager::ChannelManager
/// [`ChannelManager::funding_transaction_signed`]: crate::ln::channelmanager::ChannelManager::funding_transaction_signed
FundingTransactionReadyForSigning {
/// The channel_id of the V2 channel which you'll need to pass back into
/// [`ChannelManager::funding_transaction_signed`].
///
/// [`ChannelManager::funding_transaction_signed`]: crate::ln::channelmanager::ChannelManager::funding_transaction_signed
channel_id: ChannelId,
/// The counterparty's node_id, which you'll need to pass back into
/// [`ChannelManager::funding_transaction_signed`].
///
/// [`ChannelManager::funding_transaction_signed`]: crate::ln::channelmanager::ChannelManager::funding_transaction_signed
counterparty_node_id: PublicKey,
/// The `user_channel_id` value passed in to [`ChannelManager::create_dual_funded_channel`] for outbound
/// channels, or to [`ChannelManager::accept_inbound_channel`] or [`ChannelManager::accept_inbound_channel_with_contribution`]
/// 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_dual_funded_channel`]: crate::ln::channelmanager::ChannelManager::create_dual_funded_channel
/// [`ChannelManager::accept_inbound_channel`]: crate::ln::channelmanager::ChannelManager::accept_inbound_channel
/// [`ChannelManager::accept_inbound_channel_with_contribution`]: crate::ln::channelmanager::ChannelManager::accept_inbound_channel_with_contribution
/// [`UserConfig::manually_accept_inbound_channels`]: crate::util::config::UserConfig::manually_accept_inbound_channels
user_channel_id: u128,
/// The unsigned transaction to be signed and passed back to
/// [`ChannelManager::funding_transaction_signed`].
///
/// [`ChannelManager::funding_transaction_signed`]: crate::ln::channelmanager::ChannelManager::funding_transaction_signed
unsigned_transaction: Transaction,
},
}

impl Writeable for Event {
Expand Down Expand Up @@ -1530,6 +1605,14 @@ impl Writeable for Event {
(4, responder, option),
})
},
#[cfg(any(splicing, dual_funding))]
dunxen marked this conversation as resolved.
Show resolved Hide resolved
&Event::FundingTransactionReadyForSigning { .. } => {
43u8.write(writer)?;
// We never write out FundingTransactionReadyForSigning events as, upon disconnection, peers
// drop any V2-established channels which have not yet exchanged the initial `commitment_signed`.
// We only exhange the initial `commitment_signed` after the client calls
// `ChannelManager::funding_transaction_signed` and ALWAYS before we send a `tx_signatures`
},
// 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
Loading
Loading