Skip to content

Commit b64c45f

Browse files
committed
f - Move begin_interactive_funding_tx_construction
1 parent f75c489 commit b64c45f

File tree

1 file changed

+129
-133
lines changed

1 file changed

+129
-133
lines changed

lightning/src/ln/channel.rs

Lines changed: 129 additions & 133 deletions
Original file line numberDiff line numberDiff line change
@@ -2942,87 +2942,6 @@ where
29422942
/// - [`FundedChannel`], when splicing.
29432943
pub(super) struct NegotiatingChannelView<'a>(&'a mut InteractiveTxConstructor);
29442944

2945-
/// Prepare and start interactive transaction negotiation.
2946-
/// `change_destination_opt` - Optional destination for optional change; if None,
2947-
/// default destination address is used.
2948-
/// If error occurs, it is caused by our side, not the counterparty.
2949-
#[allow(dead_code)] // TODO(dual_funding): Remove once contribution to V2 channels is enabled
2950-
fn begin_interactive_funding_tx_construction<SP: Deref, ES: Deref>(
2951-
funding: &FundingScope, context: &ChannelContext<SP>,
2952-
funding_negotiation_context: FundingNegotiationContext, is_splice: bool,
2953-
signer_provider: &SP, entropy_source: &ES, holder_node_id: PublicKey,
2954-
change_destination_opt: Option<ScriptBuf>, shared_funding_input: Option<SharedOwnedInput>,
2955-
) -> Result<InteractiveTxConstructor, AbortReason>
2956-
where
2957-
SP::Target: SignerProvider,
2958-
ES::Target: EntropySource,
2959-
{
2960-
if is_splice {
2961-
debug_assert!(matches!(context.channel_state, ChannelState::ChannelReady(_)));
2962-
} else {
2963-
debug_assert!(matches!(context.channel_state, ChannelState::NegotiatingFunding(_)));
2964-
}
2965-
2966-
// Add output for funding tx
2967-
// Note: For the error case when the inputs are insufficient, it will be handled after
2968-
// the `calculate_change_output_value` call below
2969-
let mut funding_outputs = Vec::new();
2970-
2971-
let shared_funding_output = TxOut {
2972-
value: Amount::from_sat(funding.get_value_satoshis()),
2973-
script_pubkey: funding.get_funding_redeemscript().to_p2wsh(),
2974-
};
2975-
2976-
// Optionally add change output
2977-
let change_script = if let Some(script) = change_destination_opt {
2978-
script
2979-
} else {
2980-
signer_provider
2981-
.get_destination_script(context.channel_keys_id)
2982-
.map_err(|_err| AbortReason::InternalError("Error getting destination script"))?
2983-
};
2984-
let change_value_opt = calculate_change_output_value(
2985-
&funding_negotiation_context,
2986-
shared_funding_input.as_ref().map(|input| input.local_owned()),
2987-
&shared_funding_output.script_pubkey,
2988-
&funding_outputs,
2989-
change_script.minimal_non_dust().to_sat(),
2990-
)?;
2991-
if let Some(change_value) = change_value_opt {
2992-
let mut change_output =
2993-
TxOut { value: Amount::from_sat(change_value), script_pubkey: change_script };
2994-
let change_output_weight = get_output_weight(&change_output.script_pubkey).to_wu();
2995-
let change_output_fee = fee_for_weight(
2996-
funding_negotiation_context.funding_feerate_sat_per_1000_weight,
2997-
change_output_weight,
2998-
);
2999-
let change_value_decreased_with_fee = change_value.saturating_sub(change_output_fee);
3000-
// Check dust limit again
3001-
if change_value_decreased_with_fee > context.holder_dust_limit_satoshis {
3002-
change_output.value = Amount::from_sat(change_value_decreased_with_fee);
3003-
funding_outputs.push(change_output);
3004-
}
3005-
}
3006-
3007-
let constructor_args = InteractiveTxConstructorArgs {
3008-
entropy_source,
3009-
holder_node_id,
3010-
counterparty_node_id: context.counterparty_node_id,
3011-
channel_id: context.channel_id(),
3012-
feerate_sat_per_kw: funding_negotiation_context.funding_feerate_sat_per_1000_weight,
3013-
is_initiator: funding_negotiation_context.is_initiator,
3014-
funding_tx_locktime: funding_negotiation_context.funding_tx_locktime,
3015-
inputs_to_contribute: funding_negotiation_context.our_funding_inputs,
3016-
shared_funding_input,
3017-
shared_funding_output: SharedOwnedOutput::new(
3018-
shared_funding_output,
3019-
funding_negotiation_context.our_funding_satoshis,
3020-
),
3021-
outputs_to_contribute: funding_outputs,
3022-
};
3023-
InteractiveTxConstructor::new(constructor_args)
3024-
}
3025-
30262945
#[rustfmt::skip]
30272946
fn funding_tx_constructed<SP:Deref, L: Deref>(
30282947
funding: &mut FundingScope, context: &mut ChannelContext<SP>,
@@ -6031,6 +5950,85 @@ pub(super) struct FundingNegotiationContext {
60315950
pub our_funding_inputs: Vec<(TxIn, TransactionU16LenLimited)>,
60325951
}
60335952

5953+
impl FundingNegotiationContext {
5954+
/// Prepare and start interactive transaction negotiation.
5955+
/// `change_destination_opt` - Optional destination for optional change; if None,
5956+
/// default destination address is used.
5957+
/// If error occurs, it is caused by our side, not the counterparty.
5958+
fn into_interactive_tx_constructor<SP: Deref, ES: Deref>(
5959+
self, context: &ChannelContext<SP>, funding: &FundingScope, is_splice: bool,
5960+
signer_provider: &SP, entropy_source: &ES, holder_node_id: PublicKey,
5961+
change_destination_opt: Option<ScriptBuf>, shared_funding_input: Option<SharedOwnedInput>,
5962+
) -> Result<InteractiveTxConstructor, AbortReason>
5963+
where
5964+
SP::Target: SignerProvider,
5965+
ES::Target: EntropySource,
5966+
{
5967+
if is_splice {
5968+
debug_assert!(matches!(context.channel_state, ChannelState::ChannelReady(_)));
5969+
} else {
5970+
debug_assert!(matches!(context.channel_state, ChannelState::NegotiatingFunding(_)));
5971+
}
5972+
5973+
// Add output for funding tx
5974+
// Note: For the error case when the inputs are insufficient, it will be handled after
5975+
// the `calculate_change_output_value` call below
5976+
let mut funding_outputs = Vec::new();
5977+
5978+
let shared_funding_output = TxOut {
5979+
value: Amount::from_sat(funding.get_value_satoshis()),
5980+
script_pubkey: funding.get_funding_redeemscript().to_p2wsh(),
5981+
};
5982+
5983+
// Optionally add change output
5984+
let change_script = if let Some(script) = change_destination_opt {
5985+
script
5986+
} else {
5987+
signer_provider
5988+
.get_destination_script(context.channel_keys_id)
5989+
.map_err(|_err| AbortReason::InternalError("Error getting destination script"))?
5990+
};
5991+
let change_value_opt = calculate_change_output_value(
5992+
&self,
5993+
shared_funding_input.as_ref().map(|input| input.local_owned()),
5994+
&shared_funding_output.script_pubkey,
5995+
&funding_outputs,
5996+
change_script.minimal_non_dust().to_sat(),
5997+
)?;
5998+
if let Some(change_value) = change_value_opt {
5999+
let mut change_output =
6000+
TxOut { value: Amount::from_sat(change_value), script_pubkey: change_script };
6001+
let change_output_weight = get_output_weight(&change_output.script_pubkey).to_wu();
6002+
let change_output_fee =
6003+
fee_for_weight(self.funding_feerate_sat_per_1000_weight, change_output_weight);
6004+
let change_value_decreased_with_fee = change_value.saturating_sub(change_output_fee);
6005+
// Check dust limit again
6006+
if change_value_decreased_with_fee > context.holder_dust_limit_satoshis {
6007+
change_output.value = Amount::from_sat(change_value_decreased_with_fee);
6008+
funding_outputs.push(change_output);
6009+
}
6010+
}
6011+
6012+
let constructor_args = InteractiveTxConstructorArgs {
6013+
entropy_source,
6014+
holder_node_id,
6015+
counterparty_node_id: context.counterparty_node_id,
6016+
channel_id: context.channel_id(),
6017+
feerate_sat_per_kw: self.funding_feerate_sat_per_1000_weight,
6018+
is_initiator: self.is_initiator,
6019+
funding_tx_locktime: self.funding_tx_locktime,
6020+
inputs_to_contribute: self.our_funding_inputs,
6021+
shared_funding_input,
6022+
shared_funding_output: SharedOwnedOutput::new(
6023+
shared_funding_output,
6024+
self.our_funding_satoshis,
6025+
),
6026+
outputs_to_contribute: funding_outputs,
6027+
};
6028+
InteractiveTxConstructor::new(constructor_args)
6029+
}
6030+
}
6031+
60346032
// Holder designates channel data owned for the benefit of the user client.
60356033
// Counterparty designates channel data owned by the another channel participant entity.
60366034
pub(super) struct FundedChannel<SP: Deref>
@@ -10530,7 +10528,7 @@ where
1053010528
their_funding_contribution,
1053110529
);
1053210530

