Skip to content

Commit 8e2974f

Browse files
committed
HTLC Failure message handling
1 parent 53d1518 commit 8e2974f

File tree

5 files changed

+176
-45
lines changed

5 files changed

+176
-45
lines changed

src/ln/channel.rs

Lines changed: 8 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -1315,7 +1315,8 @@ impl Channel {
13151315
}
13161316

13171317
/// Removes an outbound HTLC which has been commitment_signed by the remote end
1318-
fn mark_outbound_htlc_removed(&mut self, htlc_id: u64, check_preimage: Option<[u8; 32]>, fail_reason: Option<HTLCFailReason>) -> Result<(), HandleError> {
1318+
#[inline]
1319+
fn mark_outbound_htlc_removed(&mut self, htlc_id: u64, check_preimage: Option<[u8; 32]>, fail_reason: Option<HTLCFailReason>) -> Result<[u8; 32], HandleError> {
13191320
for mut htlc in self.pending_htlcs.iter_mut() {
13201321
if htlc.outbound && htlc.htlc_id == htlc_id {
13211322
match check_preimage {
@@ -1335,7 +1336,7 @@ impl Channel {
13351336
} else {
13361337
panic!("Got a non-outbound state on an outbound HTLC");
13371338
}
1338-
return Ok(());
1339+
return Ok(htlc.payment_hash.clone());
13391340
}
13401341
}
13411342
Err(HandleError{err: "Remote tried to fulfill/fail an HTLC we couldn't find", msg: None})
@@ -1352,10 +1353,11 @@ impl Channel {
13521353
sha.result(&mut payment_hash);
13531354

13541355
self.channel_monitor.provide_payment_preimage(&msg.payment_preimage);
1355-
self.mark_outbound_htlc_removed(msg.htlc_id, Some(payment_hash), None)
1356+
self.mark_outbound_htlc_removed(msg.htlc_id, Some(payment_hash), None)?;
1357+
Ok(())
13561358
}
13571359

1358-
pub fn update_fail_htlc(&mut self, msg: &msgs::UpdateFailHTLC, fail_reason: HTLCFailReason) -> Result<(), HandleError> {
1360+
pub fn update_fail_htlc(&mut self, msg: &msgs::UpdateFailHTLC, fail_reason: HTLCFailReason) -> Result<[u8; 32], HandleError> {
13591361
if (self.channel_state & (ChannelState::ChannelFunded as u32)) != (ChannelState::ChannelFunded as u32) {
13601362
return Err(HandleError{err: "Got add HTLC message when channel was not in an operational state", msg: None});
13611363
}
@@ -1368,7 +1370,8 @@ impl Channel {
13681370
return Err(HandleError{err: "Got add HTLC message when channel was not in an operational state", msg: None});
13691371
}
13701372

1371-
self.mark_outbound_htlc_removed(msg.htlc_id, None, Some(fail_reason))
1373+
self.mark_outbound_htlc_removed(msg.htlc_id, None, Some(fail_reason))?;
1374+
Ok(())
13721375
}
13731376

13741377
pub fn commitment_signed(&mut self, msg: &msgs::CommitmentSigned) -> Result<(msgs::RevokeAndACK, Option<msgs::CommitmentSigned>), HandleError> {

src/ln/channelmanager.rs

Lines changed: 111 additions & 34 deletions
Original file line numberDiff line numberDiff line change
@@ -14,12 +14,13 @@ use secp256k1;
1414
use chain::chaininterface::{BroadcasterInterface,ChainListener,ChainWatchInterface,FeeEstimator};
1515
use ln::channel::{Channel, ChannelKeys};
1616
use ln::channelmonitor::ManyChannelMonitor;
17-
use ln::router::Route;
17+
use ln::router::{Route,RouteHop};
1818
use ln::msgs;
1919
use ln::msgs::{HandleError,ChannelMessageHandler,MsgEncodable,MsgDecodable};
2020
use util::{byte_utils, events, internal_traits, rng};
2121
use util::sha2::Sha256;
2222

23+
use crypto;
2324
use crypto::mac::{Mac,MacResult};
2425
use crypto::hmac::Hmac;
2526
use crypto::digest::Digest;
@@ -91,12 +92,14 @@ enum PendingOutboundHTLC {
9192
},
9293
OutboundRoute {
9394
route: Route,
95+
session_priv: SecretKey,
9496
},
9597
/// Used for channel rebalancing
9698
CycledRoute {
9799
source_short_channel_id: u64,
98100
incoming_packet_shared_secret: SharedSecret,
99101
route: Route,
102+
session_priv: SecretKey,
100103
}
101104
}
102105

@@ -336,8 +339,9 @@ impl ChannelManager {
336339
res
337340
}
338341

339-
fn construct_onion_keys(secp_ctx: &Secp256k1, route: &Route, session_priv: &SecretKey) -> Result<Vec<OnionKeys>, HandleError> {
340-
let mut res = Vec::with_capacity(route.hops.len());
342+
// can only fail if an intermediary hop has an invalid public key or session_priv is invalid
343+
#[inline]
344+
fn construct_onion_keys_callback<FType: FnMut(SharedSecret, [u8; 32], PublicKey, &RouteHop)> (secp_ctx: &Secp256k1, route: &Route, session_priv: &SecretKey, mut callback: FType) -> Result<(), HandleError> {
341345
let mut blinded_priv = session_priv.clone();
342346
let mut blinded_pub = secp_call!(PublicKey::from_secret_key(secp_ctx, &blinded_priv));
343347
let mut first_iteration = true;
@@ -360,18 +364,29 @@ impl ChannelManager {
360364
secp_call!(blinded_priv.mul_assign(secp_ctx, &secp_call!(SecretKey::from_slice(secp_ctx, &blinding_factor))));
361365
blinded_pub = secp_call!(PublicKey::from_secret_key(secp_ctx, &blinded_priv));
362366

367+
callback(shared_secret, blinding_factor, ephemeral_pubkey, hop);
368+
}
369+
370+
Ok(())
371+
}
372+
373+
// can only fail if an intermediary hop has an invalid public key or session_priv is invalid
374+
fn construct_onion_keys(secp_ctx: &Secp256k1, route: &Route, session_priv: &SecretKey) -> Result<Vec<OnionKeys>, HandleError> {
375+
let mut res = Vec::with_capacity(route.hops.len());
376+
377+
Self::construct_onion_keys_callback(secp_ctx, route, session_priv, |shared_secret, _blinding_factor, ephemeral_pubkey, _| {
363378
let (rho, mu) = ChannelManager::gen_rho_mu_from_shared_secret(&shared_secret);
364379

365380
res.push(OnionKeys {
366381
#[cfg(test)]
367-
shared_secret: shared_secret,
382+
shared_secret,
368383
#[cfg(test)]
369-
blinding_factor: blinding_factor,
370-
ephemeral_pubkey: ephemeral_pubkey,
371-
rho: rho,
372-
mu: mu,
384+
blinding_factor: _blinding_factor,
385+
ephemeral_pubkey,
386+
rho,
387+
mu,
373388
});
374-
}
389+
})?;
375390

376391
Ok(res)
377392
}
@@ -602,7 +617,8 @@ impl ChannelManager {
602617
};
603618

604619
if channel_state.claimable_htlcs.insert(payment_hash, PendingOutboundHTLC::OutboundRoute {
605-
route: route,
620+
route,
621+
session_priv,
606622
}).is_some() {
607623
// TODO: We need to track these better, we're not generating these, so a
608624
// third-party might make this happen:
@@ -747,7 +763,7 @@ impl ChannelManager {
747763
for failed_forward in failed_forwards.drain(..) {
748764
match failed_forward.2 {
749765
None => self.fail_htlc_backwards_internal(self.channel_state.lock().unwrap(), &failed_forward.0, HTLCFailReason::Reason { failure_code: failed_forward.1, data: Vec::new() }),
750-
Some(chan_update) => self.fail_htlc_backwards_internal(self.channel_state.lock().unwrap(), &failed_forward.0, HTLCFailReason::Reason { failure_code: failed_forward.1, data: chan_update.encode() }),
766+
Some(chan_update) => self.fail_htlc_backwards_internal(self.channel_state.lock().unwrap(), &failed_forward.0, HTLCFailReason::Reason { failure_code: failed_forward.1, data: chan_update.encode_with_len() }),
751767
};
752768
}
753769

@@ -774,7 +790,11 @@ impl ChannelManager {
774790
};
775791

776792
match pending_htlc {
777-
PendingOutboundHTLC::CycledRoute { source_short_channel_id, incoming_packet_shared_secret, .. } => {
793+
PendingOutboundHTLC::CycledRoute { source_short_channel_id, incoming_packet_shared_secret, route, session_priv } => {
794+
channel_state.claimable_htlcs.insert(payment_hash.clone(), PendingOutboundHTLC::OutboundRoute {
795+
route,
796+
session_priv,
797+
});
778798
pending_htlc = PendingOutboundHTLC::IntermediaryHopData { source_short_channel_id, incoming_packet_shared_secret };
779799
},
780800
_ => {}
@@ -783,8 +803,8 @@ impl ChannelManager {
783803
match pending_htlc {
784804
PendingOutboundHTLC::CycledRoute { .. } => { panic!("WAT"); },
785805
PendingOutboundHTLC::OutboundRoute { .. } => {
786-
//TODO: DECRYPT route from OutboundRoute
787806
mem::drop(channel_state);
807+
788808
let mut pending_events = self.pending_events.lock().unwrap();
789809
pending_events.push(events::Event::PaymentFailed {
790810
payment_hash: payment_hash.clone()
@@ -858,13 +878,13 @@ impl ChannelManager {
858878
};
859879

860880
match pending_htlc {
861-
PendingOutboundHTLC::CycledRoute { source_short_channel_id, incoming_packet_shared_secret, route } => {
881+
PendingOutboundHTLC::CycledRoute { source_short_channel_id, incoming_packet_shared_secret, route, session_priv } => {
862882
if from_user { // This was the end hop back to us
863883
pending_htlc = PendingOutboundHTLC::IntermediaryHopData { source_short_channel_id, incoming_packet_shared_secret };
864-
channel_state.claimable_htlcs.insert(payment_hash, PendingOutboundHTLC::OutboundRoute { route });
884+
channel_state.claimable_htlcs.insert(payment_hash, PendingOutboundHTLC::OutboundRoute { route, session_priv });
865885
} else { // This came from the first upstream node
866886
// Bank error in our favor! Maybe we should tell the user this somehow???
867-
pending_htlc = PendingOutboundHTLC::OutboundRoute { route };
887+
pending_htlc = PendingOutboundHTLC::OutboundRoute { route, session_priv };
868888
channel_state.claimable_htlcs.insert(payment_hash, PendingOutboundHTLC::IntermediaryHopData { source_short_channel_id, incoming_packet_shared_secret });
869889
}
870890
},
@@ -1332,7 +1352,7 @@ impl ChannelMessageHandler for ChannelManager {
13321352
let chan = channel_state.by_id.get_mut(&forwarding_id).unwrap();
13331353
if !chan.is_live() {
13341354
let chan_update = self.get_channel_update(chan).unwrap();
1335-
return_err!("Forwarding channel is not in a ready state.", 0x4000 | 10, &chan_update.encode()[..]);
1355+
return_err!("Forwarding channel is not in a ready state.", 0x4000 | 7, &chan_update.encode_with_len()[..]);
13361356
}
13371357
}
13381358

@@ -1376,16 +1396,17 @@ impl ChannelMessageHandler for ChannelManager {
13761396
match claimable_htlcs_entry {
13771397
hash_map::Entry::Occupied(mut e) => {
13781398
let outbound_route = e.get_mut();
1379-
let route = match outbound_route {
1380-
&mut PendingOutboundHTLC::OutboundRoute { ref route } => {
1381-
route.clone()
1399+
let (route, session_priv) = match outbound_route {
1400+
&mut PendingOutboundHTLC::OutboundRoute { ref route, ref session_priv } => {
1401+
(route.clone(), session_priv.clone())
13821402
},
13831403
_ => { panic!("WAT") },
13841404
};
13851405
*outbound_route = PendingOutboundHTLC::CycledRoute {
13861406
source_short_channel_id,
13871407
incoming_packet_shared_secret: shared_secret,
1388-
route
1408+
route,
1409+
session_priv,
13891410
};
13901411
},
13911412
hash_map::Entry::Vacant(e) => {
@@ -1422,16 +1443,78 @@ impl ChannelMessageHandler for ChannelManager {
14221443
Ok(())
14231444
}
14241445

1425-
fn handle_update_fail_htlc(&self, their_node_id: &PublicKey, msg: &msgs::UpdateFailHTLC) -> Result<(), HandleError> {
1446+
fn handle_update_fail_htlc(&self, their_node_id: &PublicKey, msg: &msgs::UpdateFailHTLC) -> Result<Option<msgs::HTLCFailChannelUpdate>, HandleError> {
14261447
let mut channel_state = self.channel_state.lock().unwrap();
1427-
match channel_state.by_id.get_mut(&msg.channel_id) {
1448+
let payment_hash = match channel_state.by_id.get_mut(&msg.channel_id) {
14281449
Some(chan) => {
14291450
if chan.get_their_node_id() != *their_node_id {
14301451
return Err(HandleError{err: "Got a message for a channel from the wrong node!", msg: None})
14311452
}
14321453
chan.update_fail_htlc(&msg, HTLCFailReason::ErrorPacket { err: msg.reason.clone() })
14331454
},
14341455
None => return Err(HandleError{err: "Failed to find corresponding channel", msg: None})
1456+
}?;
1457+
1458+
if let Some(pending_htlc) = channel_state.claimable_htlcs.get(&payment_hash) {
1459+
match pending_htlc {
1460+
&PendingOutboundHTLC::OutboundRoute { ref route, ref session_priv } => {
1461+
// Handle packed channel/node updates for passing back for the route handler
1462+
let mut packet_decrypted = msg.reason.data.clone();
1463+
let mut res = None;
1464+
Self::construct_onion_keys_callback(&self.secp_ctx, &route, &session_priv, |shared_secret, _, _, route_hop| {
1465+
if res.is_some() { return; }
1466+
1467+
let ammag = ChannelManager::gen_ammag_from_shared_secret(&shared_secret);
1468+
1469+
let mut decryption_tmp = Vec::with_capacity(packet_decrypted.len());
1470+
decryption_tmp.resize(packet_decrypted.len(), 0);
1471+
let mut chacha = ChaCha20::new(&ammag, &[0u8; 8]);
1472+
chacha.process(&packet_decrypted, &mut decryption_tmp[..]);
1473+
packet_decrypted = decryption_tmp;
1474+
1475+
if let Ok(err_packet) = msgs::DecodedOnionErrorPacket::decode(&packet_decrypted) {
1476+
if err_packet.failuremsg.len() >= 2 {
1477+
let um = ChannelManager::gen_um_from_shared_secret(&shared_secret);
1478+
1479+
let mut hmac = Hmac::new(Sha256::new(), &um);
1480+
hmac.input(&err_packet.encode()[32..]);
1481+
let mut calc_tag = [0u8; 32];
1482+
hmac.raw_result(&mut calc_tag);
1483+
if crypto::util::fixed_time_eq(&calc_tag, &err_packet.hmac) {
1484+
const UNKNOWN_CHAN: u16 = 0x4000|10;
1485+
const TEMP_CHAN_FAILURE: u16 = 0x4000|7;
1486+
match byte_utils::slice_to_be16(&err_packet.failuremsg[0..2]) {
1487+
TEMP_CHAN_FAILURE => {
1488+
if err_packet.failuremsg.len() >= 4 {
1489+
let update_len = byte_utils::slice_to_be16(&err_packet.failuremsg[2..4]) as usize;
1490+
if err_packet.failuremsg.len() >= 4 + update_len {
1491+
if let Ok(chan_update) = msgs::ChannelUpdate::decode(&err_packet.failuremsg[4..4 + update_len]) {
1492+
res = Some(msgs::HTLCFailChannelUpdate::ChannelUpdateMessage {
1493+
msg: chan_update,
1494+
});
1495+
}
1496+
}
1497+
}
1498+
},
1499+
UNKNOWN_CHAN => {
1500+
// No such next-hop. We know this came from the
1501+
// current node as the HMAC validated.
1502+
res = Some(msgs::HTLCFailChannelUpdate::ChannelClosed {
1503+
short_channel_id: route_hop.short_channel_id
1504+
});
1505+
},
1506+
_ => {}, //TODO: Enumerate all of these!
1507+
}
1508+
}
1509+
}
1510+
}
1511+
}).unwrap();
1512+
Ok(res)
1513+
},
1514+
_ => { Ok(None) },
1515+
}
1516+
} else {
1517+
Ok(None)
14351518
}
14361519
}
14371520

@@ -2169,14 +2252,7 @@ mod tests {
21692252
claim_payment(&origin, expected_route, our_payment_preimage);
21702253
}
21712254

2172-
fn send_failed_payment(origin_node: &Node, expected_route: &[&Node]) {
2173-
let route = origin_node.router.get_route(&expected_route.last().unwrap().node.get_our_node_id(), &Vec::new(), 1000000, 142).unwrap();
2174-
assert_eq!(route.hops.len(), expected_route.len());
2175-
for (node, hop) in expected_route.iter().zip(route.hops.iter()) {
2176-
assert_eq!(hop.pubkey, node.node.get_our_node_id());
2177-
}
2178-
let our_payment_hash = send_along_route(origin_node, route, expected_route, 1000000).1;
2179-
2255+
fn fail_payment(origin_node: &Node, expected_route: &[&Node], our_payment_hash: [u8; 32]) {
21802256
assert!(expected_route.last().unwrap().node.fail_htlc_backwards(&our_payment_hash));
21812257

21822258
let mut next_msgs: Option<(msgs::UpdateFailHTLC, msgs::CommitmentSigned)> = None;
@@ -2288,7 +2364,8 @@ mod tests {
22882364
send_payment(&nodes[3], &vec!(&nodes[2], &nodes[1])[..], 1000000);
22892365

22902366
// Test failure packets
2291-
send_failed_payment(&nodes[0], &vec!(&nodes[1], &nodes[2], &nodes[3])[..]);
2367+
let payment_hash_1 = route_payment(&nodes[0], &vec!(&nodes[1], &nodes[2], &nodes[3])[..], 1000000).1;
2368+
fail_payment(&nodes[0], &vec!(&nodes[1], &nodes[2], &nodes[3])[..], payment_hash_1);
22922369

22932370
// Add a new channel that skips 3
22942371
let chan_4 = create_announced_chan_between_nodes(&nodes, 1, 3);
@@ -2346,10 +2423,10 @@ mod tests {
23462423
});
23472424
hops[1].fee_msat = chan_2.1.contents.fee_base_msat as u64 + chan_2.1.contents.fee_proportional_millionths as u64 * hops[2].fee_msat as u64 / 1000000;
23482425
hops[0].fee_msat = chan_3.1.contents.fee_base_msat as u64 + chan_3.1.contents.fee_proportional_millionths as u64 * hops[1].fee_msat as u64 / 1000000;
2349-
let payment_preimage_2 = send_along_route(&nodes[1], Route { hops }, &vec!(&nodes[3], &nodes[2], &nodes[1])[..], 1000000).0;
2426+
let payment_hash_2 = send_along_route(&nodes[1], Route { hops }, &vec!(&nodes[3], &nodes[2], &nodes[1])[..], 1000000).1;
23502427

23512428
// Claim the rebalances...
2352-
claim_payment(&nodes[1], &vec!(&nodes[3], &nodes[2], &nodes[1])[..], payment_preimage_2);
2429+
fail_payment(&nodes[1], &vec!(&nodes[3], &nodes[2], &nodes[1])[..], payment_hash_2);
23532430
claim_payment(&nodes[1], &vec!(&nodes[2], &nodes[3], &nodes[1])[..], payment_preimage_1);
23542431

23552432
// Add a duplicate new channel from 2 to 4

0 commit comments

Comments
 (0)