16
16
use bitcoin:: { BlockHash , TxOut } ;
17
17
use bitcoin:: hashes:: hex:: ToHex ;
18
18
19
+ use bitcoin:: secp256k1:: PublicKey ;
20
+
19
21
use crate :: ln:: chan_utils:: make_funding_redeemscript;
20
22
use crate :: ln:: msgs:: { self , LightningError , ErrorAction } ;
21
23
use crate :: routing:: gossip:: { NetworkGraph , NodeId } ;
@@ -70,10 +72,48 @@ enum ChannelAnnouncement {
70
72
Full ( msgs:: ChannelAnnouncement ) ,
71
73
Unsigned ( msgs:: UnsignedChannelAnnouncement ) ,
72
74
}
75
+ impl ChannelAnnouncement {
76
+ fn node_id_1 ( & self ) -> & PublicKey {
77
+ match self {
78
+ ChannelAnnouncement :: Full ( msg) => & msg. contents . node_id_1 ,
79
+ ChannelAnnouncement :: Unsigned ( msg) => & msg. node_id_1 ,
80
+ }
81
+ }
82
+ }
83
+
84
+ enum NodeAnnouncement {
85
+ Full ( msgs:: NodeAnnouncement ) ,
86
+ Unsigned ( msgs:: UnsignedNodeAnnouncement ) ,
87
+ }
88
+ impl NodeAnnouncement {
89
+ fn timestamp ( & self ) -> u32 {
90
+ match self {
91
+ NodeAnnouncement :: Full ( msg) => msg. contents . timestamp ,
92
+ NodeAnnouncement :: Unsigned ( msg) => msg. timestamp ,
93
+ }
94
+ }
95
+ }
96
+
97
+ enum ChannelUpdate {
98
+ Full ( msgs:: ChannelUpdate ) ,
99
+ Unsigned ( msgs:: UnsignedChannelUpdate ) ,
100
+ }
101
+ impl ChannelUpdate {
102
+ fn timestamp ( & self ) -> u32 {
103
+ match self {
104
+ ChannelUpdate :: Full ( msg) => msg. contents . timestamp ,
105
+ ChannelUpdate :: Unsigned ( msg) => msg. timestamp ,
106
+ }
107
+ }
108
+ }
73
109
74
110
struct AccessMessages {
75
111
complete : Option < Result < TxOut , ChainAccessError > > ,
76
112
channel_announce : Option < ChannelAnnouncement > ,
113
+ latest_node_announce_a : Option < NodeAnnouncement > ,
114
+ latest_node_announce_b : Option < NodeAnnouncement > ,
115
+ latest_channel_update_a : Option < ChannelUpdate > ,
116
+ latest_channel_update_b : Option < ChannelUpdate > ,
77
117
}
78
118
79
119
/// Represents a future resolution of a [`ChainAccess::get_utxo`] query resolving async.
@@ -99,13 +139,17 @@ impl AccessFuture {
99
139
Self { state : Arc :: new ( Mutex :: new ( AccessMessages {
100
140
complete : None ,
101
141
channel_announce : None ,
142
+ latest_node_announce_a : None ,
143
+ latest_node_announce_b : None ,
144
+ latest_channel_update_a : None ,
145
+ latest_channel_update_b : None ,
102
146
} ) ) }
103
147
}
104
148
105
149
/// Resolves this future against the given `graph` and with the given `result`.
106
150
pub fn resolve < L : Deref > ( & self , graph : & NetworkGraph < L > , result : Result < TxOut , ChainAccessError > )
107
151
where L :: Target : Logger {
108
- let announcement = {
152
+ let ( announcement, node_a , node_b , update_a , update_b ) = {
109
153
let mut pending_checks = graph. pending_checks . internal . lock ( ) . unwrap ( ) ;
110
154
let mut async_messages = self . state . lock ( ) . unwrap ( ) ;
111
155
@@ -116,14 +160,19 @@ impl AccessFuture {
116
160
async_messages. complete = Some ( result) ;
117
161
return ;
118
162
}
163
+
119
164
let announcement_msg = match async_messages. channel_announce . as_ref ( ) . unwrap ( ) {
120
165
ChannelAnnouncement :: Full ( signed_msg) => & signed_msg. contents ,
121
166
ChannelAnnouncement :: Unsigned ( msg) => & msg,
122
167
} ;
123
168
124
169
pending_checks. lookup_completed ( announcement_msg, & Arc :: downgrade ( & self . state ) ) ;
125
170
126
- async_messages. channel_announce . take ( ) . unwrap ( )
171
+ ( async_messages. channel_announce . take ( ) . unwrap ( ) ,
172
+ async_messages. latest_node_announce_a . take ( ) ,
173
+ async_messages. latest_node_announce_b . take ( ) ,
174
+ async_messages. latest_channel_update_a . take ( ) ,
175
+ async_messages. latest_channel_update_b . take ( ) )
127
176
} ;
128
177
129
178
// Now that we've updated our internal state, pass the pending messages back through the
@@ -139,11 +188,36 @@ impl AccessFuture {
139
188
let _ = graph. update_channel_from_unsigned_announcement ( & msg, & Some ( & resolver) ) ;
140
189
} ,
141
190
}
191
+
192
+ for announce in core:: iter:: once ( node_a) . chain ( core:: iter:: once ( node_b) ) {
193
+ match announce {
194
+ Some ( NodeAnnouncement :: Full ( signed_msg) ) => {
195
+ let _ = graph. update_node_from_announcement ( & signed_msg) ;
196
+ } ,
197
+ Some ( NodeAnnouncement :: Unsigned ( msg) ) => {
198
+ let _ = graph. update_node_from_unsigned_announcement ( & msg) ;
199
+ } ,
200
+ None => { } ,
201
+ }
202
+ }
203
+
204
+ for update in core:: iter:: once ( update_a) . chain ( core:: iter:: once ( update_b) ) {
205
+ match update {
206
+ Some ( ChannelUpdate :: Full ( signed_msg) ) => {
207
+ let _ = graph. update_channel ( & signed_msg) ;
208
+ } ,
209
+ Some ( ChannelUpdate :: Unsigned ( msg) ) => {
210
+ let _ = graph. update_channel_unsigned ( & msg) ;
211
+ } ,
212
+ None => { } ,
213
+ }
214
+ }
142
215
}
143
216
}
144
217
145
218
struct PendingChecksContext {
146
219
channels : HashMap < u64 , Weak < Mutex < AccessMessages > > > ,
220
+ nodes : HashMap < NodeId , Vec < Weak < Mutex < AccessMessages > > > > ,
147
221
}
148
222
149
223
impl PendingChecksContext {
@@ -155,6 +229,17 @@ impl PendingChecksContext {
155
229
e. remove ( ) ;
156
230
}
157
231
}
232
+
233
+ let node_id_1 = NodeId :: from_pubkey ( & msg. node_id_1 ) ;
234
+ if let hash_map:: Entry :: Occupied ( mut e) = self . nodes . entry ( node_id_1) {
235
+ e. get_mut ( ) . retain ( |elem| !Weak :: ptr_eq ( & elem, & completed_state) ) ;
236
+ if e. get ( ) . is_empty ( ) { e. remove ( ) ; }
237
+ }
238
+ let node_id_2 = NodeId :: from_pubkey ( & msg. node_id_2 ) ;
239
+ if let hash_map:: Entry :: Occupied ( mut e) = self . nodes . entry ( node_id_2) {
240
+ e. get_mut ( ) . retain ( |elem| !Weak :: ptr_eq ( & elem, & completed_state) ) ;
241
+ if e. get ( ) . is_empty ( ) { e. remove ( ) ; }
242
+ }
158
243
}
159
244
}
160
245
@@ -166,10 +251,98 @@ pub(super) struct PendingChecks {
166
251
impl PendingChecks {
167
252
pub ( super ) fn new ( ) -> Self {
168
253
PendingChecks { internal : Mutex :: new ( PendingChecksContext {
169
- channels : HashMap :: new ( ) ,
254
+ channels : HashMap :: new ( ) , nodes : HashMap :: new ( ) ,
170
255
} ) }
171
256
}
172
257
258
+ /// Checks if there is a pending `channel_update` UTXO validation for the given channel,
259
+ /// and, if so, stores the channel message for handling later and returns an `Err`.
260
+ pub ( super ) fn check_hold_pending_channel_update (
261
+ & self , msg : & msgs:: UnsignedChannelUpdate , full_msg : Option < & msgs:: ChannelUpdate >
262
+ ) -> Result < ( ) , LightningError > {
263
+ let mut pending_checks = self . internal . lock ( ) . unwrap ( ) ;
264
+ if let hash_map:: Entry :: Occupied ( e) = pending_checks. channels . entry ( msg. short_channel_id ) {
265
+ let is_from_a = ( msg. flags & 1 ) == 1 ;
266
+ match Weak :: upgrade ( e. get ( ) ) {
267
+ Some ( msgs_ref) => {
268
+ let mut messages = msgs_ref. lock ( ) . unwrap ( ) ;
269
+ let latest_update = if is_from_a {
270
+ & mut messages. latest_channel_update_a
271
+ } else {
272
+ & mut messages. latest_channel_update_b
273
+ } ;
274
+ if latest_update. is_none ( ) || latest_update. as_ref ( ) . unwrap ( ) . timestamp ( ) < msg. timestamp {
275
+ // If the messages we got has a higher timestamp, just blindly assume the
276
+ // signatures on the new message are correct and drop the old message. This
277
+ // may cause us to end up dropping valid `channel_update`s if a peer is
278
+ // malicious, but we should get the correct ones when the node updates them.
279
+ * latest_update = Some (
280
+ if let Some ( msg) = full_msg { ChannelUpdate :: Full ( msg. clone ( ) ) }
281
+ else { ChannelUpdate :: Unsigned ( msg. clone ( ) ) } ) ;
282
+ }
283
+ return Err ( LightningError {
284
+ err : "Awaiting channel_announcement validation to accept channel_update" . to_owned ( ) ,
285
+ action : ErrorAction :: IgnoreAndLog ( Level :: Gossip ) ,
286
+ } ) ;
287
+ } ,
288
+ None => { e. remove ( ) ; } ,
289
+ }
290
+ }
291
+ Ok ( ( ) )
292
+ }
293
+
294
+ /// Checks if there is a pending `node_announcement` UTXO validation for a channel with the
295
+ /// given node and, if so, stores the channel message for handling later and returns an `Err`.
296
+ pub ( super ) fn check_hold_pending_node_announcement (
297
+ & self , msg : & msgs:: UnsignedNodeAnnouncement , full_msg : Option < & msgs:: NodeAnnouncement >
298
+ ) -> Result < ( ) , LightningError > {
299
+ let mut pending_checks = self . internal . lock ( ) . unwrap ( ) ;
300
+ if let hash_map:: Entry :: Occupied ( mut e) = pending_checks. nodes . entry ( NodeId :: from_pubkey ( & msg. node_id ) ) {
301
+ let mut found_at_least_one_chan = false ;
302
+ e. get_mut ( ) . retain ( |node_msgs| {
303
+ match Weak :: upgrade ( & node_msgs) {
304
+ Some ( chan_mtx) => {
305
+ let mut chan_msgs = chan_mtx. lock ( ) . unwrap ( ) ;
306
+ if let Some ( chan_announce) = & chan_msgs. channel_announce {
307
+ let latest_announce =
308
+ if * chan_announce. node_id_1 ( ) == msg. node_id {
309
+ & mut chan_msgs. latest_node_announce_a
310
+ } else {
311
+ & mut chan_msgs. latest_node_announce_b
312
+ } ;
313
+ if latest_announce. is_none ( ) ||
314
+ latest_announce. as_ref ( ) . unwrap ( ) . timestamp ( ) < msg. timestamp
315
+ {
316
+ // If the messages we got has a higher timestamp, just blindly
317
+ // assume the signatures on the new message are correct and drop
318
+ // the old message. This may cause us to end up dropping valid
319
+ // `node_announcement`s if a peer is malicious, but we should get
320
+ // the correct ones when the node updates them.
321
+ * latest_announce = Some (
322
+ if let Some ( msg) = full_msg { NodeAnnouncement :: Full ( msg. clone ( ) ) }
323
+ else { NodeAnnouncement :: Unsigned ( msg. clone ( ) ) } ) ;
324
+ }
325
+ found_at_least_one_chan = true ;
326
+ true
327
+ } else {
328
+ debug_assert ! ( false , "channel_announce is set before struct is added to node map" ) ;
329
+ false
330
+ }
331
+ } ,
332
+ None => false ,
333
+ }
334
+ } ) ;
335
+ if e. get ( ) . is_empty ( ) { e. remove ( ) ; }
336
+ if found_at_least_one_chan {
337
+ return Err ( LightningError {
338
+ err : "Awaiting channel_announcement validation to accept node_announcement" . to_owned ( ) ,
339
+ action : ErrorAction :: IgnoreAndLog ( Level :: Gossip ) ,
340
+ } ) ;
341
+ }
342
+ }
343
+ Ok ( ( ) )
344
+ }
345
+
173
346
fn check_replace_previous_entry ( msg : & msgs:: UnsignedChannelAnnouncement ,
174
347
full_msg : Option < & msgs:: ChannelAnnouncement > , replacement : Option < Weak < Mutex < AccessMessages > > > ,
175
348
pending_channels : & mut HashMap < u64 , Weak < Mutex < AccessMessages > > >
@@ -283,6 +456,10 @@ impl PendingChecks {
283
456
async_messages. channel_announce = Some (
284
457
if let Some ( msg) = full_msg { ChannelAnnouncement :: Full ( msg. clone ( ) ) }
285
458
else { ChannelAnnouncement :: Unsigned ( msg. clone ( ) ) } ) ;
459
+ pending_checks. nodes . entry ( NodeId :: from_pubkey ( & msg. node_id_1 ) )
460
+ . or_insert ( Vec :: new ( ) ) . push ( Arc :: downgrade ( & future. state ) ) ;
461
+ pending_checks. nodes . entry ( NodeId :: from_pubkey ( & msg. node_id_2 ) )
462
+ . or_insert ( Vec :: new ( ) ) . push ( Arc :: downgrade ( & future. state ) ) ;
286
463
Err ( LightningError {
287
464
err : "Channel being checked async" . to_owned ( ) ,
288
465
action : ErrorAction :: IgnoreAndLog ( Level :: Gossip ) ,
0 commit comments