@@ -102,7 +102,21 @@ struct NetworkMap {
102
102
our_node_id : PublicKey ,
103
103
nodes : HashMap < PublicKey , NodeInfo > ,
104
104
}
105
-
105
+ struct MutNetworkMap < ' a > {
106
+ #[ cfg( feature = "non_bitcoin_chain_hash_routing" ) ]
107
+ channels : & ' a mut HashMap < ( u64 , Sha256dHash ) , ChannelInfo > ,
108
+ #[ cfg( not( feature = "non_bitcoin_chain_hash_routing" ) ) ]
109
+ channels : & ' a mut HashMap < u64 , ChannelInfo > ,
110
+ nodes : & ' a mut HashMap < PublicKey , NodeInfo > ,
111
+ }
112
+ impl NetworkMap {
113
+ fn borrow_parts ( & mut self ) -> MutNetworkMap {
114
+ MutNetworkMap {
115
+ channels : & mut self . channels ,
116
+ nodes : & mut self . nodes ,
117
+ }
118
+ }
119
+ }
106
120
impl std:: fmt:: Display for NetworkMap {
107
121
fn fmt ( & self , f : & mut std:: fmt:: Formatter ) -> Result < ( ) , std:: fmt:: Error > {
108
122
write ! ( f, "Node id {} network map\n [Channels]\n " , log_pubkey!( self . our_node_id) ) ?;
@@ -213,7 +227,7 @@ impl RoutingMessageHandler for Router {
213
227
panic ! ( "Unknown-required-features ChannelAnnouncements should never deserialize!" ) ;
214
228
}
215
229
216
- match self . chain_monitor . get_chain_utxo ( msg. contents . chain_hash , msg. contents . short_channel_id ) {
230
+ let checked_utxo = match self . chain_monitor . get_chain_utxo ( msg. contents . chain_hash , msg. contents . short_channel_id ) {
217
231
Ok ( ( script_pubkey, _value) ) => {
218
232
let expected_script = Builder :: new ( ) . push_opcode ( opcodes:: All :: OP_PUSHNUM_2 )
219
233
. push_slice ( & msg. contents . bitcoin_key_1 . serialize ( ) )
@@ -224,49 +238,67 @@ impl RoutingMessageHandler for Router {
224
238
}
225
239
//TODO: Check if value is worth storing, use it to inform routing, and compare it
226
240
//to the new HTLC max field in channel_update
241
+ true
227
242
} ,
228
243
Err ( ChainError :: NotSupported ) => {
229
244
// Tentatively accept, potentially exposing us to DoS attacks
245
+ false
230
246
} ,
231
247
Err ( ChainError :: NotWatched ) => {
232
248
return Err ( HandleError { err : "Channel announced on an unknown chain" , action : Some ( ErrorAction :: IgnoreError ) } ) ;
233
249
} ,
234
250
Err ( ChainError :: UnknownTx ) => {
235
251
return Err ( HandleError { err : "Channel announced without corresponding UTXO entry" , action : Some ( ErrorAction :: IgnoreError ) } ) ;
236
252
} ,
237
- }
253
+ } ;
238
254
239
- let mut network = self . network_map . write ( ) . unwrap ( ) ;
255
+ let mut network_lock = self . network_map . write ( ) . unwrap ( ) ;
256
+ let network = network_lock. borrow_parts ( ) ;
257
+
258
+ let chan_info = ChannelInfo {
259
+ features : msg. contents . features . clone ( ) ,
260
+ one_to_two : DirectionalChannelInfo {
261
+ src_node_id : msg. contents . node_id_1 . clone ( ) ,
262
+ last_update : 0 ,
263
+ enabled : false ,
264
+ cltv_expiry_delta : u16:: max_value ( ) ,
265
+ htlc_minimum_msat : u64:: max_value ( ) ,
266
+ fee_base_msat : u32:: max_value ( ) ,
267
+ fee_proportional_millionths : u32:: max_value ( ) ,
268
+ } ,
269
+ two_to_one : DirectionalChannelInfo {
270
+ src_node_id : msg. contents . node_id_2 . clone ( ) ,
271
+ last_update : 0 ,
272
+ enabled : false ,
273
+ cltv_expiry_delta : u16:: max_value ( ) ,
274
+ htlc_minimum_msat : u64:: max_value ( ) ,
275
+ fee_base_msat : u32:: max_value ( ) ,
276
+ fee_proportional_millionths : u32:: max_value ( ) ,
277
+ }
278
+ } ;
240
279
241
280
match network. channels . entry ( NetworkMap :: get_key ( msg. contents . short_channel_id , msg. contents . chain_hash ) ) {
242
- Entry :: Occupied ( _ ) => {
281
+ Entry :: Occupied ( mut entry ) => {
243
282
//TODO: because asking the blockchain if short_channel_id is valid is only optional
244
283
//in the blockchain API, we need to handle it smartly here, though its unclear
245
284
//exactly how...
246
- return Err ( HandleError { err : "Already have knowledge of channel" , action : Some ( ErrorAction :: IgnoreError ) } )
285
+ if checked_utxo {
286
+ // Either our UTXO provider is busted, there was a reorg, or the UTXO provider
287
+ // only sometimes returns results. In any case remove the previous entry. Note
288
+ // that the spec expects us to "blacklist" the node_ids involved, but we can't
289
+ // do that because
290
+ // a) we don't *require* a UTXO provider that always returns results.
291
+ // b) we don't track UTXOs of channels we know about and remove them if they
292
+ // get reorg'd out.
293
+ // c) it's unclear how to do so without exposing ourselves to massive DoS risk.
294
+ Self :: remove_channel_in_nodes ( network. nodes , & entry. get ( ) , msg. contents . short_channel_id ) ;
295
+ * entry. get_mut ( ) = chan_info;
296
+ } else {
297
+ return Err ( HandleError { err : "Already have knowledge of channel" , action : Some ( ErrorAction :: IgnoreError ) } )
298
+ }
247
299
} ,
248
300
Entry :: Vacant ( entry) => {
249
- entry. insert ( ChannelInfo {
250
- features : msg. contents . features . clone ( ) ,
251
- one_to_two : DirectionalChannelInfo {
252
- src_node_id : msg. contents . node_id_1 . clone ( ) ,
253
- last_update : 0 ,
254
- enabled : false ,
255
- cltv_expiry_delta : u16:: max_value ( ) ,
256
- htlc_minimum_msat : u64:: max_value ( ) ,
257
- fee_base_msat : u32:: max_value ( ) ,
258
- fee_proportional_millionths : u32:: max_value ( ) ,
259
- } ,
260
- two_to_one : DirectionalChannelInfo {
261
- src_node_id : msg. contents . node_id_2 . clone ( ) ,
262
- last_update : 0 ,
263
- enabled : false ,
264
- cltv_expiry_delta : u16:: max_value ( ) ,
265
- htlc_minimum_msat : u64:: max_value ( ) ,
266
- fee_base_msat : u32:: max_value ( ) ,
267
- fee_proportional_millionths : u32:: max_value ( ) ,
268
- }
269
- } ) ;
301
+ entry. insert ( chan_info) ;
270
302
}
271
303
} ;
272
304
0 commit comments