Skip to content

Commit 4f7e41b

Browse files
committed
Moved need_to_add_funding_change_output() to interactivetxs.rs
1 parent acf9853 commit 4f7e41b

File tree

2 files changed

+118
-119
lines changed

2 files changed

+118
-119
lines changed

lightning/src/ln/channel.rs

Lines changed: 2 additions & 118 deletions
Original file line numberDiff line numberDiff line change
@@ -31,7 +31,7 @@ use crate::ln::types::ChannelId;
3131
use crate::types::payment::{PaymentPreimage, PaymentHash};
3232
use crate::types::features::{ChannelTypeFeatures, InitFeatures};
3333
use crate::ln::interactivetxs::{
34-
estimate_input_weight, get_output_weight, HandleTxCompleteValue, HandleTxCompleteResult, InteractiveTxConstructor,
34+
get_output_weight, need_to_add_funding_change_output, HandleTxCompleteValue, HandleTxCompleteResult, InteractiveTxConstructor,
3535
InteractiveTxConstructorArgs, InteractiveTxMessageSend, InteractiveTxSigningSession, InteractiveTxMessageSendResult,
3636
OutputOwned, SharedOwnedOutput, TX_COMMON_FIELDS_WEIGHT,
3737
};
@@ -4252,42 +4252,6 @@ fn get_v2_channel_reserve_satoshis(channel_value_satoshis: u64, dust_limit_satos
42524252
cmp::min(channel_value_satoshis, cmp::max(q, dust_limit_satoshis))
42534253
}
42544254

