Skip to content

Commit 0b5b282

Browse files
authored
Merge pull request #447 from ariard/2020-01-fix-weight-computation
Bound incoming HTLC witnessScript to min/max limits
2 parents f605eb3 + fbc7885 commit 0b5b282

File tree

6 files changed

+54
-23
lines changed

6 files changed

+54
-23
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 len matchs one of a pre-signed HTLC
36+
pub(crate) fn scriptlen_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
@@ -368,12 +368,6 @@ const B_OUTPUT_PLUS_SPENDING_INPUT_WEIGHT: u64 = 104; // prevout: 40, nSequence:
368368
/// it's 2^24.
369369
pub const MAX_FUNDING_SATOSHIS: u64 = (1 << 24);
370370

371-
#[cfg(test)]
372-
pub const ACCEPTED_HTLC_SCRIPT_WEIGHT: usize = 138; //Here we have a diff due to HTLC CLTV expiry being < 2^15 in test
373-
#[cfg(not(test))]
374-
pub const ACCEPTED_HTLC_SCRIPT_WEIGHT: usize = 139;
375-
pub const OFFERED_HTLC_SCRIPT_WEIGHT: usize = 133;
376-
377371
/// Used to return a simple Error back to ChannelManager. Will get converted to a
378372
/// msgs::ErrorAction::SendErrorMessage or msgs::ErrorAction::IgnoreError as appropriate with our
379373
/// 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;
@@ -2677,10 +2676,10 @@ impl ChannelMonitor {
26772676

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

26852684
macro_rules! log_claim {
26862685
($tx_info: expr, $local_tx: expr, $htlc: expr, $source_avail: expr) => {
@@ -2871,7 +2870,8 @@ impl ChannelMonitor {
28712870
for per_outp_material in cached_claim_datas.per_input_material.values() {
28722871
match per_outp_material {
28732872
&InputMaterial::Revoked { ref script, ref is_htlc, ref amount, .. } => {
2874-
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 { &[] });
2873+
log_trace!(self, "Is HLTC ? {}", is_htlc);
2874+
inputs_witnesses_weight += Self::get_witnesses_weight(if !is_htlc { &[InputDescriptors::RevokedOutput] } else if HTLCType::scriptlen_to_htlctype(script.len()) == Some(HTLCType::OfferedHTLC) { &[InputDescriptors::RevokedOfferedHTLC] } else if HTLCType::scriptlen_to_htlctype(script.len()) == Some(HTLCType::AcceptedHTLC) { &[InputDescriptors::RevokedReceivedHTLC] } else { unreachable!() });
28752875
amt += *amount;
28762876
},
28772877
&InputMaterial::RemoteHTLC { ref preimage, ref amount, .. } => {
@@ -2911,7 +2911,7 @@ impl ChannelMonitor {
29112911
bumped_tx.input[i].witness.push(vec!(1));
29122912
}
29132913
bumped_tx.input[i].witness.push(script.clone().into_bytes());
2914-
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);
2914+
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::scriptlen_to_htlctype(script.len()) == Some(HTLCType::OfferedHTLC) { "offered" } else if HTLCType::scriptlen_to_htlctype(script.len()) == Some(HTLCType::AcceptedHTLC) { "received" } else { "" }, outp.vout, outp.txid, new_feerate);
29152915
},
29162916
&InputMaterial::RemoteHTLC { ref script, ref key, ref preimage, ref amount, ref locktime } => {
29172917
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
@@ -876,6 +876,9 @@ pub fn create_network(node_count: usize, node_config: &[Option<UserConfig>]) ->
876876
nodes
877877
}
878878

879+
pub const ACCEPTED_HTLC_SCRIPT_WEIGHT: usize = 138; //Here we have a diff due to HTLC CLTV expiry being < 2^15 in test
880+
pub const OFFERED_HTLC_SCRIPT_WEIGHT: usize = 133;
881+
879882
#[derive(PartialEq)]
880883
pub enum HTLCType { NONE, TIMEOUT, SUCCESS }
881884
/// 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::features::{ChannelFeatures, InitFeatures};

lightning/src/util/macro_logger.rs

Lines changed: 23 additions & 8 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

@@ -93,15 +94,29 @@ macro_rules! log_route {
9394
pub(crate) struct DebugTx<'a>(pub &'a Transaction);
9495
impl<'a> std::fmt::Display for DebugTx<'a> {
9596
fn fmt(&self, f: &mut std::fmt::Formatter) -> Result<(), std::fmt::Error> {
96-
if self.0.input.len() == 1 && self.0.input[0].witness.last().unwrap().len() == 71 && (self.0.input[0].sequence >> 8*3) as u8 == 0x80 { write!(f, "commitment tx")?; }
97-
else if self.0.input.len() == 1 && self.0.input[0].witness.last().unwrap().len() == 71 { write!(f, "closing tx")?; }
98-
else if self.0.input.len() == 1 && self.0.input[0].witness.last().unwrap().len() == 133 && self.0.input[0].witness.len() == 5 { write!(f, "HTLC-timeout tx")?; }
99-
else if self.0.input.len() == 1 && (self.0.input[0].witness.last().unwrap().len() == 138 || self.0.input[0].witness.last().unwrap().len() == 139) && self.0.input[0].witness.len() == 5 { write!(f, "HTLC-success tx")?; }
100-
else {
101-
for inp in &self.0.input {
102-
if inp.witness.last().unwrap().len() == 133 { write!(f, "preimage tx")?; break }
103-
else if inp.witness.last().unwrap().len() == 138 { write!(f, "timeout tx")?; break }
97+
if self.0.input.len() >= 1 && self.0.input.iter().any(|i| !i.witness.is_empty()) {
98+
if self.0.input.len() == 1 && self.0.input[0].witness.last().unwrap().len() == 71 &&
99+
(self.0.input[0].sequence >> 8*3) as u8 == 0x80 {
100+
write!(f, "commitment tx")?;
101+
} else if self.0.input.len() == 1 && self.0.input[0].witness.last().unwrap().len() == 71 {
102+
write!(f, "closing tx")?;
103+
} else if self.0.input.len() == 1 && HTLCType::scriptlen_to_htlctype(self.0.input[0].witness.last().unwrap().len()) == Some(HTLCType::OfferedHTLC) &&
104+
self.0.input[0].witness.len() == 5 {
105+
write!(f, "HTLC-timeout tx")?;
106+
} else if self.0.input.len() == 1 && HTLCType::scriptlen_to_htlctype(self.0.input[0].witness.last().unwrap().len()) == Some(HTLCType::AcceptedHTLC) &&
107+
self.0.input[0].witness.len() == 5 {
108+
write!(f, "HTLC-success tx")?;
109+
} else {
110+
for inp in &self.0.input {
111+
if !inp.witness.is_empty() {
112+
if HTLCType::scriptlen_to_htlctype(inp.witness.last().unwrap().len()) == Some(HTLCType::OfferedHTLC) { write!(f, "preimage-")?; break }
113+
else if HTLCType::scriptlen_to_htlctype(inp.witness.last().unwrap().len()) == Some(HTLCType::AcceptedHTLC) { write!(f, "timeout-")?; break }
114+
}
115+
}
116+
write!(f, "tx")?;
104117
}
118+
} else {
119+
write!(f, "INVALID TRANSACTION")?;
105120
}
106121
Ok(())
107122
}

0 commit comments

Comments
 (0)