@@ -32,7 +32,7 @@ use crate::ln::types::ChannelId;
3232use crate::types::payment::{PaymentPreimage, PaymentHash};
3333use crate::types::features::{ChannelTypeFeatures, InitFeatures};
3434use crate::ln::interactivetxs::{
35- get_output_weight, calculate_change_output_value, HandleTxCompleteValue, HandleTxCompleteResult, InteractiveTxConstructor,
35+ estimate_input_weight, get_output_weight, calculate_change_output_value, HandleTxCompleteValue, HandleTxCompleteResult, InteractiveTxConstructor,
3636 InteractiveTxConstructorArgs, InteractiveTxMessageSend, InteractiveTxSigningSession, InteractiveTxMessageSendResult,
3737 OutputOwned, SharedOwnedOutput, TX_COMMON_FIELDS_WEIGHT,
3838};
@@ -1142,7 +1142,7 @@ pub(super) enum Channel<SP: Deref> where SP::Target: SignerProvider {
11421142 Funded(FundedChannel<SP>),
11431143 #[cfg(splicing)]
11441144 /// Used during splicing, channel is funded but a new funding is being renegotiated.
1145- RefundingV2(FundedChannel <SP>),
1145+ RefundingV2(SplicingChannel <SP>),
11461146}
11471147
11481148impl<SP: Deref> Channel<SP> where
@@ -1156,7 +1156,7 @@ impl<SP: Deref> Channel<SP> where
11561156 Channel::UnfundedInboundV1(chan) => &chan.context,
11571157 Channel::UnfundedV2(chan) => &chan.context,
11581158 #[cfg(splicing)]
1159- Channel::RefundingV2(chan) => &chan.context,
1159+ Channel::RefundingV2(chan) => &chan.pre_funded. context,
11601160 }
11611161 }
11621162
@@ -1167,7 +1167,7 @@ impl<SP: Deref> Channel<SP> where
11671167 Channel::UnfundedInboundV1(ref mut chan) => &mut chan.context,
11681168 Channel::UnfundedV2(ref mut chan) => &mut chan.context,
11691169 #[cfg(splicing)]
1170- Channel::RefundingV2(ref mut chan) => &mut chan.context,
1170+ Channel::RefundingV2(ref mut chan) => &mut chan.pre_funded. context,
11711171 }
11721172 }
11731173
@@ -1183,22 +1183,29 @@ impl<SP: Deref> Channel<SP> where
11831183 }
11841184
11851185 pub fn is_funded(&self) -> bool {
1186- matches!(self, Channel::Funded(_))
1186+ match self {
1187+ Channel::Funded(_) => true,
1188+ #[cfg(splicing)]
1189+ Channel::RefundingV2(_) => true,
1190+ _ => false,
1191+ }
11871192 }
11881193
11891194 pub fn as_funded(&self) -> Option<&FundedChannel<SP>> {
1190- if let Channel::Funded(channel) = self {
1191- Some(channel)
1192- } else {
1193- None
1195+ match self {
1196+ Channel::Funded(channel) => Some(channel),
1197+ #[cfg(splicing)]
1198+ Channel::RefundingV2(channel) => Some(&channel.pre_funded),
1199+ _ => None,
11941200 }
11951201 }
11961202
11971203 pub fn as_funded_mut(&mut self) -> Option<&mut FundedChannel<SP>> {
1198- if let Channel::Funded(channel) = self {
1199- Some(channel)
1200- } else {
1201- None
1204+ match self {
1205+ Channel::Funded(channel) => Some(channel),
1206+ #[cfg(splicing)]
1207+ Channel::RefundingV2(channel) => Some(&mut channel.pre_funded),
1208+ _ => None,
12021209 }
12031210 }
12041211
@@ -1239,10 +1246,11 @@ impl<SP: Deref> Channel<SP> where
12391246 }
12401247
12411248 pub fn as_unfunded_v2_mut(&mut self) -> Option<&mut PendingV2Channel<SP>> {
1242- if let Channel::UnfundedV2(channel) = self {
1243- Some(channel)
1244- } else {
1245- None
1249+ match self {
1250+ Channel::UnfundedV2(channel) => Some(channel),
1251+ #[cfg(splicing)]
1252+ Channel::RefundingV2(channel) => Some(&mut channel.post_pending),
1253+ _ => None,
12461254 }
12471255 }
12481256
@@ -1294,7 +1302,7 @@ impl<SP: Deref> Channel<SP> where
12941302 },
12951303 Channel::UnfundedV2(_) => None,
12961304 #[cfg(splicing)]
1297- Channel::RefundingV2(chan) => Some(chan.signer_maybe_unblocked(logger)),
1305+ Channel::RefundingV2(chan) => Some(chan.pre_funded. signer_maybe_unblocked(logger)),
12981306 }
12991307 }
13001308
@@ -1423,6 +1431,55 @@ where
14231431 }
14241432}
14251433
1434+ /// Struct holding together various state dureing splicing negotiation
1435+ #[cfg(splicing)]
1436+ pub(super) struct SplicingChannel<SP: Deref> where SP::Target: SignerProvider {
1437+ pub pre_funded: FundedChannel<SP>,
1438+ pub post_pending: PendingV2Channel<SP>,
1439+ pub post_funded: Option<FundedChannel<SP>>,
1440+ }
1441+
1442+ #[cfg(splicing)]
1443+ impl<SP: Deref> SplicingChannel<SP> where SP::Target: SignerProvider {
1444+ pub(super) fn new(pre_funded: FundedChannel<SP>, post_pending: PendingV2Channel<SP>) -> Self {
1445+ Self {
1446+ pre_funded,
1447+ post_pending,
1448+ post_funded: None,
1449+ }
1450+ }
1451+
1452+ pub fn splice_init<ES: Deref, L: Deref>(
1453+ &mut self, msg: &msgs::SpliceInit, signer_provider: &SP, entropy_source: &ES, holder_node_id: PublicKey, logger: &L,
1454+ ) -> Result<msgs::SpliceAck,ChannelError> where ES::Target: EntropySource, L::Target: Logger {
1455+ self.post_pending.splice_init(msg, signer_provider, entropy_source, holder_node_id, logger)
1456+ }
1457+
1458+ pub fn splice_ack<ES: Deref, L: Deref>(
1459+ &mut self, msg: &msgs::SpliceAck, our_funding_contribution: i64, signer_provider: &SP, entropy_source: &ES, holder_node_id: PublicKey, logger: &L,
1460+ ) -> Result<Option<InteractiveTxMessageSend>, ChannelError> where ES::Target: EntropySource, L::Target: Logger {
1461+ self.post_pending.splice_ack(msg, our_funding_contribution, signer_provider, entropy_source, holder_node_id, logger)
1462+ }
1463+
1464+ pub fn tx_add_input(&mut self, msg: &msgs::TxAddInput) -> InteractiveTxMessageSendResult {
1465+ self.post_pending.tx_add_input(msg)
1466+ }
1467+
1468+ pub fn tx_add_output(&mut self, msg: &msgs::TxAddOutput)-> InteractiveTxMessageSendResult {
1469+ self.post_pending.tx_add_output(msg)
1470+ }
1471+
1472+ pub fn tx_complete(&mut self, msg: &msgs::TxComplete) -> HandleTxCompleteResult {
1473+ self.post_pending.tx_complete(msg)
1474+ }
1475+
1476+ pub fn funding_tx_constructed<L: Deref>(
1477+ &mut self, signing_session: &mut InteractiveTxSigningSession, logger: &L
1478+ ) -> Result<(msgs::CommitmentSigned, Option<Event>), ChannelError> where L::Target: Logger {
1479+ self.post_pending.funding_tx_constructed(signing_session, logger)
1480+ }
1481+ }
1482+
14261483/// Contains all state common to unfunded inbound/outbound channels.
14271484pub(super) struct UnfundedChannelContext {
14281485 /// A counter tracking how many ticks have elapsed since this unfunded channel was
@@ -1455,7 +1512,7 @@ impl UnfundedChannelContext {
14551512/// Info about a pending splice, used in the pre-splice channel
14561513#[cfg(splicing)]
14571514#[derive(Clone)]
1458- struct PendingSplicePre {
1515+ pub(super) struct PendingSplicePre {
14591516 pub our_funding_contribution: i64,
14601517 pub funding_feerate_perkw: u32,
14611518 pub locktime: u32,
@@ -4869,6 +4926,54 @@ fn get_v2_channel_reserve_satoshis(channel_value_satoshis: u64, dust_limit_satos
48694926 cmp::min(channel_value_satoshis, cmp::max(q, dust_limit_satoshis))
48704927}
48714928
4929+ pub(super) fn maybe_add_funding_change_output<SP: Deref>(signer_provider: &SP, is_initiator: bool,
4930+ our_funding_satoshis: u64, funding_inputs_prev_outputs: &Vec<TxOut>,
4931+ funding_outputs: &mut Vec<OutputOwned>, funding_feerate_sat_per_1000_weight: u32,
4932+ total_input_satoshis: u64, holder_dust_limit_satoshis: u64, channel_keys_id: [u8; 32],
4933+ ) -> Result<Option<TxOut>, ChannelError> where
4934+ SP::Target: SignerProvider,
4935+ {
4936+ let our_funding_inputs_weight = funding_inputs_prev_outputs.iter().fold(0u64, |weight, prev_output| {
4937+ weight.saturating_add(estimate_input_weight(prev_output).to_wu())
4938+ });
4939+ let our_funding_outputs_weight = funding_outputs.iter().fold(0u64, |weight, out| {
4940+ weight.saturating_add(get_output_weight(&out.tx_out().script_pubkey).to_wu())
4941+ });
4942+ let our_contributed_weight = our_funding_outputs_weight.saturating_add(our_funding_inputs_weight);
4943+ let mut fees_sats = fee_for_weight(funding_feerate_sat_per_1000_weight, our_contributed_weight);
4944+
4945+ // If we are the initiator, we must pay for weight of all common fields in the funding transaction.
4946+ if is_initiator {
4947+ let common_fees = fee_for_weight(funding_feerate_sat_per_1000_weight, TX_COMMON_FIELDS_WEIGHT);
4948+ fees_sats = fees_sats.saturating_add(common_fees);
4949+ }
4950+
4951+ let remaining_value = total_input_satoshis
4952+ .saturating_sub(our_funding_satoshis)
4953+ .saturating_sub(fees_sats);
4954+
4955+ if remaining_value < holder_dust_limit_satoshis {
4956+ Ok(None)
4957+ } else {
4958+ let change_script = signer_provider.get_destination_script(channel_keys_id).map_err(
4959+ |_| ChannelError::Close((
4960+ "Failed to get change script as new destination script".to_owned(),
4961+ ClosureReason::ProcessingError { err: "Failed to get change script as new destination script".to_owned() }
4962+ ))
4963+ )?;
4964+ let mut change_output = TxOut {
4965+ value: Amount::from_sat(remaining_value),
4966+ script_pubkey: change_script,
4967+ };
4968+ let change_output_weight = get_output_weight(&change_output.script_pubkey).to_wu();
4969+
4970+ let change_output_fee = fee_for_weight(funding_feerate_sat_per_1000_weight, change_output_weight);
4971+ change_output.value = Amount::from_sat(remaining_value.saturating_sub(change_output_fee));
4972+ funding_outputs.push(OutputOwned::Single(change_output.clone()));
4973+ Ok(Some(change_output))
4974+ }
4975+ }
4976+
48724977pub(super) fn calculate_our_funding_satoshis(
48734978 is_initiator: bool, funding_inputs: &[(TxIn, TransactionU16LenLimited)],
48744979 total_witness_weight: Weight, funding_feerate_sat_per_1000_weight: u32,
@@ -4941,7 +5046,7 @@ pub(super) struct FundedChannel<SP: Deref> where SP::Target: SignerProvider {
49415046 holder_commitment_point: HolderCommitmentPoint,
49425047 /// Info about an in-progress, pending splice (if any), on the pre-splice channel
49435048 #[cfg(splicing)]
4944- pending_splice_pre: Option<PendingSplicePre>,
5049+ pub pending_splice_pre: Option<PendingSplicePre>,
49455050 /// Info about an in-progress, pending splice (if any), on the post-splice channel
49465051 #[cfg(splicing)]
49475052 pending_splice_post: Option<PendingSplicePost>,
@@ -8632,11 +8737,11 @@ impl<SP: Deref> FundedChannel<SP> where
86328737 Ok(msg)
86338738 }
86348739
8635- /// Handle splice_init
8740+ /// Checks during handling splice_init
86368741 #[cfg(splicing)]
8637- pub fn splice_init <ES: Deref, L : Deref>(
8638- &mut self, msg: &msgs::SpliceInit, _signer_provider: &SP, _entropy_source: &ES, _holder_node_id: PublicKey, logger: &L,
8639- ) -> Result<msgs::SpliceAck , ChannelError> where ES::Target: EntropySource, L::Target: Logger {
8742+ pub fn splice_init_checks <ES: Deref>(
8743+ &mut self, msg: &msgs::SpliceInit, _signer_provider: &SP, _entropy_source: &ES, _holder_node_id: PublicKey,
8744+ ) -> Result<() , ChannelError> where ES::Target: EntropySource {
86408745 let their_funding_contribution_satoshis = msg.funding_contribution_satoshis;
86418746 // TODO(splicing): Currently not possible to contribute on the splicing-acceptor side
86428747 let our_funding_contribution_satoshis = 0i64;
@@ -8677,52 +8782,7 @@ impl<SP: Deref> FundedChannel<SP> where
86778782 // Early check for reserve requirement, assuming maximum balance of full channel value
86788783 // This will also be checked later at tx_complete
86798784 let _res = self.context.check_balance_meets_reserve_requirements(post_balance, post_channel_value)?;
8680-
8681- // TODO(splicing): Store msg.funding_pubkey
8682-
8683- // Apply start of splice change in the state
8684- self.context.splice_start(false, logger);
8685-
8686- let splice_ack_msg = self.context.get_splice_ack(our_funding_contribution_satoshis);
8687-
8688- // TODO(splicing): start interactive funding negotiation
8689- // let _msg = self.begin_interactive_funding_tx_construction(signer_provider, entropy_source, holder_node_id)
8690- // .map_err(|err| ChannelError::Warn(format!("Failed to start interactive transaction construction, {:?}", err)))?;
8691-
8692- Ok(splice_ack_msg)
8693- }
8694-
8695- /// Handle splice_ack
8696- #[cfg(splicing)]
8697- pub fn splice_ack<ES: Deref, L: Deref>(
8698- &mut self, msg: &msgs::SpliceAck, _signer_provider: &SP, _entropy_source: &ES, _holder_node_id: PublicKey, logger: &L,
8699- ) -> Result<Option<InteractiveTxMessageSend>, ChannelError> where ES::Target: EntropySource, L::Target: Logger {
8700- let their_funding_contribution_satoshis = msg.funding_contribution_satoshis;
8701-
8702- // check if splice is pending
8703- let pending_splice = if let Some(pending_splice) = &self.pending_splice_pre {
8704- pending_splice
8705- } else {
8706- return Err(ChannelError::Warn(format!("Channel is not in pending splice")));
8707- };
8708-
8709- let our_funding_contribution = pending_splice.our_funding_contribution;
8710-
8711- let pre_channel_value = self.context.get_value_satoshis();
8712- let post_channel_value = PendingSplicePre::compute_post_value(pre_channel_value, our_funding_contribution, their_funding_contribution_satoshis);
8713- let post_balance = PendingSplicePre::add_checked(self.context.value_to_self_msat, our_funding_contribution);
8714- // Early check for reserve requirement, assuming maximum balance of full channel value
8715- // This will also be checked later at tx_complete
8716- let _res = self.context.check_balance_meets_reserve_requirements(post_balance, post_channel_value)?;
8717-
8718- // Apply start of splice change in the state
8719- self.context.splice_start(true, logger);
8720-
8721- // TODO(splicing): start interactive funding negotiation
8722- // let tx_msg_opt = self.begin_interactive_funding_tx_construction(signer_provider, entropy_source, holder_node_id)
8723- // .map_err(|err| ChannelError::Warn(format!("V2 channel rejected due to sender error, {:?}", err)))?;
8724- // Ok(tx_msg_opt)
8725- Ok(None)
8785+ Ok(())
87268786 }
87278787
87288788 // Send stuff to our remote peers:
@@ -9965,6 +10025,56 @@ impl<SP: Deref> PendingV2Channel<SP> where SP::Target: SignerProvider {
996510025 }
996610026 }
996710027
10028+ pub fn into_channel(self, signing_session: InteractiveTxSigningSession) -> Result<FundedChannel<SP>, ChannelError>{
10029+ let holder_commitment_point = self.unfunded_context.holder_commitment_point.ok_or(ChannelError::close(
10030+ format!("Expected to have holder commitment points available upon finishing interactive tx construction for channel {}",
10031+ self.context.channel_id())))?;
10032+ let channel = FundedChannel {
10033+ context: self.context,
10034+ interactive_tx_signing_session: Some(signing_session),
10035+ holder_commitment_point,
10036+ #[cfg(splicing)]
10037+ pending_splice_pre: None,
10038+ #[cfg(splicing)]
10039+ pending_splice_post: self.pending_splice_post,
10040+ };
10041+
10042+ Ok(channel)
10043+ }
10044+
10045+ /// Handle splice_ack
10046+ #[cfg(splicing)]
10047+ pub fn splice_ack<ES: Deref, L: Deref>(
10048+ &mut self, msg: &msgs::SpliceAck, our_funding_contribution: i64, signer_provider: &SP, entropy_source: &ES, holder_node_id: PublicKey, logger: &L,
10049+ ) -> Result<Option<InteractiveTxMessageSend>, ChannelError> where ES::Target: EntropySource, L::Target: Logger {
10050+ let their_funding_contribution_satoshis = msg.funding_contribution_satoshis;
10051+
10052+ // check if splice is pending
10053+ let pending_splice = if let Some(pending_splice) = &self.pending_splice_post {
10054+ pending_splice
10055+ } else {
10056+ return Err(ChannelError::Warn(format!("Channel is not in pending splice")));
10057+ };
10058+
10059+ let pre_channel_value = self.context.get_value_satoshis();
10060+ let post_channel_value = PendingSplicePre::compute_post_value(pre_channel_value, our_funding_contribution, their_funding_contribution_satoshis);
10061+ let post_balance = PendingSplicePre::add_checked(self.context.value_to_self_msat, our_funding_contribution);
10062+ // Early check for reserve requirement, assuming maximum balance of full channel value
10063+ // This will also be checked later at tx_complete
10064+ let _res = self.context.check_balance_meets_reserve_requirements(post_balance, post_channel_value)?;
10065+
10066+ // We need the current funding tx as an extra input
10067+ let prev_funding_input = pending_splice.get_input_of_previous_funding()?;
10068+
10069+ // Apply start of splice change in the state
10070+ self.context.splice_start(true, logger);
10071+
10072+ // Start interactive funding negotiation, with the previous funding transaction as an extra shared input
10073+ let tx_msg_opt = self.begin_interactive_funding_tx_construction(signer_provider, entropy_source, holder_node_id, Some(prev_funding_input))
10074+ .map_err(|err| ChannelError::Warn(format!("V2 channel rejected due to sender error, {:?}", err)))?;
10075+ Ok(tx_msg_opt)
10076+ }
10077+
996810078 /// Creates a new dual-funded channel from a remote side's request for one.
996910079 /// Assumes chain_hash has already been checked and corresponds with what we expect!
997010080 #[allow(dead_code)] // TODO(dual_funding): Remove once V2 channels is enabled.
@@ -10149,21 +10259,27 @@ impl<SP: Deref> PendingV2Channel<SP> where SP::Target: SignerProvider {
1014910259 self.generate_accept_channel_v2_message()
1015010260 }
1015110261
10152- pub fn into_channel(self, signing_session: InteractiveTxSigningSession) -> Result<FundedChannel<SP>, ChannelError>{
10153- let holder_commitment_point = self.unfunded_context.holder_commitment_point.ok_or(ChannelError::close(
10154- format!("Expected to have holder commitment points available upon finishing interactive tx construction for channel {}",
10155- self.context.channel_id())))?;
10156- let channel = FundedChannel {
10157- context: self.context,
10158- interactive_tx_signing_session: Some(signing_session),
10159- holder_commitment_point,
10160- #[cfg(splicing)]
10161- pending_splice_pre: None,
10162- #[cfg(splicing)]
10163- pending_splice_post: self.pending_splice_post,
10164- };
10262+ /// Handle splice_init
10263+ /// See also [`splice_init_checks`]
10264+ #[cfg(splicing)]
10265+ pub fn splice_init<ES: Deref, L: Deref>(
10266+ &mut self, _msg: &msgs::SpliceInit, signer_provider: &SP, entropy_source: &ES, holder_node_id: PublicKey, logger: &L,
10267+ ) -> Result<msgs::SpliceAck,ChannelError> where ES::Target: EntropySource, L::Target: Logger {
10268+ // TODO(splicing): Currently not possible to contribute on the splicing-acceptor side
10269+ let our_funding_contribution_satoshis = 0i64;
1016510270
10166- Ok(channel)
10271+ // TODO(splicing): Store msg.funding_pubkey
10272+
10273+ // Apply start of splice change in the state
10274+ self.context.splice_start(false, logger);
10275+
10276+ let splice_ack_msg = self.context.get_splice_ack(our_funding_contribution_satoshis);
10277+
10278+ // Start interactive funding negotiation. No extra input, as we are not the splice initiator
10279+ let _msg = self.begin_interactive_funding_tx_construction(signer_provider, entropy_source, holder_node_id, None)
10280+ .map_err(|err| ChannelError::Warn(format!("Failed to start interactive transaction construction, {:?}", err)))?;
10281+
10282+ Ok(splice_ack_msg)
1016710283 }
1016810284}
1016910285
0 commit comments