@@ -1433,6 +1433,39 @@ impl<L: Deref> NetworkGraph<L> where L::Target: Logger {
1433
1433
return Err ( LightningError { err : "Channel announcement node had a channel with itself" . to_owned ( ) , action : ErrorAction :: IgnoreError } ) ;
1434
1434
}
1435
1435
1436
+ {
1437
+ let channels = self . channels . read ( ) . unwrap ( ) ;
1438
+
1439
+ if let Some ( chan) = channels. get ( & msg. short_channel_id ) {
1440
+ if chan. capacity_sats . is_some ( ) {
1441
+ // If we'd previously looked up the channel on-chain and checked the script
1442
+ // against what appears on-chain, ignore the duplicate announcement.
1443
+ //
1444
+ // Because a reorg could replace one channel with another at the same SCID, if
1445
+ // the channel appears to be different, we re-validate. This doesn't expose us
1446
+ // to any more DoS risk than not, as a peer can always flood us with
1447
+ // randomly-generated SCID values anyway.
1448
+ //
1449
+ // We use the Node IDs rather than the bitcoin_keys to check for "equivalence"
1450
+ // as we didn't (necessarily) store the bitcoin keys, and we only really care
1451
+ // if the peers on the channel changed anyway.
1452
+ if NodeId :: from_pubkey ( & msg. node_id_1 ) == chan. node_one && NodeId :: from_pubkey ( & msg. node_id_2 ) == chan. node_two {
1453
+ return Err ( LightningError {
1454
+ err : "Already have chain-validated channel" . to_owned ( ) ,
1455
+ action : ErrorAction :: IgnoreDuplicateGossip
1456
+ } ) ;
1457
+ }
1458
+ } else if chain_access. is_none ( ) {
1459
+ // Similarly, if we can't check the chain right now anyway, ignore the
1460
+ // duplicate announcement without bothering to take the channels write lock.
1461
+ return Err ( LightningError {
1462
+ err : "Already have non-chain-validated channel" . to_owned ( ) ,
1463
+ action : ErrorAction :: IgnoreDuplicateGossip
1464
+ } ) ;
1465
+ }
1466
+ }
1467
+ }
1468
+
1436
1469
let utxo_value = match & chain_access {
1437
1470
& None => {
1438
1471
// Tentatively accept, potentially exposing us to DoS attacks
@@ -2046,7 +2079,7 @@ mod tests {
2046
2079
// drop new one on the floor, since we can't see any changes.
2047
2080
match gossip_sync. handle_channel_announcement ( & valid_announcement) {
2048
2081
Ok ( _) => panic ! ( ) ,
2049
- Err ( e) => assert_eq ! ( e. err, "Already have knowledge of channel" )
2082
+ Err ( e) => assert_eq ! ( e. err, "Already have non-chain-validated channel" )
2050
2083
} ;
2051
2084
2052
2085
// Test if an associated transaction were not on-chain (or not confirmed).
@@ -2080,32 +2113,13 @@ mod tests {
2080
2113
} ;
2081
2114
}
2082
2115
2083
- // If we receive announcement for the same channel (but TX is not confirmed),
2084
- // drop new one on the floor, since we can't see any changes.
2085
- * chain_source. utxo_ret . lock ( ) . unwrap ( ) = Err ( chain:: AccessError :: UnknownTx ) ;
2086
- match gossip_sync. handle_channel_announcement ( & valid_announcement) {
2087
- Ok ( _) => panic ! ( ) ,
2088
- Err ( e) => assert_eq ! ( e. err, "Channel announced without corresponding UTXO entry" )
2089
- } ;
2090
-
2091
- // But if it is confirmed, replace the channel
2116
+ // If we receive announcement for the same channel, once we've validated it against the
2117
+ // chain, we simply ignore all new (duplicate) announcements.
2092
2118
* chain_source. utxo_ret . lock ( ) . unwrap ( ) = Ok ( TxOut { value : 0 , script_pubkey : good_script } ) ;
2093
- let valid_announcement = get_signed_channel_announcement ( |unsigned_announcement| {
2094
- unsigned_announcement. features = ChannelFeatures :: empty ( ) ;
2095
- unsigned_announcement. short_channel_id += 2 ;
2096
- } , node_1_privkey, node_2_privkey, & secp_ctx) ;
2097
2119
match gossip_sync. handle_channel_announcement ( & valid_announcement) {
2098
- Ok ( res ) => assert ! ( res ) ,
2099
- _ => panic ! ( )
2120
+ Ok ( _ ) => panic ! ( ) ,
2121
+ Err ( e ) => assert_eq ! ( e . err , "Already have chain-validated channel" )
2100
2122
} ;
2101
- {
2102
- match network_graph. read_only ( ) . channels ( ) . get ( & valid_announcement. contents . short_channel_id ) {
2103
- Some ( channel_entry) => {
2104
- assert_eq ! ( channel_entry. features, ChannelFeatures :: empty( ) ) ;
2105
- } ,
2106
- _ => panic ! ( )
2107
- } ;
2108
- }
2109
2123
2110
2124
// Don't relay valid channels with excess data
2111
2125
let valid_announcement = get_signed_channel_announcement ( |unsigned_announcement| {
0 commit comments