Skip to content

Commit 9150bc8

Browse files
authored
Merge pull request #4208 from jkczyz/2025-11-signature-weight
Use 72 WU instead of 73 WU for signature weight
2 parents 7815e54 + 2330ed9 commit 9150bc8

File tree

6 files changed

+185
-95
lines changed

6 files changed

+185
-95
lines changed

lightning/src/ln/chan_utils.rs

Lines changed: 14 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -116,19 +116,27 @@ pub const HTLC_SUCCESS_INPUT_P2A_ANCHOR_WITNESS_WEIGHT: u64 = 324;
116116
/// The size of the 2-of-2 multisig script
117117
const MULTISIG_SCRIPT_SIZE: u64 = 1 + // OP_2
118118
1 + // data len
119-
33 + // pubkey1
119+
crate::sign::COMPRESSED_PUBLIC_KEY_SIZE as u64 + // pubkey1
120120
1 + // data len
121-
33 + // pubkey2
121+
crate::sign::COMPRESSED_PUBLIC_KEY_SIZE as u64 + // pubkey2
122122
1 + // OP_2
123123
1; // OP_CHECKMULTISIG
124-
/// The weight of a funding transaction input (2-of-2 P2WSH)
125-
/// See https://github.com/lightning/bolts/blob/master/03-transactions.md#expected-weight-of-the-commitment-transaction
124+
125+
/// The weight of a funding transaction input (2-of-2 P2WSH).
126+
///
127+
/// Unlike in the [spec], 72 WU is used for the max signature size since 73 WU signatures are
128+
/// non-standard.
129+
///
130+
/// Note: If you have the `grind_signatures` feature enabled, this will be at least 1 byte
131+
/// shorter.
132+
///
133+
/// [spec]: https://github.com/lightning/bolts/blob/master/03-transactions.md#expected-weight-of-the-commitment-transaction
126134
pub const FUNDING_TRANSACTION_WITNESS_WEIGHT: u64 = 1 + // number_of_witness_elements
127135
1 + // nil_len
128136
1 + // sig len
129-
73 + // sig1
137+
crate::sign::MAX_STANDARD_SIGNATURE_SIZE as u64 + // sig1
130138
1 + // sig len
131-
73 + // sig2
139+
crate::sign::MAX_STANDARD_SIGNATURE_SIZE as u64 + // sig2
132140
1 + // witness_script_length
133141
MULTISIG_SCRIPT_SIZE;
134142

lightning/src/ln/channel.rs

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

