Skip to content

Commit a610437

Browse files
committed
Avoid re-allocating to encrypt gossip messages when forwarding
When we forward gossip messages, we store them in a separate buffer before we encrypt them (and commit to the order in which they'll appear on the wire). Rather than storing that buffer encoded with no headroom, requiring re-allocating to add the message length and two MAC blocks, we here add the headroom prior to pushing it into the gossip buffer, avoiding an allocation.
1 parent 03f81ff commit a610437

File tree

2 files changed

+41
-43
lines changed

2 files changed

+41
-43
lines changed

lightning/src/ln/peer_channel_encryptor.rs

Lines changed: 34 additions & 36 deletions
Original file line numberDiff line numberDiff line change
@@ -427,16 +427,12 @@ impl PeerChannelEncryptor {
427427
Ok(self.their_node_id.unwrap().clone())
428428
}
429429

430-
/// Encrypts the given pre-serialized message, returning the encrypted version.
431-
/// panics if msg.len() > 65535 or Noise handshake has not finished.
432-
pub fn encrypt_buffer(&mut self, msg: &[u8]) -> Vec<u8> {
433-
if msg.len() > LN_MAX_MSG_LEN {
430+
fn encrypt_message_with_header_0s(&mut self, msgbuf: &mut Vec<u8>) {
431+
let msg_len = msgbuf.len() - 16 - 2;
432+
if msg_len > LN_MAX_MSG_LEN {
434433
panic!("Attempted to encrypt message longer than 65535 bytes!");
435434
}
436435

437-
let mut res = Vec::with_capacity(msg.len() + 16*2 + 2);
438-
res.resize(msg.len() + 16*2 + 2, 0);
439-
440436
match self.noise_state {
441437
NoiseState::Finished { ref mut sk, ref mut sn, ref mut sck, rk: _, rn: _, rck: _ } => {
442438
if *sn >= 1000 {
@@ -446,16 +442,21 @@ impl PeerChannelEncryptor {
446442
*sn = 0;
447443
}
448444

449-
Self::encrypt_with_ad(&mut res[0..16+2], *sn, sk, &[0; 0], &(msg.len() as u16).to_be_bytes());
445+
Self::encrypt_with_ad(&mut msgbuf[0..16+2], *sn, sk, &[0; 0], &(msg_len as u16).to_be_bytes());
450446
*sn += 1;
451447

452-
Self::encrypt_with_ad(&mut res[16+2..], *sn, sk, &[0; 0], msg);
448+
Self::encrypt_in_place_with_ad(msgbuf, 16+2, *sn, sk, &[0; 0]);
453449
*sn += 1;
454450
},
455451
_ => panic!("Tried to encrypt a message prior to noise handshake completion"),
456452
}
453+
}
457454

458-
res
455+
/// Encrypts the given pre-serialized message, returning the encrypted version.
456+
/// panics if msg.len() > 65535 or Noise handshake has not finished.
457+
pub fn encrypt_buffer(&mut self, mut msg: MessageBuf) -> Vec<u8> {
458+
self.encrypt_message_with_header_0s(&mut msg.0);
459+
msg.0
459460
}
460461

461462
/// Encrypts the given message, returning the encrypted version.
@@ -468,29 +469,7 @@ impl PeerChannelEncryptor {
468469
res.0.resize(16 + 2, 0);
469470
wire::write(message, &mut res).expect("In-memory messages must never fail to serialize");
470471

471-
let msg_len = res.0.len() - 16 - 2;
472-
if msg_len > LN_MAX_MSG_LEN {
473-
panic!("Attempted to encrypt message longer than 65535 bytes!");
474-
}
475-
476-
match self.noise_state {
477-
NoiseState::Finished { ref mut sk, ref mut sn, ref mut sck, rk: _, rn: _, rck: _ } => {
478-
if *sn >= 1000 {
479-
let (new_sck, new_sk) = hkdf_extract_expand_twice(sck, sk);
480-
*sck = new_sck;
481-
*sk = new_sk;
482-
*sn = 0;
483-
}
484-
485-
Self::encrypt_with_ad(&mut res.0[0..16+2], *sn, sk, &[0; 0], &(msg_len as u16).to_be_bytes());
486-
*sn += 1;
487-
488-
Self::encrypt_in_place_with_ad(&mut res.0, 16+2, *sn, sk, &[0; 0]);
489-
*sn += 1;
490-
},
491-
_ => panic!("Tried to encrypt a message prior to noise handshake completion"),
492-
}
493-
472+
self.encrypt_message_with_header_0s(&mut res.0);
494473
res.0
495474
}
496475

@@ -557,9 +536,28 @@ impl PeerChannelEncryptor {
557536
}
558537
}
559538

539+
/// A buffer which stores an encoded message with some padding to allow for future
540+
/// encryption/MACing
541+
pub struct MessageBuf(Vec<u8>);
542+
impl MessageBuf {
543+
/// Creates a new buffer from an encoded message (i.e. the two message-type bytes followed by
544+
/// the message contents).
545+
///
546+
/// Panics if the message is longer than 2^16.
547+
pub fn from_encoded(encoded_msg: &[u8]) -> Self {
548+
if encoded_msg.len() > LN_MAX_MSG_LEN {
549+
panic!("Attempted to encrypt message longer than 65535 bytes!");
550+
}
551+
let mut res = Vec::with_capacity(encoded_msg.len() + 16*2 + 2);
552+
res.resize(encoded_msg.len() + 16 + 2, 0);
553+
res[16 + 2..].copy_from_slice(&encoded_msg);
554+
Self(res)
555+
}
556+
}
557+
560558
#[cfg(test)]
561559
mod tests {
562-
use super::LN_MAX_MSG_LEN;
560+
use super::{MessageBuf, LN_MAX_MSG_LEN};
563561

564562
use bitcoin::secp256k1::{PublicKey, SecretKey};
565563
use bitcoin::secp256k1::Secp256k1;
@@ -775,7 +773,7 @@ mod tests {
775773

776774
for i in 0..1005 {
777775
let msg = [0x68, 0x65, 0x6c, 0x6c, 0x6f];
778-
let mut res = outbound_peer.encrypt_buffer(&msg);
776+
let mut res = outbound_peer.encrypt_buffer(MessageBuf::from_encoded(&msg));
779777
assert_eq!(res.len(), 5 + 2*16 + 2);
780778

781779
let len_header = res[0..2+16].to_vec();
@@ -811,7 +809,7 @@ mod tests {
811809
fn max_message_len_encryption() {
812810
let mut outbound_peer = get_outbound_peer_for_initiator_test_vectors();
813811
let msg = [4u8; LN_MAX_MSG_LEN + 1];
814-
outbound_peer.encrypt_buffer(&msg);
812+
outbound_peer.encrypt_buffer(MessageBuf::from_encoded(&msg));
815813
}
816814

817815
#[test]

lightning/src/ln/peer_handler.rs

Lines changed: 7 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -27,7 +27,7 @@ use crate::ln::msgs::{ChannelMessageHandler, LightningError, SocketAddress, Onio
2727
#[cfg(not(c_bindings))]
2828
use crate::ln::channelmanager::{SimpleArcChannelManager, SimpleRefChannelManager};
2929
use crate::util::ser::{VecWriter, Writeable, Writer};
30-
use crate::ln::peer_channel_encryptor::{PeerChannelEncryptor, NextNoiseStep, MSG_BUF_ALLOC_SIZE};
30+
use crate::ln::peer_channel_encryptor::{PeerChannelEncryptor, NextNoiseStep, MessageBuf, MSG_BUF_ALLOC_SIZE};
3131
use crate::ln::wire;
3232
use crate::ln::wire::{Encode, Type};
3333
#[cfg(not(c_bindings))]
@@ -495,7 +495,7 @@ struct Peer {
495495
/// prioritize channel messages over them.
496496
///
497497
/// Note that these messages are *not* encrypted/MAC'd, and are only serialized.
498-
gossip_broadcast_buffer: VecDeque<Vec<u8>>,
498+
gossip_broadcast_buffer: VecDeque<MessageBuf>,
499499
awaiting_write_event: bool,
500500

501501
pending_read_buffer: Vec<u8>,
@@ -1102,7 +1102,7 @@ impl<Descriptor: SocketDescriptor, CM: Deref, RM: Deref, OM: Deref, L: Deref, CM
11021102
}
11031103
if peer.should_buffer_gossip_broadcast() {
11041104
if let Some(msg) = peer.gossip_broadcast_buffer.pop_front() {
1105-
peer.pending_outbound_buffer.push_back(peer.channel_encryptor.encrypt_buffer(&msg[..]));
1105+
peer.pending_outbound_buffer.push_back(peer.channel_encryptor.encrypt_buffer(msg));
11061106
}
11071107
}
11081108
if peer.should_buffer_gossip_backfill() {
@@ -1252,7 +1252,7 @@ impl<Descriptor: SocketDescriptor, CM: Deref, RM: Deref, OM: Deref, L: Deref, CM
12521252
}
12531253

12541254
/// Append a message to a peer's pending outbound/write gossip broadcast buffer
1255-
fn enqueue_encoded_gossip_broadcast(&self, peer: &mut Peer, encoded_message: Vec<u8>) {
1255+
fn enqueue_encoded_gossip_broadcast(&self, peer: &mut Peer, encoded_message: MessageBuf) {
12561256
peer.msgs_sent_since_pong += 1;
12571257
debug_assert!(peer.gossip_broadcast_buffer.len() <= OUTBOUND_BUFFER_LIMIT_DROP_GOSSIP);
12581258
peer.gossip_broadcast_buffer.push_back(encoded_message);
@@ -1801,7 +1801,7 @@ impl<Descriptor: SocketDescriptor, CM: Deref, RM: Deref, OM: Deref, L: Deref, CM
18011801
if except_node.is_some() && peer.their_node_id.as_ref().map(|(pk, _)| pk) == except_node {
18021802
continue;
18031803
}
1804-
self.enqueue_encoded_gossip_broadcast(&mut *peer, encoded_msg.clone());
1804+
self.enqueue_encoded_gossip_broadcast(&mut *peer, MessageBuf::from_encoded(&encoded_msg));
18051805
}
18061806
},
18071807
wire::Message::NodeAnnouncement(ref msg) => {
@@ -1828,7 +1828,7 @@ impl<Descriptor: SocketDescriptor, CM: Deref, RM: Deref, OM: Deref, L: Deref, CM
18281828
if except_node.is_some() && peer.their_node_id.as_ref().map(|(pk, _)| pk) == except_node {
18291829
continue;
18301830
}
1831-
self.enqueue_encoded_gossip_broadcast(&mut *peer, encoded_msg.clone());
1831+
self.enqueue_encoded_gossip_broadcast(&mut *peer, MessageBuf::from_encoded(&encoded_msg));
18321832
}
18331833
},
18341834
wire::Message::ChannelUpdate(ref msg) => {
@@ -1850,7 +1850,7 @@ impl<Descriptor: SocketDescriptor, CM: Deref, RM: Deref, OM: Deref, L: Deref, CM
18501850
if except_node.is_some() && peer.their_node_id.as_ref().map(|(pk, _)| pk) == except_node {
18511851
continue;
18521852
}
1853-
self.enqueue_encoded_gossip_broadcast(&mut *peer, encoded_msg.clone());
1853+
self.enqueue_encoded_gossip_broadcast(&mut *peer, MessageBuf::from_encoded(&encoded_msg));
18541854
}
18551855
},
18561856
_ => debug_assert!(false, "We shouldn't attempt to forward anything but gossip messages"),

0 commit comments

Comments
 (0)