Skip to content

Commit dcbd225

Browse files
committed
Forward gossip messages which were verified asynchronously
Gossip messages which were verified against the chain asynchronously should still be forwarded to peers, but must now go out via a new `P2PGossipSync` parameter in the `AccessResolver::resolve` method, allowing us to wire them up to the `P2PGossipSync`'s `MessageSendEventsProvider` implementation.
1 parent 11d33fa commit dcbd225

File tree

3 files changed

+74
-7
lines changed

3 files changed

+74
-7
lines changed

fuzz/src/router.rs

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -99,12 +99,12 @@ impl<Out: test_logger::Output> ChainAccess for FuzzChainSource<'_, '_, Out> {
9999
&[1, _] => ChainAccessResult::Sync(Err(ChainAccessError::UnknownTx)),
100100
&[2, _] => {
101101
let future = AccessFuture::new();
102-
future.resolve(self.net_graph, Err(ChainAccessError::UnknownTx));
102+
future.resolve_without_forwarding(self.net_graph, Err(ChainAccessError::UnknownTx));
103103
ChainAccessResult::Async(future.clone())
104104
},
105105
&[3, _] => {
106106
let future = AccessFuture::new();
107-
future.resolve(self.net_graph, Err(ChainAccessError::UnknownTx));
107+
future.resolve_without_forwarding(self.net_graph, Err(ChainAccessError::UnknownTx));
108108
ChainAccessResult::Async(future.clone())
109109
},
110110
&[4, _] => {

lightning/src/routing/gossip.rs

Lines changed: 30 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -268,6 +268,36 @@ where C::Target: ChainAccess, L::Target: Logger
268268
false
269269
}
270270
}
271+
272+
/// Used to broadcast forward gossip messages which were validated async.
273+
///
274+
/// Note that this will ignore events other than `Broadcast*` or messages with too much excess
275+
/// data.
276+
pub(super) fn forward_gossip_msg(&self, mut ev: MessageSendEvent) {
277+
match &mut ev {
278+
MessageSendEvent::BroadcastChannelAnnouncement { msg, ref mut update_msg } => {
279+
if msg.contents.excess_data.len() > MAX_EXCESS_BYTES_FOR_RELAY { return; }
280+
if update_msg.as_ref()
281+
.map(|msg| msg.contents.excess_data.len()).unwrap_or(0) > MAX_EXCESS_BYTES_FOR_RELAY
282+
{
283+
*update_msg = None;
284+
}
285+
},
286+
MessageSendEvent::BroadcastChannelUpdate { msg } => {
287+
if msg.contents.excess_data.len() > MAX_EXCESS_BYTES_FOR_RELAY { return; }
288+
},
289+
MessageSendEvent::BroadcastNodeAnnouncement { msg } => {
290+
if msg.contents.excess_data.len() > MAX_EXCESS_BYTES_FOR_RELAY ||
291+
msg.contents.excess_address_data.len() > MAX_EXCESS_BYTES_FOR_RELAY ||
292+
msg.contents.excess_data.len() + msg.contents.excess_address_data.len() > MAX_EXCESS_BYTES_FOR_RELAY
293+
{
294+
return;
295+
}
296+
},
297+
_ => return,
298+
}
299+
self.pending_events.lock().unwrap().push(ev);
300+
}
271301
}
272302

