Skip to content

Commit 270d1bd

Browse files
authored
Merge pull request #219 from TheBlueMatt/2018-10-157-merge
Partially implement more onion error handling for sent payments
2 parents 0baf72b + 920d145 commit 270d1bd

File tree

9 files changed

+388
-121
lines changed

9 files changed

+388
-121
lines changed

fuzz/fuzz_targets/router_target.rs

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -187,7 +187,7 @@ pub fn do_test(data: &[u8]) {
187187
},
188188
1 => {
189189
let short_channel_id = slice_to_be64(get_slice!(8));
190-
router.handle_htlc_fail_channel_update(&msgs::HTLCFailChannelUpdate::ChannelClosed {short_channel_id});
190+
router.handle_htlc_fail_channel_update(&msgs::HTLCFailChannelUpdate::ChannelClosed {short_channel_id, is_permanent: false});
191191
},
192192
_ => return,
193193
}

src/ln/channel.rs

Lines changed: 8 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -1545,7 +1545,7 @@ impl Channel {
15451545
Ok(())
15461546
}
15471547

1548-
/// Removes an outbound HTLC which has been commitment_signed by the remote end
1548+
/// Marks an outbound HTLC which we have received update_fail/fulfill/malformed
15491549
#[inline]
15501550
fn mark_outbound_htlc_removed(&mut self, htlc_id: u64, check_preimage: Option<[u8; 32]>, fail_reason: Option<HTLCFailReason>) -> Result<&HTLCSource, ChannelError> {
15511551
for htlc in self.pending_outbound_htlcs.iter_mut() {
@@ -1559,13 +1559,13 @@ impl Channel {
15591559
};
15601560
match htlc.state {
15611561
OutboundHTLCState::LocalAnnounced(_) =>
1562-
return Err(ChannelError::Close("Remote tried to fulfill HTLC before it had been committed")),
1562+
return Err(ChannelError::Close("Remote tried to fulfill/fail HTLC before it had been committed")),
15631563
OutboundHTLCState::Committed => {
15641564
htlc.state = OutboundHTLCState::RemoteRemoved;
15651565
htlc.fail_reason = fail_reason;
15661566
},
15671567
OutboundHTLCState::AwaitingRemoteRevokeToRemove | OutboundHTLCState::AwaitingRemovedRemoteRevoke | OutboundHTLCState::RemoteRemoved =>
1568-
return Err(ChannelError::Close("Remote tried to fulfill HTLC that they'd already fulfilled")),
1568+
return Err(ChannelError::Close("Remote tried to fulfill/fail HTLC that they'd already fulfilled/failed")),
15691569
}
15701570
return Ok(&htlc.source);
15711571
}
@@ -2450,6 +2450,11 @@ impl Channel {
24502450
self.our_htlc_minimum_msat
24512451
}
24522452

2453+
/// Allowed in any state (including after shutdown)
2454+
pub fn get_their_htlc_minimum_msat(&self) -> u64 {
2455+
self.our_htlc_minimum_msat
2456+
}
2457+
24532458
pub fn get_value_satoshis(&self) -> u64 {
24542459
self.channel_value_satoshis
24552460
}

src/ln/channelmanager.rs

Lines changed: 309 additions & 95 deletions
Large diffs are not rendered by default.

src/ln/channelmonitor.rs

Lines changed: 31 additions & 15 deletions
Original file line numberDiff line numberDiff line change
@@ -155,7 +155,13 @@ impl ManyChannelMonitor for SimpleManyChannelMonitor<OutPoint> {
155155
const CLTV_SHARED_CLAIM_BUFFER: u32 = 12;
156156
/// If an HTLC expires within this many blocks, force-close the channel to broadcast the
157157
/// HTLC-Success transaction.
158-
const CLTV_CLAIM_BUFFER: u32 = 6;
158+
/// In other words, this is an upper bound on how many blocks we think it can take us to get a
159+
/// transaction confirmed (and we use it in a few more, equivalent, places).
160+
pub(crate) const CLTV_CLAIM_BUFFER: u32 = 6;
161+
/// Number of blocks by which point we expect our counterparty to have seen new blocks on the
162+
/// network and done a full update_fail_htlc/commitment_signed dance (+ we've updated all our
163+
/// copies of ChannelMonitors, including watchtowers).
164+
pub(crate) const HTLC_FAIL_TIMEOUT_BLOCKS: u32 = 3;
159165

160166
#[derive(Clone, PartialEq)]
161167
enum KeyStorage {
@@ -1184,16 +1190,7 @@ impl ChannelMonitor {
11841190
}
11851191
}
11861192
if let Some(ref cur_local_tx) = self.current_local_signed_commitment_tx {
1187-
let mut needs_broadcast = false;
1188-
for &(ref htlc, _, _) in cur_local_tx.htlc_outputs.iter() {
1189-
if htlc.cltv_expiry <= height + CLTV_CLAIM_BUFFER {
1190-
if htlc.offered || self.payment_preimages.contains_key(&htlc.payment_hash) {
1191-
needs_broadcast = true;
1192-
}
1193-
}
1194-
}
1195-
1196-
if needs_broadcast {
1193+
if self.would_broadcast_at_height(height) {
11971194
broadcaster.broadcast_transaction(&cur_local_tx.tx);
11981195
for tx in self.broadcast_by_local_state(&cur_local_tx) {
11991196
broadcaster.broadcast_transaction(&tx);
@@ -1206,10 +1203,29 @@ impl ChannelMonitor {
12061203
pub(super) fn would_broadcast_at_height(&self, height: u32) -> bool {
12071204
if let Some(ref cur_local_tx) = self.current_local_signed_commitment_tx {
12081205
for &(ref htlc, _, _) in cur_local_tx.htlc_outputs.iter() {
1209-
if htlc.cltv_expiry <= height + CLTV_CLAIM_BUFFER {
1210-
if htlc.offered || self.payment_preimages.contains_key(&htlc.payment_hash) {
1211-
return true;
1212-
}
1206+
// For inbound HTLCs which we know the preimage for, we have to ensure we hit the
1207+
// chain with enough room to claim the HTLC without our counterparty being able to
1208+
// time out the HTLC first.
1209+
// For outbound HTLCs which our counterparty hasn't failed/claimed, our primary
1210+
// concern is being able to claim the corresponding inbound HTLC (on another
1211+
// channel) before it expires. In fact, we don't even really care if our
1212+
// counterparty here claims such an outbound HTLC after it expired as long as we
1213+
// can still claim the corresponding HTLC. Thus, to avoid needlessly hitting the
1214+
// chain when our counterparty is waiting for expiration to off-chain fail an HTLC
1215+
// we give ourselves a few blocks of headroom after expiration before going
1216+
// on-chain for an expired HTLC.
1217+
// Note that, to avoid a potential attack whereby a node delays claiming an HTLC
1218+
// from us until we've reached the point where we go on-chain with the
1219+
// corresponding inbound HTLC, we must ensure that outbound HTLCs go on chain at
1220+
// least CLTV_CLAIM_BUFFER blocks prior to the inbound HTLC.
1221+
// aka outbound_cltv + HTLC_FAIL_TIMEOUT_BLOCKS == height - CLTV_CLAIM_BUFFER
1222+
// inbound_cltv == height + CLTV_CLAIM_BUFFER
1223+
// outbound_cltv + HTLC_FAIL_TIMEOUT_BLOCKS + CLTV_CLAIM_BUFER <= inbound_cltv - CLTV_CLAIM_BUFFER
1224+
// HTLC_FAIL_TIMEOUT_BLOCKS + 2*CLTV_CLAIM_BUFER <= inbound_cltv - outbound_cltv
1225+
// HTLC_FAIL_TIMEOUT_BLOCKS + 2*CLTV_CLAIM_BUFER <= CLTV_EXPIRY_DELTA
1226+
if ( htlc.offered && htlc.cltv_expiry + HTLC_FAIL_TIMEOUT_BLOCKS <= height) ||
1227+
(!htlc.offered && htlc.cltv_expiry <= height + CLTV_CLAIM_BUFFER && self.payment_preimages.contains_key(&htlc.payment_hash)) {
1228+
return true;
12131229
}
12141230
}
12151231
}

src/ln/msgs.rs

Lines changed: 13 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -485,7 +485,19 @@ pub enum HTLCFailChannelUpdate {
485485
ChannelClosed {
486486
/// The short_channel_id which has now closed.
487487
short_channel_id: u64,
488+
/// when this true, this channel should be permanently removed from the
489+
/// consideration. Otherwise, this channel can be restored as new channel_update is received
490+
is_permanent: bool,
488491
},
492+
/// We received an error which indicated only that a node has failed
493+
NodeFailure {
494+
/// The node_id that has failed.
495+
node_id: PublicKey,
496+
/// when this true, node should be permanently removed from the
497+
/// consideration. Otherwise, the channels connected to this node can be
498+
/// restored as new channel_update is received
499+
is_permanent: bool,
500+
}
489501
}
490502

491503
/// A trait to describe an object which can receive channel messages.
@@ -517,7 +529,7 @@ pub trait ChannelMessageHandler : events::EventsProvider + Send + Sync {
517529
/// Handle an incoming update_fulfill_htlc message from the given peer.
518530
fn handle_update_fulfill_htlc(&self, their_node_id: &PublicKey, msg: &UpdateFulfillHTLC) -> Result<(), HandleError>;
519531
/// Handle an incoming update_fail_htlc message from the given peer.
520-
fn handle_update_fail_htlc(&self, their_node_id: &PublicKey, msg: &UpdateFailHTLC) -> Result<Option<HTLCFailChannelUpdate>, HandleError>;
532+
fn handle_update_fail_htlc(&self, their_node_id: &PublicKey, msg: &UpdateFailHTLC) -> Result<(), HandleError>;
521533
/// Handle an incoming update_fail_malformed_htlc message from the given peer.
522534
fn handle_update_fail_malformed_htlc(&self, their_node_id: &PublicKey, msg: &UpdateFailMalformedHTLC) -> Result<(), HandleError>;
523535
/// Handle an incoming commitment_signed message from the given peer.

src/ln/peer_handler.rs

Lines changed: 5 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -615,10 +615,7 @@ impl<Descriptor: SocketDescriptor> PeerManager<Descriptor> {
615615
},
616616
131 => {
617617
let msg = try_potential_decodeerror!(msgs::UpdateFailHTLC::read(&mut reader));
618-
let chan_update = try_potential_handleerror!(self.message_handler.chan_handler.handle_update_fail_htlc(&peer.their_node_id.unwrap(), &msg));
619-
if let Some(update) = chan_update {
620-
self.message_handler.route_handler.handle_htlc_fail_channel_update(&update);
621-
}
618+
try_potential_handleerror!(self.message_handler.chan_handler.handle_update_fail_htlc(&peer.their_node_id.unwrap(), &msg));
622619
},
623620
135 => {
624621
let msg = try_potential_decodeerror!(msgs::UpdateFailMalformedHTLC::read(&mut reader));
@@ -906,6 +903,10 @@ impl<Descriptor: SocketDescriptor> PeerManager<Descriptor> {
906903
}
907904
continue;
908905
},
906+
Event::PaymentFailureNetworkUpdate { ref update } => {
907+
self.message_handler.route_handler.handle_htlc_fail_channel_update(update);
908+
continue;
909+
},
909910
Event::HandleError { ref node_id, ref action } => {
910911
if let Some(ref action) = *action {
911912
match *action {

src/ln/router.rs

Lines changed: 8 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -349,12 +349,19 @@ impl RoutingMessageHandler for Router {
349349
&msgs::HTLCFailChannelUpdate::ChannelUpdateMessage { ref msg } => {
350350
let _ = self.handle_channel_update(msg);
351351
},
352-
&msgs::HTLCFailChannelUpdate::ChannelClosed { ref short_channel_id } => {
352+
&msgs::HTLCFailChannelUpdate::ChannelClosed { ref short_channel_id, is_permanent:_ } => {
353+
//XXX
353354
let mut network = self.network_map.write().unwrap();
354355
if let Some(chan) = network.channels.remove(short_channel_id) {
355356
Self::remove_channel_in_nodes(&mut network.nodes, &chan, *short_channel_id);
356357
}
357358
},
359+
&msgs::HTLCFailChannelUpdate::NodeFailure { ref node_id, is_permanent:_ } => {
360+
//XXX
361+
//let mut network = self.network_map.write().unwrap();
362+
//TODO: check _blamed_upstream_node
363+
self.mark_node_bad(node_id, false);
364+
},
358365
}
359366
}
360367

src/util/events.rs

Lines changed: 12 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -75,6 +75,10 @@ pub enum Event {
7575
PaymentFailed {
7676
/// The hash which was given to ChannelManager::send_payment.
7777
payment_hash: [u8; 32],
78+
/// Indicates the payment was rejected for some reason by the recipient. This implies that
79+
/// the payment has failed, not just the route in question. If this is not set, you may
80+
/// retry the payment via a different route.
81+
rejected_by_dest: bool,
7882
},
7983
/// Used to indicate that ChannelManager::process_pending_htlc_forwards should be called at a
8084
/// time in the future.
@@ -161,6 +165,14 @@ pub enum Event {
161165
node_id: PublicKey,
162166
/// The action which should be taken.
163167
action: Option<msgs::ErrorAction>
168+
},
169+
/// When a payment fails we may receive updates back from the hop where it failed. In such
170+
/// cases this event is generated so that we can inform the router of this information.
171+
///
172+
/// This event is handled by PeerManager::process_events if you are using a PeerManager.
173+
PaymentFailureNetworkUpdate {
174+
/// The channel/node update which should be sent to router
175+
update: msgs::HTLCFailChannelUpdate,
164176
}
165177
}
166178

src/util/test_utils.rs

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -110,7 +110,7 @@ impl msgs::ChannelMessageHandler for TestChannelMessageHandler {
110110
fn handle_update_fulfill_htlc(&self, _their_node_id: &PublicKey, _msg: &msgs::UpdateFulfillHTLC) -> Result<(), HandleError> {
111111
Err(HandleError { err: "", action: None })
112112
}
113-
fn handle_update_fail_htlc(&self, _their_node_id: &PublicKey, _msg: &msgs::UpdateFailHTLC) -> Result<Option<msgs::HTLCFailChannelUpdate>, HandleError> {
113+
fn handle_update_fail_htlc(&self, _their_node_id: &PublicKey, _msg: &msgs::UpdateFailHTLC) -> Result<(), HandleError> {
114114
Err(HandleError { err: "", action: None })
115115
}
116116
fn handle_update_fail_malformed_htlc(&self, _their_node_id: &PublicKey, _msg: &msgs::UpdateFailMalformedHTLC) -> Result<(), HandleError> {

0 commit comments

Comments
 (0)