@@ -2302,7 +2302,21 @@ impl<SP: Deref> InitialRemoteCommitmentReceiver<SP> for FundedChannel<SP> where
23022302 }
23032303}
23042304
2305- impl<SP: Deref> PendingV2Channel<SP> where SP::Target: SignerProvider {
2305+ /// A channel struct implementing this trait can perform V2 transaction negotiation,
2306+ /// either at channel open or during splicing.
2307+ /// Accessors return a Result, because [`FundedChannel`] can act like a TX constructor,
2308+ /// but not always (only during splicing).
2309+ pub(super) trait FundingTxConstructorV2<SP: Deref>: ChannelContextProvider<SP> where SP::Target: SignerProvider {
2310+ fn pending_funding(&self) -> Result<&FundingScope, &'static str>;
2311+ fn pending_funding_mut(&mut self) -> Result<&mut FundingScope, &'static str>;
2312+ fn pending_funding_and_context_mut(&mut self) -> Result<(&FundingScope, &mut ChannelContext<SP>), &'static str>;
2313+ fn dual_funding_context(&self) -> Result<&DualFundingChannelContext, &'static str>;
2314+ fn swap_out_dual_funding_context_inputs(&mut self, funding_inputs: &mut Vec<(TxIn, TransactionU16LenLimited)>) -> Result<(), &'static str>;
2315+ fn unfunded_context(&self) -> Result<&UnfundedChannelContext, &'static str>;
2316+ fn interactive_tx_constructor(&self) -> Result<Option<&InteractiveTxConstructor>, &'static str>;
2317+ fn interactive_tx_constructor_mut(&mut self) -> Result<&mut Option<InteractiveTxConstructor>, &'static str>;
2318+ fn interactive_tx_signing_session_mut(&mut self) -> Result<&mut Option<InteractiveTxSigningSession>, &'static str>;
2319+
23062320 /// Prepare and start interactive transaction negotiation.
23072321 /// `change_destination_opt` - Optional destination for optional change; if None,
23082322 /// default destination address is used.
@@ -2314,11 +2328,12 @@ impl<SP: Deref> PendingV2Channel<SP> where SP::Target: SignerProvider {
23142328 ) -> Result<Option<InteractiveTxMessageSend>, AbortReason>
23152329 where ES::Target: EntropySource
23162330 {
2317- debug_assert!(matches!(self.context.channel_state, ChannelState::NegotiatingFunding(_)));
2318- debug_assert!(self.interactive_tx_constructor.is_none());
2331+ debug_assert!(matches!(self.context() .channel_state, ChannelState::NegotiatingFunding(_)));
2332+ debug_assert!(self.interactive_tx_constructor().unwrap_or(None) .is_none());
23192333
23202334 let mut funding_inputs = Vec::new();
2321- mem::swap(&mut self.dual_funding_context.our_funding_inputs, &mut funding_inputs);
2335+ self.swap_out_dual_funding_context_inputs(&mut funding_inputs)
2336+ .map_err(|e| AbortReason::InternalError(e))?;
23222337
23232338 // TODO(splicing): Add prev funding tx as input, must be provided as a parameter
23242339
@@ -2328,15 +2343,20 @@ impl<SP: Deref> PendingV2Channel<SP> where SP::Target: SignerProvider {
23282343 let mut funding_outputs = Vec::new();
23292344 let mut expected_remote_shared_funding_output = None;
23302345
2346+ let pending_funding = self.pending_funding()
2347+ .map_err(|e| AbortReason::InternalError(e))?;
2348+
23312349 let shared_funding_output = TxOut {
2332- value: Amount::from_sat(self.funding .get_value_satoshis()),
2333- script_pubkey: self.funding .get_funding_redeemscript().to_p2wsh(),
2350+ value: Amount::from_sat(pending_funding .get_value_satoshis()),
2351+ script_pubkey: pending_funding .get_funding_redeemscript().to_p2wsh(),
23342352 };
23352353
2336- if self.funding.is_outbound() {
2354+ let dual_funding_context = &self.dual_funding_context()
2355+ .map_err(|e| AbortReason::InternalError(e))?;
2356+ if pending_funding.is_outbound() {
23372357 funding_outputs.push(
23382358 OutputOwned::Shared(SharedOwnedOutput::new(
2339- shared_funding_output, self. dual_funding_context.our_funding_satoshis,
2359+ shared_funding_output, dual_funding_context.our_funding_satoshis,
23402360 ))
23412361 );
23422362 } else {
@@ -2348,13 +2368,13 @@ impl<SP: Deref> PendingV2Channel<SP> where SP::Target: SignerProvider {
23482368 let change_script = if let Some(script) = change_destination_opt {
23492369 script
23502370 } else {
2351- signer_provider.get_destination_script(self.context.channel_keys_id)
2371+ signer_provider.get_destination_script(self.context() .channel_keys_id)
23522372 .map_err(|_err| AbortReason::InternalError("Error getting destination script"))?
23532373 };
23542374 let change_value_opt = calculate_change_output_value(
2355- self.funding. is_outbound(), self. dual_funding_context.our_funding_satoshis,
2375+ pending_funding. is_outbound(), dual_funding_context.our_funding_satoshis,
23562376 &funding_inputs, &funding_outputs,
2357- self. dual_funding_context.funding_feerate_sat_per_1000_weight,
2377+ dual_funding_context.funding_feerate_sat_per_1000_weight,
23582378 change_script.minimal_non_dust().to_sat(),
23592379 )?;
23602380 if let Some(change_value) = change_value_opt {
@@ -2363,10 +2383,10 @@ impl<SP: Deref> PendingV2Channel<SP> where SP::Target: SignerProvider {
23632383 script_pubkey: change_script,
23642384 };
23652385 let change_output_weight = get_output_weight(&change_output.script_pubkey).to_wu();
2366- let change_output_fee = fee_for_weight(self. dual_funding_context.funding_feerate_sat_per_1000_weight, change_output_weight);
2386+ let change_output_fee = fee_for_weight(dual_funding_context.funding_feerate_sat_per_1000_weight, change_output_weight);
23672387 let change_value_decreased_with_fee = change_value.saturating_sub(change_output_fee);
23682388 // Check dust limit again
2369- if change_value_decreased_with_fee > self.context.holder_dust_limit_satoshis {
2389+ if change_value_decreased_with_fee > self.context() .holder_dust_limit_satoshis {
23702390 change_output.value = Amount::from_sat(change_value_decreased_with_fee);
23712391 funding_outputs.push(OutputOwned::Single(change_output));
23722392 }
@@ -2375,71 +2395,74 @@ impl<SP: Deref> PendingV2Channel<SP> where SP::Target: SignerProvider {
23752395 let constructor_args = InteractiveTxConstructorArgs {
23762396 entropy_source,
23772397 holder_node_id,
2378- counterparty_node_id: self.context.counterparty_node_id,
2379- channel_id: self.context.channel_id(),
2380- feerate_sat_per_kw: self. dual_funding_context.funding_feerate_sat_per_1000_weight,
2381- is_initiator: self.funding .is_outbound(),
2382- funding_tx_locktime: self. dual_funding_context.funding_tx_locktime,
2398+ counterparty_node_id: self.context() .counterparty_node_id,
2399+ channel_id: self.context() .channel_id(),
2400+ feerate_sat_per_kw: dual_funding_context.funding_feerate_sat_per_1000_weight,
2401+ is_initiator: pending_funding .is_outbound(),
2402+ funding_tx_locktime: dual_funding_context.funding_tx_locktime,
23832403 inputs_to_contribute: funding_inputs,
23842404 outputs_to_contribute: funding_outputs,
23852405 expected_remote_shared_funding_output,
23862406 };
23872407 let mut tx_constructor = InteractiveTxConstructor::new(constructor_args)?;
23882408 let msg = tx_constructor.take_initiator_first_message();
23892409
2390- self.interactive_tx_constructor = Some(tx_constructor);
2410+ *(
2411+ self.interactive_tx_constructor_mut().map_err(|e| AbortReason::InternalError(e))?
2412+ ) = Some(tx_constructor);
23912413
23922414 Ok(msg)
23932415 }
23942416
2395- pub fn tx_add_input(&mut self, msg: &msgs::TxAddInput) -> InteractiveTxMessageSendResult {
2396- InteractiveTxMessageSendResult(match &mut self.interactive_tx_constructor {
2397- Some(ref mut tx_constructor) => tx_constructor.handle_tx_add_input(msg).map_err(
2398- |reason| reason.into_tx_abort_msg(self.context.channel_id())),
2399- None => Err(msgs::TxAbort {
2400- channel_id: self.context.channel_id(),
2417+ fn tx_add_input(&mut self, msg: &msgs::TxAddInput) -> InteractiveTxMessageSendResult {
2418+ InteractiveTxMessageSendResult(match self.interactive_tx_constructor_mut() {
2419+ Ok( Some(ref mut tx_constructor) ) => tx_constructor.handle_tx_add_input(msg).map_err(
2420+ |reason| reason.into_tx_abort_msg(self.context() .channel_id())),
2421+ Ok( None) | Err(_) => Err(msgs::TxAbort {
2422+ channel_id: self.context() .channel_id(),
24012423 data: b"No interactive transaction negotiation in progress".to_vec()
24022424 }),
24032425 })
24042426 }
24052427
2406- pub fn tx_add_output(&mut self, msg: &msgs::TxAddOutput)-> InteractiveTxMessageSendResult {
2407- InteractiveTxMessageSendResult(match &mut self.interactive_tx_constructor {
2408- Some(ref mut tx_constructor) => tx_constructor.handle_tx_add_output(msg).map_err(
2409- |reason| reason.into_tx_abort_msg(self.context.channel_id())),
2410- None => Err(msgs::TxAbort {
2411- channel_id: self.context.channel_id(),
2428+ fn tx_add_output(&mut self, msg: &msgs::TxAddOutput)-> InteractiveTxMessageSendResult {
2429+ InteractiveTxMessageSendResult(match self.interactive_tx_constructor_mut() {
2430+ Ok( Some(ref mut tx_constructor) ) => tx_constructor.handle_tx_add_output(msg).map_err(
2431+ |reason| reason.into_tx_abort_msg(self.context() .channel_id())),
2432+ Ok( None) | Err(_) => Err(msgs::TxAbort {
2433+ channel_id: self.context() .channel_id(),
24122434 data: b"No interactive transaction negotiation in progress".to_vec()
24132435 }),
24142436 })
24152437 }
24162438
2417- pub fn tx_remove_input(&mut self, msg: &msgs::TxRemoveInput)-> InteractiveTxMessageSendResult {
2418- InteractiveTxMessageSendResult(match &mut self.interactive_tx_constructor {
2419- Some(ref mut tx_constructor) => tx_constructor.handle_tx_remove_input(msg).map_err(
2420- |reason| reason.into_tx_abort_msg(self.context.channel_id())),
2421- None => Err(msgs::TxAbort {
2422- channel_id: self.context.channel_id(),
2439+ fn tx_remove_input(&mut self, msg: &msgs::TxRemoveInput)-> InteractiveTxMessageSendResult {
2440+ InteractiveTxMessageSendResult(match self.interactive_tx_constructor_mut() {
2441+ Ok( Some(ref mut tx_constructor) ) => tx_constructor.handle_tx_remove_input(msg).map_err(
2442+ |reason| reason.into_tx_abort_msg(self.context() .channel_id())),
2443+ Ok( None) | Err(_) => Err(msgs::TxAbort {
2444+ channel_id: self.context() .channel_id(),
24232445 data: b"No interactive transaction negotiation in progress".to_vec()
24242446 }),
24252447 })
24262448 }
24272449
2428- pub fn tx_remove_output(&mut self, msg: &msgs::TxRemoveOutput)-> InteractiveTxMessageSendResult {
2429- InteractiveTxMessageSendResult(match &mut self.interactive_tx_constructor {
2430- Some(ref mut tx_constructor) => tx_constructor.handle_tx_remove_output(msg).map_err(
2431- |reason| reason.into_tx_abort_msg(self.context.channel_id())),
2432- None => Err(msgs::TxAbort {
2433- channel_id: self.context.channel_id(),
2450+ fn tx_remove_output(&mut self, msg: &msgs::TxRemoveOutput)-> InteractiveTxMessageSendResult {
2451+ InteractiveTxMessageSendResult(match self.interactive_tx_constructor_mut() {
2452+ Ok( Some(ref mut tx_constructor) ) => tx_constructor.handle_tx_remove_output(msg).map_err(
2453+ |reason| reason.into_tx_abort_msg(self.context() .channel_id())),
2454+ Ok( None) | Err(_) => Err(msgs::TxAbort {
2455+ channel_id: self.context() .channel_id(),
24342456 data: b"No interactive transaction negotiation in progress".to_vec()
24352457 }),
24362458 })
24372459 }
24382460
2439- pub fn tx_complete(&mut self, msg: &msgs::TxComplete) -> HandleTxCompleteResult {
2440- let tx_constructor = match &mut self.interactive_tx_constructor {
2441- Some(ref mut tx_constructor) => tx_constructor,
2442- None => {
2461+ fn tx_complete(&mut self, msg: &msgs::TxComplete) -> HandleTxCompleteResult {
2462+ let interactive_tx_constructor = self.interactive_tx_constructor_mut();
2463+ let tx_constructor = match interactive_tx_constructor {
2464+ Ok(Some(tx_constructor)) => tx_constructor,
2465+ Ok(None) | Err(_) => {
24432466 let tx_abort = msgs::TxAbort {
24442467 channel_id: msg.channel_id,
24452468 data: b"No interactive transaction negotiation in progress".to_vec(),
@@ -2456,25 +2479,31 @@ impl<SP: Deref> PendingV2Channel<SP> where SP::Target: SignerProvider {
24562479 };
24572480
24582481 if let HandleTxCompleteValue::SendTxComplete(_, ref signing_session) = tx_complete {
2459- self.context .next_funding_txid = Some(signing_session.unsigned_tx.compute_txid());
2482+ self.context_mut() .next_funding_txid = Some(signing_session.unsigned_tx.compute_txid());
24602483 };
24612484
24622485 HandleTxCompleteResult(Ok(tx_complete))
24632486 }
24642487
2465- pub fn funding_tx_constructed<L: Deref>(
2488+ fn funding_tx_constructed<L: Deref>(
24662489 &mut self, mut signing_session: InteractiveTxSigningSession, logger: &L
24672490 ) -> Result<(msgs::CommitmentSigned, Option<Event>), ChannelError>
24682491 where
24692492 L::Target: Logger
24702493 {
2471- let our_funding_satoshis = self.dual_funding_context.our_funding_satoshis;
2472- let transaction_number = self.unfunded_context.transaction_number();
2494+ let our_funding_satoshis = self.dual_funding_context()
2495+ .map_err(|e| ChannelError::close(e.to_owned()))?
2496+ .our_funding_satoshis;
2497+ let transaction_number = self.unfunded_context()
2498+ .map_err(|e| ChannelError::close(e.to_owned()))?
2499+ .transaction_number();
2500+ let pending_funding = self.pending_funding()
2501+ .map_err(|e| ChannelError::close(e.to_owned()))?;
24732502
24742503 let mut output_index = None;
2475- let expected_spk = self.funding .get_funding_redeemscript().to_p2wsh();
2504+ let expected_spk = pending_funding .get_funding_redeemscript().to_p2wsh();
24762505 for (idx, outp) in signing_session.unsigned_tx.outputs().enumerate() {
2477- if outp.script_pubkey() == &expected_spk && outp.value() == self.funding .get_value_satoshis() {
2506+ if outp.script_pubkey() == &expected_spk && outp.value() == pending_funding .get_value_satoshis() {
24782507 if output_index.is_some() {
24792508 return Err(ChannelError::Close(
24802509 (
@@ -2494,24 +2523,32 @@ impl<SP: Deref> PendingV2Channel<SP> where SP::Target: SignerProvider {
24942523 ClosureReason::HolderForceClosed { broadcasted_latest_txn: Some(false) },
24952524 )));
24962525 };
2497- self.funding.channel_transaction_parameters.funding_outpoint = Some(outpoint);
2498-
2499- self.context.assert_no_commitment_advancement(transaction_number, "initial commitment_signed");
2500- let commitment_signed = self.context.get_initial_commitment_signed(&self.funding, logger);
2526+ self.pending_funding_mut()
2527+ .map_err(|e| ChannelError::close(e.to_owned()))?
2528+ .channel_transaction_parameters.funding_outpoint = Some(outpoint);
2529+
2530+ self.context().assert_no_commitment_advancement(transaction_number, "initial commitment_signed");
2531+ let (funding, context_mut) = self.pending_funding_and_context_mut()
2532+ .map_err(|e| ChannelError::close(e.to_owned()))?;
2533+ let commitment_signed = context_mut.get_initial_commitment_signed(&funding, logger);
25012534 let commitment_signed = match commitment_signed {
25022535 Ok(commitment_signed) => {
2503- self.funding.funding_transaction = Some(signing_session.unsigned_tx.build_unsigned_tx());
2536+ self.pending_funding_mut()
2537+ .map_err(|e| ChannelError::close(e.to_owned()))?
2538+ .funding_transaction = Some(signing_session.unsigned_tx.build_unsigned_tx());
25042539 commitment_signed
25052540 },
25062541 Err(err) => {
2507- self.funding.channel_transaction_parameters.funding_outpoint = None;
2542+ self.pending_funding_mut()
2543+ .map_err(|e| ChannelError::close(e.to_owned()))?
2544+ .channel_transaction_parameters.funding_outpoint = None;
25082545 return Err(ChannelError::Close((err.to_string(), ClosureReason::HolderForceClosed { broadcasted_latest_txn: Some(false) })));
25092546 },
25102547 };
25112548
25122549 let funding_ready_for_sig_event = if signing_session.local_inputs_count() == 0 {
25132550 debug_assert_eq!(our_funding_satoshis, 0);
2514- if signing_session.provide_holder_witnesses(self.context.channel_id, Vec::new()).is_err() {
2551+ if signing_session.provide_holder_witnesses(self.context() .channel_id, Vec::new()).is_err() {
25152552 debug_assert!(
25162553 false,
25172554 "Zero inputs were provided & zero witnesses were provided, but a count mismatch was somehow found",
@@ -2547,16 +2584,81 @@ impl<SP: Deref> PendingV2Channel<SP> where SP::Target: SignerProvider {
25472584 )));
25482585 };
25492586
2550- self.context .channel_state = ChannelState::FundingNegotiated;
2587+ self.context_mut() .channel_state = ChannelState::FundingNegotiated;
25512588
25522589 // Clear the interactive transaction constructor
2553- self.interactive_tx_constructor.take();
2554- self.interactive_tx_signing_session = Some(signing_session);
2590+ *(
2591+ self.interactive_tx_constructor_mut()
2592+ .map_err(|e| ChannelError::close(e.to_owned()))?
2593+ ) = None;
2594+ *(
2595+ self.interactive_tx_signing_session_mut()
2596+ .map_err(|e| ChannelError::close(e.to_owned()))?
2597+ ) = Some(signing_session);
25552598
25562599 Ok((commitment_signed, funding_ready_for_sig_event))
25572600 }
25582601}
25592602
2603+ impl<SP: Deref> ChannelContextProvider<SP> for PendingV2Channel<SP> where SP::Target: SignerProvider {
2604+ #[inline]
2605+ fn context(&self) -> &ChannelContext<SP> {
2606+ &self.context
2607+ }
2608+
2609+ #[inline]
2610+ fn context_mut(&mut self) -> &mut ChannelContext<SP> {
2611+ &mut self.context
2612+ }
2613+ }
2614+
2615+ impl<SP: Deref> FundingTxConstructorV2<SP> for PendingV2Channel<SP> where SP::Target: SignerProvider {
2616+ #[inline]
2617+ fn pending_funding(&self) -> Result<&FundingScope, &'static str> {
2618+ Ok(&self.funding)
2619+ }
2620+
2621+ #[inline]
2622+ fn pending_funding_mut(&mut self) -> Result<&mut FundingScope, &'static str> {
2623+ Ok(&mut self.funding)
2624+ }
2625+
2626+ #[inline]
2627+ fn pending_funding_and_context_mut(&mut self) -> Result<(&FundingScope, &mut ChannelContext<SP>), &'static str> {
2628+ Ok((&self.funding, &mut self.context))
2629+ }
2630+
2631+ #[inline]
2632+ fn dual_funding_context(&self) -> Result<&DualFundingChannelContext, &'static str> {
2633+ Ok(&self.dual_funding_context)
2634+ }
2635+
2636+ fn swap_out_dual_funding_context_inputs(&mut self, funding_inputs: &mut Vec<(TxIn, TransactionU16LenLimited)>) -> Result<(), &'static str> {
2637+ mem::swap(&mut self.dual_funding_context.our_funding_inputs, funding_inputs);
2638+ Ok(())
2639+ }
2640+
2641+ #[inline]
2642+ fn unfunded_context(&self) -> Result<&UnfundedChannelContext, &'static str> {
2643+ Ok(&self.unfunded_context)
2644+ }
2645+
2646+ #[inline]
2647+ fn interactive_tx_constructor(&self) -> Result<Option<&InteractiveTxConstructor>, &'static str> {
2648+ Ok(self.interactive_tx_constructor.as_ref())
2649+ }
2650+
2651+ #[inline]
2652+ fn interactive_tx_constructor_mut(&mut self) -> Result<&mut Option<InteractiveTxConstructor>, &'static str> {
2653+ Ok(&mut self.interactive_tx_constructor)
2654+ }
2655+
2656+ #[inline]
2657+ fn interactive_tx_signing_session_mut(&mut self) -> Result<&mut Option<InteractiveTxSigningSession>, &'static str> {
2658+ Ok(&mut self.interactive_tx_signing_session)
2659+ }
2660+ }
2661+
25602662impl<SP: Deref> ChannelContext<SP> where SP::Target: SignerProvider {
25612663 fn new_for_inbound_channel<'a, ES: Deref, F: Deref, L: Deref>(
25622664 fee_estimator: &'a LowerBoundedFeeEstimator<F>,
0 commit comments