273303
impl<L: Deref> NetworkGraph<L> where L::Target: Logger {

lightning/src/routing/gossip_checking.rs

Lines changed: 42 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -20,7 +20,8 @@ use bitcoin::secp256k1::PublicKey;
2020

2121
use crate::ln::chan_utils::make_funding_redeemscript;
2222
use crate::ln::msgs::{self, LightningError, ErrorAction};
23-
use crate::routing::gossip::{NetworkGraph, NodeId};
23+
use crate::routing::gossip::{NetworkGraph, NodeId, P2PGossipSync};
24+
use crate::util::events::MessageSendEvent;
2425
use crate::util::logger::Logger;
2526
use crate::util::ser::Writeable;
2627

@@ -142,8 +143,26 @@ impl AccessFuture {
142143
}
143144

144145
/// Resolves this future against the given `graph` and with the given `result`.
145-
pub fn resolve<L: Deref>(&self, graph: &NetworkGraph<L>, result: Result<TxOut, ChainAccessError>)
146+
///
147+
/// This is identical to calling [`AccessFuture::resolve`] with a `None` for the `gossip`
148+
/// field, disabling forwarding the validated gossip message onwards to peers. It avoids
149+
/// needing to specify a full concrete type for the generic parameters on the gossip parameter.
150+
pub fn resolve_without_forwarding<L: Deref>(&self,
151+
graph: &NetworkGraph<L>, result: Result<TxOut, ChainAccessError>)
146152
where L::Target: Logger {
153+
// Sadly there's no great way to guess the types the user uses for their P2PGossipSync
154+
// here, so we have to just make something up, nearly guaranteeing we end up with two
155+
// copies of every P2PGossipSync method in the build.
156+
self.resolve(graph, None::<&P2PGossipSync<&NetworkGraph<L>, &dyn ChainAccess, L>>, result);
157+
}
158+
159+
/// Resolves this future against the given `graph` and with the given `result`.
160+
///
161+
/// If provided, the given `gossip` is used to broadcast any validated messages onwards to all
162+
/// peers which have available buffer space.
163+
pub fn resolve<L: Deref, G: Deref<Target=NetworkGraph<L>>, C: Deref, GS: Deref<Target = P2PGossipSync<G, C, L>>>(&self,
164+
graph: &NetworkGraph<L>, gossip: Option<GS>, result: Result<TxOut, ChainAccessError>)
165+
where L::Target: Logger, C::Target: ChainAccess {
147166
let (announcement, node_a, node_b, update_a, update_b) = {
148167
let mut pending_checks = graph.pending_checks.internal.lock().unwrap();
149168
let mut async_messages = self.state.lock().unwrap();
@@ -197,7 +216,13 @@ impl AccessFuture {
197216
let resolver = AccessResolver(result);
198217
match announcement {
199218
ChannelAnnouncement::Full(signed_msg) => {
200-
let _ = graph.update_channel_from_announcement(&signed_msg, &Some(&resolver));
219+
if graph.update_channel_from_announcement(&signed_msg, &Some(&resolver)).is_ok() {
220+
if let Some(broadcaster) = &gossip {
221+
broadcaster.forward_gossip_msg(MessageSendEvent::BroadcastChannelAnnouncement {
222+
msg: signed_msg, update_msg: None,
223+
});
224+
}
225+
}
201226
},
202227
ChannelAnnouncement::Unsigned(msg) => {
203228
let _ = graph.update_channel_from_unsigned_announcement(&msg, &Some(&resolver));
@@ -207,7 +232,13 @@ impl AccessFuture {
207232
for announce in core::iter::once(node_a).chain(core::iter::once(node_b)) {
208233
match announce {
209234
Some(NodeAnnouncement::Full(signed_msg)) => {
210-
let _ = graph.update_node_from_announcement(&signed_msg);
235+
if graph.update_node_from_announcement(&signed_msg).is_ok() {
236+
if let Some(broadcaster) = &gossip {
237+
broadcaster.forward_gossip_msg(MessageSendEvent::BroadcastNodeAnnouncement {
238+
msg: signed_msg,
239+
});
240+
}
241+
}
211242
},
212243
Some(NodeAnnouncement::Unsigned(msg)) => {
213244
let _ = graph.update_node_from_unsigned_announcement(&msg);
@@ -219,7 +250,13 @@ impl AccessFuture {
219250
for update in core::iter::once(update_a).chain(core::iter::once(update_b)) {
220251
match update {
221252
Some(ChannelUpdate::Full(signed_msg)) => {
222-
let _ = graph.update_channel(&signed_msg);
253+
if graph.update_channel(&signed_msg).is_ok() {
254+
if let Some(broadcaster) = &gossip {
255+
broadcaster.forward_gossip_msg(MessageSendEvent::BroadcastChannelUpdate {
256+
msg: signed_msg,
257+
});
258+
}
259+
}
223260
},
224261
Some(ChannelUpdate::Unsigned(msg)) => {
225262
let _ = graph.update_channel_unsigned(&msg);

0 commit comments

Comments
 (0)