Skip to content

Commit 4698026

Browse files
committed
Account for grind_signatures in splice funding tx
When estimating the splice funding transaction fees, adjust for grind_signatures. Since LDK supplies one of the signatures, only adjust by 1 WU even though spending the shared input requires two signatures.
1 parent eb341de commit 4698026

File tree

6 files changed

+97
-49
lines changed

6 files changed

+97
-49
lines changed

lightning/src/ln/chan_utils.rs

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -127,6 +127,9 @@ const MULTISIG_SCRIPT_SIZE: u64 = 1 + // OP_2
127127
/// Unlike in the [spec], 72 WU is used for the max signature size since 73 WU signatures are
128128
/// non-standard.
129129
///
130+
/// Note: If you have the `grind_signatures` feature enabled, this will be at least 1 byte
131+
/// shorter.
132+
///
130133
/// [spec]: https://github.com/lightning/bolts/blob/master/03-transactions.md#expected-weight-of-the-commitment-transaction
131134
pub const FUNDING_TRANSACTION_WITNESS_WEIGHT: u64 = 1 + // number_of_witness_elements
132135
1 + // nil_len

lightning/src/ln/channel.rs

Lines changed: 58 additions & 44 deletions
Original file line numberDiff line numberDiff line change
@@ -6547,6 +6547,11 @@ fn estimate_v2_funding_transaction_fee(
65476547
.saturating_add(BASE_INPUT_WEIGHT)
65486548
.saturating_add(EMPTY_SCRIPT_SIG_WEIGHT)
65496549
.saturating_add(FUNDING_TRANSACTION_WITNESS_WEIGHT);
6550+
#[cfg(feature = "grind_signatures")]
6551+
{
6552+
// Guarantees a low R signature
6553+
weight -= 1;
6554+
}
65506555
}
65516556
}
65526557

