Skip to content

Commit 8c17afd

Browse files
author
Antoine Riard
committed
Bound incoming HTLC witnessScript to min/max limits
Fix a crash where previously we weren't able to detect any accepted HTLC if its witness-encoded cltv expiry was different from expected ACCEPTED_HTLC_SCRIPT_WEIGHT. This should work for any cltv expiry included between 0 and 16777216 on mainnet, testnet and regtest.
1 parent ace26de commit 8c17afd

File tree

6 files changed

+36
-20
lines changed

6 files changed

+36
-20
lines changed

lightning/src/ln/chan_utils.rs

Lines changed: 19 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -25,6 +25,25 @@ use secp256k1;
2525
pub(super) const HTLC_SUCCESS_TX_WEIGHT: u64 = 703;
2626
pub(super) const HTLC_TIMEOUT_TX_WEIGHT: u64 = 663;
2727

28+
#[derive(PartialEq)]
29+
pub(crate) enum HTLCType {
30+
AcceptedHTLC,
31+
OfferedHTLC
32+
}
33+
34+
impl HTLCType {
35+
/// Check if a given tx witnessScript weight matchs one of a pre-signed HTLC
36+
pub(crate) fn weight_to_htlctype(witness_script_len: usize) -> Option<HTLCType> {
37+
if witness_script_len == 133 {
38+
Some(HTLCType::OfferedHTLC)
39+
} else if witness_script_len >= 136 && witness_script_len <= 139 {
40+
Some(HTLCType::AcceptedHTLC)
41+
} else {
42+
None
43+
}
44+
}
45+
}
46+
2847
// Various functions for key derivation and transaction creation for use within channels. Primarily
2948
// used in Channel and ChannelMonitor.
3049

lightning/src/ln/channel.rs

Lines changed: 0 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -367,12 +367,6 @@ const B_OUTPUT_PLUS_SPENDING_INPUT_WEIGHT: u64 = 104; // prevout: 40, nSequence:
367367
/// it's 2^24.
368368
pub const MAX_FUNDING_SATOSHIS: u64 = (1 << 24);
369369

370-
#[cfg(test)]
371-
pub const ACCEPTED_HTLC_SCRIPT_WEIGHT: usize = 138; //Here we have a diff due to HTLC CLTV expiry being < 2^15 in test
372-
#[cfg(not(test))]
373-
pub const ACCEPTED_HTLC_SCRIPT_WEIGHT: usize = 139;
374-
pub const OFFERED_HTLC_SCRIPT_WEIGHT: usize = 133;
375-
376370
/// Used to return a simple Error back to ChannelManager. Will get converted to a
377371
/// msgs::ErrorAction::SendErrorMessage or msgs::ErrorAction::IgnoreError as appropriate with our
378372
/// channel_id in ChannelManager.

lightning/src/ln/channelmonitor.rs

Lines changed: 8 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -31,9 +31,8 @@ use secp256k1;
3131

