@@ -1433,6 +1433,39 @@ impl<L: Deref> NetworkGraph<L> where L::Target: Logger {
14331433 return Err ( LightningError { err : "Channel announcement node had a channel with itself" . to_owned ( ) , action : ErrorAction :: IgnoreError } ) ;
14341434 }
14351435
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+
14361469 let utxo_value = match & chain_access {
14371470 & None => {
14381471 // Tentatively accept, potentially exposing us to DoS attacks
@@ -2046,7 +2079,7 @@ mod tests {
20462079 // drop new one on the floor, since we can't see any changes.
20472080 match gossip_sync. handle_channel_announcement ( & valid_announcement) {
20482081 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" )
20502083 } ;
20512084
20522085 // Test if an associated transaction were not on-chain (or not confirmed).
@@ -2080,32 +2113,13 @@ mod tests {
20802113 } ;
20812114 }
20822115
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.
20922118 * 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) ;
20972119 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" )
21002122 } ;
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- }
21092123
21102124 // Don't relay valid channels with excess data
21112125 let valid_announcement = get_signed_channel_announcement ( |unsigned_announcement| {
0 commit comments