@@ -1582,6 +1582,61 @@ impl<SP: Deref> Channel<SP> where
15821582 }
15831583 }
15841584
1585+ pub fn tx_add_input(&mut self, msg: &msgs::TxAddInput) -> Result<InteractiveTxMessageSendResult, ChannelError> {
1586+ match &mut self.phase {
1587+ ChannelPhase::UnfundedV2(chan) => Ok(chan.as_negotiating_channel().tx_add_input(msg)),
1588+ #[cfg(splicing)]
1589+ ChannelPhase::Funded(chan) => Ok(chan.as_renegotiating_channel()
1590+ .map_err(|err| ChannelError::Warn(err.into()))?
1591+ .tx_add_input(msg)),
1592+ _ => Err(ChannelError::Warn("Got tx_add_input in an invalid phase".to_owned())),
1593+ }
1594+ }
1595+
1596+ pub fn tx_add_output(&mut self, msg: &msgs::TxAddOutput) -> Result<InteractiveTxMessageSendResult, ChannelError> {
1597+ match &mut self.phase {
1598+ ChannelPhase::UnfundedV2(chan) => Ok(chan.as_negotiating_channel().tx_add_output(msg)),
1599+ #[cfg(splicing)]
1600+ ChannelPhase::Funded(chan) => Ok(chan.as_renegotiating_channel()
1601+ .map_err(|err| ChannelError::Warn(err.into()))?
1602+ .tx_add_output(msg)),
1603+ _ => Err(ChannelError::Warn("Got tx_add_output in an invalid phase".to_owned())),
1604+ }
1605+ }
1606+
1607+ pub fn tx_remove_input(&mut self, msg: &msgs::TxRemoveInput) -> Result<InteractiveTxMessageSendResult, ChannelError> {
1608+ match &mut self.phase {
1609+ ChannelPhase::UnfundedV2(chan) => Ok(chan.as_negotiating_channel().tx_remove_input(msg)),
1610+ #[cfg(splicing)]
1611+ ChannelPhase::Funded(chan) => Ok(chan.as_renegotiating_channel()
1612+ .map_err(|err| ChannelError::Warn(err.into()))?
1613+ .tx_remove_input(msg)),
1614+ _ => Err(ChannelError::Warn("Got tx_remove_input in an invalid phase".to_owned())),
1615+ }
1616+ }
1617+
1618+ pub fn tx_remove_output(&mut self, msg: &msgs::TxRemoveOutput) -> Result<InteractiveTxMessageSendResult, ChannelError> {
1619+ match &mut self.phase {
1620+ ChannelPhase::UnfundedV2(chan) => Ok(chan.as_negotiating_channel().tx_remove_output(msg)),
1621+ #[cfg(splicing)]
1622+ ChannelPhase::Funded(chan) => Ok(chan.as_renegotiating_channel()
1623+ .map_err(|err| ChannelError::Warn(err.into()))?
1624+ .tx_remove_output(msg)),
1625+ _ => Err(ChannelError::Warn("Got tx_remove_output in an invalid phase".to_owned())),
1626+ }
1627+ }
1628+
1629+ pub fn tx_complete(&mut self, msg: &msgs::TxComplete) -> Result<HandleTxCompleteResult, ChannelError> {
1630+ match &mut self.phase {
1631+ ChannelPhase::UnfundedV2(chan) => Ok(chan.as_negotiating_channel().tx_complete(msg)),
1632+ #[cfg(splicing)]
1633+ ChannelPhase::Funded(chan) => Ok(chan.as_renegotiating_channel()
1634+ .map_err(|err| ChannelError::Warn(err.into()))?
1635+ .tx_complete(msg)),
1636+ _ => Err(ChannelError::Warn("Got tx_complete in an invalid phase".to_owned())),
1637+ }
1638+ }
1639+
15851640 pub fn funding_signed<L: Deref>(
15861641 &mut self, msg: &msgs::FundingSigned, best_block: BestBlock, signer_provider: &SP, logger: &L
15871642 ) -> Result<(&mut FundedChannel<SP>, ChannelMonitor<<SP::Target as SignerProvider>::EcdsaSigner>), ChannelError>
@@ -1621,7 +1676,7 @@ impl<SP: Deref> Channel<SP> where
16211676 {
16221677 if let ChannelPhase::UnfundedV2(chan) = &mut self.phase {
16231678 let logger = WithChannelContext::from(logger, &chan.context, None);
1624- chan.funding_tx_constructed(signing_session, &&logger)
1679+ chan.as_negotiating_channel(). funding_tx_constructed(signing_session, &&logger)
16251680 } else {
16261681 Err(ChannelError::Warn("Got a tx_complete message with no interactive transaction construction expected or in-progress".to_owned()))
16271682 }
@@ -1932,10 +1987,19 @@ impl FundingScope {
19321987 }
19331988}
19341989
1935- /// Info about a pending splice, used in the pre-splice channel
1990+ /// Info about a pending splice
19361991#[cfg(splicing)]
19371992struct PendingSplice {
1993+ /// Intended contributions to the splice from our end
19381994 pub our_funding_contribution: i64,
1995+ /// Set when splice_ack has been processed (on the initiator side),
1996+ /// used to prevent processing of multiple splice_ack's.
1997+ awaiting_splice_ack: bool,
1998+ funding_scope: Option<FundingScope>,
1999+ funding_negotiation_context: FundingNegotiationContext,
2000+ /// The current interactive transaction construction session under negotiation.
2001+ interactive_tx_constructor: Option<InteractiveTxConstructor>,
2002+ interactive_tx_signing_session: Option<InteractiveTxSigningSession>,
19392003}
19402004
19412005/// Contains everything about the channel including state, and various flags.
@@ -2399,10 +2463,12 @@ impl<SP: Deref> InitialRemoteCommitmentReceiver<SP> for InboundV1Channel<SP> whe
23992463}
24002464
24012465impl<SP: Deref> InitialRemoteCommitmentReceiver<SP> for FundedChannel<SP> where SP::Target: SignerProvider {
2466+ #[inline]
24022467 fn context(&self) -> &ChannelContext<SP> {
24032468 &self.context
24042469 }
24052470
2471+ #[inline]
24062472 fn context_mut(&mut self) -> &mut ChannelContext<SP> {
24072473 &mut self.context
24082474 }
@@ -2432,7 +2498,21 @@ impl<SP: Deref> InitialRemoteCommitmentReceiver<SP> for FundedChannel<SP> where
24322498 }
24332499}
24342500
2435- impl<SP: Deref> PendingV2Channel<SP> where SP::Target: SignerProvider {
2501+ /// A short-lived subset view of a channel, used for V2 funding negotiation or re-negotiation.
2502+ /// Can be produced by:
2503+ /// - [`PendingV2Channel`], at V2 channel open, and
2504+ /// - [`FundedChannel`], when splicing.
2505+ struct NegotiatingV2ChannelView<'a, SP: Deref> where SP::Target: SignerProvider {
2506+ context: &'a mut ChannelContext<SP>,
2507+ funding: &'a mut FundingScope,
2508+ funding_negotiation_context: &'a mut FundingNegotiationContext,
2509+ interactive_tx_constructor: &'a mut Option<InteractiveTxConstructor>,
2510+ interactive_tx_signing_session: &'a mut Option<InteractiveTxSigningSession>,
2511+ holder_commitment_transaction_number: u64,
2512+ is_splice: bool,
2513+ }
2514+
2515+ impl<'a, SP: Deref> NegotiatingV2ChannelView<'a, SP> where SP::Target: SignerProvider {
24362516 /// Prepare and start interactive transaction negotiation.
24372517 /// `change_destination_opt` - Optional destination for optional change; if None,
24382518 /// default destination address is used.
@@ -2522,13 +2602,13 @@ impl<SP: Deref> PendingV2Channel<SP> where SP::Target: SignerProvider {
25222602 let mut tx_constructor = InteractiveTxConstructor::new(constructor_args)?;
25232603 let msg = tx_constructor.take_initiator_first_message();
25242604
2525- self.interactive_tx_constructor = Some(tx_constructor);
2605+ * self.interactive_tx_constructor = Some(tx_constructor);
25262606
25272607 Ok(msg)
25282608 }
25292609
2530- pub fn tx_add_input(&mut self, msg: &msgs::TxAddInput) -> InteractiveTxMessageSendResult {
2531- InteractiveTxMessageSendResult(match &mut self.interactive_tx_constructor {
2610+ fn tx_add_input(&mut self, msg: &msgs::TxAddInput) -> InteractiveTxMessageSendResult {
2611+ InteractiveTxMessageSendResult(match self.interactive_tx_constructor {
25322612 Some(ref mut tx_constructor) => tx_constructor.handle_tx_add_input(msg).map_err(
25332613 |reason| reason.into_tx_abort_msg(self.context.channel_id())),
25342614 None => Err(msgs::TxAbort {
@@ -2538,8 +2618,8 @@ impl<SP: Deref> PendingV2Channel<SP> where SP::Target: SignerProvider {
25382618 })
25392619 }
25402620
2541- pub fn tx_add_output(&mut self, msg: &msgs::TxAddOutput)-> InteractiveTxMessageSendResult {
2542- InteractiveTxMessageSendResult(match &mut self.interactive_tx_constructor {
2621+ fn tx_add_output(&mut self, msg: &msgs::TxAddOutput)-> InteractiveTxMessageSendResult {
2622+ InteractiveTxMessageSendResult(match self.interactive_tx_constructor {
25432623 Some(ref mut tx_constructor) => tx_constructor.handle_tx_add_output(msg).map_err(
25442624 |reason| reason.into_tx_abort_msg(self.context.channel_id())),
25452625 None => Err(msgs::TxAbort {
@@ -2549,8 +2629,8 @@ impl<SP: Deref> PendingV2Channel<SP> where SP::Target: SignerProvider {
25492629 })
25502630 }
25512631
2552- pub fn tx_remove_input(&mut self, msg: &msgs::TxRemoveInput)-> InteractiveTxMessageSendResult {
2553- InteractiveTxMessageSendResult(match &mut self.interactive_tx_constructor {
2632+ fn tx_remove_input(&mut self, msg: &msgs::TxRemoveInput)-> InteractiveTxMessageSendResult {
2633+ InteractiveTxMessageSendResult(match self.interactive_tx_constructor {
25542634 Some(ref mut tx_constructor) => tx_constructor.handle_tx_remove_input(msg).map_err(
25552635 |reason| reason.into_tx_abort_msg(self.context.channel_id())),
25562636 None => Err(msgs::TxAbort {
@@ -2560,8 +2640,8 @@ impl<SP: Deref> PendingV2Channel<SP> where SP::Target: SignerProvider {
25602640 })
25612641 }
25622642
2563- pub fn tx_remove_output(&mut self, msg: &msgs::TxRemoveOutput)-> InteractiveTxMessageSendResult {
2564- InteractiveTxMessageSendResult(match &mut self.interactive_tx_constructor {
2643+ fn tx_remove_output(&mut self, msg: &msgs::TxRemoveOutput)-> InteractiveTxMessageSendResult {
2644+ InteractiveTxMessageSendResult(match self.interactive_tx_constructor {
25652645 Some(ref mut tx_constructor) => tx_constructor.handle_tx_remove_output(msg).map_err(
25662646 |reason| reason.into_tx_abort_msg(self.context.channel_id())),
25672647 None => Err(msgs::TxAbort {
@@ -2571,9 +2651,9 @@ impl<SP: Deref> PendingV2Channel<SP> where SP::Target: SignerProvider {
25712651 })
25722652 }
25732653
2574- pub fn tx_complete(&mut self, msg: &msgs::TxComplete) -> HandleTxCompleteResult {
2575- let tx_constructor = match &mut self.interactive_tx_constructor {
2576- Some(ref mut tx_constructor) => tx_constructor,
2654+ fn tx_complete(&mut self, msg: &msgs::TxComplete) -> HandleTxCompleteResult {
2655+ let tx_constructor = match self.interactive_tx_constructor {
2656+ Some(tx_constructor) => tx_constructor,
25772657 None => {
25782658 let tx_abort = msgs::TxAbort {
25792659 channel_id: msg.channel_id,
@@ -2593,14 +2673,14 @@ impl<SP: Deref> PendingV2Channel<SP> where SP::Target: SignerProvider {
25932673 HandleTxCompleteResult(Ok(tx_complete))
25942674 }
25952675
2596- pub fn funding_tx_constructed<L: Deref>(
2676+ fn funding_tx_constructed<L: Deref>(
25972677 &mut self, mut signing_session: InteractiveTxSigningSession, logger: &L
25982678 ) -> Result<(msgs::CommitmentSigned, Option<Event>), ChannelError>
25992679 where
26002680 L::Target: Logger
26012681 {
2602- let our_funding_satoshis = self.funding_negotiation_context.our_funding_satoshis;
2603- let transaction_number = self.unfunded_context.transaction_number() ;
2682+ let our_funding_satoshis = self.funding_negotiation_context
2683+ .our_funding_satoshis ;
26042684
26052685 let mut output_index = None;
26062686 let expected_spk = self.funding.get_funding_redeemscript().to_p2wsh();
@@ -2627,7 +2707,7 @@ impl<SP: Deref> PendingV2Channel<SP> where SP::Target: SignerProvider {
26272707 };
26282708 self.funding.channel_transaction_parameters.funding_outpoint = Some(outpoint);
26292709
2630- self.context.assert_no_commitment_advancement(transaction_number , "initial commitment_signed");
2710+ self.context.assert_no_commitment_advancement(self.holder_commitment_transaction_number , "initial commitment_signed");
26312711 let commitment_signed = self.context.get_initial_commitment_signed(&self.funding, logger);
26322712 let commitment_signed = match commitment_signed {
26332713 Ok(commitment_signed) => commitment_signed,
@@ -2680,8 +2760,8 @@ impl<SP: Deref> PendingV2Channel<SP> where SP::Target: SignerProvider {
26802760 self.context.channel_state = channel_state;
26812761
26822762 // Clear the interactive transaction constructor
2683- self.interactive_tx_constructor.take() ;
2684- self.interactive_tx_signing_session = Some(signing_session);
2763+ * self.interactive_tx_constructor = None ;
2764+ * self.interactive_tx_signing_session = Some(signing_session);
26852765
26862766 Ok((commitment_signed, funding_ready_for_sig_event))
26872767 }
@@ -5262,6 +5342,35 @@ impl<SP: Deref> FundedChannel<SP> where
52625342 SP::Target: SignerProvider,
52635343 <SP::Target as SignerProvider>::EcdsaSigner: EcdsaChannelSigner
52645344{
5345+ /// If we are in splicing/refunding, return a short-lived [`NegotiatingV2ChannelView`].
5346+ #[cfg(splicing)]
5347+ fn as_renegotiating_channel(&mut self) -> Result<NegotiatingV2ChannelView<SP>, &'static str> {
5348+ if let Some(ref mut pending_splice) = &mut self.pending_splice {
5349+ if let Some(ref mut funding) = &mut pending_splice.funding_scope {
5350+ if
5351+ pending_splice.funding_negotiation_context.our_funding_satoshis != 0 ||
5352+ pending_splice.funding_negotiation_context.their_funding_satoshis.unwrap_or_default() != 0
5353+ {
5354+ Ok(NegotiatingV2ChannelView {
5355+ context: &mut self.context,
5356+ funding,
5357+ funding_negotiation_context: &mut pending_splice.funding_negotiation_context,
5358+ interactive_tx_constructor: &mut pending_splice.interactive_tx_constructor,
5359+ interactive_tx_signing_session: &mut pending_splice.interactive_tx_signing_session,
5360+ holder_commitment_transaction_number: self.holder_commitment_point.transaction_number(),
5361+ is_splice: true,
5362+ })
5363+ } else {
5364+ Err("Channel is not actively refunding")
5365+ }
5366+ } else {
5367+ Err("Channel is not refunding")
5368+ }
5369+ } else {
5370+ Err("Channel is not splice pending")
5371+ }
5372+ }
5373+
52655374 fn check_remote_fee<F: Deref, L: Deref>(
52665375 channel_type: &ChannelTypeFeatures, fee_estimator: &LowerBoundedFeeEstimator<F>,
52675376 feerate_per_kw: u32, cur_feerate_per_kw: Option<u32>, logger: &L
@@ -8895,10 +9004,11 @@ impl<SP: Deref> FundedChannel<SP> where
88959004 ) -> Result<msgs::SpliceInit, APIError> {
88969005 // Check if a splice has been initiated already.
88979006 // Note: only a single outstanding splice is supported (per spec)
8898- if let Some(splice_info ) = &self.pending_splice {
9007+ if let Some(pending_splice ) = &self.pending_splice {
88999008 return Err(APIError::APIMisuseError { err: format!(
89009009 "Channel {} cannot be spliced, as it has already a splice pending (contribution {})",
8901- self.context.channel_id(), splice_info.our_funding_contribution
9010+ self.context.channel_id(),
9011+ pending_splice.our_funding_contribution,
89029012 )});
89039013 }
89049014
@@ -8930,9 +9040,27 @@ impl<SP: Deref> FundedChannel<SP> where
89309040 "Insufficient inputs for splicing; channel ID {}, err {}",
89319041 self.context.channel_id(), err,
89329042 )})?;
9043+ // Convert inputs
9044+ let mut funding_inputs = Vec::new();
9045+ for (tx_in, tx, _w) in our_funding_inputs.into_iter() {
9046+ let tx16 = TransactionU16LenLimited::new(tx.clone()).map_err(|_e| APIError::APIMisuseError { err: format!("Too large transaction")})?;
9047+ funding_inputs.push((tx_in.clone(), tx16));
9048+ }
89339049
9050+ let funding_negotiation_context = FundingNegotiationContext {
9051+ our_funding_satoshis: 0, // set at later phase
9052+ their_funding_satoshis: None, // set at later phase
9053+ funding_tx_locktime: LockTime::from_consensus(locktime),
9054+ funding_feerate_sat_per_1000_weight: funding_feerate_per_kw,
9055+ our_funding_inputs: funding_inputs,
9056+ };
89349057 self.pending_splice = Some(PendingSplice {
89359058 our_funding_contribution: our_funding_contribution_satoshis,
9059+ awaiting_splice_ack: true, // we await splice_ack
9060+ funding_scope: None,
9061+ funding_negotiation_context,
9062+ interactive_tx_constructor: None,
9063+ interactive_tx_signing_session: None,
89369064 });
89379065
89389066 let msg = self.get_splice_init(our_funding_contribution_satoshis, funding_feerate_per_kw, locktime);
@@ -8965,9 +9093,11 @@ impl<SP: Deref> FundedChannel<SP> where
89659093 let our_funding_contribution_satoshis = 0i64;
89669094
89679095 // Check if a splice has been initiated already.
8968- if let Some(splice_info ) = &self.pending_splice {
9096+ if let Some(pending_splice ) = &self.pending_splice {
89699097 return Err(ChannelError::Warn(format!(
8970- "Channel has already a splice pending, contribution {}", splice_info.our_funding_contribution,
9098+ "Channel {} has already a splice pending, contribution {}",
9099+ self.context.channel_id(),
9100+ pending_splice.our_funding_contribution,
89719101 )));
89729102 }
89739103
@@ -10648,6 +10778,19 @@ impl<SP: Deref> PendingV2Channel<SP> where SP::Target: SignerProvider {
1064810778 pub fn get_accept_channel_v2_message(&self) -> msgs::AcceptChannelV2 {
1064910779 self.generate_accept_channel_v2_message()
1065010780 }
10781+
10782+ /// Return a short-lived [`NegotiatingV2ChannelView`].
10783+ fn as_negotiating_channel(&mut self) -> NegotiatingV2ChannelView<SP> {
10784+ NegotiatingV2ChannelView {
10785+ context: &mut self.context,
10786+ funding: &mut self.funding,
10787+ funding_negotiation_context: &mut self.funding_negotiation_context,
10788+ interactive_tx_constructor: &mut self.interactive_tx_constructor,
10789+ interactive_tx_signing_session: &mut self.interactive_tx_signing_session,
10790+ holder_commitment_transaction_number: self.unfunded_context.transaction_number(),
10791+ is_splice: false,
10792+ }
10793+ }
1065110794}
1065210795
1065310796// Unfunded channel utilities
0 commit comments