@@ -30,9 +30,7 @@ use bitcoin::hash_types::{BlockHash, Txid};
3030
3131use bitcoin::secp256k1::{SecretKey,PublicKey};
3232use bitcoin::secp256k1::Secp256k1;
33- use bitcoin::{secp256k1, Sequence};
34- #[cfg(splicing)]
35- use bitcoin::{TxIn, Weight};
33+ use bitcoin::{secp256k1, Sequence, TxIn, Weight};
3634
3735use crate::events::{FundingInfo, PaidBolt12Invoice};
3836use crate::blinded_path::message::{AsyncPaymentsContext, MessageContext, OffersContext};
@@ -84,7 +82,7 @@ use crate::util::config::{ChannelConfig, ChannelConfigUpdate, ChannelConfigOverr
8482use crate::util::wakers::{Future, Notifier};
8583use crate::util::scid_utils::fake_scid;
8684use crate::util::string::UntrustedString;
87- use crate::util::ser::{BigSize, FixedLengthReader, LengthReadable, Readable, ReadableArgs, MaybeReadable, Writeable, Writer, VecWriter };
85+ use crate::util::ser::{BigSize, FixedLengthReader, LengthReadable, MaybeReadable, Readable, ReadableArgs, TransactionU16LenLimited, VecWriter, Writeable, Writer };
8886use crate::util::logger::{Level, Logger, WithContext};
8987use crate::util::errors::APIError;
9088
@@ -7892,7 +7890,7 @@ This indicates a bug inside LDK. Please report this error at https://github.com/
78927890 /// [`Event::OpenChannelRequest`]: events::Event::OpenChannelRequest
78937891 /// [`Event::ChannelClosed::user_channel_id`]: events::Event::ChannelClosed::user_channel_id
78947892 pub fn accept_inbound_channel(&self, temporary_channel_id: &ChannelId, counterparty_node_id: &PublicKey, user_channel_id: u128, config_overrides: Option<ChannelConfigOverrides>) -> Result<(), APIError> {
7895- self.do_accept_inbound_channel(temporary_channel_id, counterparty_node_id, false, user_channel_id, config_overrides)
7893+ self.do_accept_inbound_channel(temporary_channel_id, counterparty_node_id, false, user_channel_id, config_overrides, 0, vec![] )
78967894 }
78977895
78987896 /// Accepts a request to open a channel after a [`events::Event::OpenChannelRequest`], treating
@@ -7914,13 +7912,64 @@ This indicates a bug inside LDK. Please report this error at https://github.com/
79147912 /// [`Event::OpenChannelRequest`]: events::Event::OpenChannelRequest
79157913 /// [`Event::ChannelClosed::user_channel_id`]: events::Event::ChannelClosed::user_channel_id
79167914 pub fn accept_inbound_channel_from_trusted_peer_0conf(&self, temporary_channel_id: &ChannelId, counterparty_node_id: &PublicKey, user_channel_id: u128, config_overrides: Option<ChannelConfigOverrides>) -> Result<(), APIError> {
7917- self.do_accept_inbound_channel(temporary_channel_id, counterparty_node_id, true, user_channel_id, config_overrides)
7915+ self.do_accept_inbound_channel(temporary_channel_id, counterparty_node_id, true, user_channel_id, config_overrides, 0, vec![])
7916+ }
7917+
7918+ /// Accepts a request to open a dual-funded channel with a contribution provided by us after an
7919+ /// [`Event::OpenChannelRequest`].
7920+ ///
7921+ /// The [`Event::OpenChannelRequest::InboundChannelFunds`] field will indicate the open channel
7922+ /// request is for a dual-funded channel when the variant is `InboundChannelFunds::DualFunded`.
7923+ ///
7924+ /// The `temporary_channel_id` parameter indicates which inbound channel should be accepted,
7925+ /// and the `counterparty_node_id` parameter is the id of the peer which has requested to open
7926+ /// the channel.
7927+ ///
7928+ /// The `user_channel_id` parameter will be provided back in
7929+ /// [`Event::ChannelClosed::user_channel_id`] to allow tracking of which events correspond
7930+ /// with which `accept_inbound_channel_*` call.
7931+ ///
7932+ /// The `funding_inputs` parameter provides the `txin`s along with their previous transactions, and
7933+ /// a corresponding witness weight for each input that will be used to contribute towards our
7934+ /// portion of the channel value. Our contribution will be calculated as the total value of these
7935+ /// inputs minus the fees we need to cover for the interactive funding transaction. The witness
7936+ /// weights must correspond to the witnesses you will provide through [`ChannelManager::funding_transaction_signed`]
7937+ /// after receiving [`Event::FundingTransactionReadyForSigning`].
7938+ ///
7939+ /// Note that this method will return an error and reject the channel if it requires support for
7940+ /// zero confirmations.
7941+ // TODO(dual_funding): Discussion on complications with 0conf dual-funded channels where "locking"
7942+ // of UTXOs used for funding would be required and other issues.
7943+ // See https://diyhpl.us/~bryan/irc/bitcoin/bitcoin-dev/linuxfoundation-pipermail/lightning-dev/2023-May/003922.txt
7944+ ///
7945+ /// [`Event::OpenChannelRequest`]: events::Event::OpenChannelRequest
7946+ /// [`Event::ChannelClosed::user_channel_id`]: events::Event::ChannelClosed::user_channel_id
7947+ /// [`Event::FundingTransactionReadyForSigning`]: events::Event::FundingTransactionReadyForSigning
7948+ /// [`ChannelManager::funding_transaction_signed`]: ChannelManager::funding_transaction_signed
7949+ pub fn accept_inbound_channel_with_contribution(
7950+ &self, temporary_channel_id: &ChannelId, counterparty_node_id: &PublicKey, user_channel_id: u128,
7951+ config_overrides: Option<ChannelConfigOverrides>, our_funding_satoshis: u64,
7952+ funding_inputs: Vec<(TxIn, Transaction, Weight)>
7953+ ) -> Result<(), APIError> {
7954+ let funding_inputs = Self::length_limit_holder_input_prev_txs(funding_inputs)?;
7955+ self.do_accept_inbound_channel(temporary_channel_id, counterparty_node_id, false, user_channel_id,
7956+ config_overrides, our_funding_satoshis, funding_inputs)
7957+ }
7958+
7959+ fn length_limit_holder_input_prev_txs(funding_inputs: Vec<(TxIn, Transaction, Weight)>) -> Result<Vec<(TxIn, TransactionU16LenLimited, Weight)>, APIError> {
7960+ funding_inputs.into_iter().map(|(txin, tx, witness_weight)| {
7961+ match TransactionU16LenLimited::new(tx) {
7962+ Ok(tx) => Ok((txin, tx, witness_weight)),
7963+ Err(err) => Err(err)
7964+ }
7965+ }).collect::<Result<Vec<(TxIn, TransactionU16LenLimited, Weight)>, ()>>()
7966+ .map_err(|_| APIError::APIMisuseError { err: "One or more transactions had a serialized length exceeding 65535 bytes".into() })
79187967 }
79197968
7920- /// TODO(dual_funding): Allow contributions, pass intended amount and inputs
79217969 fn do_accept_inbound_channel(
79227970 &self, temporary_channel_id: &ChannelId, counterparty_node_id: &PublicKey, accept_0conf: bool,
7923- user_channel_id: u128, config_overrides: Option<ChannelConfigOverrides>
7971+ user_channel_id: u128, config_overrides: Option<ChannelConfigOverrides>, our_funding_satoshis: u64,
7972+ funding_inputs: Vec<(TxIn, TransactionU16LenLimited, Weight)>
79247973 ) -> Result<(), APIError> {
79257974
79267975 let mut config = self.default_configuration.clone();
@@ -7979,7 +8028,7 @@ This indicates a bug inside LDK. Please report this error at https://github.com/
79798028 &self.channel_type_features(), &peer_state.latest_features,
79808029 &open_channel_msg,
79818030 user_channel_id, &config, best_block_height,
7982- &self.logger,
8031+ &self.logger, our_funding_satoshis, funding_inputs,
79838032 ).map_err(|_| MsgHandleErrInternal::from_chan_no_close(
79848033 ChannelError::Close(
79858034 (
@@ -8260,7 +8309,7 @@ This indicates a bug inside LDK. Please report this error at https://github.com/
82608309 &self.fee_estimator, &self.entropy_source, &self.signer_provider,
82618310 self.get_our_node_id(), *counterparty_node_id, &self.channel_type_features(),
82628311 &peer_state.latest_features, msg, user_channel_id,
8263- &self.default_configuration, best_block_height, &self.logger,
8312+ &self.default_configuration, best_block_height, &self.logger, 0, vec![],
82648313 ).map_err(|e| MsgHandleErrInternal::from_chan_no_close(e, msg.common_fields.temporary_channel_id))?;
82658314 let message_send_event = MessageSendEvent::SendAcceptChannelV2 {
82668315 node_id: *counterparty_node_id,
0 commit comments