4255-
/// Determine whether with our given inputs, outputs, and intended contribution
4256-
/// a change output should be added or not, and if so, of waht size
4257-
#[allow(dead_code)] // TODO(dual_funding): Remove once begin_interactive_funding_tx_construction() is used
4258-
fn need_to_add_funding_change_output(is_initiator: bool,
4259-
our_contribution: u64,
4260-
funding_inputs_prev_outputs: &Vec<TxOut>, funding_outputs: &Vec<OutputOwned>,
4261-
funding_feerate_sat_per_1000_weight: u32, holder_dust_limit_satoshis: u64,
4262-
) -> Option<u64> {
4263-
let our_funding_inputs_weight = funding_inputs_prev_outputs.iter().fold(0u64, |weight, prev_output| {
4264-
weight.saturating_add(estimate_input_weight(prev_output).to_wu())
4265-
});
4266-
let our_funding_outputs_weight = funding_outputs.iter().fold(0u64, |weight, out| {
4267-
weight.saturating_add(get_output_weight(&out.tx_out().script_pubkey).to_wu())
4268-
});
4269-
let our_contributed_weight = our_funding_outputs_weight.saturating_add(our_funding_inputs_weight);
4270-
let mut fees_sats = fee_for_weight(funding_feerate_sat_per_1000_weight, our_contributed_weight);
4271-
4272-
// If we are the initiator, we must pay for weight of all common fields in the funding transaction.
4273-
if is_initiator {
4274-
let common_fees = fee_for_weight(funding_feerate_sat_per_1000_weight, TX_COMMON_FIELDS_WEIGHT);
4275-
fees_sats = fees_sats.saturating_add(common_fees);
4276-
}
4277-
4278-
let total_input_satoshis: u64 = funding_inputs_prev_outputs.iter().map(|out| out.value.to_sat()).sum();
4279-
4280-
let remaining_value = total_input_satoshis
4281-
.saturating_sub(our_contribution)
4282-
.saturating_sub(fees_sats);
4283-
4284-
if remaining_value <= holder_dust_limit_satoshis {
4285-
None
4286-
} else {
4287-
Some(remaining_value)
4288-
}
4289-
}
4290-
42914255
#[allow(dead_code)] // TODO(dual_funding): Remove once begin_interactive_funding_tx_construction() is used
42924256
fn maybe_add_funding_change_output<SP: Deref>(signer_provider: &SP, is_initiator: bool,
42934257
our_funding_satoshis: u64, funding_inputs_prev_outputs: &Vec<TxOut>,
@@ -10329,9 +10293,8 @@ mod tests {
1032910293
use crate::ln::channel_keys::{RevocationKey, RevocationBasepoint};
1033010294
use crate::ln::channelmanager::{self, HTLCSource, PaymentId};
1033110295
use crate::ln::channel::InitFeatures;
10332-
use crate::ln::channel::{AwaitingChannelReadyFlags, Channel, ChannelState, InboundHTLCOutput, OutboundV1Channel, InboundV1Channel, OutboundHTLCOutput, InboundHTLCState, OutboundHTLCState, HTLCCandidate, HTLCInitiator, HTLCUpdateAwaitingACK, commit_tx_fee_sat, need_to_add_funding_change_output};
10296+
use crate::ln::channel::{AwaitingChannelReadyFlags, Channel, ChannelState, InboundHTLCOutput, OutboundV1Channel, InboundV1Channel, OutboundHTLCOutput, InboundHTLCState, OutboundHTLCState, HTLCCandidate, HTLCInitiator, HTLCUpdateAwaitingACK, commit_tx_fee_sat};
1033310297
use crate::ln::channel::{MAX_FUNDING_SATOSHIS_NO_WUMBO, TOTAL_BITCOIN_SUPPLY_SATOSHIS, MIN_THEIR_CHAN_RESERVE_SATOSHIS};
10334-
use crate::ln::interactivetxs::{OutputOwned, SharedOwnedOutput};
1033510298
use crate::types::features::{ChannelFeatures, ChannelTypeFeatures, NodeFeatures};
1033610299
use crate::ln::msgs;
1033710300
use crate::ln::msgs::{ChannelUpdate, DecodeError, UnsignedChannelUpdate, MAX_VALUE_MSAT};
@@ -12094,83 +12057,4 @@ mod tests {
1209412057
assert_eq!(node_a_chan.context.channel_state, ChannelState::AwaitingChannelReady(AwaitingChannelReadyFlags::THEIR_CHANNEL_READY));
1209512058
assert!(node_a_chan.check_get_channel_ready(0, &&logger).is_some());
1209612059
}
12097-
12098-
#[test]
12099-
fn test_need_to_add_funding_change_output_open() {
12100-
let input_prevouts = vec![
12101-
TxOut { value: Amount::from_sat(70_000), script_pubkey: ScriptBuf::new()},
12102-
TxOut { value: Amount::from_sat(60_000), script_pubkey: ScriptBuf::new()},
12103-
];
12104-
let our_contributed = 110_000;
12105-
let txout = TxOut { value: Amount::from_sat(128_000), script_pubkey: ScriptBuf::new()};
12106-
let outputs = vec![OutputOwned::SharedControlFullyOwned(txout)];
12107-
let funding_feerate_sat_per_1000_weight = 3000;
12108-
12109-
let total_inputs: u64 = input_prevouts.iter().map(|o| o.value.to_sat()).sum();
12110-
let gross_change = total_inputs - our_contributed;
12111-
let fees = 1746;
12112-
let common_fees = 126;
12113-
{
12114-
// There is leftover for change
12115-
let res = need_to_add_funding_change_output(true, our_contributed, &input_prevouts, &outputs, funding_feerate_sat_per_1000_weight, 300);
12116-
assert_eq!(res.unwrap(), gross_change - fees - common_fees);
12117-
}
12118-
{
12119-
// There is leftover for change, without common fees
12120-
let res = need_to_add_funding_change_output(false, our_contributed, &input_prevouts, &outputs, funding_feerate_sat_per_1000_weight, 300);
12121-
assert_eq!(res.unwrap(), gross_change - fees);
12122-
}
12123-
{
12124-
// Larger fee, smaller change
12125-
let res = need_to_add_funding_change_output(true, our_contributed, &input_prevouts, &outputs, 9000, 300);
12126-
assert_eq!(res.unwrap(), 14384);
12127-
}
12128-
{
12129-
// Insufficient inputs, no leftover
12130-
let res = need_to_add_funding_change_output(false, 130_000, &input_prevouts, &outputs, funding_feerate_sat_per_1000_weight, 300);
12131-
assert!(res.is_none());
12132-
}
12133-
{
12134-
// Very small leftover
12135-
let res = need_to_add_funding_change_output(false, 128_100, &input_prevouts, &outputs, funding_feerate_sat_per_1000_weight, 300);
12136-
assert!(res.is_none());
12137-
}
12138-
{
12139-
// Small leftover, but not dust
12140-
let res = need_to_add_funding_change_output(false, 128_100, &input_prevouts, &outputs, funding_feerate_sat_per_1000_weight, 100);
12141-
assert_eq!(res.unwrap(), 154);
12142-
}
12143-
}
12144-
12145-
#[test]
12146-
fn test_need_to_add_funding_change_output_splice() {
12147-
let input_prevouts = vec![
12148-
TxOut { value: Amount::from_sat(70_000), script_pubkey: ScriptBuf::new()},
12149-
TxOut { value: Amount::from_sat(60_000), script_pubkey: ScriptBuf::new()},
12150-
];
12151-
let our_contributed = 110_000;
12152-
let txout = TxOut { value: Amount::from_sat(148_000), script_pubkey: ScriptBuf::new()};
12153-
let outputs = vec![OutputOwned::Shared(SharedOwnedOutput::new(txout, our_contributed))];
12154-
let funding_feerate_sat_per_1000_weight = 3000;
12155-
12156-
let total_inputs: u64 = input_prevouts.iter().map(|o| o.value.to_sat()).sum();
12157-
let gross_change = total_inputs - our_contributed;
12158-
let fees = 1746;
12159-
let common_fees = 126;
12160-
{
12161-
// There is leftover for change
12162-
let res = need_to_add_funding_change_output(true, our_contributed, &input_prevouts, &outputs, funding_feerate_sat_per_1000_weight, 300);
12163-
assert_eq!(res.unwrap(), gross_change - fees - common_fees);
12164-
}
12165-
{
12166-
// Very small leftover
12167-
let res = need_to_add_funding_change_output(false, 128_100, &input_prevouts, &outputs, funding_feerate_sat_per_1000_weight, 300);
12168-
assert!(res.is_none());
12169-
}
12170-
{
12171-
// Small leftover, but not dust
12172-
let res = need_to_add_funding_change_output(false, 128_100, &input_prevouts, &outputs, funding_feerate_sat_per_1000_weight, 100);
12173-
assert_eq!(res.unwrap(), 154);
12174-
}
12175-
}
1217612060
}

lightning/src/ln/interactivetxs.rs

Lines changed: 116 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1662,12 +1662,48 @@ impl InteractiveTxConstructor {
16621662
}
16631663
}
16641664