10533-
let funding_scope = FundingScope::for_splice(
10531+
let splice_funding = FundingScope::for_splice(
1053410532
&self.funding,
1053510533
&self.context,
1053610534
our_funding_contribution,
@@ -10556,43 +10554,39 @@ where
1055610554
our_funding_inputs: Vec::new(),
1055710555
};
1055810556

10559-
self.pending_splice = Some(PendingSplice {
10560-
our_funding_contribution,
10561-
funding: Some(funding_scope),
10562-
funding_negotiation_context: Some(funding_negotiation_context),
10563-
interactive_tx_constructor: None,
10564-
received_funding_txid: None,
10565-
sent_funding_txid: None,
10566-
});
10567-
1056810557
log_info!(logger, "Splicing process started after splice_init, new channel value {}, old {}, outgoing {}, channel_id {}",
1056910558
post_channel_value, pre_channel_value, false, self.context.channel_id);
1057010559

1057110560
let splice_ack_msg = self.get_splice_ack(our_funding_contribution);
1057210561

10573-
let pending_splice = self.pending_splice.as_mut().unwrap();
10574-
let mut interactive_tx_constructor = begin_interactive_funding_tx_construction(
10575-
pending_splice.funding.as_ref().unwrap(),
10576-
&self.context,
10577-
pending_splice.funding_negotiation_context.take().unwrap(),
10578-
true,
10579-
signer_provider,
10580-
entropy_source,
10581-
holder_node_id.clone(),
10582-
None,
10583-
Some(prev_funding_input),
10584-
)
10585-
.map_err(|err| {
10586-
ChannelError::Warn(format!(
10587-
"Failed to start interactive transaction construction, {:?}",
10588-
err
10589-
))
10590-
})?;
10591-
10562+
let mut interactive_tx_constructor = funding_negotiation_context
10563+
.into_interactive_tx_constructor(
10564+
&self.context,
10565+
&splice_funding,
10566+
true,
10567+
signer_provider,
10568+
entropy_source,
10569+
holder_node_id.clone(),
10570+
None,
10571+
Some(prev_funding_input),
10572+
)
10573+
.map_err(|err| {
10574+
ChannelError::Warn(format!(
10575+
"Failed to start interactive transaction construction, {:?}",
10576+
err
10577+
))
10578+
})?;
1059210579
// TODO: Propagate message
1059310580
let _msg = interactive_tx_constructor.take_initiator_first_message();
10594-
self.pending_splice.as_mut().unwrap().interactive_tx_constructor =
10595-
Some(interactive_tx_constructor);
10581+
10582+
self.pending_splice = Some(PendingSplice {
10583+
our_funding_contribution,
10584+
funding: Some(splice_funding),
10585+
funding_negotiation_context: None,
10586+
interactive_tx_constructor: Some(interactive_tx_constructor),
10587+
received_funding_txid: None,
10588+
sent_funding_txid: None,
10589+
});
1059610590

1059710591
Ok(splice_ack_msg)
1059810592
}
@@ -10654,7 +10648,7 @@ where
1065410648
// TODO(splicing): Pre-check for reserve requirement
1065510649
// (Note: It should also be checked later at tx_complete)
1065610650

