Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
2 changes: 1 addition & 1 deletion fuzz/Cargo.toml
Original file line number Diff line number Diff line change
Expand Up @@ -6,7 +6,7 @@ publish = false
edition = "2021"

[dependencies]
lightning = { path = "../lightning", features = ["regex", "_test_utils"] }
lightning = { path = "../lightning", default-features = false, features = ["std", "regex", "_test_utils"] }
lightning-invoice = { path = "../lightning-invoice" }
lightning-liquidity = { path = "../lightning-liquidity" }
lightning-rapid-gossip-sync = { path = "../lightning-rapid-gossip-sync" }
Expand Down
18 changes: 9 additions & 9 deletions fuzz/src/full_stack.rs
Original file line number Diff line number Diff line change
Expand Up @@ -1885,8 +1885,8 @@ fn splice_seed() -> Vec<u8> {
// CommitmentSigned message with proper signature (r=f7, s=01...) and funding_txid TLV
// signature r encodes sighash first byte f7, s follows the pattern from funding_created
// TLV type 1 (odd/optional) for funding_txid as per impl_writeable_msg!(CommitmentSigned, ...)
// Note: txid is encoded in reverse byte order (Bitcoin standard), so to get display 0000...0031, encode 3100...0000
ext_from_hex("0084 c000000000000000000000000000000000000000000000000000000000000000 00000000000000000000000000000000000000000000000000000000000000f7 0100000000000000000000000000000000000000000000000000000000000000 0000 01 20 3100000000000000000000000000000000000000000000000000000000000000 03000000000000000000000000000000", &mut test);
// Note: txid is encoded in reverse byte order (Bitcoin standard), so to get display 0000...0032, encode 3200...0000
ext_from_hex("0084 c000000000000000000000000000000000000000000000000000000000000000 00000000000000000000000000000000000000000000000000000000000000f7 0100000000000000000000000000000000000000000000000000000000000000 0000 01 20 3200000000000000000000000000000000000000000000000000000000000000 03000000000000000000000000000000", &mut test);

// After commitment_signed exchange, we need to exchange tx_signatures.
// Message type IDs: TxSignatures = 71 (0x0047)
Expand All @@ -1899,19 +1899,19 @@ fn splice_seed() -> Vec<u8> {
// inbound read from peer id 0 of len 150 (134 message + 16 MAC)
ext_from_hex("030096", &mut test);
// TxSignatures message with shared_input_signature TLV (type 0)
// txid must match the splice funding txid (0x31 in reverse byte order)
// txid must match the splice funding txid (0x32 in reverse byte order)
// shared_input_signature: 64-byte fuzz signature for the shared input
ext_from_hex("0047 c000000000000000000000000000000000000000000000000000000000000000 3100000000000000000000000000000000000000000000000000000000000000 0000 00 40 00000000000000000000000000000000000000000000000000000000000000dc 0100000000000000000000000000000000000000000000000000000000000000 03000000000000000000000000000000", &mut test);
ext_from_hex("0047 c000000000000000000000000000000000000000000000000000000000000000 3200000000000000000000000000000000000000000000000000000000000000 0000 00 40 00000000000000000000000000000000000000000000000000000000000000dc 0100000000000000000000000000000000000000000000000000000000000000 03000000000000000000000000000000", &mut test);

// Connect a block with the splice funding transaction to confirm it
// The splice funding tx: version(4) + input_count(1) + txid(32) + vout(4) + script_len(1) + sequence(4)
// + output_count(1) + value(8) + script_len(1) + script(34) + locktime(4) = 94 bytes = 0x5e
// Transaction structure from FundingTransactionReadyForSigning:
// - Input: spending c000...00:0 with sequence 0xfffffffd
// - Output: 115538 sats to OP_0 PUSH32 6e00...00
// - Output: 115537 sats to OP_0 PUSH32 6e00...00
// - Locktime: 13
ext_from_hex("0c005e", &mut test);
ext_from_hex("02000000 01 c000000000000000000000000000000000000000000000000000000000000000 00000000 00 fdffffff 01 52c3010000000000 22 00206e00000000000000000000000000000000000000000000000000000000000000 0d000000", &mut test);
ext_from_hex("02000000 01 c000000000000000000000000000000000000000000000000000000000000000 00000000 00 fdffffff 01 51c3010000000000 22 00206e00000000000000000000000000000000000000000000000000000000000000 0d000000", &mut test);

// Connect additional blocks to reach minimum_depth confirmations
for _ in 0..5 {
Expand All @@ -1928,8 +1928,8 @@ fn splice_seed() -> Vec<u8> {
// inbound read from peer id 0 of len 82 (66 message + 16 MAC)
ext_from_hex("030052", &mut test);
// SpliceLocked message (type 77 = 0x004d): channel_id + splice_txid + mac
// splice_txid must match the splice funding txid (0x31 in reverse byte order)
ext_from_hex("004d c000000000000000000000000000000000000000000000000000000000000000 3100000000000000000000000000000000000000000000000000000000000000 03000000000000000000000000000000", &mut test);
// splice_txid must match the splice funding txid (0x32 in reverse byte order)
ext_from_hex("004d c000000000000000000000000000000000000000000000000000000000000000 3200000000000000000000000000000000000000000000000000000000000000 03000000000000000000000000000000", &mut test);

test
}
Expand Down Expand Up @@ -2059,6 +2059,6 @@ mod tests {

// Splice locked
assert_eq!(log_entries.get(&("lightning::ln::peer_handler".to_string(), "Handling SendSpliceLocked event in peer_handler for node 030000000000000000000000000000000000000000000000000000000000000002 for channel c000000000000000000000000000000000000000000000000000000000000000".to_string())), Some(&1));
assert_eq!(log_entries.get(&("lightning::ln::channel".to_string(), "Promoting splice funding txid 0000000000000000000000000000000000000000000000000000000000000031".to_string())), Some(&1));
assert_eq!(log_entries.get(&("lightning::ln::channel".to_string(), "Promoting splice funding txid 0000000000000000000000000000000000000000000000000000000000000032".to_string())), Some(&1));
}
}
2 changes: 1 addition & 1 deletion lightning-persister/Cargo.toml
Original file line number Diff line number Diff line change
Expand Up @@ -20,7 +20,7 @@ tokio = ["dep:tokio"]

[dependencies]
bitcoin = "0.32.2"
lightning = { version = "0.3.0", path = "../lightning" }
lightning = { version = "0.3.0", path = "../lightning", default-features = false, features = ["std"] }
tokio = { version = "1.35", optional = true, default-features = false, features = ["rt-multi-thread"] }

[target.'cfg(windows)'.dependencies]
Expand Down
29 changes: 23 additions & 6 deletions lightning/src/events/bump_transaction/mod.rs
Original file line number Diff line number Diff line change
Expand Up @@ -331,7 +331,13 @@ impl<B: BroadcasterInterface, C: CoinSelectionSource, SP: SignerProvider, L: Log
let anchor_input_witness_weight = if channel_type.supports_anchor_zero_fee_commitments() {
EMPTY_WITNESS_WEIGHT
} else {
ANCHOR_INPUT_WITNESS_WEIGHT
let weight = ANCHOR_INPUT_WITNESS_WEIGHT;
#[cfg(secp256k1_fuzz)]
let weight = {
// The secp256k1 fuzz signer does not low-S normalize dummy signatures.
weight + 1
};
weight
};

// First, check if the commitment transaction has sufficient fees on its own.
Expand Down Expand Up @@ -547,6 +553,18 @@ impl<B: BroadcasterInterface, C: CoinSelectionSource, SP: SignerProvider, L: Log
} else {
panic!("channel type should be either zero-fee HTLCs, or zero-fee commitments");
};
// The secp256k1 fuzz signer emits dummy signatures without low-S normalization, so
// DER+sighash can be one byte larger for each of the two HTLC signatures.
#[cfg(secp256k1_fuzz)]
let (htlc_success_witness_weight, htlc_timeout_witness_weight) =
(htlc_success_witness_weight + 2, htlc_timeout_witness_weight + 2);
Comment on lines +556 to +560
Copy link
Copy Markdown
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Nit: The +2 correctly adjusts satisfaction_weight in the Input structs (used for the debug assertion at line 740), but the aggregated_htlc_success_input_output_pair_weight() / aggregated_htlc_timeout_input_output_pair_weight() functions called on lines 595/597 still use the unadjusted constants for batch sizing. Under secp256k1_fuzz, the per-HTLC weight is underestimated by 2 WU in those calls.

In practice this is safe — worst case is 483 HTLCs × 2 WU = 966 WU undercounting, which is absorbed by the 1000 WU USER_COINS_WEIGHT_BUDGET margin. But it's a conceptual inconsistency worth noting if this area evolves.

let (htlc_success_input_output_pair_weight, htlc_timeout_input_output_pair_weight) = (
chan_utils::aggregated_htlc_success_input_output_pair_weight(channel_type),
chan_utils::aggregated_htlc_timeout_input_output_pair_weight(channel_type),
);
#[cfg(secp256k1_fuzz)]
let (htlc_success_input_output_pair_weight, htlc_timeout_input_output_pair_weight) =
(htlc_success_input_output_pair_weight + 2, htlc_timeout_input_output_pair_weight + 2);

let max_tx_weight = if channel_type.supports_anchor_zero_fee_commitments() {
// Cap the size of transactions claiming `HolderHTLCOutput` in 0FC channels.
Expand Down Expand Up @@ -587,9 +605,9 @@ impl<B: BroadcasterInterface, C: CoinSelectionSource, SP: SignerProvider, L: Log
&htlc_descriptors[broadcasted_htlcs..broadcasted_htlcs + batch_size]
{
let input_output_weight = if htlc_descriptor.preimage.is_some() {
chan_utils::aggregated_htlc_success_input_output_pair_weight(channel_type)
htlc_success_input_output_pair_weight
} else {
chan_utils::aggregated_htlc_timeout_input_output_pair_weight(channel_type)
htlc_timeout_input_output_pair_weight
};
if htlc_weight_sum + input_output_weight >= max_tx_weight - USER_COINS_WEIGHT_BUDGET
{
Expand Down Expand Up @@ -649,9 +667,8 @@ impl<B: BroadcasterInterface, C: CoinSelectionSource, SP: SignerProvider, L: Log
{
Ok(selection) => selection,
Err(()) => {
let htlcs_to_remove = USER_COINS_WEIGHT_BUDGET.div_ceil(
chan_utils::aggregated_htlc_timeout_input_output_pair_weight(channel_type),
);
let htlcs_to_remove =
USER_COINS_WEIGHT_BUDGET.div_ceil(htlc_timeout_input_output_pair_weight);
batch_size = batch_size.checked_sub(htlcs_to_remove as usize).ok_or(())?;
if batch_size == 0 {
return Err(());
Expand Down
3 changes: 3 additions & 0 deletions lightning/src/lib.rs
Original file line number Diff line number Diff line change
Expand Up @@ -43,6 +43,9 @@
#[cfg(all(fuzzing, test))]
compile_error!("Tests will always fail with cfg=fuzzing");

#[cfg(all(fuzzing, feature = "grind_signatures"))]
compile_error!("Fuzz builds must not enable grind_signatures");

#[macro_use]
extern crate alloc;

Expand Down
Loading