Skip to content

Commit 6c5cd1e

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 3d171d3 commit 6c5cd1e

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
@@ -11,7 +11,8 @@ use bitcoin::secp256k1::PublicKey;
1111

1212
use crate::ln::chan_utils::make_funding_redeemscript;
1313
use crate::ln::msgs::{self, LightningError, ErrorAction};
14-
use crate::routing::gossip::{NetworkGraph, NodeId};
14+
use crate::routing::gossip::{NetworkGraph, NodeId, P2PGossipSync};
15+
use crate::util::events::MessageSendEvent;
1516
use crate::util::logger::Logger;
1617
use crate::util::ser::Writeable;
1718

@@ -131,8 +132,26 @@ impl AccessFuture {
131132
}
132133

133134
/// Resolves this future against the given `graph` and with the given `result`.
134-
pub fn resolve<L: Deref>(&self, graph: &NetworkGraph<L>, result: Result<TxOut, ChainAccessError>)
135+
///
136+
/// This is identical to calling [`AccessFuture::resolve`] with a `None` for the `gossip`
137+
/// field, disabling forwarding the validated gossip message onwards to peers. It avoids
138+
/// needing to specify a full concrete type for the generic parameters on the gossip parameter.
139+
pub fn resolve_without_forwarding<L: Deref>(&self,
140+
graph: &NetworkGraph<L>, result: Result<TxOut, ChainAccessError>)
135141
where L::Target: Logger {
142+
// Sadly there's no great way to guess the types the user uses for their P2PGossipSync
143+
// here, so we have to just make something up, nearly guaranteeing we end up with two
144+
// copies of every P2PGossipSync method in the build.
145+
self.resolve(graph, None::<&P2PGossipSync<&NetworkGraph<L>, &dyn ChainAccess, L>>, result);
146+
}
147+
148+
/// Resolves this future against the given `graph` and with the given `result`.
149+
///
150+
/// If provided, the given `gossip` is used to broadcast any validated messages onwards to all
151+
/// peers which have available buffer space.
152+
pub fn resolve<L: Deref, G: Deref<Target=NetworkGraph<L>>, C: Deref, GS: Deref<Target = P2PGossipSync<G, C, L>>>(&self,
153+
graph: &NetworkGraph<L>, gossip: Option<GS>, result: Result<TxOut, ChainAccessError>)
154+
where L::Target: Logger, C::Target: ChainAccess {
136155
let (announcement, node_a, node_b, update_a, update_b) = {
137156
let mut pending_checks = graph.pending_checks.internal.lock().unwrap();
138157
let mut async_messages = self.state.lock().unwrap();
@@ -186,7 +205,13 @@ impl AccessFuture {
186205
let resolver = AccessResolver(result);
187206
match announcement {
188207
ChannelAnnouncement::Full(signed_msg) => {
189-
let _ = graph.update_channel_from_announcement(&signed_msg, &Some(&resolver));
208+
if graph.update_channel_from_announcement(&signed_msg, &Some(&resolver)).is_ok() {
209+
if let Some(broadcaster) = &gossip {
210+
broadcaster.forward_gossip_msg(MessageSendEvent::BroadcastChannelAnnouncement {
211+
msg: signed_msg, update_msg: None,
212+
});
213+
}
214+
}
190215
},
191216
ChannelAnnouncement::Unsigned(msg) => {
192217
let _ = graph.update_channel_from_unsigned_announcement(&msg, &Some(&resolver));
@@ -196,7 +221,13 @@ impl AccessFuture {
196221
for announce in [node_a, node_b] {
197222
match announce {
198223
Some(NodeAnnouncement::Full(signed_msg)) => {
199-
let _ = graph.update_node_from_announcement(&signed_msg);
224+
if graph.update_node_from_announcement(&signed_msg).is_ok() {
225+
if let Some(broadcaster) = &gossip {
226+
broadcaster.forward_gossip_msg(MessageSendEvent::BroadcastNodeAnnouncement {
227+
msg: signed_msg,
228+
});
229+
}
230+
}
200231
},
201232
Some(NodeAnnouncement::Unsigned(msg)) => {
202233
let _ = graph.update_node_from_unsigned_announcement(&msg);
@@ -208,7 +239,13 @@ impl AccessFuture {
208239
for update in [update_a, update_b] {
209240
match update {
210241
Some(ChannelUpdate::Full(signed_msg)) => {
211-
let _ = graph.update_channel(&signed_msg);
242+
if graph.update_channel(&signed_msg).is_ok() {
243+
if let Some(broadcaster) = &gossip {
244+
broadcaster.forward_gossip_msg(MessageSendEvent::BroadcastChannelUpdate {
245+
msg: signed_msg,
246+
});
247+
}
248+
}
212249
},
213250
Some(ChannelUpdate::Unsigned(msg)) => {
214251
let _ = graph.update_channel_unsigned(&msg);

0 commit comments

Comments
 (0)