10657-
let funding_scope = FundingScope::for_splice(
10651+
let splice_funding = FundingScope::for_splice(
1065810652
&self.funding,
1065910653
&self.context,
1066010654
our_funding_contribution,
@@ -10671,37 +10665,39 @@ where
1067110665

1067210666
let prev_funding_input = self.funding.to_splice_funding_input();
1067310667

10674-
debug_assert!(pending_splice.funding.is_none());
10675-
pending_splice.funding = Some(funding_scope);
1067610668
// update funding values
1067710669
pending_splice.funding_negotiation_context.as_mut().unwrap().our_funding_satoshis =
1067810670
our_funding_satoshis;
1067910671
pending_splice.funding_negotiation_context.as_mut().unwrap().their_funding_satoshis =
1068010672
Some(their_funding_satoshis);
10681-
debug_assert!(pending_splice.interactive_tx_constructor.is_none());
10682-
debug_assert!(self.interactive_tx_signing_session.is_none());
1068310673

1068410674
log_info!(logger, "Splicing process started after splice_ack, new channel value {}, old {}, outgoing {}, channel_id {}",
1068510675
post_channel_value, pre_channel_value, true, self.context.channel_id);
1068610676

1068710677
// Start interactive funding negotiation, with the previous funding transaction as an extra shared input
10688-
let mut interactive_tx_constructor = begin_interactive_funding_tx_construction(
10689-
pending_splice.funding.as_ref().unwrap(),
10690-
&self.context,
10691-
pending_splice.funding_negotiation_context.take().unwrap(),
10692-
true,
10693-
signer_provider,
10694-
entropy_source,
10695-
holder_node_id.clone(),
10696-
None,
10697-
Some(prev_funding_input),
10698-
)
10699-
.map_err(|err| {
10700-
ChannelError::Warn(format!("V2 channel rejected due to sender error, {:?}", err))
10701-
})?;
10678+
let funding_negotiation_context = pending_splice.funding_negotiation_context.take().unwrap();
10679+
let mut interactive_tx_constructor = funding_negotiation_context
10680+
.into_interactive_tx_constructor(
10681+
&self.context,
10682+
&splice_funding,
10683+
true,
10684+
signer_provider,
10685+
entropy_source,
10686+
holder_node_id.clone(),
10687+
None,
10688+
Some(prev_funding_input),
10689+
)
10690+
.map_err(|err| {
10691+
ChannelError::Warn(format!("V2 channel rejected due to sender error, {:?}", err))
10692+
})?;
1070210693
let tx_msg_opt = interactive_tx_constructor.take_initiator_first_message();
10703-
self.pending_splice.as_mut().unwrap().interactive_tx_constructor =
10704-
Some(interactive_tx_constructor);
10694+
10695+
debug_assert!(pending_splice.funding.is_none());
10696+
debug_assert!(pending_splice.interactive_tx_constructor.is_none());
10697+
debug_assert!(self.interactive_tx_signing_session.is_none());
10698+
pending_splice.funding = Some(splice_funding);
10699+
pending_splice.interactive_tx_constructor = Some(interactive_tx_constructor);
10700+
1070510701
Ok(tx_msg_opt)
1070610702
}
1070710703

0 commit comments

Comments
 (0)