@@ -4252,12 +4252,14 @@ fn get_v2_channel_reserve_satoshis(channel_value_satoshis: u64, dust_limit_satos
4252
4252
cmp::min(channel_value_satoshis, cmp::max(q, dust_limit_satoshis))
4253
4253
}
4254
4254
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
4255
4257
#[allow(dead_code)] // TODO(dual_funding): Remove once begin_interactive_funding_tx_construction() is used
4256
4258
fn need_to_add_funding_change_output(is_initiator: bool,
4257
- our_funding_satoshis : u64, funding_inputs_prev_outputs: &Vec<TxOut> ,
4258
- funding_outputs : &Vec<OutputOwned >, funding_feerate_sat_per_1000_weight: u32 ,
4259
- holder_dust_limit_satoshis: u64,
4260
- ) -> Result< Option<u64>, ChannelError > {
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> {
4261
4263
let our_funding_inputs_weight = funding_inputs_prev_outputs.iter().fold(0u64, |weight, prev_output| {
4262
4264
weight.saturating_add(estimate_input_weight(prev_output).to_wu())
4263
4265
});
@@ -4276,13 +4278,13 @@ fn need_to_add_funding_change_output(is_initiator: bool,
4276
4278
let total_input_satoshis: u64 = funding_inputs_prev_outputs.iter().map(|out| out.value.to_sat()).sum();
4277
4279
4278
4280
let remaining_value = total_input_satoshis
4279
- .saturating_sub(our_funding_satoshis )
4281
+ .saturating_sub(our_contribution )
4280
4282
.saturating_sub(fees_sats);
4281
4283
4282
- if remaining_value < holder_dust_limit_satoshis {
4283
- Ok( None)
4284
+ if remaining_value <= holder_dust_limit_satoshis {
4285
+ None
4284
4286
} else {
4285
- Ok( Some(remaining_value) )
4287
+ Some(remaining_value)
4286
4288
}
4287
4289
}
4288
4290
@@ -4295,7 +4297,7 @@ fn maybe_add_funding_change_output<SP: Deref>(signer_provider: &SP, is_initiator
4295
4297
let remaining_value = match need_to_add_funding_change_output(
4296
4298
is_initiator, our_funding_satoshis, funding_inputs_prev_outputs,
4297
4299
funding_outputs, funding_feerate_sat_per_1000_weight, holder_dust_limit_satoshis
4298
- )? {
4300
+ ) {
4299
4301
None => {
4300
4302
// No need to add
4301
4303
return Ok(None);
@@ -12094,44 +12096,81 @@ mod tests {
12094
12096
}
12095
12097
12096
12098
#[test]
12097
- fn test_need_to_add_funding_change_output () {
12098
- let prevouts = vec![
12099
+ fn test_need_to_add_funding_change_output_open () {
12100
+ let input_prevouts = vec![
12099
12101
TxOut { value: Amount::from_sat(70_000), script_pubkey: ScriptBuf::new()},
12100
12102
TxOut { value: Amount::from_sat(60_000), script_pubkey: ScriptBuf::new()},
12101
12103
];
12102
- let txout = TxOut { value: Amount::from_sat(125_000), script_pubkey: ScriptBuf::new()};
12103
- let outputs = vec![OutputOwned::Shared(SharedOwnedOutput::new(txout, 105_000))];
12104
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)];
12105
12107
let funding_feerate_sat_per_1000_weight = 3000;
12106
12108
12107
- let total_inputs: u64 = prevouts .iter().map(|o| o.value.to_sat()).sum();
12109
+ let total_inputs: u64 = input_prevouts .iter().map(|o| o.value.to_sat()).sum();
12108
12110
let gross_change = total_inputs - our_contributed;
12109
12111
let fees = 1746;
12110
12112
let common_fees = 126;
12111
12113
{
12112
12114
// There is leftover for change
12113
- let res = need_to_add_funding_change_output(true, our_contributed, &prevouts , &outputs, funding_feerate_sat_per_1000_weight, 300);
12114
- assert_eq!(res.unwrap().unwrap() , gross_change - fees - common_fees);
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);
12115
12117
}
12116
12118
{
12117
12119
// There is leftover for change, without common fees
12118
- let res = need_to_add_funding_change_output(false, our_contributed, &prevouts, &outputs, funding_feerate_sat_per_1000_weight, 300);
12119
- assert_eq!(res.unwrap().unwrap(), gross_change - 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);
12120
12127
}
12121
12128
{
12122
12129
// Insufficient inputs, no leftover
12123
- let res = need_to_add_funding_change_output(false, 130_000, &prevouts, &outputs, funding_feerate_sat_per_1000_weight, 300);
12124
- assert!(res.unwrap().is_none());
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);
12125
12164
}
12126
12165
{
12127
12166
// Very small leftover
12128
- let res = need_to_add_funding_change_output(false, 128_100, &prevouts , &outputs, funding_feerate_sat_per_1000_weight, 300);
12129
- assert!(res.unwrap(). is_none());
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());
12130
12169
}
12131
12170
{
12132
12171
// Small leftover, but not dust
12133
- let res = need_to_add_funding_change_output(false, 128_100, &prevouts , &outputs, funding_feerate_sat_per_1000_weight, 100);
12134
- assert_eq!(res.unwrap().unwrap() , 154);
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);
12135
12174
}
12136
12175
}
12137
12176
}
0 commit comments