@@ -1335,6 +1335,7 @@ impl<SP: Deref> Channel<SP> where
13351335 }
13361336 }
13371337
1338+ #[cfg(splicing)]
13381339 fn as_splicing_mut(&mut self) -> Option<&mut SplicingChannel<SP>> {
13391340 if let ChannelPhase::RefundingV2(channel) = &mut self.phase {
13401341 Some(channel)
@@ -1481,6 +1482,7 @@ impl<SP: Deref> Channel<SP> where
14811482 if let Some(unfunded) = self.as_unfunded_v2_mut() {
14821483 return unfunded.tx_add_input(msg);
14831484 }
1485+ #[cfg(splicing)]
14841486 if let Some(splicing) = self.as_splicing_mut() {
14851487 return splicing.tx_add_input(msg);
14861488 }
@@ -1492,6 +1494,7 @@ impl<SP: Deref> Channel<SP> where
14921494 if let Some(unfunded) = self.as_unfunded_v2_mut() {
14931495 return unfunded.tx_add_output(msg);
14941496 }
1497+ #[cfg(splicing)]
14951498 if let Some(splicing) = self.as_splicing_mut() {
14961499 return splicing.tx_add_output(msg);
14971500 }
@@ -1503,6 +1506,7 @@ impl<SP: Deref> Channel<SP> where
15031506 if let Some(unfunded) = self.as_unfunded_v2_mut() {
15041507 return unfunded.tx_complete(msg);
15051508 }
1509+ #[cfg(splicing)]
15061510 if let Some(splicing) = self.as_splicing_mut() {
15071511 return splicing.tx_complete(msg);
15081512 }
@@ -1546,22 +1550,55 @@ impl<SP: Deref> Channel<SP> where
15461550 where
15471551 L::Target: Logger
15481552 {
1549- if let ChannelPhase::UnfundedV2(chan) = &mut self.phase {
1550- let logger = WithChannelContext::from(logger, &chan.context, None);
1551- chan.funding_tx_constructed(signing_session, &&logger)
1552- } else {
1553- Err(ChannelError::Warn("Got a tx_complete message with no interactive transaction construction expected or in-progress".to_owned()))
1554- }
1553+ let phase = core::mem::replace(&mut self.phase, ChannelPhase::Undefined);
1554+ let result = match phase {
1555+ ChannelPhase::UnfundedV2(mut chan) => {
1556+ let logger = WithChannelContext::from(logger, &chan.context, None);
1557+ match chan.funding_tx_constructed(signing_session, &&logger) {
1558+ Ok((commitment_signed, event)) => {
1559+ // TODO: Transition to Funded ? Which chan? // self.phase = ChannelPhase::Funded(chan);
1560+ self.phase = ChannelPhase::UnfundedV2(chan);
1561+ Ok((commitment_signed, event))
1562+ },
1563+ Err(e) => {
1564+ // revert
1565+ self.phase = ChannelPhase::UnfundedV2(chan);
1566+ Err(e)
1567+ },
1568+ }
1569+ }
1570+ #[cfg(splicing)]
1571+ ChannelPhase::RefundingV2(chan) => {
1572+ let logger = WithChannelContext::from(logger, &chan.pre_funded.context, None);
1573+ match chan.funding_tx_constructed(signing_session, &&logger) {
1574+ Ok((signing_session, holder_commitment_point, commitment_signed, event)) => {
1575+ let _res = self.phase_from_splice_to_funded(signing_session, holder_commitment_point)?;
1576+ Ok((commitment_signed, event))
1577+ },
1578+ Err((chan, e)) => {
1579+ // revert
1580+ self.phase = ChannelPhase::RefundingV2(chan);
1581+ Err(e)
1582+ },
1583+ }
1584+ }
1585+ _ => {
1586+ self.phase = phase;
1587+ Err(ChannelError::Warn("Got a tx_complete message with no interactive transaction construction expected or in-progress".to_owned()))
1588+ }
1589+ };
1590+
1591+ debug_assert!(!matches!(self.phase, ChannelPhase::Undefined));
1592+ result
15551593 }
15561594
15571595 /// Transition the channel from Funded to SplicingChannel.
15581596 /// Done in one go, as the existing ('pre') channel is put in the new channel (alongside a new one).
15591597 #[cfg(splicing)]
1560- fn phase_to_splice(&mut self, post_funding: FundingScope, dual_funding_context: DualFundingChannelContext, pending_splice_post: PendingSplicePost) -> Result<(), ChannelError>
1561- {
1598+ fn phase_from_funded_to_splice(&mut self, post_funding: FundingScope, dual_funding_context: DualFundingChannelContext, unfunded_context: UnfundedChannelContext, pending_splice_post: PendingSplicePost) -> Result<(), ChannelError> {
15621599 let phase = core::mem::replace(&mut self.phase, ChannelPhase::Undefined);
15631600 let result = if let ChannelPhase::Funded(prev_chan) = phase {
1564- self.phase = ChannelPhase::RefundingV2(SplicingChannel::new(prev_chan, post_funding, dual_funding_context, pending_splice_post));
1601+ self.phase = ChannelPhase::RefundingV2(SplicingChannel::new(prev_chan, post_funding, dual_funding_context, unfunded_context, pending_splice_post));
15651602 Ok(())
15661603 } else {
15671604 // revert phase
@@ -1572,6 +1609,30 @@ impl<SP: Deref> Channel<SP> where
15721609 result
15731610 }
15741611
1612+ /// Transition the channel from SplicingChannel to Funded, after negotiating new funded.
1613+ #[cfg(splicing)]
1614+ fn phase_from_splice_to_funded(&mut self, signing_session: InteractiveTxSigningSession, holder_commitment_point: HolderCommitmentPoint) -> Result<(), ChannelError> {
1615+ let phase = core::mem::replace(&mut self.phase, ChannelPhase::Undefined);
1616+ let result = if let ChannelPhase::RefundingV2(chan) = phase {
1617+ self.phase = ChannelPhase::Funded(FundedChannel {
1618+ funding: chan.post_funding,
1619+ context: chan.pre_funded.context,
1620+ interactive_tx_signing_session: Some(signing_session),
1621+ holder_commitment_point,
1622+ is_v2_established: true,
1623+ pending_splice_pre: None,
1624+ pending_splice_post: None,
1625+ });
1626+ Ok(())
1627+ } else {
1628+ // revert phase
1629+ self.phase = phase;
1630+ Err(ChannelError::Warn("Cannot transition away from splicing, not in splicing phase".to_owned()))
1631+ };
1632+ debug_assert!(!matches!(self.phase, ChannelPhase::Undefined));
1633+ result
1634+ }
1635+
15751636 #[cfg(splicing)]
15761637 pub fn splice_init<ES: Deref, L: Deref>(
15771638 &mut self, msg: &msgs::SpliceInit, our_funding_contribution: i64,
@@ -1583,10 +1644,10 @@ impl<SP: Deref> Channel<SP> where
15831644 {
15841645 // Explicit check for Funded, not as_funded; RefundingV2 not allowed
15851646 if let ChannelPhase::Funded(prev_chan) = &mut self.phase {
1586- let (pending_splice_post, post_funding, dual_funding_context) =
1647+ let (pending_splice_post, post_funding, dual_funding_context, unfunded_context ) =
15871648 prev_chan.splice_init(msg, our_funding_contribution)?;
15881649
1589- let _res = self.phase_to_splice (post_funding, dual_funding_context, pending_splice_post)?;
1650+ let _res = self.phase_from_funded_to_splice (post_funding, dual_funding_context, unfunded_context , pending_splice_post)?;
15901651
15911652 if let ChannelPhase::RefundingV2(chan) = &mut self.phase {
15921653 let splice_ack_msg = chan.splice_init(msg, our_funding_contribution, signer_provider, entropy_source, our_node_id, logger)?;
@@ -1610,10 +1671,10 @@ impl<SP: Deref> Channel<SP> where
16101671 {
16111672 // Explicit check for Funded, not as_funded; RefundingV2 not allowed
16121673 if let ChannelPhase::Funded(prev_chan) = &mut self.phase {
1613- let (pending_splice_post, post_funding, dual_funding_context, our_funding_contribution) =
1674+ let (pending_splice_post, post_funding, dual_funding_context, unfunded_context, our_funding_contribution) =
16141675 prev_chan.splice_ack(msg)?;
16151676
1616- let _res = self.phase_to_splice (post_funding, dual_funding_context, pending_splice_post)?;
1677+ let _res = self.phase_from_funded_to_splice (post_funding, dual_funding_context, unfunded_context , pending_splice_post)?;
16171678
16181679 if let ChannelPhase::RefundingV2(chan) = &mut self.phase {
16191680 let tx_msg_opt = chan.splice_ack(msg, our_funding_contribution, signer_provider, entropy_source, our_node_id, logger)?;
@@ -1740,9 +1801,9 @@ pub(super) struct SplicingChannel<SP: Deref> where SP::Target: SignerProvider {
17401801 /// TODO: replace it with its fields; done with trait?
17411802 pub pre_funded: FundedChannel<SP>,
17421803
1743- // Fields for PendingV2Channel follow, except ChannelContext
1804+ // Fields from PendingV2Channel follow, except ChannelContext, which is reused from above
17441805 pub post_funding: FundingScope,
1745- // pub unfunded_context: Option< UnfundedChannelContext> ,
1806+ pub unfunded_context: UnfundedChannelContext,
17461807 /// Used when negotiating the splice transaction
17471808 pub dual_funding_context: DualFundingChannelContext,
17481809 /// The current interactive transaction construction session under negotiation.
@@ -1755,18 +1816,18 @@ pub(super) struct SplicingChannel<SP: Deref> where SP::Target: SignerProvider {
17551816
17561817#[cfg(splicing)]
17571818impl<SP: Deref> SplicingChannel<SP> where SP::Target: SignerProvider {
1758- fn new(pre_funded: FundedChannel<SP>, post_funding: FundingScope, dual_funding_context: DualFundingChannelContext, pending_splice_post: PendingSplicePost) -> Self {
1819+ fn new(pre_funded: FundedChannel<SP>, post_funding: FundingScope, dual_funding_context: DualFundingChannelContext, unfunded_context: UnfundedChannelContext, pending_splice_post: PendingSplicePost) -> Self {
17591820 Self {
17601821 pre_funded,
17611822 post_funding,
17621823 dual_funding_context,
1824+ unfunded_context,
17631825 interactive_tx_constructor: None,
17641826 pending_splice_post,
17651827 }
17661828 }
17671829
17681830 /// Handle splice_init
1769- #[cfg(splicing)]
17701831 pub fn splice_init<ES: Deref, L: Deref>(
17711832 &mut self, _msg: &msgs::SpliceInit, our_funding_contribution: i64,
17721833 signer_provider: &SP, entropy_source: &ES, holder_node_id: &PublicKey, logger: &L,
@@ -1788,7 +1849,6 @@ impl<SP: Deref> SplicingChannel<SP> where SP::Target: SignerProvider {
17881849 }
17891850
17901851 /// Handle splice_ack
1791- #[cfg(splicing)]
17921852 pub fn splice_ack<ES: Deref, L: Deref>(
17931853 &mut self, msg: &msgs::SpliceAck, our_funding_contribution: i64,
17941854 signer_provider: &SP, entropy_source: &ES, holder_node_id: &PublicKey, logger: &L,
@@ -1824,7 +1884,6 @@ impl<SP: Deref> SplicingChannel<SP> where SP::Target: SignerProvider {
18241884 }
18251885
18261886 /// Splice process starting; update state, log, etc.
1827- #[cfg(splicing)]
18281887 pub(crate) fn splice_start<L: Deref>(&mut self, is_outgoing: bool, logger: &L) where L::Target: Logger {
18291888 // Set state, by this point splice_init/splice_ack handshake is complete
18301889 // TODO(splicing)
@@ -1997,15 +2056,99 @@ impl<SP: Deref> SplicingChannel<SP> where SP::Target: SignerProvider {
19972056 HandleTxCompleteResult(Ok(tx_complete))
19982057 }
19992058
2000- // TODO implement and use
2001- // pub fn funding_tx_constructed<L: Deref>(
2002- // self, signing_session: InteractiveTxSigningSession, logger: &L
2003- // ) -> Result<(msgs::CommitmentSigned, Option<Event>), ChannelError> where L::Target: Logger {
2004- // match self.post_pending.funding_tx_constructed(signing_session, logger) {
2005- // Ok((_chan, msg, event)) => Ok((msg, event)),
2006- // Err((_chan, err)) => Err(err),
2007- // }
2008- // }
2059+ /// Copied from PendingV2Channel::funding_tx_constructed
2060+ /// TODO avoid code duplication with traits
2061+ fn funding_tx_constructed<L: Deref>(
2062+ mut self, mut signing_session: InteractiveTxSigningSession, logger: &L
2063+ ) -> Result<(InteractiveTxSigningSession, HolderCommitmentPoint, msgs::CommitmentSigned, Option<Event>), (SplicingChannel<SP>, ChannelError)>
2064+ where
2065+ L::Target: Logger
2066+ {
2067+ let our_funding_satoshis = self.dual_funding_context.our_funding_satoshis;
2068+ let transaction_number = self.unfunded_context.transaction_number();
2069+
2070+ let mut output_index = None;
2071+ let expected_spk = self.pre_funded.funding.get_funding_redeemscript().to_p2wsh();
2072+ for (idx, outp) in signing_session.unsigned_tx.outputs().enumerate() {
2073+ if outp.script_pubkey() == &expected_spk && outp.value() == self.post_funding.get_value_satoshis() {
2074+ if output_index.is_some() {
2075+ return Err(ChannelError::Close((
2076+ "Multiple outputs matched the expected script and value".to_owned(),
2077+ ClosureReason::HolderForceClosed { broadcasted_latest_txn: Some(false) },
2078+ ))).map_err(|e| (self, e));
2079+ }
2080+ output_index = Some(idx as u16);
2081+ }
2082+ }
2083+ let outpoint = if let Some(output_index) = output_index {
2084+ OutPoint { txid: signing_session.unsigned_tx.compute_txid(), index: output_index }
2085+ } else {
2086+ return Err(ChannelError::Close((
2087+ "No output matched the funding script_pubkey".to_owned(),
2088+ ClosureReason::HolderForceClosed { broadcasted_latest_txn: Some(false) },
2089+ ))).map_err(|e| (self, e));
2090+ };
2091+ self.pre_funded.funding.channel_transaction_parameters.funding_outpoint = Some(outpoint);
2092+ // self.pre_funded.context.holder_signer.as_mut_ecdsa().provide_channel_parameters(&self.pre_funded.funding.channel_transaction_parameters);
2093+
2094+ self.pre_funded.context.assert_no_commitment_advancement(transaction_number, "initial commitment_signed");
2095+ let commitment_signed = self.pre_funded.context.get_initial_commitment_signed(&self.post_funding, logger);
2096+ let commitment_signed = match commitment_signed {
2097+ Ok(commitment_signed) => {
2098+ self.pre_funded.funding.funding_transaction = Some(signing_session.unsigned_tx.build_unsigned_tx());
2099+ commitment_signed
2100+ },
2101+ Err(err) => {
2102+ self.pre_funded.funding.channel_transaction_parameters.funding_outpoint = None;
2103+ return Err(ChannelError::Close((err.to_string(), ClosureReason::HolderForceClosed { broadcasted_latest_txn: Some(false) })))
2104+ .map_err(|e| (self, e));
2105+ },
2106+ };
2107+
2108+ let funding_ready_for_sig_event = None;
2109+ if signing_session.local_inputs_count() == 0 {
2110+ debug_assert_eq!(our_funding_satoshis, 0);
2111+ if signing_session.provide_holder_witnesses(self.pre_funded.context.channel_id, Vec::new()).is_err() {
2112+ debug_assert!(
2113+ false,
2114+ "Zero inputs were provided & zero witnesses were provided, but a count mismatch was somehow found",
2115+ );
2116+ }
2117+ } else {
2118+ // TODO(dual_funding): Send event for signing if we've contributed funds.
2119+ // Inform the user that SIGHASH_ALL must be used for all signatures when contributing
2120+ // inputs/signatures.
2121+ // Also warn the user that we don't do anything to prevent the counterparty from
2122+ // providing non-standard witnesses which will prevent the funding transaction from
2123+ // confirming. This warning must appear in doc comments wherever the user is contributing
2124+ // funds, whether they are initiator or acceptor.
2125+ //
2126+ // The following warning can be used when the APIs allowing contributing inputs become available:
2127+ // <div class="warning">
2128+ // WARNING: LDK makes no attempt to prevent the counterparty from using non-standard inputs which
2129+ // will prevent the funding transaction from being relayed on the bitcoin network and hence being
2130+ // confirmed.
2131+ // </div>
2132+ }
2133+
2134+ self.pre_funded.context.channel_state = ChannelState::FundingNegotiated;
2135+
2136+ // Clear the interactive transaction constructor
2137+ self.interactive_tx_constructor.take();
2138+
2139+ match self.unfunded_context.holder_commitment_point {
2140+ Some(holder_commitment_point) => {
2141+ Ok((signing_session, holder_commitment_point, commitment_signed, funding_ready_for_sig_event))
2142+ },
2143+ None => {
2144+ let err = ChannelError::close(format!(
2145+ "Expected to have holder commitment points available upon finishing interactive tx construction for channel {}",
2146+ self.pre_funded.context.channel_id(),
2147+ ));
2148+ Err((self, err))
2149+ },
2150+ }
2151+ }
20092152}
20102153
20112154/// Contains all state common to unfunded inbound/outbound channels.
@@ -9213,7 +9356,7 @@ impl<SP: Deref> FundedChannel<SP> where
92139356 #[cfg(splicing)]
92149357 fn splice_init(
92159358 &mut self, msg: &msgs::SpliceInit, our_funding_contribution: i64,
9216- ) -> Result<(PendingSplicePost, FundingScope, DualFundingChannelContext), ChannelError>
9359+ ) -> Result<(PendingSplicePost, FundingScope, DualFundingChannelContext, UnfundedChannelContext ), ChannelError>
92179360 {
92189361 let _res = self.splice_init_checks(msg)?;
92199362
@@ -9264,12 +9407,12 @@ impl<SP: Deref> FundedChannel<SP> where
92649407 funding_feerate_sat_per_1000_weight: msg.funding_feerate_per_kw,
92659408 our_funding_inputs: Vec::new(),
92669409 };
9267- // let unfunded_context = UnfundedChannelContext {
9268- // unfunded_channel_age_ticks: 0,
9269- // holder_commitment_point: HolderCommitmentPoint::new(&context.holder_signer, &context.secp_ctx),
9270- // };
9410+ let unfunded_context = UnfundedChannelContext {
9411+ unfunded_channel_age_ticks: 0,
9412+ holder_commitment_point: HolderCommitmentPoint::new(&self. context.holder_signer, &self. context.secp_ctx),
9413+ };
92719414
9272- Ok((pending_splice_post, post_funding, dual_funding_context))
9415+ Ok((pending_splice_post, post_funding, dual_funding_context, unfunded_context ))
92739416 }
92749417
92759418 /// Get the splice_ack message that can be sent in response to splice initiation.
@@ -9301,7 +9444,7 @@ impl<SP: Deref> FundedChannel<SP> where
93019444 #[cfg(splicing)]
93029445 fn splice_ack(
93039446 &mut self, msg: &msgs::SpliceAck,
9304- ) -> Result<(PendingSplicePost, FundingScope, DualFundingChannelContext, i64), ChannelError>
9447+ ) -> Result<(PendingSplicePost, FundingScope, DualFundingChannelContext, UnfundedChannelContext, i64), ChannelError>
93059448 {
93069449 let pending_splice = self.splice_ack_checks()?;
93079450
@@ -9352,12 +9495,12 @@ impl<SP: Deref> FundedChannel<SP> where
93529495 funding_feerate_sat_per_1000_weight: pending_splice.funding_feerate_per_kw,
93539496 our_funding_inputs: pending_splice.our_funding_inputs.clone(),
93549497 };
9355- // let unfunded_context = UnfundedChannelContext {
9356- // unfunded_channel_age_ticks: 0,
9357- // holder_commitment_point: HolderCommitmentPoint::new(&context.holder_signer, &context.secp_ctx),
9358- // };
9498+ let unfunded_context = UnfundedChannelContext {
9499+ unfunded_channel_age_ticks: 0,
9500+ holder_commitment_point: HolderCommitmentPoint::new(&self. context.holder_signer, &self. context.secp_ctx),
9501+ };
93599502
9360- Ok((pending_splice_post, post_funding, dual_funding_context, pending_splice.our_funding_contribution))
9503+ Ok((pending_splice_post, post_funding, dual_funding_context, unfunded_context, pending_splice.our_funding_contribution))
93619504 }
93629505
93639506 // Send stuff to our remote peers:
0 commit comments