@@ -57,6 +57,7 @@ use crate::chain::transaction::{OutPoint, TransactionData};
57
57
use crate::sign::ecdsa::EcdsaChannelSigner;
58
58
use crate::sign::{EntropySource, ChannelSigner, SignerProvider, NodeSigner, Recipient};
59
59
use crate::events::{ClosureReason, Event};
60
+ use crate::events::bump_transaction::BASE_INPUT_WEIGHT;
60
61
use crate::routing::gossip::NodeId;
61
62
use crate::util::ser::{Readable, ReadableArgs, TransactionU16LenLimited, Writeable, Writer};
62
63
use crate::util::logger::{Logger, Record, WithContext};
@@ -4470,46 +4471,33 @@ fn get_v2_channel_reserve_satoshis(channel_value_satoshis: u64, dust_limit_satos
4470
4471
cmp::min(channel_value_satoshis, cmp::max(q, dust_limit_satoshis))
4471
4472
}
4472
4473
4473
- #[allow(dead_code)] // TODO(dual_funding): Remove once V2 channels is enabled.
4474
- pub(super) fn calculate_our_funding_satoshis(
4475
- is_initiator: bool, funding_inputs: &[(TxIn, TransactionU16LenLimited)],
4476
- total_witness_weight: Weight, funding_feerate_sat_per_1000_weight: u32,
4477
- holder_dust_limit_satoshis: u64,
4478
- ) -> Result<u64, APIError> {
4479
- let mut total_input_satoshis = 0u64;
4480
- let mut our_contributed_weight = 0u64;
4474
+ /// Estimate our part of the fee of the new funding transaction.
4475
+ /// input_count: Number of contributed inputs.
4476
+ /// witness_weight: The witness weight for contributed inputs.
4477
+ #[allow(dead_code)] // TODO(dual_funding): TODO(splicing): Remove allow once used.
4478
+ fn estimate_v2_funding_transaction_fee(
4479
+ is_initiator: bool, input_count: usize, witness_weight: Weight,
4480
+ funding_feerate_sat_per_1000_weight: u32,
4481
+ ) -> u64 {
4482
+ // Inputs
4483
+ let mut weight = (input_count as u64) * BASE_INPUT_WEIGHT;
4481
4484
4482
- for (idx, input) in funding_inputs.iter().enumerate() {
4483
- if let Some(output) = input.1.as_transaction().output.get(input.0.previous_output.vout as usize) {
4484
- total_input_satoshis = total_input_satoshis.saturating_add(output.value.to_sat());
4485
- } else {
4486
- return Err(APIError::APIMisuseError {
4487
- err: format!("Transaction with txid {} does not have an output with vout of {} corresponding to TxIn at funding_inputs[{}]",
4488
- input.1.as_transaction().compute_txid(), input.0.previous_output.vout, idx) });
4489
- }
4490
- }
4491
- our_contributed_weight = our_contributed_weight.saturating_add(total_witness_weight.to_wu());
4485
+ // Witnesses
4486
+ weight = weight.saturating_add(witness_weight.to_wu());
4492
4487
4493
4488
// If we are the initiator, we must pay for weight of all common fields in the funding transaction.
4494
4489
if is_initiator {
4495
- our_contributed_weight = our_contributed_weight
4490
+ weight = weight
4496
4491
.saturating_add(TX_COMMON_FIELDS_WEIGHT)
4497
- // The weight of a P2WSH output to be added later.
4498
- //
4492
+ // The weight of the funding output, a P2WSH output
4499
4493
// NOTE: The witness script hash given here is irrelevant as it's a fixed size and we just want
4500
4494
// to calculate the contributed weight, so we use an all-zero hash.
4501
4495
.saturating_add(get_output_weight(&ScriptBuf::new_p2wsh(
4502
4496
&WScriptHash::from_raw_hash(Hash::all_zeros())
4503
4497
)).to_wu())
4504
4498
}
4505
4499
4506
- let funding_satoshis = total_input_satoshis
4507
- .saturating_sub(fee_for_weight(funding_feerate_sat_per_1000_weight, our_contributed_weight));
4508
- if funding_satoshis < holder_dust_limit_satoshis {
4509
- Ok(0)
4510
- } else {
4511
- Ok(funding_satoshis)
4512
- }
4500
+ fee_for_weight(funding_feerate_sat_per_1000_weight, weight)
4513
4501
}
4514
4502
4515
4503
/// Context for dual-funded channels.
@@ -9249,27 +9237,23 @@ impl<SP: Deref> PendingV2Channel<SP> where SP::Target: SignerProvider {
9249
9237
9250
9238
/// Creates a new dual-funded channel from a remote side's request for one.
9251
9239
/// Assumes chain_hash has already been checked and corresponds with what we expect!
9240
+ /// TODO(dual_funding): Allow contributions, pass intended amount and inputs
9252
9241
#[allow(dead_code)] // TODO(dual_funding): Remove once V2 channels is enabled.
9253
9242
pub fn new_inbound<ES: Deref, F: Deref, L: Deref>(
9254
9243
fee_estimator: &LowerBoundedFeeEstimator<F>, entropy_source: &ES, signer_provider: &SP,
9255
9244
holder_node_id: PublicKey, counterparty_node_id: PublicKey, our_supported_features: &ChannelTypeFeatures,
9256
9245
their_features: &InitFeatures, msg: &msgs::OpenChannelV2,
9257
- funding_inputs: Vec<(TxIn, TransactionU16LenLimited)>, total_witness_weight: Weight,
9258
9246
user_id: u128, config: &UserConfig, current_chain_height: u32, logger: &L,
9259
9247
) -> Result<Self, ChannelError>
9260
9248
where ES::Target: EntropySource,
9261
9249
F::Target: FeeEstimator,
9262
9250
L::Target: Logger,
9263
9251
{
9264
- let funding_satoshis = calculate_our_funding_satoshis(
9265
- false, &funding_inputs, total_witness_weight, msg.funding_feerate_sat_per_1000_weight,
9266
- msg.common_fields.dust_limit_satoshis
9267
- ).map_err(|_| ChannelError::Close(
9268
- (
9269
- "Failed to accept channel".to_string(),
9270
- ClosureReason::HolderForceClosed { broadcasted_latest_txn: Some(false) },
9271
- )))?;
9272
- let channel_value_satoshis = funding_satoshis.saturating_add(msg.common_fields.funding_satoshis);
9252
+ // TODO(dual_funding): Take these as input once supported
9253
+ let our_funding_satoshis = 0u64;
9254
+ let our_funding_inputs = Vec::new();
9255
+
9256
+ let channel_value_satoshis = our_funding_satoshis.saturating_add(msg.common_fields.funding_satoshis);
9273
9257
let counterparty_selected_channel_reserve_satoshis = get_v2_channel_reserve_satoshis(
9274
9258
channel_value_satoshis, msg.common_fields.dust_limit_satoshis);
9275
9259
let holder_selected_channel_reserve_satoshis = get_v2_channel_reserve_satoshis(
@@ -9303,7 +9287,7 @@ impl<SP: Deref> PendingV2Channel<SP> where SP::Target: SignerProvider {
9303
9287
logger,
9304
9288
false,
9305
9289
9306
- funding_satoshis ,
9290
+ our_funding_satoshis ,
9307
9291
9308
9292
counterparty_pubkeys,
9309
9293
channel_type,
@@ -9318,10 +9302,10 @@ impl<SP: Deref> PendingV2Channel<SP> where SP::Target: SignerProvider {
9318
9302
context.channel_id = channel_id;
9319
9303
9320
9304
let dual_funding_context = DualFundingChannelContext {
9321
- our_funding_satoshis: funding_satoshis ,
9305
+ our_funding_satoshis: our_funding_satoshis ,
9322
9306
funding_tx_locktime: LockTime::from_consensus(msg.locktime),
9323
9307
funding_feerate_sat_per_1000_weight: msg.funding_feerate_sat_per_1000_weight,
9324
- our_funding_inputs: funding_inputs .clone(),
9308
+ our_funding_inputs: our_funding_inputs .clone(),
9325
9309
};
9326
9310
9327
9311
let interactive_tx_constructor = Some(InteractiveTxConstructor::new(
@@ -9333,7 +9317,7 @@ impl<SP: Deref> PendingV2Channel<SP> where SP::Target: SignerProvider {
9333
9317
feerate_sat_per_kw: dual_funding_context.funding_feerate_sat_per_1000_weight,
9334
9318
funding_tx_locktime: dual_funding_context.funding_tx_locktime,
9335
9319
is_initiator: false,
9336
- inputs_to_contribute: funding_inputs ,
9320
+ inputs_to_contribute: our_funding_inputs ,
9337
9321
outputs_to_contribute: Vec::new(),
9338
9322
expected_remote_shared_funding_output: Some((context.get_funding_redeemscript().to_p2wsh(), context.channel_value_satoshis)),
9339
9323
}
@@ -12238,4 +12222,40 @@ mod tests {
12238
12222
assert_eq!(node_a_chan.context.channel_state, ChannelState::AwaitingChannelReady(AwaitingChannelReadyFlags::THEIR_CHANNEL_READY));
12239
12223
assert!(node_a_chan.check_get_channel_ready(0, &&logger).is_some());
12240
12224
}
12225
+
12226
+ #[test]
12227
+ fn test_estimate_v2_funding_transaction_fee() {
12228
+ use crate::ln::channel::estimate_v2_funding_transaction_fee;
12229
+ use bitcoin::Weight;
12230
+
12231
+ // 2 inputs with weight 300, initiator, 2000 sat/kw feerate
12232
+ assert_eq!(
12233
+ estimate_v2_funding_transaction_fee(true, 2, Weight::from_wu(300), 2000),
12234
+ 1668
12235
+ );
12236
+
12237
+ // higher feerate
12238
+ assert_eq!(
12239
+ estimate_v2_funding_transaction_fee(true, 2, Weight::from_wu(300), 3000),
12240
+ 2502
12241
+ );
12242
+
12243
+ // only 1 input
12244
+ assert_eq!(
12245
+ estimate_v2_funding_transaction_fee(true, 1, Weight::from_wu(300), 2000),
12246
+ 1348
12247
+ );
12248
+
12249
+ // 0 input weight
12250
+ assert_eq!(
12251
+ estimate_v2_funding_transaction_fee(true, 1, Weight::from_wu(0), 2000),
12252
+ 748
12253
+ );
12254
+
12255
+ // not initiator
12256
+ assert_eq!(
12257
+ estimate_v2_funding_transaction_fee(false, 1, Weight::from_wu(0), 2000),
12258
+ 320
12259
+ );
12260
+ }
12241
12261
}
0 commit comments