Skip to content

Commit f32d1ea

Browse files
author
Antoine Riard
committed
Implement DisconnectPeer and HandleOutboundMsgGenerationError events
Add test for DisconnectPeer event Update DisconnectPeer with optional ErrorMessage Manage error for funding_transaction_generated Add disconnect_socket to SocketDescriptor trait
1 parent fdfe483 commit f32d1ea

File tree

8 files changed

+261
-28
lines changed

8 files changed

+261
-28
lines changed

fuzz/fuzz_targets/full_stack_target.rs

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -107,12 +107,16 @@ impl BroadcasterInterface for TestBroadcaster {
107107
#[derive(Clone, PartialEq, Eq, Hash)]
108108
struct Peer {
109109
id: u8,
110+
connected: bool,
110111
}
111112
impl SocketDescriptor for Peer {
112113
fn send_data(&mut self, data: &Vec<u8>, write_offset: usize, _resume_read: bool) -> usize {
113114
assert!(write_offset < data.len());
114115
data.len() - write_offset
115116
}
117+
fn disconnect_socket(&mut self) {
118+
self.connected = false;
119+
}
116120
}
117121

118122
#[inline]

src/ln/channel.rs

Lines changed: 14 additions & 11 deletions
Original file line numberDiff line numberDiff line change
@@ -328,7 +328,7 @@ macro_rules! secp_call {
328328
match $res {
329329
Ok(key) => key,
330330
//TODO: make the error a parameter
331-
Err(_) => return Err(HandleError{err: $err, action: Some(msgs::ErrorAction::DisconnectPeer{})})
331+
Err(_) => return Err(HandleError{err: $err, action: Some(msgs::ErrorAction::DisconnectPeer{ msg: None })})
332332
}
333333
};
334334
}
@@ -433,10 +433,10 @@ impl Channel {
433433

434434
fn check_remote_fee(fee_estimator: &FeeEstimator, feerate_per_kw: u32) -> Result<(), HandleError> {
435435
if (feerate_per_kw as u64) < fee_estimator.get_est_sat_per_vbyte(ConfirmationTarget::Background) * 250 {
436-
return Err(HandleError{err: "Peer's feerate much too low", action: Some(msgs::ErrorAction::DisconnectPeer{})});
436+
return Err(HandleError{err: "Peer's feerate much too low", action: Some(msgs::ErrorAction::DisconnectPeer{ msg: None })});
437437
}
438438
if (feerate_per_kw as u64) > fee_estimator.get_est_sat_per_vbyte(ConfirmationTarget::HighPriority) * 375 { // 375 = 250 * 1.5x
439-
return Err(HandleError{err: "Peer's feerate much too high", action: Some(msgs::ErrorAction::DisconnectPeer{})});
439+
return Err(HandleError{err: "Peer's feerate much too high", action: Some(msgs::ErrorAction::DisconnectPeer{ msg: None })});
440440
}
441441
Ok(())
442442
}
@@ -448,29 +448,32 @@ impl Channel {
448448
pub fn new_from_req(fee_estimator: &FeeEstimator, chan_keys: ChannelKeys, their_node_id: PublicKey, msg: &msgs::OpenChannel, user_id: u64, announce_publicly: bool) -> Result<Channel, HandleError> {
449449
// Check sanity of message fields:
450450
if msg.funding_satoshis >= MAX_FUNDING_SATOSHIS {
451-
return Err(HandleError{err: "funding value > 2^24", action: Some(msgs::ErrorAction::DisconnectPeer{})});
451+
return Err(HandleError{err: "funding value > 2^24", action: Some(msgs::ErrorAction::DisconnectPeer{ msg: None })});
452452
}
453453
if msg.channel_reserve_satoshis > msg.funding_satoshis {
454-
return Err(HandleError{err: "Bogus channel_reserve_satoshis", action: Some(msgs::ErrorAction::DisconnectPeer{})});
454+
return Err(HandleError{err: "Bogus channel_reserve_satoshis", action: Some(msgs::ErrorAction::DisconnectPeer{ msg: None })});
455455
}
456456
if msg.push_msat > (msg.funding_satoshis - msg.channel_reserve_satoshis) * 1000 {
457-
return Err(HandleError{err: "push_msat more than highest possible value", action: Some(msgs::ErrorAction::DisconnectPeer{})});
457+
return Err(HandleError{err: "push_msat more than highest possible value", action: Some(msgs::ErrorAction::DisconnectPeer{ msg: None })});
458458
}
459459
if msg.dust_limit_satoshis > msg.funding_satoshis {
460-
return Err(HandleError{err: "Peer never wants payout outputs?", action: Some(msgs::ErrorAction::DisconnectPeer{})});
460+
return Err(HandleError{err: "Peer never wants payout outputs?", action: Some(msgs::ErrorAction::DisconnectPeer{ msg: None })});
461+
}
462+
if msg.max_htlc_value_in_flight_msat > msg.funding_satoshis * 1000 {
463+
return Err(HandleError{err: "Bogus max_htlc_value_in_flight_satoshis", action: Some(msgs::ErrorAction::DisconnectPeer{ msg: None })});
461464
}
462465
if msg.htlc_minimum_msat >= (msg.funding_satoshis - msg.channel_reserve_satoshis) * 1000 {
463-
return Err(HandleError{err: "Minimum htlc value is full channel value", action: Some(msgs::ErrorAction::DisconnectPeer{})});
466+
return Err(HandleError{err: "Minimum htlc value is full channel value", action: Some(msgs::ErrorAction::DisconnectPeer{ msg: None })});
464467
}
465468
Channel::check_remote_fee(fee_estimator, msg.feerate_per_kw)?;
466469
if msg.to_self_delay > MAX_LOCAL_BREAKDOWN_TIMEOUT {
467-
return Err(HandleError{err: "They wanted our payments to be delayed by a needlessly long period", action: Some(msgs::ErrorAction::DisconnectPeer{})});
470+
return Err(HandleError{err: "They wanted our payments to be delayed by a needlessly long period", action: Some(msgs::ErrorAction::DisconnectPeer{ msg: None })});
468471
}
469472
if msg.max_accepted_htlcs < 1 {
470-
return Err(HandleError{err: "0 max_accpted_htlcs makes for a useless channel", action: Some(msgs::ErrorAction::DisconnectPeer{})});
473+
return Err(HandleError{err: "0 max_accpted_htlcs makes for a useless channel", action: Some(msgs::ErrorAction::DisconnectPeer{ msg: None })});
471474
}
472475
if (msg.channel_flags & 254) != 0 {
473-
return Err(HandleError{err: "unknown channel_flags", action: Some(msgs::ErrorAction::DisconnectPeer{})});
476+
return Err(HandleError{err: "unknown channel_flags", action: Some(msgs::ErrorAction::DisconnectPeer{ msg: None })});
474477
}
475478

476479
// Convert things into internal flags and prep our state:

src/ln/channelmanager.rs

Lines changed: 22 additions & 10 deletions
Original file line numberDiff line numberDiff line change
@@ -676,6 +676,16 @@ impl ChannelManager {
676676
/// Call this upon creation of a funding transaction for the given channel.
677677
/// Panics if a funding transaction has already been provided for this channel.
678678
pub fn funding_transaction_generated(&self, temporary_channel_id: &[u8; 32], funding_txo: OutPoint) {
679+
680+
macro_rules! add_pending_event {
681+
($event: expr) => {
682+
{
683+
let mut pending_events = self.pending_events.lock().unwrap();
684+
pending_events.push($event);
685+
}
686+
}
687+
}
688+
679689
let (chan, msg, chan_monitor) = {
680690
let mut channel_state = self.channel_state.lock().unwrap();
681691
match channel_state.by_id.remove(temporary_channel_id) {
@@ -684,10 +694,15 @@ impl ChannelManager {
684694
Ok(funding_msg) => {
685695
(chan, funding_msg.0, funding_msg.1)
686696
},
687-
Err(_e) => {
688-
//TODO: Push e to pendingevents
697+
Err(e) => {
698+
mem::drop(channel_state);
699+
add_pending_event!(events::Event::DisconnectPeer {
700+
node_id: chan.get_their_node_id(),
701+
msg: if let Some(msgs::ErrorAction::DisconnectPeer { msg } ) = e.action { msg } else { None },
702+
});
703+
689704
return;
690-
}
705+
},
691706
}
692707
},
693708
None => return
@@ -696,13 +711,10 @@ impl ChannelManager {
696711
if let Err(_e) = self.monitor.add_update_monitor(chan_monitor.get_funding_txo().unwrap(), chan_monitor) {
697712
unimplemented!(); // maybe remove from claimable_htlcs?
698713
}
699-
{
700-
let mut pending_events = self.pending_events.lock().unwrap();
701-
pending_events.push(events::Event::SendFundingCreated {
702-
node_id: chan.get_their_node_id(),
703-
msg: msg,
704-
});
705-
}
714+
add_pending_event!(events::Event::SendFundingCreated {
715+
node_id: chan.get_their_node_id(),
716+
msg: msg,
717+
});
706718

707719
let mut channel_state = self.channel_state.lock().unwrap();
708720
channel_state.by_id.insert(chan.channel_id(), chan);

src/ln/msgs.rs

Lines changed: 3 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -377,7 +377,9 @@ pub enum ErrorAction {
377377
msg: UpdateFailHTLC
378378
},
379379
/// The peer took some action which made us think they were useless. Disconnect them.
380-
DisconnectPeer,
380+
DisconnectPeer {
381+
msg: Option<ErrorMessage>
382+
},
381383
/// The peer did something harmless that we weren't able to process, just log and ignore
382384
IgnoreError,
383385
/// The peer did something incorrect. Tell them.

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", action: Some(msgs::ErrorAction::DisconnectPeer{})});
150+
return Err(HandleError{err: "Bad MAC", action: Some(msgs::ErrorAction::DisconnectPeer{ msg: None })});
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", action: Some(msgs::ErrorAction::DisconnectPeer{})});
198+
return Err(HandleError{err: "Unknown handshake version number", action: Some(msgs::ErrorAction::DisconnectPeer{ msg: None })});
199199
}
200200

201201
let their_pub = match PublicKey::from_slice(secp_ctx, &act[1..34]) {
202-
Err(_) => return Err(HandleError{err: "Invalid public key", action: Some(msgs::ErrorAction::DisconnectPeer{})}),
202+
Err(_) => return Err(HandleError{err: "Invalid public key", action: Some(msgs::ErrorAction::DisconnectPeer{ msg: None })}),
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", action: Some(msgs::ErrorAction::DisconnectPeer{})});
352+
return Err(HandleError{err: "Unknown handshake version number", action: Some(msgs::ErrorAction::DisconnectPeer{ msg: None })});
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", action: Some(msgs::ErrorAction::DisconnectPeer{})}),
359+
Err(_) => return Err(HandleError{err: "Bad node_id from peer", action: Some(msgs::ErrorAction::DisconnectPeer{ msg: None })}),
360360
});
361361

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

src/ln/peer_handler.rs

Lines changed: 105 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -37,6 +37,12 @@ pub trait SocketDescriptor : cmp::Eq + hash::Hash + Clone {
3737
/// indicating that read events on this descriptor should resume. A resume_read of false does
3838
/// *not* imply that further read events should be paused.
3939
fn send_data(&mut self, data: &Vec<u8>, write_offset: usize, resume_read: bool) -> usize;
40+
/// Disconnect the socket pointed to by this SocketDescriptor. Once this function returns, no
41+
/// more calls to write_event, read_event or disconnect_event may be made with this descriptor.
42+
/// No disconnect_event should be generated as a result of this call, though obviously races
43+
/// may occur whereby disconnect_socket is called after a call to disconnect_event but prior to
44+
/// that event completing.
45+
fn disconnect_socket(&mut self);
4046
}
4147

4248
/// Error for PeerManager errors. If you get one of these, you must disconnect the socket and
@@ -296,7 +302,7 @@ impl<Descriptor: SocketDescriptor> PeerManager<Descriptor> {
296302
encode_and_send_msg!(msg, 131);
297303
continue;
298304
},
299-
msgs::ErrorAction::DisconnectPeer => {
305+
msgs::ErrorAction::DisconnectPeer { msg: _ } => {
300306
return Err(PeerHandleError{ no_connection_possible: false });
301307
},
302308
msgs::ErrorAction::IgnoreError => {
@@ -723,6 +729,24 @@ impl<Descriptor: SocketDescriptor> PeerManager<Descriptor> {
723729
}
724730
continue;
725731
},
732+
Event::HandleOutboundMsgGenerationError { ref node_id, ref msg } => {
733+
let (mut descriptor, peer) = get_peer_for_forwarding!(node_id, {
734+
});
735+
peer.pending_outbound_buffer.push_back(peer.channel_encryptor.encrypt_message(&encode_msg!(msg, 17)));
736+
Self::do_attempt_write_data(&mut descriptor, peer);
737+
},
738+
Event::DisconnectPeer { ref node_id, ref msg } => {
739+
if let Some(mut descriptor) = peers.node_id_to_descriptor.remove(node_id) {
740+
if let Some(mut peer) = peers.peers.remove(&descriptor) {
741+
if let Some(ref msg) = *msg {
742+
peer.pending_outbound_buffer.push_back(peer.channel_encryptor.encrypt_message(&encode_msg!(msg, 17)));
743+
Self::do_attempt_write_data(&mut descriptor, &mut peer);
744+
}
745+
}
746+
descriptor.disconnect_socket();
747+
}
748+
self.message_handler.chan_handler.peer_disconnected(&node_id, false);
749+
},
726750
}
727751

728752
upstream_events.push(event);
@@ -769,3 +793,83 @@ impl<Descriptor: SocketDescriptor> EventsProvider for PeerManager<Descriptor> {
769793
ret
770794
}
771795
}
796+
797+
#[cfg(test)]
798+
mod tests {
799+
use ln::peer_handler::{PeerManager, MessageHandler, SocketDescriptor};
800+
use util::events;
801+
use util::test_utils;
802+
803+
use secp256k1::Secp256k1;
804+
use secp256k1::key::{SecretKey, PublicKey};
805+
806+
use rand::{thread_rng, Rng};
807+
808+
use std::sync::{Arc};
809+
810+
#[derive(PartialEq, Eq, Clone, Hash)]
811+
struct FileDescriptor {
812+
fd: u16,
813+
}
814+
815+
impl SocketDescriptor for FileDescriptor {
816+
fn send_data(&mut self, data: &Vec<u8>, write_offset: usize, _resume_read: bool) -> usize {
817+
assert!(write_offset < data.len());
818+
data.len() - write_offset
819+
}
820+
821+
fn disconnect_socket(&mut self) {}
822+
}
823+
824+
fn create_network(peer_count: usize) -> Vec<PeerManager<FileDescriptor>> {
825+
let secp_ctx = Secp256k1::new();
826+
let mut peers = Vec::new();
827+
let mut rng = thread_rng();
828+
829+
for _ in 0..peer_count {
830+
let chan_handler = test_utils::TestChannelMessageHandler::new();
831+
let router = test_utils::TestRoutingMessageHandler::new();
832+
let node_id = {
833+
let mut key_slice = [0;32];
834+
rng.fill_bytes(&mut key_slice);
835+
SecretKey::from_slice(&secp_ctx, &key_slice).unwrap()
836+
};
837+
let msg_handler = MessageHandler { chan_handler: Arc::new(chan_handler), route_handler: Arc::new(router) };
838+
let peer = PeerManager::new(msg_handler, node_id);
839+
peers.push(peer);
840+
}
841+
842+
peers
843+
}
844+
845+
fn establish_connection(peer_a: &PeerManager<FileDescriptor>, peer_b: &PeerManager<FileDescriptor>) {
846+
let secp_ctx = Secp256k1::new();
847+
let their_id = PublicKey::from_secret_key(&secp_ctx, &peer_b.our_node_secret).unwrap();
848+
let fd = FileDescriptor { fd: 1};
849+
peer_a.new_inbound_connection(fd.clone()).unwrap();
850+
peer_a.peers.lock().unwrap().node_id_to_descriptor.insert(their_id, fd.clone());
851+
}
852+
853+
#[test]
854+
fn test_disconnect_peer() {
855+
// Simple test which builds a network of PeerManager, connects and brings them to NoiseState::Finished and
856+
// push an DisconnectPeer event to remove the node flagged by id
857+
let mut peers = create_network(2);
858+
establish_connection(&peers[0], &peers[1]);
859+
assert_eq!(peers[0].peers.lock().unwrap().peers.len(), 1);
860+
861+
let secp_ctx = Secp256k1::new();
862+
let their_id = PublicKey::from_secret_key(&secp_ctx, &peers[1].our_node_secret).unwrap();
863+
864+
let chan_handler = test_utils::TestChannelMessageHandler::new();
865+
chan_handler.pending_events.lock().unwrap().push(events::Event::DisconnectPeer {
866+
node_id: their_id,
867+
msg: None,
868+
});
869+
assert_eq!(chan_handler.pending_events.lock().unwrap().len(), 1);
870+
peers[0].message_handler.chan_handler = Arc::new(chan_handler);
871+
872+
peers[0].process_events();
873+
assert_eq!(peers[0].peers.lock().unwrap().peers.len(), 0);
874+
}
875+
}

src/util/events.rs

Lines changed: 10 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -99,6 +99,16 @@ pub enum Event {
9999
BroadcastChannelUpdate {
100100
msg: msgs::ChannelUpdate,
101101
},
102+
/// Used to tell a peer that something is incorrect
103+
HandleOutboundMsgGenerationError {
104+
node_id: PublicKey,
105+
msg: msgs::ErrorMessage,
106+
},
107+
// Events indicating the network loop should change the state of connection with peer
108+
DisconnectPeer {
109+
node_id: PublicKey,
110+
msg: Option<msgs::ErrorMessage>,
111+
}
102112
}
103113

104114
pub trait EventsProvider {

0 commit comments

Comments
 (0)