3232
use ln::msgs::DecodeError;
3333
use ln::chan_utils;
34-
use ln::chan_utils::{HTLCOutputInCommitment, LocalCommitmentTransaction};
34+
use ln::chan_utils::{HTLCOutputInCommitment, LocalCommitmentTransaction, HTLCType};
3535
use ln::channelmanager::{HTLCSource, PaymentPreimage, PaymentHash};
36-
use ln::channel::{ACCEPTED_HTLC_SCRIPT_WEIGHT, OFFERED_HTLC_SCRIPT_WEIGHT};
3736
use chain::chaininterface::{ChainListener, ChainWatchInterface, BroadcasterInterface, FeeEstimator, ConfirmationTarget, MIN_RELAY_FEE_SAT_PER_1000_WEIGHT};
3837
use chain::transaction::OutPoint;
3938
use chain::keysinterface::SpendableOutputDescriptor;
@@ -2676,10 +2675,10 @@ impl ChannelMonitor {
26762675

26772676
'outer_loop: for input in &tx.input {
26782677
let mut payment_data = None;
2679-
let revocation_sig_claim = (input.witness.len() == 3 && input.witness[2].len() == OFFERED_HTLC_SCRIPT_WEIGHT && input.witness[1].len() == 33)
2680-
|| (input.witness.len() == 3 && input.witness[2].len() == ACCEPTED_HTLC_SCRIPT_WEIGHT && input.witness[1].len() == 33);
2681-
let accepted_preimage_claim = input.witness.len() == 5 && input.witness[4].len() == ACCEPTED_HTLC_SCRIPT_WEIGHT;
2682-
let offered_preimage_claim = input.witness.len() == 3 && input.witness[2].len() == OFFERED_HTLC_SCRIPT_WEIGHT;
2678+
let revocation_sig_claim = (input.witness.len() == 3 && HTLCType::weight_to_htlctype(input.witness[2].len()) == Some(HTLCType::OfferedHTLC) && input.witness[1].len() == 33)
2679+
|| (input.witness.len() == 3 && HTLCType::weight_to_htlctype(input.witness[2].len()) == Some(HTLCType::AcceptedHTLC) && input.witness[1].len() == 33);
2680+
let accepted_preimage_claim = input.witness.len() == 5 && HTLCType::weight_to_htlctype(input.witness[4].len()) == Some(HTLCType::AcceptedHTLC);
2681+
let offered_preimage_claim = input.witness.len() == 3 && HTLCType::weight_to_htlctype(input.witness[2].len()) == Some(HTLCType::OfferedHTLC);
26832682

26842683
macro_rules! log_claim {
26852684
($tx_info: expr, $local_tx: expr, $htlc: expr, $source_avail: expr) => {
@@ -2870,7 +2869,8 @@ impl ChannelMonitor {
28702869
for per_outp_material in cached_claim_datas.per_input_material.values() {
28712870
match per_outp_material {
28722871
&InputMaterial::Revoked { ref script, ref is_htlc, ref amount, .. } => {
2873-
inputs_witnesses_weight += Self::get_witnesses_weight(if !is_htlc { &[InputDescriptors::RevokedOutput] } else if script.len() == OFFERED_HTLC_SCRIPT_WEIGHT { &[InputDescriptors::RevokedOfferedHTLC] } else if script.len() == ACCEPTED_HTLC_SCRIPT_WEIGHT { &[InputDescriptors::RevokedReceivedHTLC] } else { &[] });
2872+
log_trace!(self, "Is HLTC ? {}", is_htlc);
2873+
inputs_witnesses_weight += Self::get_witnesses_weight(if !is_htlc { &[InputDescriptors::RevokedOutput] } else if HTLCType::weight_to_htlctype(script.len()) == Some(HTLCType::OfferedHTLC) { &[InputDescriptors::RevokedOfferedHTLC] } else if HTLCType::weight_to_htlctype(script.len()) == Some(HTLCType::AcceptedHTLC) { &[InputDescriptors::RevokedReceivedHTLC] } else { unreachable!() });
28742874
amt += *amount;
28752875
},
28762876
&InputMaterial::RemoteHTLC { ref preimage, ref amount, .. } => {
@@ -2910,7 +2910,7 @@ impl ChannelMonitor {
29102910
bumped_tx.input[i].witness.push(vec!(1));
29112911
}
29122912
bumped_tx.input[i].witness.push(script.clone().into_bytes());
2913-
log_trace!(self, "Going to broadcast bumped Penalty Transaction {} claiming revoked {} output {} from {} with new feerate {}", bumped_tx.txid(), if !is_htlc { "to_local" } else if script.len() == OFFERED_HTLC_SCRIPT_WEIGHT { "offered" } else if script.len() == ACCEPTED_HTLC_SCRIPT_WEIGHT { "received" } else { "" }, outp.vout, outp.txid, new_feerate);
2913+
log_trace!(self, "Going to broadcast bumped Penalty Transaction {} claiming revoked {} output {} from {} with new feerate {}", bumped_tx.txid(), if !is_htlc { "to_local" } else if HTLCType::weight_to_htlctype(script.len()) == Some(HTLCType::OfferedHTLC) { "offered" } else if HTLCType::weight_to_htlctype(script.len()) == Some(HTLCType::AcceptedHTLC) { "received" } else { "" }, outp.vout, outp.txid, new_feerate);
29142914
},
29152915
&InputMaterial::RemoteHTLC { ref script, ref key, ref preimage, ref amount, ref locktime } => {
29162916
if !preimage.is_some() { bumped_tx.lock_time = *locktime };

lightning/src/ln/functional_test_utils.rs

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -875,6 +875,9 @@ pub fn create_network(node_count: usize, node_config: &[Option<UserConfig>]) ->
875875
nodes
876876
}
877877

878+
pub const ACCEPTED_HTLC_SCRIPT_WEIGHT: usize = 138; //Here we have a diff due to HTLC CLTV expiry being < 2^15 in test
879+
pub const OFFERED_HTLC_SCRIPT_WEIGHT: usize = 133;
880+
878881
#[derive(PartialEq)]
879882
pub enum HTLCType { NONE, TIMEOUT, SUCCESS }
880883
/// Tests that the given node has broadcast transactions for the given Channel

lightning/src/ln/functional_tests.rs

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -8,7 +8,7 @@ use chain::keysinterface::{KeysInterface, SpendableOutputDescriptor};
88
use ln::channel::{COMMITMENT_TX_BASE_WEIGHT, COMMITMENT_TX_WEIGHT_PER_HTLC};
99
use ln::channelmanager::{ChannelManager,ChannelManagerReadArgs,HTLCForwardInfo,RAACommitmentOrder, PaymentPreimage, PaymentHash, BREAKDOWN_TIMEOUT};
1010
use ln::channelmonitor::{ChannelMonitor, CLTV_CLAIM_BUFFER, LATENCY_GRACE_PERIOD_BLOCKS, ManyChannelMonitor, ANTI_REORG_DELAY};
11-
use ln::channel::{ACCEPTED_HTLC_SCRIPT_WEIGHT, OFFERED_HTLC_SCRIPT_WEIGHT, Channel, ChannelError};
11+
use ln::channel::{Channel, ChannelError};
1212
use ln::onion_utils;
1313
use ln::router::{Route, RouteHop};
1414
use ln::msgs;

lightning/src/util/macro_logger.rs

Lines changed: 5 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -5,6 +5,7 @@ use bitcoin::blockdata::transaction::Transaction;
55
use secp256k1::key::PublicKey;
66

77
use ln::router::Route;
8+
use ln::chan_utils::HTLCType;
89

910
use std;
1011

@@ -99,18 +100,17 @@ impl<'a> std::fmt::Display for DebugTx<'a> {
99100
write!(f, "commitment tx")?;
100101
} else if self.0.input.len() == 1 && self.0.input[0].witness.last().unwrap().len() == 71 {
101102
write!(f, "closing tx")?;
102-
} else if self.0.input.len() == 1 && self.0.input[0].witness.last().unwrap().len() == 133 &&
103+
} else if self.0.input.len() == 1 && HTLCType::weight_to_htlctype(self.0.input[0].witness.last().unwrap().len()) == Some(HTLCType::OfferedHTLC) &&
103104
self.0.input[0].witness.len() == 5 {
104105
write!(f, "HTLC-timeout tx")?;
105-
} else if self.0.input.len() == 1 &&
106-
(self.0.input[0].witness.last().unwrap().len() == 138 || self.0.input[0].witness.last().unwrap().len() == 139) &&
106+
} else if self.0.input.len() == 1 && HTLCType::weight_to_htlctype(self.0.input[0].witness.last().unwrap().len()) == Some(HTLCType::AcceptedHTLC) &&
107107
self.0.input[0].witness.len() == 5 {
108108
write!(f, "HTLC-success tx")?;
109109
} else {
110110
for inp in &self.0.input {
111111
if !inp.witness.is_empty() {
112-
if inp.witness.last().unwrap().len() == 133 { write!(f, "preimage-")?; break }
113-
else if inp.witness.last().unwrap().len() == 138 { write!(f, "timeout-")?; break }
112+
if HTLCType::weight_to_htlctype(inp.witness.last().unwrap().len()) == Some(HTLCType::OfferedHTLC) { write!(f, "preimage-")?; break }
113+
else if HTLCType::weight_to_htlctype(inp.witness.last().unwrap().len()) == Some(HTLCType::AcceptedHTLC) { write!(f, "timeout-")?; break }
114114
}
115115
}
116116
write!(f, " tx")?;

0 commit comments

Comments
 (0)