@@ -1335,6 +1335,7 @@ impl<SP: Deref> Channel<SP> where
1335
1335
}
1336
1336
}
1337
1337
1338
+ #[cfg(splicing)]
1338
1339
fn as_splicing_mut(&mut self) -> Option<&mut SplicingChannel<SP>> {
1339
1340
if let ChannelPhase::RefundingV2(channel) = &mut self.phase {
1340
1341
Some(channel)
@@ -1481,6 +1482,7 @@ impl<SP: Deref> Channel<SP> where
1481
1482
if let Some(unfunded) = self.as_unfunded_v2_mut() {
1482
1483
return unfunded.tx_add_input(msg);
1483
1484
}
1485
+ #[cfg(splicing)]
1484
1486
if let Some(splicing) = self.as_splicing_mut() {
1485
1487
return splicing.tx_add_input(msg);
1486
1488
}
@@ -1492,6 +1494,7 @@ impl<SP: Deref> Channel<SP> where
1492
1494
if let Some(unfunded) = self.as_unfunded_v2_mut() {
1493
1495
return unfunded.tx_add_output(msg);
1494
1496
}
1497
+ #[cfg(splicing)]
1495
1498
if let Some(splicing) = self.as_splicing_mut() {
1496
1499
return splicing.tx_add_output(msg);
1497
1500
}
@@ -1503,6 +1506,7 @@ impl<SP: Deref> Channel<SP> where
1503
1506
if let Some(unfunded) = self.as_unfunded_v2_mut() {
1504
1507
return unfunded.tx_complete(msg);
1505
1508
}
1509
+ #[cfg(splicing)]
1506
1510
if let Some(splicing) = self.as_splicing_mut() {
1507
1511
return splicing.tx_complete(msg);
1508
1512
}
@@ -1546,22 +1550,55 @@ impl<SP: Deref> Channel<SP> where
1546
1550
where
1547
1551
L::Target: Logger
1548
1552
{
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
1555
1593
}
1556
1594
1557
1595
/// Transition the channel from Funded to SplicingChannel.
1558
1596
/// Done in one go, as the existing ('pre') channel is put in the new channel (alongside a new one).
1559
1597
#[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> {
1562
1599
let phase = core::mem::replace(&mut self.phase, ChannelPhase::Undefined);
1563
1600
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));
1565
1602
Ok(())
1566
1603
} else {
1567
1604
// revert phase
@@ -1572,6 +1609,30 @@ impl<SP: Deref> Channel<SP> where
1572
1609
result
1573
1610
}
1574
1611
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
+
1575
1636
#[cfg(splicing)]
1576
1637
pub fn splice_init<ES: Deref, L: Deref>(
1577
1638
&mut self, msg: &msgs::SpliceInit, our_funding_contribution: i64,
@@ -1583,10 +1644,10 @@ impl<SP: Deref> Channel<SP> where
1583
1644
{
1584
1645
// Explicit check for Funded, not as_funded; RefundingV2 not allowed
1585
1646
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 ) =
1587
1648
prev_chan.splice_init(msg, our_funding_contribution)?;
1588
1649
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)?;
1590
1651
1591
1652
if let ChannelPhase::RefundingV2(chan) = &mut self.phase {
1592
1653
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
1610
1671
{
1611
1672
// Explicit check for Funded, not as_funded; RefundingV2 not allowed
1612
1673
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) =
1614
1675
prev_chan.splice_ack(msg)?;
1615
1676
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)?;
1617
1678
1618
1679
if let ChannelPhase::RefundingV2(chan) = &mut self.phase {
1619
1680
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 {
1740
1801
/// TODO: replace it with its fields; done with trait?
1741
1802
pub pre_funded: FundedChannel<SP>,
1742
1803
1743
- // Fields for PendingV2Channel follow, except ChannelContext
1804
+ // Fields from PendingV2Channel follow, except ChannelContext, which is reused from above
1744
1805
pub post_funding: FundingScope,
1745
- // pub unfunded_context: Option< UnfundedChannelContext> ,
1806
+ pub unfunded_context: UnfundedChannelContext,
1746
1807
/// Used when negotiating the splice transaction
1747
1808
pub dual_funding_context: DualFundingChannelContext,
1748
1809
/// The current interactive transaction construction session under negotiation.
@@ -1755,18 +1816,18 @@ pub(super) struct SplicingChannel<SP: Deref> where SP::Target: SignerProvider {
1755
1816
1756
1817
#[cfg(splicing)]
1757
1818
impl<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 {
1759
1820
Self {
1760
1821
pre_funded,
1761
1822
post_funding,
1762
1823
dual_funding_context,
1824
+ unfunded_context,
1763
1825
interactive_tx_constructor: None,
1764
1826
pending_splice_post,
1765
1827
}
1766
1828
}
1767
1829
1768
1830
/// Handle splice_init
1769
- #[cfg(splicing)]
1770
1831
pub fn splice_init<ES: Deref, L: Deref>(
1771
1832
&mut self, _msg: &msgs::SpliceInit, our_funding_contribution: i64,
1772
1833
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 {
1788
1849
}
1789
1850
1790
1851
/// Handle splice_ack
1791
- #[cfg(splicing)]
1792
1852
pub fn splice_ack<ES: Deref, L: Deref>(
1793
1853
&mut self, msg: &msgs::SpliceAck, our_funding_contribution: i64,
1794
1854
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 {
1824
1884
}
1825
1885
1826
1886
/// Splice process starting; update state, log, etc.
1827
- #[cfg(splicing)]
1828
1887
pub(crate) fn splice_start<L: Deref>(&mut self, is_outgoing: bool, logger: &L) where L::Target: Logger {
1829
1888
// Set state, by this point splice_init/splice_ack handshake is complete
1830
1889
// TODO(splicing)
@@ -1997,15 +2056,99 @@ impl<SP: Deref> SplicingChannel<SP> where SP::Target: SignerProvider {
1997
2056
HandleTxCompleteResult(Ok(tx_complete))
1998
2057
}
1999
2058
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
+ }
2009
2152
}
2010
2153
2011
2154
/// Contains all state common to unfunded inbound/outbound channels.
@@ -9213,7 +9356,7 @@ impl<SP: Deref> FundedChannel<SP> where
9213
9356
#[cfg(splicing)]
9214
9357
fn splice_init(
9215
9358
&mut self, msg: &msgs::SpliceInit, our_funding_contribution: i64,
9216
- ) -> Result<(PendingSplicePost, FundingScope, DualFundingChannelContext), ChannelError>
9359
+ ) -> Result<(PendingSplicePost, FundingScope, DualFundingChannelContext, UnfundedChannelContext ), ChannelError>
9217
9360
{
9218
9361
let _res = self.splice_init_checks(msg)?;
9219
9362
@@ -9264,12 +9407,12 @@ impl<SP: Deref> FundedChannel<SP> where
9264
9407
funding_feerate_sat_per_1000_weight: msg.funding_feerate_per_kw,
9265
9408
our_funding_inputs: Vec::new(),
9266
9409
};
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
+ };
9271
9414
9272
- Ok((pending_splice_post, post_funding, dual_funding_context))
9415
+ Ok((pending_splice_post, post_funding, dual_funding_context, unfunded_context ))
9273
9416
}
9274
9417
9275
9418
/// Get the splice_ack message that can be sent in response to splice initiation.
@@ -9301,7 +9444,7 @@ impl<SP: Deref> FundedChannel<SP> where
9301
9444
#[cfg(splicing)]
9302
9445
fn splice_ack(
9303
9446
&mut self, msg: &msgs::SpliceAck,
9304
- ) -> Result<(PendingSplicePost, FundingScope, DualFundingChannelContext, i64), ChannelError>
9447
+ ) -> Result<(PendingSplicePost, FundingScope, DualFundingChannelContext, UnfundedChannelContext, i64), ChannelError>
9305
9448
{
9306
9449
let pending_splice = self.splice_ack_checks()?;
9307
9450
@@ -9352,12 +9495,12 @@ impl<SP: Deref> FundedChannel<SP> where
9352
9495
funding_feerate_sat_per_1000_weight: pending_splice.funding_feerate_per_kw,
9353
9496
our_funding_inputs: pending_splice.our_funding_inputs.clone(),
9354
9497
};
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
+ };
9359
9502
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))
9361
9504
}
9362
9505
9363
9506
// Send stuff to our remote peers:
0 commit comments