1665+
/// Determine whether with our given inputs, outputs, and intended contribution
1666+
/// a change output should be added or not, and if so, of waht size
1667+
#[allow(dead_code)] // TODO(dual_funding): Remove once begin_interactive_funding_tx_construction() is used
1668+
pub(super) fn need_to_add_funding_change_output(is_initiator: bool,
1669+
our_contribution: u64,
1670+
funding_inputs_prev_outputs: &Vec<TxOut>, funding_outputs: &Vec<OutputOwned>,
1671+
funding_feerate_sat_per_1000_weight: u32, holder_dust_limit_satoshis: u64,
1672+
) -> Option<u64> {
1673+
let our_funding_inputs_weight = funding_inputs_prev_outputs.iter().fold(0u64, |weight, prev_output| {
1674+
weight.saturating_add(estimate_input_weight(prev_output).to_wu())
1675+
});
1676+
let our_funding_outputs_weight = funding_outputs.iter().fold(0u64, |weight, out| {
1677+
weight.saturating_add(get_output_weight(&out.tx_out().script_pubkey).to_wu())
1678+
});
1679+
let our_contributed_weight = our_funding_outputs_weight.saturating_add(our_funding_inputs_weight);
1680+
let mut fees_sats = fee_for_weight(funding_feerate_sat_per_1000_weight, our_contributed_weight);
1681+
1682+
// If we are the initiator, we must pay for weight of all common fields in the funding transaction.
1683+
if is_initiator {
1684+
let common_fees = fee_for_weight(funding_feerate_sat_per_1000_weight, TX_COMMON_FIELDS_WEIGHT);
1685+
fees_sats = fees_sats.saturating_add(common_fees);
1686+
}
1687+
1688+
let total_input_satoshis: u64 = funding_inputs_prev_outputs.iter().map(|out| out.value.to_sat()).sum();
1689+
1690+
let remaining_value = total_input_satoshis
1691+
.saturating_sub(our_contribution)
1692+
.saturating_sub(fees_sats);
1693+
1694+
if remaining_value <= holder_dust_limit_satoshis {
1695+
None
1696+
} else {
1697+
Some(remaining_value)
1698+
}
1699+
}
1700+
16651701
#[cfg(test)]
16661702
mod tests {
16671703
use crate::chain::chaininterface::{fee_for_weight, FEERATE_FLOOR_SATS_PER_KW};
16681704
use crate::ln::channel::TOTAL_BITCOIN_SUPPLY_SATOSHIS;
16691705
use crate::ln::interactivetxs::{
1670-
generate_holder_serial_id, AbortReason, HandleTxCompleteValue, InteractiveTxConstructor,
1706+
generate_holder_serial_id, need_to_add_funding_change_output, AbortReason, HandleTxCompleteValue, InteractiveTxConstructor,
16711707
InteractiveTxConstructorArgs, InteractiveTxMessageSend, MAX_INPUTS_OUTPUTS_COUNT,
16721708
MAX_RECEIVED_TX_ADD_INPUT_COUNT, MAX_RECEIVED_TX_ADD_OUTPUT_COUNT,
16731709
};
@@ -2594,4 +2630,83 @@ mod tests {
25942630
assert_eq!(generate_holder_serial_id(&&entropy_source, true) % 2, 0);
25952631
assert_eq!(generate_holder_serial_id(&&entropy_source, false) % 2, 1)
25962632
}
2633+
2634+
#[test]
2635+
fn test_need_to_add_funding_change_output_open() {
2636+
let input_prevouts = vec![
2637+
TxOut { value: Amount::from_sat(70_000), script_pubkey: ScriptBuf::new()},
2638+
TxOut { value: Amount::from_sat(60_000), script_pubkey: ScriptBuf::new()},
2639+
];
2640+
let our_contributed = 110_000;
2641+
let txout = TxOut { value: Amount::from_sat(128_000), script_pubkey: ScriptBuf::new()};
2642+
let outputs = vec![OutputOwned::SharedControlFullyOwned(txout)];
2643+
let funding_feerate_sat_per_1000_weight = 3000;
2644+
2645+
let total_inputs: u64 = input_prevouts.iter().map(|o| o.value.to_sat()).sum();
2646+
let gross_change = total_inputs - our_contributed;
2647+
let fees = 1746;
2648+
let common_fees = 126;
2649+
{
2650+
// There is leftover for change
2651+
let res = need_to_add_funding_change_output(true, our_contributed, &input_prevouts, &outputs, funding_feerate_sat_per_1000_weight, 300);
2652+
assert_eq!(res.unwrap(), gross_change - fees - common_fees);
2653+
}
2654+
{
2655+
// There is leftover for change, without common fees
2656+
let res = need_to_add_funding_change_output(false, our_contributed, &input_prevouts, &outputs, funding_feerate_sat_per_1000_weight, 300);
2657+
assert_eq!(res.unwrap(), gross_change - fees);
2658+
}
2659+
{
2660+
// Larger fee, smaller change
2661+
let res = need_to_add_funding_change_output(true, our_contributed, &input_prevouts, &outputs, 9000, 300);
2662+
assert_eq!(res.unwrap(), 14384);
2663+
}
2664+
{
2665+
// Insufficient inputs, no leftover
2666+
let res = need_to_add_funding_change_output(false, 130_000, &input_prevouts, &outputs, funding_feerate_sat_per_1000_weight, 300);
2667+
assert!(res.is_none());
2668+
}
2669+
{
2670+
// Very small leftover
2671+
let res = need_to_add_funding_change_output(false, 128_100, &input_prevouts, &outputs, funding_feerate_sat_per_1000_weight, 300);
2672+
assert!(res.is_none());
2673+
}
2674+
{
2675+
// Small leftover, but not dust
2676+
let res = need_to_add_funding_change_output(false, 128_100, &input_prevouts, &outputs, funding_feerate_sat_per_1000_weight, 100);
2677+
assert_eq!(res.unwrap(), 154);
2678+
}
2679+
}
2680+
2681+
#[test]
2682+
fn test_need_to_add_funding_change_output_splice() {
2683+
let input_prevouts = vec![
2684+
TxOut { value: Amount::from_sat(70_000), script_pubkey: ScriptBuf::new()},
2685+
TxOut { value: Amount::from_sat(60_000), script_pubkey: ScriptBuf::new()},
2686+
];
2687+
let our_contributed = 110_000;
2688+
let txout = TxOut { value: Amount::from_sat(148_000), script_pubkey: ScriptBuf::new()};
2689+
let outputs = vec![OutputOwned::Shared(SharedOwnedOutput::new(txout, our_contributed))];
2690+
let funding_feerate_sat_per_1000_weight = 3000;
2691+
2692+
let total_inputs: u64 = input_prevouts.iter().map(|o| o.value.to_sat()).sum();
2693+
let gross_change = total_inputs - our_contributed;
2694+
let fees = 1746;
2695+
let common_fees = 126;
2696+
{
2697+
// There is leftover for change
2698+
let res = need_to_add_funding_change_output(true, our_contributed, &input_prevouts, &outputs, funding_feerate_sat_per_1000_weight, 300);
2699+
assert_eq!(res.unwrap(), gross_change - fees - common_fees);
2700+
}
2701+
{
2702+
// Very small leftover
2703+
let res = need_to_add_funding_change_output(false, 128_100, &input_prevouts, &outputs, funding_feerate_sat_per_1000_weight, 300);
2704+
assert!(res.is_none());
2705+
}
2706+
{
2707+
// Small leftover, but not dust
2708+
let res = need_to_add_funding_change_output(false, 128_100, &input_prevouts, &outputs, funding_feerate_sat_per_1000_weight, 100);
2709+
assert_eq!(res.unwrap(), 154);
2710+
}
2711+
}
25972712
}

0 commit comments

Comments
 (0)