@@ -17437,19 +17442,19 @@ mod tests {
1743717442
// 2 inputs, initiator, 2000 sat/kw feerate
1743817443
assert_eq!(
1743917444
estimate_v2_funding_transaction_fee(&two_inputs, &[], true, false, 2000),
17440-
1520,
17445+
if cfg!(feature = "grind_signatures") { 1512 } else { 1516 },
1744117446
);
1744217447

1744317448
// higher feerate
1744417449
assert_eq!(
1744517450
estimate_v2_funding_transaction_fee(&two_inputs, &[], true, false, 3000),
17446-
2280,
17451+
if cfg!(feature = "grind_signatures") { 2268 } else { 2274 },
1744717452
);
1744817453

1744917454
// only 1 input
1745017455
assert_eq!(
1745117456
estimate_v2_funding_transaction_fee(&one_input, &[], true, false, 2000),
17452-
974,
17457+
if cfg!(feature = "grind_signatures") { 970 } else { 972 },
1745317458
);
1745417459

1745517460
// 0 inputs
@@ -17467,13 +17472,13 @@ mod tests {
1746717472
// splice initiator
1746817473
assert_eq!(
1746917474
estimate_v2_funding_transaction_fee(&one_input, &[], true, true, 2000),
17470-
1746,
17475+
if cfg!(feature = "grind_signatures") { 1736 } else { 1740 },
1747117476
);
1747217477

1747317478
// splice acceptor
1747417479
assert_eq!(
1747517480
estimate_v2_funding_transaction_fee(&one_input, &[], false, true, 2000),
17476-
546,
17481+
if cfg!(feature = "grind_signatures") { 542 } else { 544 },
1747717482
);
1747817483
}
1747917484

@@ -17497,40 +17502,46 @@ mod tests {
1749717502
use crate::ln::channel::check_v2_funding_inputs_sufficient;
1749817503

1749917504
// positive case, inputs well over intended contribution
17500-
assert_eq!(
17501-
check_v2_funding_inputs_sufficient(
17502-
220_000,
17503-
&[
17504-
funding_input_sats(200_000),
17505-
funding_input_sats(100_000),
17506-
],
17507-
true,
17508-
true,
17509-
2000,
17510-
).unwrap(),
17511-
2292,
17512-
);
17505+
{
17506+
let expected_fee = if cfg!(feature = "grind_signatures") { 2278 } else { 2284 };
17507+
assert_eq!(
17508+
check_v2_funding_inputs_sufficient(
17509+
220_000,
17510+
&[
17511+
funding_input_sats(200_000),
17512+
funding_input_sats(100_000),
17513+
],
17514+
true,
17515+
true,
17516+
2000,
17517+
).unwrap(),
17518+
expected_fee,
17519+
);
17520+
}
1751317521

1751417522
// negative case, inputs clearly insufficient
1751517523
{
17516-
let res = check_v2_funding_inputs_sufficient(
17517-
220_000,
17518-
&[
17519-
funding_input_sats(100_000),
17520-
],
17521-
true,
17522-
true,
17523-
2000,
17524-
);
17524+
let expected_fee = if cfg!(feature = "grind_signatures") { 1736 } else { 1740 };
1752517525
assert_eq!(
17526-
res.err().unwrap(),
17527-
"Total input amount 100000 is lower than needed for contribution 220000, considering fees of 1746. Need more inputs.",
17526+
check_v2_funding_inputs_sufficient(
17527+
220_000,
17528+
&[
17529+
funding_input_sats(100_000),
17530+
],
17531+
true,
17532+
true,
17533+
2000,
17534+
),
17535+
Err(format!(
17536+
"Total input amount 100000 is lower than needed for contribution 220000, considering fees of {}. Need more inputs.",
17537+
expected_fee,
17538+
)),
1752817539
);
1752917540
}
1753017541

1753117542
// barely covers
1753217543
{
17533-
let expected_fee: u64 = 2292;
17544+
let expected_fee = if cfg!(feature = "grind_signatures") { 2278 } else { 2284 };
1753417545
assert_eq!(
1753517546
check_v2_funding_inputs_sufficient(
1753617547
(300_000 - expected_fee - 20) as i64,
@@ -17548,25 +17559,28 @@ mod tests {
1754817559

1754917560
// higher fee rate, does not cover
1755017561
{
17551-
let res = check_v2_funding_inputs_sufficient(
17552-
298032,
17553-
&[
17554-
funding_input_sats(200_000),
17555-
funding_input_sats(100_000),
17556-
],
17557-
true,
17558-
true,
17559-
2200,
17560-
);
17562+
let expected_fee = if cfg!(feature = "grind_signatures") { 2506 } else { 2513 };
1756117563
assert_eq!(
17562-
res.err().unwrap(),
17563-
"Total input amount 300000 is lower than needed for contribution 298032, considering fees of 2522. Need more inputs.",
17564+
check_v2_funding_inputs_sufficient(
17565+
298032,
17566+
&[
17567+
funding_input_sats(200_000),
17568+
funding_input_sats(100_000),
17569+
],
17570+
true,
17571+
true,
17572+
2200,
17573+
),
17574+
Err(format!(
17575+
"Total input amount 300000 is lower than needed for contribution 298032, considering fees of {}. Need more inputs.",
17576+
expected_fee
17577+
)),
1756417578
);
1756517579
}
1756617580

17567-
// barely covers, less fees (no extra weight, no init)
17581+
// barely covers, less fees (no extra weight, not initiator)
1756817582
{
17569-
let expected_fee: u64 = 1092;
17583+
let expected_fee = if cfg!(feature = "grind_signatures") { 1084 } else { 1088 };
1757017584
assert_eq!(
1757117585
check_v2_funding_inputs_sufficient(
1757217586
(300_000 - expected_fee - 20) as i64,

lightning/src/ln/funding.rs

Lines changed: 12 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

@@ -224,4 +230,9 @@ impl FundingTxInput {
224230
pub fn set_sequence(&mut self, sequence: Sequence) {
225231
self.sequence = sequence;
226232
}
233+
234+
/// Converts the [`FundingTxInput`] into a [`Utxo`] for coin selection.
235+
pub fn into_utxo(self) -> Utxo {
236+
self.utxo
237+
}
227238
}

0 commit comments

Comments
 (0)