7
7
use bitcoin:: { BlockHash , TxOut } ;
8
8
use bitcoin:: hashes:: hex:: ToHex ;
9
9
10
+ use bitcoin:: secp256k1:: PublicKey ;
11
+
10
12
use crate :: ln:: chan_utils:: make_funding_redeemscript;
11
13
use crate :: ln:: msgs:: { self , LightningError , ErrorAction } ;
12
14
use crate :: routing:: gossip:: { NetworkGraph , NodeId } ;
@@ -57,10 +59,48 @@ enum ChannelAnnouncement {
57
59
Full ( msgs:: ChannelAnnouncement ) ,
58
60
Unsigned ( msgs:: UnsignedChannelAnnouncement ) ,
59
61
}
62
+ impl ChannelAnnouncement {
63
+ fn node_id_1 ( & self ) -> & PublicKey {
64
+ match self {
65
+ ChannelAnnouncement :: Full ( msg) => & msg. contents . node_id_1 ,
66
+ ChannelAnnouncement :: Unsigned ( msg) => & msg. node_id_1 ,
67
+ }
68
+ }
69
+ }
70
+
71
+ enum NodeAnnouncement {
72
+ Full ( msgs:: NodeAnnouncement ) ,
73
+ Unsigned ( msgs:: UnsignedNodeAnnouncement ) ,
74
+ }
75
+ impl NodeAnnouncement {
76
+ fn timestamp ( & self ) -> u32 {
77
+ match self {
78
+ NodeAnnouncement :: Full ( msg) => msg. contents . timestamp ,
79
+ NodeAnnouncement :: Unsigned ( msg) => msg. timestamp ,
80
+ }
81
+ }
82
+ }
83
+
84
+ enum ChannelUpdate {
85
+ Full ( msgs:: ChannelUpdate ) ,
86
+ Unsigned ( msgs:: UnsignedChannelUpdate ) ,
87
+ }
88
+ impl ChannelUpdate {
89
+ fn timestamp ( & self ) -> u32 {
90
+ match self {
91
+ ChannelUpdate :: Full ( msg) => msg. contents . timestamp ,
92
+ ChannelUpdate :: Unsigned ( msg) => msg. timestamp ,
93
+ }
94
+ }
95
+ }
60
96
61
97
struct AccessMessages {
62
98
complete : Option < Result < TxOut , ChainAccessError > > ,
63
99
channel_announce : Option < ChannelAnnouncement > ,
100
+ latest_node_announce_a : Option < NodeAnnouncement > ,
101
+ latest_node_announce_b : Option < NodeAnnouncement > ,
102
+ latest_channel_update_a : Option < ChannelUpdate > ,
103
+ latest_channel_update_b : Option < ChannelUpdate > ,
64
104
}
65
105
66
106
#[ derive( Clone ) ]
@@ -83,13 +123,17 @@ impl AccessFuture {
83
123
Self { state : Arc :: new ( Mutex :: new ( AccessMessages {
84
124
complete : None ,
85
125
channel_announce : None ,
126
+ latest_node_announce_a : None ,
127
+ latest_node_announce_b : None ,
128
+ latest_channel_update_a : None ,
129
+ latest_channel_update_b : None ,
86
130
} ) ) }
87
131
}
88
132
89
133
/// Resolves this future against the given `graph` and with the given `result`.
90
134
pub fn resolve < L : Deref > ( & self , graph : & NetworkGraph < L > , result : Result < TxOut , ChainAccessError > )
91
135
where L :: Target : Logger {
92
- let announcement = {
136
+ let ( announcement, node_a , node_b , update_a , update_b ) = {
93
137
let mut pending_checks = graph. pending_checks . internal . lock ( ) . unwrap ( ) ;
94
138
let mut async_messages = self . state . lock ( ) . unwrap ( ) ;
95
139
@@ -100,6 +144,7 @@ impl AccessFuture {
100
144
async_messages. complete = Some ( result) ;
101
145
return ;
102
146
}
147
+
103
148
let announcement_msg = match async_messages. channel_announce . as_ref ( ) . unwrap ( ) {
104
149
ChannelAnnouncement :: Full ( signed_msg) => & signed_msg. contents ,
105
150
ChannelAnnouncement :: Unsigned ( msg) => & msg,
@@ -114,7 +159,24 @@ impl AccessFuture {
114
159
}
115
160
}
116
161
117
- async_messages. channel_announce . take ( ) . unwrap ( )
162
+ if let hash_map:: Entry :: Occupied ( mut e) =
163
+ pending_checks. nodes . entry ( NodeId :: from_pubkey ( & announcement_msg. node_id_1 ) )
164
+ {
165
+ e. get_mut ( ) . retain ( |elem| !core:: ptr:: eq ( Weak :: as_ptr ( & elem) , Arc :: as_ptr ( & self . state ) ) ) ;
166
+ if e. get ( ) . is_empty ( ) { e. remove ( ) ; }
167
+ }
168
+ if let hash_map:: Entry :: Occupied ( mut e) =
169
+ pending_checks. nodes . entry ( NodeId :: from_pubkey ( & announcement_msg. node_id_2 ) )
170
+ {
171
+ e. get_mut ( ) . retain ( |elem| !core:: ptr:: eq ( Weak :: as_ptr ( & elem) , Arc :: as_ptr ( & self . state ) ) ) ;
172
+ if e. get ( ) . is_empty ( ) { e. remove ( ) ; }
173
+ }
174
+
175
+ ( async_messages. channel_announce . take ( ) . unwrap ( ) ,
176
+ async_messages. latest_node_announce_a . take ( ) ,
177
+ async_messages. latest_node_announce_b . take ( ) ,
178
+ async_messages. latest_channel_update_a . take ( ) ,
179
+ async_messages. latest_channel_update_b . take ( ) )
118
180
} ;
119
181
120
182
// Now that we've updated our internal state, pass the pending messages back through the
@@ -130,11 +192,36 @@ impl AccessFuture {
130
192
let _ = graph. update_channel_from_unsigned_announcement ( & msg, & Some ( & resolver) ) ;
131
193
} ,
132
194
}
195
+
196
+ for announce in [ node_a, node_b] {
197
+ match announce {
198
+ Some ( NodeAnnouncement :: Full ( signed_msg) ) => {
199
+ let _ = graph. update_node_from_announcement ( & signed_msg) ;
200
+ } ,
201
+ Some ( NodeAnnouncement :: Unsigned ( msg) ) => {
202
+ let _ = graph. update_node_from_unsigned_announcement ( & msg) ;
203
+ } ,
204
+ None => { } ,
205
+ }
206
+ }
207
+
208
+ for update in [ update_a, update_b] {
209
+ match update {
210
+ Some ( ChannelUpdate :: Full ( signed_msg) ) => {
211
+ let _ = graph. update_channel ( & signed_msg) ;
212
+ } ,
213
+ Some ( ChannelUpdate :: Unsigned ( msg) ) => {
214
+ let _ = graph. update_channel_unsigned ( & msg) ;
215
+ } ,
216
+ None => { } ,
217
+ }
218
+ }
133
219
}
134
220
}
135
221
136
222
struct PendingChecksContext {
137
223
channels : HashMap < u64 , Weak < Mutex < AccessMessages > > > ,
224
+ nodes : HashMap < NodeId , Vec < Weak < Mutex < AccessMessages > > > > ,
138
225
}
139
226
140
227
/// A set of messages which are pending UTXO lookups for processing.
@@ -145,10 +232,92 @@ pub(super) struct PendingChecks {
145
232
impl PendingChecks {
146
233
pub ( super ) fn new ( ) -> Self {
147
234
PendingChecks { internal : Mutex :: new ( PendingChecksContext {
148
- channels : HashMap :: new ( ) ,
235
+ channels : HashMap :: new ( ) , nodes : HashMap :: new ( ) ,
149
236
} ) }
150
237
}
151
238
239
+ /// Checks if there is a pending `node_announcement` UTXO validation for the given channel,
240
+ /// and, if so, stores the channel message for handling later and returns an `Err`.
241
+ pub ( super ) fn check_hold_pending_channel_update (
242
+ & self , msg : & msgs:: UnsignedChannelUpdate , full_msg : Option < & msgs:: ChannelUpdate >
243
+ ) -> Result < ( ) , LightningError > {
244
+ let mut pending_checks = self . internal . lock ( ) . unwrap ( ) ;
245
+ if let hash_map:: Entry :: Occupied ( e) = pending_checks. channels . entry ( msg. short_channel_id ) {
246
+ let is_from_a = ( msg. flags & 1 ) == 1 ;
247
+ match Weak :: upgrade ( e. get ( ) ) {
248
+ Some ( msgs_ref) => {
249
+ let mut messages = msgs_ref. lock ( ) . unwrap ( ) ;
250
+ let latest_update = if is_from_a {
251
+ & mut messages. latest_channel_update_a
252
+ } else {
253
+ & mut messages. latest_channel_update_b
254
+ } ;
255
+ if latest_update. is_none ( ) || latest_update. as_ref ( ) . unwrap ( ) . timestamp ( ) < msg. timestamp {
256
+ // If the messages we got has a higher timestamp, just blindly assume the
257
+ // signatures on the new message are correct and drop the old message. This
258
+ // may cause us to end up dropping valid `channel_update`s if a peer is
259
+ // malicious, but we should get the correct ones when the node updates them.
260
+ * latest_update = Some (
261
+ if let Some ( msg) = full_msg { ChannelUpdate :: Full ( msg. clone ( ) ) }
262
+ else { ChannelUpdate :: Unsigned ( msg. clone ( ) ) } ) ;
263
+ }
264
+ return Err ( LightningError {
265
+ err : "Awaiting channel_announcement validation to accept channel_update" . to_owned ( ) ,
266
+ action : ErrorAction :: IgnoreError ,
267
+ } ) ;
268
+ } ,
269
+ None => { e. remove ( ) ; } ,
270
+ }
271
+ }
272
+ Ok ( ( ) )
273
+ }
274
+
275
+ /// Checks if there is a pending `node_announcement` UTXO validation for a channel with the
276
+ /// given node and, if so, stores the channel message for handling later and returns an `Err`.
277
+ pub ( super ) fn check_hold_pending_node_announcement (
278
+ & self , msg : & msgs:: UnsignedNodeAnnouncement , full_msg : Option < & msgs:: NodeAnnouncement >
279
+ ) -> Result < ( ) , LightningError > {
280
+ let mut pending_checks = self . internal . lock ( ) . unwrap ( ) ;
281
+ if let hash_map:: Entry :: Occupied ( mut e) = pending_checks. nodes . entry ( NodeId :: from_pubkey ( & msg. node_id ) ) {
282
+ let mut found_at_least_one_chan = false ;
283
+ e. get_mut ( ) . retain ( |node_msgs| {
284
+ match Weak :: upgrade ( & node_msgs) {
285
+ Some ( chan_mtx) => {
286
+ let mut chan_msgs = chan_mtx. lock ( ) . unwrap ( ) ;
287
+ if let Some ( chan_announce) = & chan_msgs. channel_announce {
288
+ let latest_announce = if * chan_announce. node_id_1 ( ) == msg. node_id {
289
+ & mut chan_msgs. latest_node_announce_a
290
+ } else {
291
+ & mut chan_msgs. latest_node_announce_b
292
+ } ;
293
+ if latest_announce. is_none ( ) ||
294
+ latest_announce. as_ref ( ) . unwrap ( ) . timestamp ( ) < msg. timestamp
295
+ {
296
+ * latest_announce = Some (
297
+ if let Some ( msg) = full_msg { NodeAnnouncement :: Full ( msg. clone ( ) ) }
298
+ else { NodeAnnouncement :: Unsigned ( msg. clone ( ) ) } ) ;
299
+ }
300
+ found_at_least_one_chan = true ;
301
+ true
302
+ } else {
303
+ debug_assert ! ( false , "channel_announce is set before struct is added to node map" ) ;
304
+ false
305
+ }
306
+ } ,
307
+ None => false ,
308
+ }
309
+ } ) ;
310
+ if e. get ( ) . is_empty ( ) { e. remove ( ) ; }
311
+ if found_at_least_one_chan {
312
+ return Err ( LightningError {
313
+ err : "Awaiting channel_announcement validation to accept node_announcement" . to_owned ( ) ,
314
+ action : ErrorAction :: IgnoreError ,
315
+ } ) ;
316
+ }
317
+ }
318
+ Ok ( ( ) )
319
+ }
320
+
152
321
pub ( super ) fn check_channel_announcement < A : Deref > ( & self ,
153
322
chain_access : & Option < A > , msg : & msgs:: UnsignedChannelAnnouncement ,
154
323
full_msg : Option < & msgs:: ChannelAnnouncement >
@@ -257,6 +426,10 @@ impl PendingChecks {
257
426
async_messages. channel_announce = Some (
258
427
if let Some ( msg) = full_msg { ChannelAnnouncement :: Full ( msg. clone ( ) ) }
259
428
else { ChannelAnnouncement :: Unsigned ( msg. clone ( ) ) } ) ;
429
+ pending_checks. nodes . entry ( NodeId :: from_pubkey ( & msg. node_id_1 ) )
430
+ . or_insert ( Vec :: new ( ) ) . push ( Arc :: downgrade ( & future. state ) ) ;
431
+ pending_checks. nodes . entry ( NodeId :: from_pubkey ( & msg. node_id_2 ) )
432
+ . or_insert ( Vec :: new ( ) ) . push ( Arc :: downgrade ( & future. state ) ) ;
260
433
Err ( LightningError {
261
434
err : "Channel being checked async" . to_owned ( ) ,
262
435
action : ErrorAction :: IgnoreError
0 commit comments