@@ -85,6 +85,7 @@ pub struct OnionMessenger<Signer: Sign, K: Deref, L: Deref>
85
85
keys_manager : K ,
86
86
logger : L ,
87
87
pending_messages : Mutex < HashMap < PublicKey , Vec < msgs:: OnionMessage > > > ,
88
+ peer_set : Mutex < HashSet < PublicKey > > ,
88
89
secp_ctx : Secp256k1 < secp256k1:: All > ,
89
90
// Coming soon:
90
91
// invoice_handler: InvoiceHandler,
@@ -121,6 +122,8 @@ pub enum SendError {
121
122
/// The provided [`Destination`] was an invalid [`BlindedRoute`], due to having fewer than two
122
123
/// blinded hops.
123
124
TooFewBlindedHops ,
125
+ /// Our next-hop peer was offline or does not support onion message forwarding.
126
+ InvalidFirstHop ,
124
127
}
125
128
126
129
impl < Signer : Sign , K : Deref , L : Deref > OnionMessenger < Signer , K , L >
@@ -134,6 +137,7 @@ impl<Signer: Sign, K: Deref, L: Deref> OnionMessenger<Signer, K, L>
134
137
secp_ctx. seeded_randomize ( & keys_manager. get_secure_random_bytes ( ) ) ;
135
138
OnionMessenger {
136
139
keys_manager,
140
+ peer_set : Mutex :: new ( HashSet :: new ( ) ) ,
137
141
pending_messages : Mutex :: new ( HashMap :: new ( ) ) ,
138
142
secp_ctx,
139
143
logger,
@@ -159,6 +163,9 @@ impl<Signer: Sign, K: Deref, L: Deref> OnionMessenger<Signer, K, L>
159
163
( introduction_node_id, blinding_point) ,
160
164
}
161
165
} ;
166
+ if !self . peer_connected ( & introduction_node_id) {
167
+ return Err ( SendError :: InvalidFirstHop )
168
+ }
162
169
let ( packet_payloads, packet_keys) = packet_payloads_and_keys (
163
170
& self . secp_ctx , intermediate_nodes, destination, & blinding_secret)
164
171
. map_err ( |e| SendError :: Secp256k1 ( e) ) ?;
@@ -178,6 +185,11 @@ impl<Signer: Sign, K: Deref, L: Deref> OnionMessenger<Signer, K, L>
178
185
Ok ( ( ) )
179
186
}
180
187
188
+ fn peer_connected ( & self , peer_node_id : & PublicKey ) -> bool {
189
+ let peers = self . peer_set . lock ( ) . unwrap ( ) ;
190
+ peers. contains ( peer_node_id)
191
+ }
192
+
181
193
#[ cfg( test) ]
182
194
pub ( super ) fn release_pending_msgs ( & self ) -> HashMap < PublicKey , Vec < msgs:: OnionMessage > > {
183
195
let mut pending_msgs = self . pending_messages . lock ( ) . unwrap ( ) ;
@@ -229,6 +241,10 @@ impl<Signer: Sign, K: Deref, L: Deref> OnionMessageHandler for OnionMessenger<Si
229
241
Ok ( ( Payload :: Forward ( ForwardControlTlvs :: Unblinded ( ForwardTlvs {
230
242
next_node_id, next_blinding_override
231
243
} ) ) , Some ( ( next_hop_hmac, new_packet_bytes) ) ) ) => {
244
+ if !self . peer_connected ( & next_node_id) {
245
+ log_trace ! ( self . logger, "Dropping onion message to disconnected peer {:?}" , next_node_id) ;
246
+ return
247
+ }
232
248
// TODO: we need to check whether `next_node_id` is our node, in which case this is a dummy
233
249
// blinded hop and this onion message is destined for us. In this situation, we should keep
234
250
// unwrapping the onion layers to get to the final payload. Since we don't have the option
@@ -281,6 +297,27 @@ impl<Signer: Sign, K: Deref, L: Deref> OnionMessageHandler for OnionMessenger<Si
281
297
} ,
282
298
} ;
283
299
}
300
+
301
+ fn peer_connected ( & self , their_node_id : & PublicKey , init : & msgs:: Init ) {
302
+ if init. features . supports_onion_messages ( ) {
303
+ let mut peers = self . peer_set . lock ( ) . unwrap ( ) ;
304
+ peers. insert ( their_node_id. clone ( ) ) ;
305
+ }
306
+ }
307
+
308
+ fn peer_disconnected ( & self , their_node_id : & PublicKey , no_connection_possible : bool ) {
309
+ {
310
+ let mut peers = self . peer_set . lock ( ) . unwrap ( ) ;
311
+ peers. remove ( their_node_id) ;
312
+ }
313
+
314
+ let mut pending_msgs = self . pending_messages . lock ( ) . unwrap ( ) ;
315
+ if no_connection_possible {
316
+ pending_msgs. remove ( their_node_id) ;
317
+ } else if let Some ( msgs) = pending_msgs. get_mut ( their_node_id) {
318
+ msgs. clear ( ) ;
319
+ }
320
+ }
284
321
}
285
322
286
323
impl < Signer : Sign , K : Deref , L : Deref > OnionMessageProvider for OnionMessenger < Signer , K , L >
0 commit comments