@@ -1556,21 +1556,40 @@ impl<SP: Deref> Channel<SP> where
15561556 L::Target: Logger
15571557 {
15581558 let phase = core::mem::replace(&mut self.phase, ChannelPhase::Undefined);
1559- let result = if let ChannelPhase::UnfundedV2(chan) = phase {
1560- let logger = WithChannelContext::from(logger, &chan.context, None);
1561- match chan.funding_tx_constructed(signing_session, &&logger) {
1562- Ok((chan, commitment_signed, event)) => {
1563- self.phase = ChannelPhase::Funded(chan);
1564- Ok((commitment_signed, event))
1565- },
1566- Err((chan, e)) => {
1567- self.phase = ChannelPhase::UnfundedV2(chan);
1568- Err(e)
1569- },
1559+ let result = match phase {
1560+ ChannelPhase::UnfundedV2(chan) => {
1561+ let logger = WithChannelContext::from(logger, &chan.context, None);
1562+ match chan.funding_tx_constructed(signing_session, &&logger) {
1563+ Ok((chan, commitment_signed, event)) => {
1564+ self.phase = ChannelPhase::Funded(chan);
1565+ Ok((commitment_signed, event))
1566+ },
1567+ Err((chan, e)) => {
1568+ // revert
1569+ self.phase = ChannelPhase::UnfundedV2(chan);
1570+ Err(e)
1571+ },
1572+ }
1573+ }
1574+ #[cfg(splicing)]
1575+ ChannelPhase::RefundingV2(chan) => {
1576+ let logger = WithChannelContext::from(logger, &chan.pre_funded.context, None);
1577+ match chan.funding_tx_constructed(signing_session, &&logger) {
1578+ Ok((signing_session, holder_commitment_point, commitment_signed, event)) => {
1579+ let _res = self.phase_from_splice_to_funded(signing_session, holder_commitment_point)?;
1580+ Ok((commitment_signed, event))
1581+ },
1582+ Err((chan, e)) => {
1583+ // revert
1584+ self.phase = ChannelPhase::RefundingV2(chan);
1585+ Err(e)
1586+ },
1587+ }
1588+ }
1589+ _ => {
1590+ self.phase = phase;
1591+ Err(ChannelError::Warn("Got a tx_complete message with no interactive transaction construction expected or in-progress".to_owned()))
15701592 }
1571- } else {
1572- self.phase = phase;
1573- Err(ChannelError::Warn("Got a tx_complete message with no interactive transaction construction expected or in-progress".to_owned()))
15741593 };
15751594
15761595 debug_assert!(!matches!(self.phase, ChannelPhase::Undefined));
@@ -1580,11 +1599,10 @@ impl<SP: Deref> Channel<SP> where
15801599 /// Transition the channel from Funded to SplicingChannel.
15811600 /// Done in one go, as the existing ('pre') channel is put in the new channel (alongside a new one).
15821601 #[cfg(splicing)]
1583- fn phase_to_splice(&mut self, post_funding: FundingScope, dual_funding_context: DualFundingChannelContext, pending_splice_post: PendingSplicePost) -> Result<(), ChannelError>
1584- {
1602+ fn phase_from_funded_to_splice(&mut self, post_funding: FundingScope, dual_funding_context: DualFundingChannelContext, unfunded_context: UnfundedChannelContext, pending_splice_post: PendingSplicePost) -> Result<(), ChannelError> {
15851603 let phase = core::mem::replace(&mut self.phase, ChannelPhase::Undefined);
15861604 let result = if let ChannelPhase::Funded(prev_chan) = phase {
1587- self.phase = ChannelPhase::RefundingV2(SplicingChannel::new(prev_chan, post_funding, dual_funding_context, pending_splice_post));
1605+ self.phase = ChannelPhase::RefundingV2(SplicingChannel::new(prev_chan, post_funding, dual_funding_context, unfunded_context, pending_splice_post));
15881606 Ok(())
15891607 } else {
15901608 // revert phase
@@ -1595,6 +1613,29 @@ impl<SP: Deref> Channel<SP> where
15951613 result
15961614 }
15971615
1616+ /// Transition the channel from SplicingChannel to Funded, after negotiating new funded.
1617+ #[cfg(splicing)]
1618+ fn phase_from_splice_to_funded(&mut self, signing_session: InteractiveTxSigningSession, holder_commitment_point: HolderCommitmentPoint) -> Result<(), ChannelError> {
1619+ let phase = core::mem::replace(&mut self.phase, ChannelPhase::Undefined);
1620+ let result = if let ChannelPhase::RefundingV2(chan) = phase {
1621+ self.phase = ChannelPhase::Funded(FundedChannel {
1622+ funding: chan.post_funding,
1623+ context: chan.pre_funded.context,
1624+ interactive_tx_signing_session: Some(signing_session),
1625+ holder_commitment_point,
1626+ pending_splice_pre: None,
1627+ pending_splice_post: None,
1628+ });
1629+ Ok(())
1630+ } else {
1631+ // revert phase
1632+ self.phase = phase;
1633+ Err(ChannelError::Warn("Cannot transition away from splicing, not in splicing phase".to_owned()))
1634+ };
1635+ debug_assert!(!matches!(self.phase, ChannelPhase::Undefined));
1636+ result
1637+ }
1638+
15981639 #[cfg(splicing)]
15991640 pub fn splice_init<ES: Deref, L: Deref>(
16001641 &mut self, msg: &msgs::SpliceInit, our_funding_contribution: i64,
@@ -1606,10 +1647,10 @@ impl<SP: Deref> Channel<SP> where
16061647 {
16071648 // Explicit check for Funded, not as_funded; RefundingV2 not allowed
16081649 if let ChannelPhase::Funded(prev_chan) = &mut self.phase {
1609- let (pending_splice_post, post_funding, dual_funding_context) =
1650+ let (pending_splice_post, post_funding, dual_funding_context, unfunded_context ) =
16101651 prev_chan.splice_init(msg, our_funding_contribution)?;
16111652
1612- let _res = self.phase_to_splice (post_funding, dual_funding_context, pending_splice_post)?;
1653+ let _res = self.phase_from_funded_to_splice (post_funding, dual_funding_context, unfunded_context , pending_splice_post)?;
16131654
16141655 if let ChannelPhase::RefundingV2(chan) = &mut self.phase {
16151656 let splice_ack_msg = chan.splice_init(msg, our_funding_contribution, signer_provider, entropy_source, our_node_id, logger)?;
@@ -1633,10 +1674,10 @@ impl<SP: Deref> Channel<SP> where
16331674 {
16341675 // Explicit check for Funded, not as_funded; RefundingV2 not allowed
16351676 if let ChannelPhase::Funded(prev_chan) = &mut self.phase {
1636- let (pending_splice_post, post_funding, dual_funding_context, our_funding_contribution) =
1677+ let (pending_splice_post, post_funding, dual_funding_context, unfunded_context, our_funding_contribution) =
16371678 prev_chan.splice_ack(msg)?;
16381679
1639- let _res = self.phase_to_splice (post_funding, dual_funding_context, pending_splice_post)?;
1680+ let _res = self.phase_from_funded_to_splice (post_funding, dual_funding_context, unfunded_context , pending_splice_post)?;
16401681
16411682 if let ChannelPhase::RefundingV2(chan) = &mut self.phase {
16421683 let tx_msg_opt = chan.splice_ack(msg, our_funding_contribution, signer_provider, entropy_source, our_node_id, logger)?;
@@ -1709,9 +1750,9 @@ pub(super) struct SplicingChannel<SP: Deref> where SP::Target: SignerProvider {
17091750 /// TODO: replace it with its fields; done with trait?
17101751 pub pre_funded: FundedChannel<SP>,
17111752
1712- // Fields for PendingV2Channel follow, except ChannelContext
1753+ // Fields from PendingV2Channel follow, except ChannelContext, which is reused from above
17131754 pub post_funding: FundingScope,
1714- // pub unfunded_context: Option< UnfundedChannelContext> ,
1755+ pub unfunded_context: UnfundedChannelContext,
17151756 /// Used when negotiating the splice transaction
17161757 pub dual_funding_context: DualFundingChannelContext,
17171758 /// The current interactive transaction construction session under negotiation.
@@ -1724,11 +1765,12 @@ pub(super) struct SplicingChannel<SP: Deref> where SP::Target: SignerProvider {
17241765
17251766#[cfg(splicing)]
17261767impl<SP: Deref> SplicingChannel<SP> where SP::Target: SignerProvider {
1727- fn new(pre_funded: FundedChannel<SP>, post_funding: FundingScope, dual_funding_context: DualFundingChannelContext, pending_splice_post: PendingSplicePost) -> Self {
1768+ fn new(pre_funded: FundedChannel<SP>, post_funding: FundingScope, dual_funding_context: DualFundingChannelContext, unfunded_context: UnfundedChannelContext, pending_splice_post: PendingSplicePost) -> Self {
17281769 Self {
17291770 pre_funded,
17301771 post_funding,
17311772 dual_funding_context,
1773+ unfunded_context,
17321774 interactive_tx_constructor: None,
17331775 pending_splice_post,
17341776 }
@@ -1966,15 +2008,100 @@ impl<SP: Deref> SplicingChannel<SP> where SP::Target: SignerProvider {
19662008 HandleTxCompleteResult(Ok(tx_complete))
19672009 }
19682010
1969- // TODO implement and use
1970- // pub fn funding_tx_constructed<L: Deref>(
1971- // self, signing_session: InteractiveTxSigningSession, logger: &L
1972- // ) -> Result<(msgs::CommitmentSigned, Option<Event>), ChannelError> where L::Target: Logger {
1973- // match self.post_pending.funding_tx_constructed(signing_session, logger) {
1974- // Ok((_chan, msg, event)) => Ok((msg, event)),
1975- // Err((_chan, err)) => Err(err),
1976- // }
1977- // }
2011+ /// Copied from PendingV2Channel::funding_tx_constructed
2012+ /// TODO avoid code duplication with traits
2013+ fn funding_tx_constructed<L: Deref>(
2014+ mut self, mut signing_session: InteractiveTxSigningSession, logger: &L
2015+ ) -> Result<(InteractiveTxSigningSession, HolderCommitmentPoint, msgs::CommitmentSigned, Option<Event>), (SplicingChannel<SP>, ChannelError)>
2016+ where
2017+ L::Target: Logger
2018+ {
2019+ let our_funding_satoshis = self.dual_funding_context.our_funding_satoshis;
2020+ let transaction_number = self.unfunded_context.transaction_number();
2021+
2022+ let mut output_index = None;
2023+ let expected_spk = self.pre_funded.context.get_funding_redeemscript().to_p2wsh();
2024+ for (idx, outp) in signing_session.unsigned_tx.outputs().enumerate() {
2025+ if outp.script_pubkey() == &expected_spk && outp.value() == self.post_funding.get_value_satoshis() {
2026+ if output_index.is_some() {
2027+ return Err(ChannelError::Close((
2028+ "Multiple outputs matched the expected script and value".to_owned(),
2029+ ClosureReason::HolderForceClosed { broadcasted_latest_txn: Some(false) },
2030+ ))).map_err(|e| (self, e));
2031+ }
2032+ output_index = Some(idx as u16);
2033+ }
2034+ }
2035+ let outpoint = if let Some(output_index) = output_index {
2036+ OutPoint { txid: signing_session.unsigned_tx.compute_txid(), index: output_index }
2037+ } else {
2038+ return Err(ChannelError::Close((
2039+ "No output matched the funding script_pubkey".to_owned(),
2040+ ClosureReason::HolderForceClosed { broadcasted_latest_txn: Some(false) },
2041+ ))).map_err(|e| (self, e));
2042+ };
2043+ self.pre_funded.context.channel_transaction_parameters.funding_outpoint = Some(outpoint);
2044+ self.pre_funded.context.holder_signer.as_mut().provide_channel_parameters(&self.pre_funded.context.channel_transaction_parameters);
2045+
2046+ self.pre_funded.context.assert_no_commitment_advancement(transaction_number, "initial commitment_signed");
2047+ let commitment_signed = self.pre_funded.context.get_initial_commitment_signed(&self.post_funding, logger);
2048+ let commitment_signed = match commitment_signed {
2049+ Ok(commitment_signed) => {
2050+ // TODO: funding tx should be in FundingContext
2051+ self.pre_funded.context.funding_transaction = Some(signing_session.unsigned_tx.build_unsigned_tx());
2052+ commitment_signed
2053+ },
2054+ Err(err) => {
2055+ self.pre_funded.context.channel_transaction_parameters.funding_outpoint = None;
2056+ return Err(ChannelError::Close((err.to_string(), ClosureReason::HolderForceClosed { broadcasted_latest_txn: Some(false) })))
2057+ .map_err(|e| (self, e));
2058+ },
2059+ };
2060+
2061+ let funding_ready_for_sig_event = None;
2062+ if signing_session.local_inputs_count() == 0 {
2063+ debug_assert_eq!(our_funding_satoshis, 0);
2064+ if signing_session.provide_holder_witnesses(self.pre_funded.context.channel_id, Vec::new()).is_err() {
2065+ debug_assert!(
2066+ false,
2067+ "Zero inputs were provided & zero witnesses were provided, but a count mismatch was somehow found",
2068+ );
2069+ }
2070+ } else {
2071+ // TODO(dual_funding): Send event for signing if we've contributed funds.
2072+ // Inform the user that SIGHASH_ALL must be used for all signatures when contributing
2073+ // inputs/signatures.
2074+ // Also warn the user that we don't do anything to prevent the counterparty from
2075+ // providing non-standard witnesses which will prevent the funding transaction from
2076+ // confirming. This warning must appear in doc comments wherever the user is contributing
2077+ // funds, whether they are initiator or acceptor.
2078+ //
2079+ // The following warning can be used when the APIs allowing contributing inputs become available:
2080+ // <div class="warning">
2081+ // WARNING: LDK makes no attempt to prevent the counterparty from using non-standard inputs which
2082+ // will prevent the funding transaction from being relayed on the bitcoin network and hence being
2083+ // confirmed.
2084+ // </div>
2085+ }
2086+
2087+ self.pre_funded.context.channel_state = ChannelState::FundingNegotiated;
2088+
2089+ // Clear the interactive transaction constructor
2090+ self.interactive_tx_constructor.take();
2091+
2092+ match self.unfunded_context.holder_commitment_point {
2093+ Some(holder_commitment_point) => {
2094+ Ok((signing_session, holder_commitment_point, commitment_signed, funding_ready_for_sig_event))
2095+ },
2096+ None => {
2097+ let err = ChannelError::close(format!(
2098+ "Expected to have holder commitment points available upon finishing interactive tx construction for channel {}",
2099+ self.pre_funded.context.channel_id(),
2100+ ));
2101+ Err((self, err))
2102+ },
2103+ }
2104+ }
19782105}
19792106
19802107/// Contains all state common to unfunded inbound/outbound channels.
@@ -9181,7 +9308,7 @@ impl<SP: Deref> FundedChannel<SP> where
91819308 #[cfg(splicing)]
91829309 fn splice_init(
91839310 &mut self, msg: &msgs::SpliceInit, our_funding_contribution: i64,
9184- ) -> Result<(PendingSplicePost, FundingScope, DualFundingChannelContext), ChannelError>
9311+ ) -> Result<(PendingSplicePost, FundingScope, DualFundingChannelContext, UnfundedChannelContext ), ChannelError>
91859312 {
91869313 let _res = self.splice_init_checks(msg)?;
91879314
@@ -9229,12 +9356,12 @@ impl<SP: Deref> FundedChannel<SP> where
92299356 funding_feerate_sat_per_1000_weight: msg.funding_feerate_per_kw,
92309357 our_funding_inputs: Vec::new(),
92319358 };
9232- // let unfunded_context = UnfundedChannelContext {
9233- // unfunded_channel_age_ticks: 0,
9234- // holder_commitment_point: HolderCommitmentPoint::new(&context.holder_signer, &context.secp_ctx),
9235- // };
9359+ let unfunded_context = UnfundedChannelContext {
9360+ unfunded_channel_age_ticks: 0,
9361+ holder_commitment_point: HolderCommitmentPoint::new(&self. context.holder_signer, &self. context.secp_ctx),
9362+ };
92369363
9237- Ok((pending_splice_post, post_funding, dual_funding_context))
9364+ Ok((pending_splice_post, post_funding, dual_funding_context, unfunded_context ))
92389365 }
92399366
92409367 /// Checks during handling splice_ack
@@ -9252,7 +9379,7 @@ impl<SP: Deref> FundedChannel<SP> where
92529379 #[cfg(splicing)]
92539380 fn splice_ack(
92549381 &mut self, msg: &msgs::SpliceAck,
9255- ) -> Result<(PendingSplicePost, FundingScope, DualFundingChannelContext, i64), ChannelError>
9382+ ) -> Result<(PendingSplicePost, FundingScope, DualFundingChannelContext, UnfundedChannelContext, i64), ChannelError>
92569383 {
92579384 let pending_splice = self.splice_ack_checks()?;
92589385
@@ -9300,12 +9427,12 @@ impl<SP: Deref> FundedChannel<SP> where
93009427 funding_feerate_sat_per_1000_weight: pending_splice.funding_feerate_per_kw,
93019428 our_funding_inputs: pending_splice.our_funding_inputs.clone(),
93029429 };
9303- // let unfunded_context = UnfundedChannelContext {
9304- // unfunded_channel_age_ticks: 0,
9305- // holder_commitment_point: HolderCommitmentPoint::new(&context.holder_signer, &context.secp_ctx),
9306- // };
9430+ let unfunded_context = UnfundedChannelContext {
9431+ unfunded_channel_age_ticks: 0,
9432+ holder_commitment_point: HolderCommitmentPoint::new(&self. context.holder_signer, &self. context.secp_ctx),
9433+ };
93079434
9308- Ok((pending_splice_post, post_funding, dual_funding_context, pending_splice.our_funding_contribution))
9435+ Ok((pending_splice_post, post_funding, dual_funding_context, unfunded_context, pending_splice.our_funding_contribution))
93099436 }
93109437
93119438 // Send stuff to our remote peers:
0 commit comments