Skip to content

Commit 8b5dcd2

Browse files
committed
Add check for sufficient contributions when starting splicing
1 parent 3245114 commit 8b5dcd2

File tree

1 file changed

+48
-22
lines changed

1 file changed

+48
-22
lines changed

lightning/src/ln/channel.rs

Lines changed: 48 additions & 22 deletions
Original file line numberDiff line numberDiff line change
@@ -54,8 +54,9 @@ use crate::chain::chaininterface::{FeeEstimator, ConfirmationTarget, LowerBounde
5454
use crate::chain::channelmonitor::{ChannelMonitor, ChannelMonitorUpdate, ChannelMonitorUpdateStep, LATENCY_GRACE_PERIOD_BLOCKS};
5555
use crate::chain::transaction::{OutPoint, TransactionData};
5656
use crate::sign::ecdsa::EcdsaChannelSigner;
57-
use crate::sign::{EntropySource, ChannelSigner, SignerProvider, NodeSigner, Recipient};
57+
use crate::sign::{EntropySource, ChannelSigner, SignerProvider, NodeSigner, Recipient, P2WPKH_WITNESS_WEIGHT};
5858
use crate::events::{ClosureReason, Event};
59+
use crate::events::bump_transaction::BASE_INPUT_WEIGHT;
5960
use crate::routing::gossip::NodeId;
6061
use crate::util::ser::{Readable, ReadableArgs, TransactionU16LenLimited, Writeable, Writer};
6162
use crate::util::logger::{Logger, Record, WithContext};
@@ -4429,15 +4430,44 @@ fn get_v2_channel_reserve_satoshis(channel_value_satoshis: u64, dust_limit_satos
44294430
cmp::min(channel_value_satoshis, cmp::max(q, dust_limit_satoshis))
44304431
}
44314432

4433+
/// Estimate our part of the fee of the new funding transaction.
4434+
/// input_count: Number of contributed inputs.
4435+
/// witness_weight: The witness weight for contributed inputs.
4436+
#[allow(dead_code)] // TODO(dual_funding): Remove once V2 channels is enabled.
4437+
fn estimate_funding_transaction_fee(
4438+
is_initiator: bool, input_count: usize, witness_weight: Weight,
4439+
funding_feerate_sat_per_1000_weight: u32,
4440+
) -> u64 {
4441+
// Inputs
4442+
let mut weight = (input_count as u64) * BASE_INPUT_WEIGHT;
4443+
4444+
// Witnesses
4445+
weight = weight.saturating_add(witness_weight.to_wu());
4446+
4447+
// If we are the initiator, we must pay for weight of all common fields in the funding transaction.
4448+
if is_initiator {
4449+
weight = weight
4450+
.saturating_add(TX_COMMON_FIELDS_WEIGHT)
4451+
// The weight of the funding output, a P2WSH output
4452+
// NOTE: The witness script hash given here is irrelevant as it's a fixed size and we just want
4453+
// to calculate the contributed weight, so we use an all-zero hash.
4454+
.saturating_add(get_output_weight(&ScriptBuf::new_p2wsh(
4455+
&WScriptHash::from_raw_hash(Hash::all_zeros())
4456+
)).to_wu())
4457+
}
4458+
4459+
fee_for_weight(funding_feerate_sat_per_1000_weight, weight)
4460+
}
4461+
44324462
#[allow(dead_code)] // TODO(dual_funding): Remove once V2 channels is enabled.
44334463
pub(super) fn calculate_our_funding_satoshis(
44344464
is_initiator: bool, funding_inputs: &[(TxIn, TransactionU16LenLimited)],
44354465
total_witness_weight: Weight, funding_feerate_sat_per_1000_weight: u32,
44364466
holder_dust_limit_satoshis: u64,
44374467
) -> Result<u64, APIError> {
4438-
let mut total_input_satoshis = 0u64;
4439-
let mut our_contributed_weight = 0u64;
4468+
let estimated_fee = estimate_funding_transaction_fee(is_initiator, funding_inputs.len(), total_witness_weight, funding_feerate_sat_per_1000_weight);
44404469

4470+
let mut total_input_satoshis = 0u64;
44414471
for (idx, input) in funding_inputs.iter().enumerate() {
44424472
if let Some(output) = input.1.as_transaction().output.get(input.0.previous_output.vout as usize) {
44434473
total_input_satoshis = total_input_satoshis.saturating_add(output.value.to_sat());
@@ -4447,23 +4477,8 @@ pub(super) fn calculate_our_funding_satoshis(
44474477
input.1.as_transaction().compute_txid(), input.0.previous_output.vout, idx) });
44484478
}
44494479
}
4450-
our_contributed_weight = our_contributed_weight.saturating_add(total_witness_weight.to_wu());
44514480

4452-
// If we are the initiator, we must pay for weight of all common fields in the funding transaction.
4453-
if is_initiator {
4454-
our_contributed_weight = our_contributed_weight
4455-
.saturating_add(TX_COMMON_FIELDS_WEIGHT)
4456-
// The weight of a P2WSH output to be added later.
4457-
//
4458-
// NOTE: The witness script hash given here is irrelevant as it's a fixed size and we just want
4459-
// to calculate the contributed weight, so we use an all-zero hash.
4460-
.saturating_add(get_output_weight(&ScriptBuf::new_p2wsh(
4461-
&WScriptHash::from_raw_hash(Hash::all_zeros())
4462-
)).to_wu())
4463-
}
4464-
4465-
let funding_satoshis = total_input_satoshis
4466-
.saturating_sub(fee_for_weight(funding_feerate_sat_per_1000_weight, our_contributed_weight));
4481+
let funding_satoshis = total_input_satoshis.saturating_sub(estimated_fee);
44674482
if funding_satoshis < holder_dust_limit_satoshis {
44684483
Ok(0)
44694484
} else {
@@ -8153,10 +8168,21 @@ impl<SP: Deref> FundedChannel<SP> where
81538168

81548169
// Pre-check that inputs are sufficient to cover our contribution.
81558170
// Note: fees are not taken into account here.
8156-
let sum_input: i64 = our_funding_inputs.into_iter().map(
8157-
|(txin, tx)| tx.output.get(txin.previous_output.vout as usize).map(|tx| tx.value.to_sat() as i64).unwrap_or(0)
8171+
let sum_input: u64 = our_funding_inputs.iter().map(
8172+
|(txin, tx)| tx.output.get(txin.previous_output.vout as usize).map(|tx| tx.value.to_sat()).unwrap_or(0)
81588173
).sum();
8159-
if sum_input < our_funding_contribution_satoshis {
8174+
8175+
// The +1 is to include the input of the old funding
8176+
let funding_input_count = our_funding_inputs.len() + 1;
8177+
// Add weight for inputs (estimated as P2WPKH) *and* spending old funding
8178+
let total_witness_weight = Weight::from_wu(
8179+
our_funding_inputs.len() as u64 * P2WPKH_WITNESS_WEIGHT +
8180+
2 * P2WPKH_WITNESS_WEIGHT
8181+
);
8182+
let estimated_fee = estimate_funding_transaction_fee(true, funding_input_count, total_witness_weight, funding_feerate_per_kw);
8183+
let available_input = sum_input.saturating_sub(estimated_fee);
8184+
8185+
if (available_input as i64) < our_funding_contribution_satoshis {
81608186
return Err(ChannelError::Warn(format!(
81618187
"Provided inputs are insufficient for our contribution, {} {}",
81628188
sum_input, our_funding_contribution_satoshis,

0 commit comments

Comments
 (0)