Skip to content

Commit a8ea0bd

Browse files
Limit OnionMessenger outbound buffer size
Drop OMs if they push us over the max OnionMessenger outbound buffer size
1 parent 04f4673 commit a8ea0bd

File tree

2 files changed

+41
-0
lines changed

2 files changed

+41
-0
lines changed

lightning/src/onion_message/functional_tests.rs

+10
Original file line numberDiff line numberDiff line change
@@ -170,3 +170,13 @@ fn reply_path() {
170170
"lightning::onion_message::messenger".to_string(),
171171
format!("Received an onion message with path_id: None and reply_path").to_string(), 2);
172172
}
173+
174+
#[test]
175+
fn peer_buffer_full() {
176+
let nodes = create_nodes(2);
177+
for _ in 0..188 { // Based on MAX_PER_PEER_BUFFER_SIZE in OnionMessenger
178+
nodes[0].messenger.send_onion_message(&[], Destination::Node(nodes[1].get_node_pk()), None).unwrap();
179+
}
180+
let err = nodes[0].messenger.send_onion_message(&[], Destination::Node(nodes[1].get_node_pk()), None).unwrap_err();
181+
assert_eq!(err, SendError::BufferFull);
182+
}

lightning/src/onion_message/messenger.rs

+31
Original file line numberDiff line numberDiff line change
@@ -23,6 +23,7 @@ use super::packet::{BIG_PACKET_HOP_DATA_LEN, ForwardControlTlvs, Packet, Payload
2323
use super::utils;
2424
use util::events::OnionMessageProvider;
2525
use util::logger::Logger;
26+
use util::ser::Writeable;
2627

2728
use core::ops::Deref;
2829
use sync::{Arc, Mutex};
@@ -124,6 +125,8 @@ pub enum SendError {
124125
TooFewBlindedHops,
125126
/// Our next-hop peer was offline or does not support onion message forwarding.
126127
InvalidFirstHop,
128+
/// Our next-hop peer's buffer was full or our total outbound buffer was full.
129+
BufferFull,
127130
}
128131

129132
impl<Signer: Sign, K: Deref, L: Deref> OnionMessenger<Signer, K, L>
@@ -171,6 +174,7 @@ impl<Signer: Sign, K: Deref, L: Deref> OnionMessenger<Signer, K, L>
171174
packet_payloads, packet_keys, prng_seed).map_err(|()| SendError::TooBigPacket)?;
172175

173176
let mut pending_per_peer_msgs = self.pending_messages.lock().unwrap();
177+
if outbound_buffer_full(&introduction_node_id, &pending_per_peer_msgs) { return Err(SendError::BufferFull) }
174178
match pending_per_peer_msgs.entry(introduction_node_id) {
175179
hash_map::Entry::Vacant(_) => Err(SendError::InvalidFirstHop),
176180
hash_map::Entry::Occupied(mut e) => {
@@ -193,6 +197,29 @@ impl<Signer: Sign, K: Deref, L: Deref> OnionMessenger<Signer, K, L>
193197
}
194198
}
195199

200+
fn outbound_buffer_full(peer_node_id: &PublicKey, buffer: &HashMap<PublicKey, VecDeque<msgs::OnionMessage>>) -> bool {
201+
const MAX_TOTAL_BUFFER_SIZE: usize = (1 << 20) * 128;
202+
const MAX_PER_PEER_BUFFER_SIZE: usize = (1 << 10) * 256;
203+
let mut total_buffered_bytes = 0;
204+
let mut peer_buffered_bytes = 0;
205+
for (pk, peer_buf) in buffer {
206+
for om in peer_buf {
207+
let om_len = om.serialized_length();
208+
if pk == peer_node_id {
209+
peer_buffered_bytes += om_len;
210+
}
211+
total_buffered_bytes += om_len;
212+
213+
if total_buffered_bytes >= MAX_TOTAL_BUFFER_SIZE ||
214+
peer_buffered_bytes >= MAX_PER_PEER_BUFFER_SIZE
215+
{
216+
return true
217+
}
218+
}
219+
}
220+
false
221+
}
222+
196223
impl<Signer: Sign, K: Deref, L: Deref> OnionMessageHandler for OnionMessenger<Signer, K, L>
197224
where K::Target: KeysInterface<Signer = Signer>,
198225
L::Target: Logger,
@@ -279,6 +306,10 @@ impl<Signer: Sign, K: Deref, L: Deref> OnionMessageHandler for OnionMessenger<Si
279306
};
280307

281308
let mut pending_per_peer_msgs = self.pending_messages.lock().unwrap();
309+
if outbound_buffer_full(&next_node_id, &pending_per_peer_msgs) {
310+
log_trace!(self.logger, "Dropping forwarded onion message to peer {:?}: outbound buffer full", next_node_id);
311+
return
312+
}
282313

283314
#[cfg(fuzzing)]
284315
pending_per_peer_msgs.entry(next_node_id).or_insert_with(VecDeque::new);

0 commit comments

Comments
 (0)