Skip to content

Commit 69eb59b

Browse files
authored
Merge pull request #19 from TheBlueMatt/2018-04-error-handling-framework
Clean up peer_handler error handling a bit, clean up channel error handling a ton
2 parents 24fd566 + 9ccfb35 commit 69eb59b

File tree

7 files changed

+220
-140
lines changed

7 files changed

+220
-140
lines changed

fuzz/travis-fuzz.sh

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,6 @@
11
#!/bin/bash
2-
cargo install honggfuzz
3-
set +e
2+
set -e
3+
cargo install --force honggfuzz
44
for TARGET in fuzz_targets/*; do
55
FILENAME=$(basename $TARGET)
66
FILE="${FILENAME%.*}"

src/ln/chan_utils.rs

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -230,6 +230,6 @@ pub fn get_htlc_redeemscript_with_explicit_keys(htlc: &HTLCOutputInCommitment, a
230230
/// note here that 'a_revocation_key' is generated using b_revocation_basepoint and a's
231231
/// commitment secret. 'htlc' does *not* need to have its previous_output_index filled.
232232
#[inline]
233-
pub fn get_htlc_redeemscript(htlc: &HTLCOutputInCommitment, keys: &TxCreationKeys, offered: bool) -> Script {
234-
get_htlc_redeemscript_with_explicit_keys(htlc, &keys.a_htlc_key, &keys.b_htlc_key, &keys.revocation_key, offered)
233+
pub fn get_htlc_redeemscript(htlc: &HTLCOutputInCommitment, keys: &TxCreationKeys) -> Script {
234+
get_htlc_redeemscript_with_explicit_keys(htlc, &keys.a_htlc_key, &keys.b_htlc_key, &keys.revocation_key, htlc.offered)
235235
}

src/ln/channel.rs

Lines changed: 79 additions & 78 deletions
Large diffs are not rendered by default.

src/ln/channelmanager.rs

Lines changed: 32 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1121,7 +1121,7 @@ impl ChannelMessageHandler for ChannelManager {
11211121
($msg: expr, $err_code: expr, $data: expr) => {
11221122
return Err(msgs::HandleError {
11231123
err: $msg,
1124-
msg: Some(msgs::ErrorMessage::UpdateFailHTLC {
1124+
msg: Some(msgs::ErrorAction::UpdateFailHTLC {
11251125
msg: msgs::UpdateFailHTLC {
11261126
channel_id: msg.channel_id,
11271127
htlc_id: msg.htlc_id,
@@ -1481,6 +1481,37 @@ impl ChannelMessageHandler for ChannelManager {
14811481
pending_events.push(events::Event::BroadcastChannelAnnouncement { msg: chan_announcement, update_msg: chan_update });
14821482
Ok(())
14831483
}
1484+
1485+
fn peer_disconnected(&self, their_node_id: &PublicKey, no_connection_possible: bool) {
1486+
let mut channel_state_lock = self.channel_state.lock().unwrap();
1487+
let channel_state = channel_state_lock.borrow_parts();
1488+
let short_to_id = channel_state.short_to_id;
1489+
if no_connection_possible {
1490+
channel_state.by_id.retain(move |_, chan| {
1491+
if chan.get_their_node_id() == *their_node_id {
1492+
match chan.get_short_channel_id() {
1493+
Some(short_id) => {
1494+
short_to_id.remove(&short_id);
1495+
},
1496+
None => {},
1497+
}
1498+
//TODO: get the latest commitment tx, any HTLC txn built on top of it, etc out
1499+
//of the channel and throw those into the announcement blackhole.
1500+
false
1501+
} else {
1502+
true
1503+
}
1504+
});
1505+
} else {
1506+
for chan in channel_state.by_id {
1507+
if chan.1.get_their_node_id() == *their_node_id {
1508+
//TODO: mark channel disabled (and maybe announce such after a timeout). Also
1509+
//fail and wipe any uncommitted outbound HTLCs as those are considered after
1510+
//reconnect.
1511+
}
1512+
}
1513+
}
1514+
}
14841515
}
14851516

14861517
#[cfg(test)]

src/ln/msgs.rs

Lines changed: 12 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -342,16 +342,19 @@ pub struct ChannelUpdate {
342342
}
343343

344344
/// Used to put an error message in a HandleError
345-
pub enum ErrorMessage {
345+
pub enum ErrorAction {
346+
/// Indicates an inbound HTLC add resulted in a failure, and the UpdateFailHTLC provided in msg
347+
/// should be sent back to the sender.
346348
UpdateFailHTLC {
347349
msg: UpdateFailHTLC
348350
},
351+
/// The peer took some action which made us think they were useless. Disconnect them.
349352
DisconnectPeer {},
350353
}
351354

352355
pub struct HandleError { //TODO: rename me
353356
pub err: &'static str,
354-
pub msg: Option<ErrorMessage>, //TODO: Move into an Action enum and require it!
357+
pub msg: Option<ErrorAction>, //TODO: Make this required and rename it
355358
}
356359

357360
/// A trait to describe an object which can receive channel messages. Messages MAY be called in
@@ -381,6 +384,13 @@ pub trait ChannelMessageHandler : events::EventsProvider {
381384

382385
// Channel-to-announce:
383386
fn handle_announcement_signatures(&self, their_node_id: &PublicKey, msg: &AnnouncementSignatures) -> Result<(), HandleError>;
387+
388+
// Informational:
389+
/// Indicates a connection to the peer failed/an existing connection was lost. If no connection
390+
/// is believed to be possible in the future (eg they're sending us messages we don't
391+
/// understand or indicate they require unknown feature bits), no_connection_possible is set
392+
/// and any outstanding channels should be failed.
393+
fn peer_disconnected(&self, their_node_id: &PublicKey, no_connection_possible: bool);
384394
}
385395

386396
pub trait RoutingMessageHandler {

src/ln/peer_channel_encryptor.rs

Lines changed: 5 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -147,7 +147,7 @@ impl PeerChannelEncryptor {
147147

148148
let mut chacha = ChaCha20Poly1305RFC::new(key, &nonce, h);
149149
if !chacha.decrypt(&cyphertext[0..cyphertext.len() - 16], res, &cyphertext[cyphertext.len() - 16..]) {
150-
return Err(HandleError{err: "Bad MAC", msg: Some(msgs::ErrorMessage::DisconnectPeer{})});
150+
return Err(HandleError{err: "Bad MAC", msg: Some(msgs::ErrorAction::DisconnectPeer{})});
151151
}
152152
Ok(())
153153
}
@@ -195,11 +195,11 @@ impl PeerChannelEncryptor {
195195
assert_eq!(act.len(), 50);
196196

197197
if act[0] != 0 {
198-
return Err(HandleError{err: "Unknown handshake version number", msg: Some(msgs::ErrorMessage::DisconnectPeer{})});
198+
return Err(HandleError{err: "Unknown handshake version number", msg: Some(msgs::ErrorAction::DisconnectPeer{})});
199199
}
200200

201201
let their_pub = match PublicKey::from_slice(secp_ctx, &act[1..34]) {
202-
Err(_) => return Err(HandleError{err: "Invalid public key", msg: Some(msgs::ErrorMessage::DisconnectPeer{})}),
202+
Err(_) => return Err(HandleError{err: "Invalid public key", msg: Some(msgs::ErrorAction::DisconnectPeer{})}),
203203
Ok(key) => key,
204204
};
205205

@@ -349,14 +349,14 @@ impl PeerChannelEncryptor {
349349
panic!("Requested act at wrong step");
350350
}
351351
if act_three[0] != 0 {
352-
return Err(HandleError{err: "Unknown handshake version number", msg: Some(msgs::ErrorMessage::DisconnectPeer{})});
352+
return Err(HandleError{err: "Unknown handshake version number", msg: Some(msgs::ErrorAction::DisconnectPeer{})});
353353
}
354354

355355
let mut their_node_id = [0; 33];
356356
PeerChannelEncryptor::decrypt_with_ad(&mut their_node_id, 1, &temp_k2.unwrap(), &bidirectional_state.h, &act_three[1..50])?;
357357
self.their_node_id = Some(match PublicKey::from_slice(&self.secp_ctx, &their_node_id) {
358358
Ok(key) => key,
359-
Err(_) => return Err(HandleError{err: "Bad node_id from peer", msg: Some(msgs::ErrorMessage::DisconnectPeer{})}),
359+
Err(_) => return Err(HandleError{err: "Bad node_id from peer", msg: Some(msgs::ErrorAction::DisconnectPeer{})}),
360360
});
361361

362362
let mut sha = Sha256::new();

src/ln/peer_handler.rs

Lines changed: 88 additions & 50 deletions
Original file line numberDiff line numberDiff line change
@@ -40,16 +40,21 @@ pub trait SocketDescriptor : cmp::Eq + hash::Hash + Clone {
4040
/// generate no further read/write_events for the descriptor, only triggering a single
4141
/// disconnect_event (unless it was provided in response to a new_*_connection event, in which case
4242
/// no such disconnect_event must be generated and the socket be silently disconencted).
43-
pub struct PeerHandleError {}
43+
pub struct PeerHandleError {
44+
no_connection_possible: bool,
45+
}
4446
impl fmt::Debug for PeerHandleError {
4547
fn fmt(&self, formatter: &mut fmt::Formatter) -> Result<(), fmt::Error> {
46-
formatter.write_str("Peer Send Invalid Data")
48+
formatter.write_str("Peer Sent Invalid Data")
4749
}
4850
}
4951

5052
struct Peer {
5153
channel_encryptor: PeerChannelEncryptor,
54+
outbound: bool,
5255
their_node_id: Option<PublicKey>,
56+
their_global_features: Option<msgs::GlobalFeatures>,
57+
their_local_features: Option<msgs::LocalFeatures>,
5358

5459
pending_outbound_buffer: LinkedList<Vec<u8>>,
5560
pending_outbound_buffer_first_msg_offset: usize,
@@ -112,7 +117,10 @@ impl<Descriptor: SocketDescriptor> PeerManager<Descriptor> {
112117
let mut peers = self.peers.lock().unwrap();
113118
if peers.peers.insert(descriptor, Peer {
114119
channel_encryptor: peer_encryptor,
120+
outbound: true,
115121
their_node_id: Some(their_node_id),
122+
their_global_features: None,
123+
their_local_features: None,
116124

117125
pending_outbound_buffer: LinkedList::new(),
118126
pending_outbound_buffer_first_msg_offset: 0,
@@ -141,7 +149,10 @@ impl<Descriptor: SocketDescriptor> PeerManager<Descriptor> {
141149
let mut peers = self.peers.lock().unwrap();
142150
if peers.peers.insert(descriptor, Peer {
143151
channel_encryptor: peer_encryptor,
152+
outbound: false,
144153
their_node_id: None,
154+
their_global_features: None,
155+
their_local_features: None,
145156

146157
pending_outbound_buffer: LinkedList::new(),
147158
pending_outbound_buffer_first_msg_offset: 0,
@@ -212,7 +223,7 @@ impl<Descriptor: SocketDescriptor> PeerManager<Descriptor> {
212223
match self.do_read_event(peer_descriptor, data) {
213224
Ok(res) => Ok(res),
214225
Err(e) => {
215-
self.disconnect_event(peer_descriptor);
226+
self.disconnect_event_internal(peer_descriptor, e.no_connection_possible);
216227
Err(e)
217228
}
218229
}
@@ -227,38 +238,7 @@ impl<Descriptor: SocketDescriptor> PeerManager<Descriptor> {
227238
assert!(peer.pending_read_buffer.len() > 0);
228239
assert!(peer.pending_read_buffer.len() > peer.pending_read_buffer_pos);
229240

230-
macro_rules! try_potential_handleerror {
231-
($thing: expr) => {
232-
match $thing {
233-
Ok(x) => x,
234-
Err(_e) => {
235-
//TODO: Handle e appropriately!
236-
return Err(PeerHandleError{});
237-
}
238-
};
239-
}
240-
}
241-
242-
macro_rules! try_potential_decodeerror {
243-
($thing: expr) => {
244-
match $thing {
245-
Ok(x) => x,
246-
Err(_e) => {
247-
//TODO: Handle e?
248-
return Err(PeerHandleError{});
249-
}
250-
};
251-
}
252-
}
253-
254-
macro_rules! encode_and_send_msg {
255-
($msg: expr, $msg_code: expr) => {
256-
peer.pending_outbound_buffer.push_back(peer.channel_encryptor.encrypt_message(&encode_msg!($msg, $msg_code)[..]));
257-
}
258-
}
259-
260241
let mut insert_node_id = None;
261-
262242
let mut read_pos = 0;
263243
while read_pos < data.len() {
264244
{
@@ -267,7 +247,52 @@ impl<Descriptor: SocketDescriptor> PeerManager<Descriptor> {
267247
read_pos += data_to_copy;
268248
peer.pending_read_buffer_pos += data_to_copy;
269249
}
250+
270251
if peer.pending_read_buffer_pos == peer.pending_read_buffer.len() {
252+
peer.pending_read_buffer_pos = 0;
253+
254+
macro_rules! encode_and_send_msg {
255+
($msg: expr, $msg_code: expr) => {
256+
peer.pending_outbound_buffer.push_back(peer.channel_encryptor.encrypt_message(&encode_msg!($msg, $msg_code)[..]));
257+
}
258+
}
259+
260+
macro_rules! try_potential_handleerror {
261+
($thing: expr) => {
262+
match $thing {
263+
Ok(x) => x,
264+
Err(e) => {
265+
// TODO: Log e.err
266+
if let Some(action) = e.msg {
267+
match action {
268+
msgs::ErrorAction::UpdateFailHTLC { msg } => {
269+
encode_and_send_msg!(msg, 131);
270+
continue;
271+
},
272+
msgs::ErrorAction::DisconnectPeer {} => {
273+
return Err(PeerHandleError{ no_connection_possible: false });
274+
},
275+
}
276+
} else {
277+
return Err(PeerHandleError{ no_connection_possible: false });
278+
}
279+
}
280+
};
281+
}
282+
}
283+
284+
macro_rules! try_potential_decodeerror {
285+
($thing: expr) => {
286+
match $thing {
287+
Ok(x) => x,
288+
Err(_e) => {
289+
//TODO: Handle e?
290+
return Err(PeerHandleError{ no_connection_possible: false });
291+
}
292+
};
293+
}
294+
}
295+
271296
let next_step = peer.channel_encryptor.get_noise_step();
272297
match next_step {
273298
NextNoiseStep::ActOne => {
@@ -300,27 +325,41 @@ impl<Descriptor: SocketDescriptor> PeerManager<Descriptor> {
300325
peer.pending_read_buffer = Vec::with_capacity(msg_len as usize + 16);
301326
peer.pending_read_buffer.resize(msg_len as usize + 16, 0);
302327
if msg_len < 2 { // Need at least the message type tag
303-
return Err(PeerHandleError{});
328+
return Err(PeerHandleError{ no_connection_possible: false });
304329
}
305330
peer.pending_read_is_header = false;
306331
} else {
307332
let msg_data = try_potential_handleerror!(peer.channel_encryptor.decrypt_message(&peer.pending_read_buffer[..]));
308333
assert!(msg_data.len() >= 2);
309334

335+
// Reset read buffer
336+
peer.pending_read_buffer = [0; 18].to_vec();
337+
peer.pending_read_is_header = true;
338+
310339
let msg_type = byte_utils::slice_to_be16(&msg_data[0..2]);
340+
if msg_type != 16 && peer.their_global_features.is_none() {
341+
// Need an init message as first message
342+
return Err(PeerHandleError{ no_connection_possible: false });
343+
}
311344
match msg_type {
312345
// Connection control:
313346
16 => {
314347
let msg = try_potential_decodeerror!(msgs::Init::decode(&msg_data[2..]));
315348
if msg.global_features.requires_unknown_bits() {
316-
return Err(PeerHandleError{});
349+
return Err(PeerHandleError{ no_connection_possible: true });
317350
}
318351
if msg.local_features.requires_unknown_bits() {
319-
return Err(PeerHandleError{});
352+
return Err(PeerHandleError{ no_connection_possible: true });
353+
}
354+
peer.their_global_features = Some(msg.global_features);
355+
peer.their_local_features = Some(msg.local_features);
356+
357+
if !peer.outbound {
358+
encode_and_send_msg!(msgs::Init {
359+
global_features: msgs::GlobalFeatures::new(),
360+
local_features: msgs::LocalFeatures::new(),
361+
}, 16);
320362
}
321-
//TODO: Store features (and check that we've
322-
//received Init prior to any other messages)!
323-
//TODO: Respond to Init with Init if we're inbound.
324363
},
325364
17 => {
326365
// Error msg
@@ -439,18 +478,13 @@ impl<Descriptor: SocketDescriptor> PeerManager<Descriptor> {
439478
},
440479
_ => {
441480
if (msg_type & 1) == 0 {
442-
//TODO: Fail all channels. Kill the peer!
443-
return Err(PeerHandleError{});
481+
return Err(PeerHandleError{ no_connection_possible: true });
444482
}
445483
},
446484
}
447-
448-
peer.pending_read_buffer = [0; 18].to_vec();
449-
peer.pending_read_is_header = true;
450485
}
451486
}
452487
}
453-
peer.pending_read_buffer_pos = 0;
454488
}
455489
}
456490

@@ -602,18 +636,22 @@ impl<Descriptor: SocketDescriptor> PeerManager<Descriptor> {
602636
/// but must NOT be called if a PeerHandleError was provided out of a new_*_connection event!
603637
/// Panics if the descriptor was not previously registered in a successful new_*_connection event.
604638
pub fn disconnect_event(&self, descriptor: &Descriptor) {
639+
self.disconnect_event_internal(descriptor, false);
640+
}
641+
642+
fn disconnect_event_internal(&self, descriptor: &Descriptor, no_connection_possible: bool) {
605643
let mut peers = self.peers.lock().unwrap();
606644
let peer_option = peers.peers.remove(descriptor);
607645
match peer_option {
608646
None => panic!("Descriptor for disconnect_event is not already known to PeerManager"),
609647
Some(peer) => {
610648
match peer.their_node_id {
611-
Some(node_id) => { peers.node_id_to_descriptor.remove(&node_id); },
649+
Some(node_id) => {
650+
peers.node_id_to_descriptor.remove(&node_id);
651+
self.message_handler.chan_handler.peer_disconnected(&node_id, no_connection_possible);
652+
},
612653
None => {}
613654
}
614-
//TODO: Notify the chan_handler that this node disconnected, and do something about
615-
//handling response messages that were queued for sending (maybe the send buffer
616-
//needs to be unencrypted?)
617655
}
618656
};
619657
}

0 commit comments

Comments
 (0)