@@ -1582,6 +1582,16 @@ impl<SP: Deref> Channel<SP> where
1582
1582
}
1583
1583
}
1584
1584
1585
+ pub fn as_negotiating_channel(&mut self) -> Result<NegotiatingChannelView<SP>, ChannelError> {
1586
+ match &mut self.phase {
1587
+ ChannelPhase::UnfundedV2(chan) => Ok(chan.as_negotiating_channel()),
1588
+ #[cfg(splicing)]
1589
+ ChannelPhase::Funded(chan) => Ok(chan.as_renegotiating_channel()
1590
+ .map_err(|err| ChannelError::Warn(err.into()))?),
1591
+ _ => Err(ChannelError::Warn("Got a transaction negotiation message in an invalid phase".to_owned())),
1592
+ }
1593
+ }
1594
+
1585
1595
pub fn funding_signed<L: Deref>(
1586
1596
&mut self, msg: &msgs::FundingSigned, best_block: BestBlock, signer_provider: &SP, logger: &L
1587
1597
) -> Result<(&mut FundedChannel<SP>, ChannelMonitor<<SP::Target as SignerProvider>::EcdsaSigner>), ChannelError>
@@ -1619,9 +1629,10 @@ impl<SP: Deref> Channel<SP> where
1619
1629
where
1620
1630
L::Target: Logger
1621
1631
{
1622
- if let ChannelPhase::UnfundedV2(chan) = &mut self.phase {
1623
- let logger = WithChannelContext::from(logger, &chan.context, None);
1624
- chan.funding_tx_constructed(signing_session, &&logger)
1632
+ let logger = WithChannelContext::from(logger, self.context(), None);
1633
+ if let Ok(mut negotiating_channel) = self.as_negotiating_channel() {
1634
+ let (commitment_signed, event) = negotiating_channel.funding_tx_constructed(signing_session, &&logger)?;
1635
+ Ok((commitment_signed, event))
1625
1636
} else {
1626
1637
Err(ChannelError::Warn("Got a tx_complete message with no interactive transaction construction expected or in-progress".to_owned()))
1627
1638
}
@@ -1935,7 +1946,13 @@ impl FundingScope {
1935
1946
/// Info about a pending splice, used in the pre-splice channel
1936
1947
#[cfg(splicing)]
1937
1948
struct PendingSplice {
1949
+ /// Intended contributions to the splice from our end
1938
1950
pub our_funding_contribution: i64,
1951
+ funding_scope: Option<FundingScope>,
1952
+ funding_negotiation_context: FundingNegotiationContext,
1953
+ /// The current interactive transaction construction session under negotiation.
1954
+ interactive_tx_constructor: Option<InteractiveTxConstructor>,
1955
+ interactive_tx_signing_session: Option<InteractiveTxSigningSession>,
1939
1956
}
1940
1957
1941
1958
/// Contains everything about the channel including state, and various flags.
@@ -2432,7 +2449,20 @@ impl<SP: Deref> InitialRemoteCommitmentReceiver<SP> for FundedChannel<SP> where
2432
2449
}
2433
2450
}
2434
2451
2435
- impl<SP: Deref> PendingV2Channel<SP> where SP::Target: SignerProvider {
2452
+ /// A short-lived subset view of a channel, used for V2 funding negotiation or re-negotiation.
2453
+ /// Can be produced by:
2454
+ /// - [`PendingV2Channel`], at V2 channel open, and
2455
+ /// - [`FundedChannel`], when splicing.
2456
+ pub struct NegotiatingChannelView<'a, SP: Deref> where SP::Target: SignerProvider {
2457
+ context: &'a mut ChannelContext<SP>,
2458
+ funding: &'a mut FundingScope,
2459
+ funding_negotiation_context: &'a mut FundingNegotiationContext,
2460
+ interactive_tx_constructor: &'a mut Option<InteractiveTxConstructor>,
2461
+ interactive_tx_signing_session: &'a mut Option<InteractiveTxSigningSession>,
2462
+ holder_commitment_transaction_number: u64,
2463
+ }
2464
+
2465
+ impl<'a, SP: Deref> NegotiatingChannelView<'a, SP> where SP::Target: SignerProvider {
2436
2466
/// Prepare and start interactive transaction negotiation.
2437
2467
/// `change_destination_opt` - Optional destination for optional change; if None,
2438
2468
/// default destination address is used.
@@ -2522,13 +2552,13 @@ impl<SP: Deref> PendingV2Channel<SP> where SP::Target: SignerProvider {
2522
2552
let mut tx_constructor = InteractiveTxConstructor::new(constructor_args)?;
2523
2553
let msg = tx_constructor.take_initiator_first_message();
2524
2554
2525
- self.interactive_tx_constructor = Some(tx_constructor);
2555
+ * self.interactive_tx_constructor = Some(tx_constructor);
2526
2556
2527
2557
Ok(msg)
2528
2558
}
2529
2559
2530
- pub fn tx_add_input(&mut self, msg: &msgs::TxAddInput) -> InteractiveTxMessageSendResult {
2531
- InteractiveTxMessageSendResult(match &mut self.interactive_tx_constructor {
2560
+ pub(super) fn tx_add_input(&mut self, msg: &msgs::TxAddInput) -> InteractiveTxMessageSendResult {
2561
+ InteractiveTxMessageSendResult(match self.interactive_tx_constructor {
2532
2562
Some(ref mut tx_constructor) => tx_constructor.handle_tx_add_input(msg).map_err(
2533
2563
|reason| reason.into_tx_abort_msg(self.context.channel_id())),
2534
2564
None => Err(msgs::TxAbort {
@@ -2538,8 +2568,8 @@ impl<SP: Deref> PendingV2Channel<SP> where SP::Target: SignerProvider {
2538
2568
})
2539
2569
}
2540
2570
2541
- pub fn tx_add_output(&mut self, msg: &msgs::TxAddOutput)-> InteractiveTxMessageSendResult {
2542
- InteractiveTxMessageSendResult(match &mut self.interactive_tx_constructor {
2571
+ pub(super) fn tx_add_output(&mut self, msg: &msgs::TxAddOutput)-> InteractiveTxMessageSendResult {
2572
+ InteractiveTxMessageSendResult(match self.interactive_tx_constructor {
2543
2573
Some(ref mut tx_constructor) => tx_constructor.handle_tx_add_output(msg).map_err(
2544
2574
|reason| reason.into_tx_abort_msg(self.context.channel_id())),
2545
2575
None => Err(msgs::TxAbort {
@@ -2549,8 +2579,8 @@ impl<SP: Deref> PendingV2Channel<SP> where SP::Target: SignerProvider {
2549
2579
})
2550
2580
}
2551
2581
2552
- pub fn tx_remove_input(&mut self, msg: &msgs::TxRemoveInput)-> InteractiveTxMessageSendResult {
2553
- InteractiveTxMessageSendResult(match &mut self.interactive_tx_constructor {
2582
+ pub(super) fn tx_remove_input(&mut self, msg: &msgs::TxRemoveInput)-> InteractiveTxMessageSendResult {
2583
+ InteractiveTxMessageSendResult(match self.interactive_tx_constructor {
2554
2584
Some(ref mut tx_constructor) => tx_constructor.handle_tx_remove_input(msg).map_err(
2555
2585
|reason| reason.into_tx_abort_msg(self.context.channel_id())),
2556
2586
None => Err(msgs::TxAbort {
@@ -2560,8 +2590,8 @@ impl<SP: Deref> PendingV2Channel<SP> where SP::Target: SignerProvider {
2560
2590
})
2561
2591
}
2562
2592
2563
- pub fn tx_remove_output(&mut self, msg: &msgs::TxRemoveOutput)-> InteractiveTxMessageSendResult {
2564
- InteractiveTxMessageSendResult(match &mut self.interactive_tx_constructor {
2593
+ pub(super) fn tx_remove_output(&mut self, msg: &msgs::TxRemoveOutput)-> InteractiveTxMessageSendResult {
2594
+ InteractiveTxMessageSendResult(match self.interactive_tx_constructor {
2565
2595
Some(ref mut tx_constructor) => tx_constructor.handle_tx_remove_output(msg).map_err(
2566
2596
|reason| reason.into_tx_abort_msg(self.context.channel_id())),
2567
2597
None => Err(msgs::TxAbort {
@@ -2571,9 +2601,9 @@ impl<SP: Deref> PendingV2Channel<SP> where SP::Target: SignerProvider {
2571
2601
})
2572
2602
}
2573
2603
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,
2604
+ pub(super) fn tx_complete(&mut self, msg: &msgs::TxComplete) -> HandleTxCompleteResult {
2605
+ let tx_constructor = match self.interactive_tx_constructor {
2606
+ Some(tx_constructor) => tx_constructor,
2577
2607
None => {
2578
2608
let tx_abort = msgs::TxAbort {
2579
2609
channel_id: msg.channel_id,
@@ -2593,14 +2623,14 @@ impl<SP: Deref> PendingV2Channel<SP> where SP::Target: SignerProvider {
2593
2623
HandleTxCompleteResult(Ok(tx_complete))
2594
2624
}
2595
2625
2596
- pub fn funding_tx_constructed<L: Deref>(
2626
+ fn funding_tx_constructed<L: Deref>(
2597
2627
&mut self, mut signing_session: InteractiveTxSigningSession, logger: &L
2598
2628
) -> Result<(msgs::CommitmentSigned, Option<Event>), ChannelError>
2599
2629
where
2600
2630
L::Target: Logger
2601
2631
{
2602
- let our_funding_satoshis = self.funding_negotiation_context.our_funding_satoshis;
2603
- let transaction_number = self.unfunded_context.transaction_number() ;
2632
+ let our_funding_satoshis = self.funding_negotiation_context
2633
+ .our_funding_satoshis ;
2604
2634
2605
2635
let mut output_index = None;
2606
2636
let expected_spk = self.funding.get_funding_redeemscript().to_p2wsh();
@@ -2625,14 +2655,16 @@ impl<SP: Deref> PendingV2Channel<SP> where SP::Target: SignerProvider {
2625
2655
ClosureReason::HolderForceClosed { broadcasted_latest_txn: Some(false) },
2626
2656
)));
2627
2657
};
2628
- self.funding.channel_transaction_parameters.funding_outpoint = Some(outpoint);
2658
+ self.funding
2659
+ .channel_transaction_parameters.funding_outpoint = Some(outpoint);
2629
2660
2630
- self.context.assert_no_commitment_advancement(transaction_number , "initial commitment_signed");
2661
+ self.context.assert_no_commitment_advancement(self.holder_commitment_transaction_number , "initial commitment_signed");
2631
2662
let commitment_signed = self.context.get_initial_commitment_signed(&self.funding, logger);
2632
2663
let commitment_signed = match commitment_signed {
2633
2664
Ok(commitment_signed) => commitment_signed,
2634
2665
Err(err) => {
2635
- self.funding.channel_transaction_parameters.funding_outpoint = None;
2666
+ self.funding
2667
+ .channel_transaction_parameters.funding_outpoint = None;
2636
2668
return Err(ChannelError::Close((err.to_string(), ClosureReason::HolderForceClosed { broadcasted_latest_txn: Some(false) })));
2637
2669
},
2638
2670
};
@@ -2680,8 +2712,8 @@ impl<SP: Deref> PendingV2Channel<SP> where SP::Target: SignerProvider {
2680
2712
self.context.channel_state = channel_state;
2681
2713
2682
2714
// Clear the interactive transaction constructor
2683
- self.interactive_tx_constructor.take() ;
2684
- self.interactive_tx_signing_session = Some(signing_session);
2715
+ * self.interactive_tx_constructor = None ;
2716
+ * self.interactive_tx_signing_session = Some(signing_session);
2685
2717
2686
2718
Ok((commitment_signed, funding_ready_for_sig_event))
2687
2719
}
@@ -5262,6 +5294,36 @@ impl<SP: Deref> FundedChannel<SP> where
5262
5294
SP::Target: SignerProvider,
5263
5295
<SP::Target as SignerProvider>::EcdsaSigner: EcdsaChannelSigner
5264
5296
{
5297
+ /// If we are in splicing/refunding, return a short-lived [`NegotiatingChannelView`].
5298
+ #[cfg(splicing)]
5299
+ fn as_renegotiating_channel(&mut self) -> Result<NegotiatingChannelView<SP>, &'static str> {
5300
+ if let Some(ref mut pending_splice) = &mut self.pending_splice {
5301
+ if let Some(ref mut funding) = &mut pending_splice.funding_scope {
5302
+ if
5303
+ pending_splice.funding_negotiation_context.our_funding_satoshis != 0 ||
5304
+ pending_splice.funding_negotiation_context.their_funding_satoshis.unwrap_or_default() != 0
5305
+ {
5306
+ Ok(NegotiatingChannelView {
5307
+ context: &mut self.context,
5308
+ funding,
5309
+ funding_negotiation_context: &mut pending_splice.funding_negotiation_context,
5310
+ interactive_tx_constructor: &mut pending_splice.interactive_tx_constructor,
5311
+ interactive_tx_signing_session: &mut pending_splice.interactive_tx_signing_session,
5312
+ holder_commitment_transaction_number: self.holder_commitment_point.transaction_number(),
5313
+ })
5314
+ } else {
5315
+ Err("Received unexpected interactive transaction negotiation message: \
5316
+ the channel is splicing, but splice_init/splice_ack has not been exchanged yet")
5317
+ }
5318
+ } else {
5319
+ Err("Received unexpected interactive transaction negotiation message: \
5320
+ the channel is splicing, but splice_init/splice_ack has not been exchanged yet")
5321
+ }
5322
+ } else {
5323
+ Err("Received unexpected interactive transaction negotiation message: the channel is funded and not splicing")
5324
+ }
5325
+ }
5326
+
5265
5327
fn check_remote_fee<F: Deref, L: Deref>(
5266
5328
channel_type: &ChannelTypeFeatures, fee_estimator: &LowerBoundedFeeEstimator<F>,
5267
5329
feerate_per_kw: u32, cur_feerate_per_kw: Option<u32>, logger: &L
@@ -8895,10 +8957,11 @@ impl<SP: Deref> FundedChannel<SP> where
8895
8957
) -> Result<msgs::SpliceInit, APIError> {
8896
8958
// Check if a splice has been initiated already.
8897
8959
// Note: only a single outstanding splice is supported (per spec)
8898
- if let Some(splice_info ) = &self.pending_splice {
8960
+ if let Some(pending_splice ) = &self.pending_splice {
8899
8961
return Err(APIError::APIMisuseError { err: format!(
8900
8962
"Channel {} cannot be spliced, as it has already a splice pending (contribution {})",
8901
- self.context.channel_id(), splice_info.our_funding_contribution
8963
+ self.context.channel_id(),
8964
+ pending_splice.our_funding_contribution,
8902
8965
)});
8903
8966
}
8904
8967
@@ -8930,9 +8993,26 @@ impl<SP: Deref> FundedChannel<SP> where
8930
8993
"Insufficient inputs for splicing; channel ID {}, err {}",
8931
8994
self.context.channel_id(), err,
8932
8995
)})?;
8996
+ // Convert inputs
8997
+ let mut funding_inputs = Vec::new();
8998
+ for (tx_in, tx, _w) in our_funding_inputs.into_iter() {
8999
+ let tx16 = TransactionU16LenLimited::new(tx.clone()).map_err(|_e| APIError::APIMisuseError { err: format!("Too large transaction")})?;
9000
+ funding_inputs.push((tx_in.clone(), tx16));
9001
+ }
8933
9002
9003
+ let funding_negotiation_context = FundingNegotiationContext {
9004
+ our_funding_satoshis: 0, // set at later phase
9005
+ their_funding_satoshis: None, // set at later phase
9006
+ funding_tx_locktime: LockTime::from_consensus(locktime),
9007
+ funding_feerate_sat_per_1000_weight: funding_feerate_per_kw,
9008
+ our_funding_inputs: funding_inputs,
9009
+ };
8934
9010
self.pending_splice = Some(PendingSplice {
8935
9011
our_funding_contribution: our_funding_contribution_satoshis,
9012
+ funding_scope: None,
9013
+ funding_negotiation_context,
9014
+ interactive_tx_constructor: None,
9015
+ interactive_tx_signing_session: None,
8936
9016
});
8937
9017
8938
9018
let msg = self.get_splice_init(our_funding_contribution_satoshis, funding_feerate_per_kw, locktime);
@@ -10652,6 +10732,18 @@ impl<SP: Deref> PendingV2Channel<SP> where SP::Target: SignerProvider {
10652
10732
pub fn get_accept_channel_v2_message(&self) -> msgs::AcceptChannelV2 {
10653
10733
self.generate_accept_channel_v2_message()
10654
10734
}
10735
+
10736
+ /// Return a short-lived [`NegotiatingChannelView`].
10737
+ fn as_negotiating_channel(&mut self) -> NegotiatingChannelView<SP> {
10738
+ NegotiatingChannelView {
10739
+ context: &mut self.context,
10740
+ funding: &mut self.funding,
10741
+ funding_negotiation_context: &mut self.funding_negotiation_context,
10742
+ interactive_tx_constructor: &mut self.interactive_tx_constructor,
10743
+ interactive_tx_signing_session: &mut self.interactive_tx_signing_session,
10744
+ holder_commitment_transaction_number: self.unfunded_context.transaction_number(),
10745
+ }
10746
+ }
10655
10747
}
10656
10748
10657
10749
// Unfunded channel utilities
0 commit comments