@@ -17397,19 +17402,19 @@ mod tests {
1739717402
// 2 inputs, initiator, 2000 sat/kw feerate
1739817403
assert_eq!(
1739917404
estimate_v2_funding_transaction_fee(&two_inputs, &[], true, false, 2000),
17400-
1516,
17405+
if cfg!(feature = "grind_signatures") { 1512 } else { 1516 },
1740117406
);
1740217407

1740317408
// higher feerate
1740417409
assert_eq!(
1740517410
estimate_v2_funding_transaction_fee(&two_inputs, &[], true, false, 3000),
17406-
2274,
17411+
if cfg!(feature = "grind_signatures") { 2268 } else { 2274 },
1740717412
);
1740817413

1740917414
// only 1 input
1741017415
assert_eq!(
1741117416
estimate_v2_funding_transaction_fee(&one_input, &[], true, false, 2000),
17412-
972,
17417+
if cfg!(feature = "grind_signatures") { 970 } else { 972 },
1741317418
);
1741417419

1741517420
// 0 inputs
@@ -17427,13 +17432,13 @@ mod tests {
1742717432
// splice initiator
1742817433
assert_eq!(
1742917434
estimate_v2_funding_transaction_fee(&one_input, &[], true, true, 2000),
17430-
1740,
17435+
if cfg!(feature = "grind_signatures") { 1736 } else { 1740 },
1743117436
);
1743217437

1743317438
// splice acceptor
1743417439
assert_eq!(
1743517440
estimate_v2_funding_transaction_fee(&one_input, &[], false, true, 2000),
17436-
544,
17441+
if cfg!(feature = "grind_signatures") { 542 } else { 544 },
1743717442
);
1743817443
}
1743917444

@@ -17457,40 +17462,46 @@ mod tests {
1745717462
use crate::ln::channel::check_v2_funding_inputs_sufficient;
1745817463

1745917464
// positive case, inputs well over intended contribution
17460-
assert_eq!(
17461-
check_v2_funding_inputs_sufficient(
17462-
220_000,
17463-
&[
17464-
funding_input_sats(200_000),
17465-
funding_input_sats(100_000),
17466-
],
17467-
true,
17468-
true,
17469-
2000,
17470-
).unwrap(),
17471-
2284,
17472-
);
17465+
{
17466+
let expected_fee = if cfg!(feature = "grind_signatures") { 2278 } else { 2284 };
17467+
assert_eq!(
17468+
check_v2_funding_inputs_sufficient(
17469+
220_000,
17470+
&[
17471+
funding_input_sats(200_000),
17472+
funding_input_sats(100_000),
17473+
],
17474+
true,
17475+
true,
17476+
2000,
17477+
).unwrap(),
17478+
expected_fee,
17479+
);
17480+
}
1747317481

1747417482
// negative case, inputs clearly insufficient
1747517483
{
17476-
let res = check_v2_funding_inputs_sufficient(
17477-
220_000,
17478-
&[
17479-
funding_input_sats(100_000),
17480-
],
17481-
true,
17482-
true,
17483-
2000,
17484-
);
17484+
let expected_fee = if cfg!(feature = "grind_signatures") { 1736 } else { 1740 };
1748517485
assert_eq!(
17486-
res.err().unwrap(),
17487-
"Total input amount 100000 is lower than needed for contribution 220000, considering fees of 1740. Need more inputs.",
17486+
check_v2_funding_inputs_sufficient(
17487+
220_000,
17488+
&[
17489+
funding_input_sats(100_000),
17490+
],
17491+
true,
17492+
true,
17493+
2000,
17494+
),
17495+
Err(format!(
17496+
"Total input amount 100000 is lower than needed for contribution 220000, considering fees of {}. Need more inputs.",
17497+
expected_fee,
17498+
)),
1748817499
);
1748917500
}
1749017501

1749117502
// barely covers
1749217503
{
17493-
let expected_fee: u64 = 2284;
17504+
let expected_fee = if cfg!(feature = "grind_signatures") { 2278 } else { 2284 };
1749417505
assert_eq!(
1749517506
check_v2_funding_inputs_sufficient(
1749617507
(300_000 - expected_fee - 20) as i64,
@@ -17508,25 +17519,28 @@ mod tests {
1750817519

1750917520
// higher fee rate, does not cover
1751017521
{
17511-
let res = check_v2_funding_inputs_sufficient(
17512-
298032,
17513-
&[
17514-
funding_input_sats(200_000),
17515-
funding_input_sats(100_000),
17516-
],
17517-
true,
17518-
true,
17519-
2200,
17520-
);
17522+
let expected_fee = if cfg!(feature = "grind_signatures") { 2506 } else { 2513 };
1752117523
assert_eq!(
17522-
res.err().unwrap(),
17523-
"Total input amount 300000 is lower than needed for contribution 298032, considering fees of 2513. Need more inputs.",
17524+
check_v2_funding_inputs_sufficient(
17525+
298032,
17526+
&[
17527+
funding_input_sats(200_000),
17528+
funding_input_sats(100_000),
17529+
],
17530+
true,
17531+
true,
17532+
2200,
17533+
),
17534+
Err(format!(
17535+
"Total input amount 300000 is lower than needed for contribution 298032, considering fees of {}. Need more inputs.",
17536+
expected_fee
17537+
)),
1752417538
);
1752517539
}
1752617540

17527-
// barely covers, less fees (no extra weight, no init)
17541+
// barely covers, less fees (no extra weight, not initiator)
1752817542
{
17529-
let expected_fee: u64 = 1088;
17543+
let expected_fee = if cfg!(feature = "grind_signatures") { 1084 } else { 1088 };
1753017544
assert_eq!(
1753117545
check_v2_funding_inputs_sufficient(
1753217546
(300_000 - expected_fee - 20) as i64,

lightning/src/ln/funding.rs

Lines changed: 7 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -143,7 +143,13 @@ impl FundingTxInput {
143143
/// [`TxIn::sequence`]: bitcoin::TxIn::sequence
144144
/// [`set_sequence`]: Self::set_sequence
145145
pub fn new_p2wpkh(prevtx: Transaction, vout: u32) -> Result<Self, ()> {
146-
let witness_weight = Weight::from_wu(P2WPKH_WITNESS_WEIGHT);
146+
let witness_weight = Weight::from_wu(P2WPKH_WITNESS_WEIGHT)
147+
- if cfg!(feature = "grind_signatures") {
148+
// Guarantees a low R signature
149+
Weight::from_wu(1)
150+
} else {
151+
Weight::ZERO
152+
};
147153
FundingTxInput::new(prevtx, vout, witness_weight, Script::is_p2wpkh)
148154
}
149155

lightning/src/ln/interactivetxs.rs

Lines changed: 19 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -1706,7 +1706,15 @@ impl InputOwned {
17061706
InputOwned::Single(single) => single.satisfaction_weight,
17071707
// TODO(taproot): Needs to consider different weights based on channel type
17081708
InputOwned::Shared(_) => {
1709-
Weight::from_wu(EMPTY_SCRIPT_SIG_WEIGHT + FUNDING_TRANSACTION_WITNESS_WEIGHT)
1709+
let mut weight = 0;
1710+
weight += EMPTY_SCRIPT_SIG_WEIGHT + FUNDING_TRANSACTION_WITNESS_WEIGHT;
1711+
#[cfg(feature = "grind_signatures")]
1712+
{
1713+
// Guarantees a low R signature
1714+
weight -= 1;
1715+
}
1716+
1717+
Weight::from_wu(weight)
17101718
},
17111719
}
17121720
}
@@ -2314,6 +2322,11 @@ pub(super) fn calculate_change_output_value(
23142322
weight = weight.saturating_add(BASE_INPUT_WEIGHT);
23152323
weight = weight.saturating_add(EMPTY_SCRIPT_SIG_WEIGHT);
23162324
weight = weight.saturating_add(FUNDING_TRANSACTION_WITNESS_WEIGHT);
2325+
#[cfg(feature = "grind_signatures")]
2326+
{
2327+
// Guarantees a low R signature
2328+
weight -= 1;
2329+
}
23172330
}
23182331
}
23192332

@@ -3359,7 +3372,11 @@ mod tests {
33593372

33603373
let total_inputs: Amount = input_prevouts.iter().map(|o| o.value).sum();
33613374
let total_outputs: Amount = outputs.iter().map(|o| o.value).sum();
3362-
let fees = Amount::from_sat(1740);
3375+
let fees = if cfg!(feature = "grind_signatures") {
3376+
Amount::from_sat(1734)
3377+
} else {
3378+
Amount::from_sat(1740)
3379+
};
33633380
let common_fees = Amount::from_sat(234);
33643381

33653382
// There is leftover for change

lightning/src/sign/mod.rs

Lines changed: 4 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -117,7 +117,8 @@ pub struct DelayedPaymentOutputDescriptor {
117117

118118
impl DelayedPaymentOutputDescriptor {
119119
/// The maximum length a well-formed witness spending one of these should have.
120-
/// Note: If you have the grind_signatures feature enabled, this will be at least 1 byte
120+
///
121+
/// Note: If you have the `grind_signatures` feature enabled, this will be at least 1 byte
121122
/// shorter.
122123
pub const MAX_WITNESS_LENGTH: u64 = (1 /* witness items */
123124
+ 1 /* sig push */
@@ -198,7 +199,8 @@ impl StaticPaymentOutputDescriptor {
198199
}
199200

200201
/// The maximum length a well-formed witness spending one of these should have.
201-
/// Note: If you have the grind_signatures feature enabled, this will be at least 1 byte
202+
///
203+
/// Note: If you have the `grind_signatures` feature enabled, this will be at least 1 byte
202204
/// shorter.
203205
pub fn max_witness_length(&self) -> u64 {
204206
if self.needs_csv_1_for_spend() {

lightning/src/util/test_utils.rs

Lines changed: 6 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -2226,10 +2226,16 @@ impl TestWalletSource {
22262226
utxo.output.value,
22272227
EcdsaSighashType::All,
22282228
)?;
2229+
#[cfg(not(feature = "grind_signatures"))]
22292230
let signature = self.secp.sign_ecdsa(
22302231
&secp256k1::Message::from_digest(sighash.to_byte_array()),
22312232
&self.secret_key,
22322233
);
2234+
#[cfg(feature = "grind_signatures")]
2235+
let signature = self.secp.sign_ecdsa_low_r(
2236+
&secp256k1::Message::from_digest(sighash.to_byte_array()),
2237+
&self.secret_key,
2238+
);
22332239
let bitcoin_sig =
22342240
bitcoin::ecdsa::Signature { signature, sighash_type: EcdsaSighashType::All };
22352241
tx.input[i].witness =

0 commit comments

Comments
 (0)