@@ -72,7 +72,12 @@ const MAX_EXCESS_BYTES_FOR_RELAY: usize = 1024;
72
72
/// This value ensures a reply fits within the 65k payload limit and is consistent with other implementations.
73
73
const MAX_SCIDS_PER_REPLY : usize = 8000 ;
74
74
75
- /// Represents the compressed public key of a node
75
+ /// A compressed pubkey which a node uses to sign announcements and decode HTLCs routed through it.
76
+ ///
77
+ /// This type stores a simple byte array which is not checked for validity (i.e. that it describes
78
+ /// a point which lies on the secp256k1 curve), unlike [`PublicKey`], as validity checking would
79
+ /// otherwise represent a large portion of [`NetworkGraph`] deserialization time (and RGS
80
+ /// application).
76
81
#[ derive( Clone , Copy , PartialEq , Eq ) ]
77
82
pub struct NodeId ( [ u8 ; PUBLIC_KEY_SIZE ] ) ;
78
83
@@ -1660,8 +1665,7 @@ where
1660
1665
1661
1666
let chain_hash: ChainHash = Readable :: read ( reader) ?;
1662
1667
let channels_count: u64 = Readable :: read ( reader) ?;
1663
- // In Nov, 2023 there were about 15,000 nodes; we cap allocations to 1.5x that.
1664
- let mut channels = IndexedMap :: with_capacity ( cmp:: min ( channels_count as usize , 22500 ) ) ;
1668
+ let mut channels = IndexedMap :: with_capacity ( CHAN_COUNT_ESTIMATE ) ;
1665
1669
for _ in 0 ..channels_count {
1666
1670
let chan_id: u64 = Readable :: read ( reader) ?;
1667
1671
let chan_info: ChannelInfo = Readable :: read ( reader) ?;
@@ -1673,8 +1677,7 @@ where
1673
1677
if nodes_count > u32:: max_value ( ) as u64 / 2 {
1674
1678
return Err ( DecodeError :: InvalidValue ) ;
1675
1679
}
1676
- // In Nov, 2023 there were about 69K channels; we cap allocations to 1.5x that.
1677
- let mut nodes = IndexedMap :: with_capacity ( cmp:: min ( nodes_count as usize , 103500 ) ) ;
1680
+ let mut nodes = IndexedMap :: with_capacity ( NODE_COUNT_ESTIMATE ) ;
1678
1681
for i in 0 ..nodes_count {
1679
1682
let node_id = Readable :: read ( reader) ?;
1680
1683
let mut node_info: NodeInfo = Readable :: read ( reader) ?;
@@ -1750,6 +1753,15 @@ where
1750
1753
}
1751
1754
}
1752
1755
1756
+ // In Jan, 2025 there were about 49K channels.
1757
+ // We over-allocate by a bit because 20% more is better than the double we get if we're slightly
1758
+ // too low
1759
+ const CHAN_COUNT_ESTIMATE : usize = 60_000 ;
1760
+ // In Jan, 2025 there were about 15K nodes
1761
+ // We over-allocate by a bit because 33% more is better than the double we get if we're slightly
1762
+ // too low
1763
+ const NODE_COUNT_ESTIMATE : usize = 20_000 ;
1764
+
1753
1765
impl < L : Deref > NetworkGraph < L >
1754
1766
where
1755
1767
L :: Target : Logger ,
@@ -1760,8 +1772,8 @@ where
1760
1772
secp_ctx : Secp256k1 :: verification_only ( ) ,
1761
1773
chain_hash : ChainHash :: using_genesis_block ( network) ,
1762
1774
logger,
1763
- channels : RwLock :: new ( IndexedMap :: new ( ) ) ,
1764
- nodes : RwLock :: new ( IndexedMap :: new ( ) ) ,
1775
+ channels : RwLock :: new ( IndexedMap :: with_capacity ( CHAN_COUNT_ESTIMATE ) ) ,
1776
+ nodes : RwLock :: new ( IndexedMap :: with_capacity ( NODE_COUNT_ESTIMATE ) ) ,
1765
1777
next_node_counter : AtomicUsize :: new ( 0 ) ,
1766
1778
removed_node_counters : Mutex :: new ( Vec :: new ( ) ) ,
1767
1779
last_rapid_gossip_sync_timestamp : Mutex :: new ( None ) ,
@@ -1992,8 +2004,8 @@ where
1992
2004
///
1993
2005
/// All other parameters as used in [`msgs::UnsignedChannelAnnouncement`] fields.
1994
2006
pub fn add_channel_from_partial_announcement (
1995
- & self , short_channel_id : u64 , timestamp : u64 , features : ChannelFeatures ,
1996
- node_id_1 : PublicKey , node_id_2 : PublicKey ,
2007
+ & self , short_channel_id : u64 , timestamp : u64 , features : ChannelFeatures , node_id_1 : NodeId ,
2008
+ node_id_2 : NodeId ,
1997
2009
) -> Result < ( ) , LightningError > {
1998
2010
if node_id_1 == node_id_2 {
1999
2011
return Err ( LightningError {
@@ -2002,13 +2014,11 @@ where
2002
2014
} ) ;
2003
2015
} ;
2004
2016
2005
- let node_1 = NodeId :: from_pubkey ( & node_id_1) ;
2006
- let node_2 = NodeId :: from_pubkey ( & node_id_2) ;
2007
2017
let channel_info = ChannelInfo {
2008
2018
features,
2009
- node_one : node_1 . clone ( ) ,
2019
+ node_one : node_id_1 ,
2010
2020
one_to_two : None ,
2011
- node_two : node_2 . clone ( ) ,
2021
+ node_two : node_id_2 ,
2012
2022
two_to_one : None ,
2013
2023
capacity_sats : None ,
2014
2024
announcement_message : None ,
@@ -2537,7 +2547,7 @@ where
2537
2547
}
2538
2548
} ;
2539
2549
2540
- let node_pubkey;
2550
+ let mut node_pubkey = None ;
2541
2551
{
2542
2552
let channels = self . channels . read ( ) . unwrap ( ) ;
2543
2553
match channels. get ( & msg. short_channel_id ) {
@@ -2556,16 +2566,31 @@ where
2556
2566
} else {
2557
2567
channel. node_one . as_slice ( )
2558
2568
} ;
2559
- node_pubkey = PublicKey :: from_slice ( node_id) . map_err ( |_| LightningError {
2560
- err : "Couldn't parse source node pubkey" . to_owned ( ) ,
2561
- action : ErrorAction :: IgnoreAndLog ( Level :: Debug ) ,
2562
- } ) ?;
2569
+ if sig. is_some ( ) {
2570
+ // PublicKey parsing isn't entirely trivial as it requires that we check
2571
+ // that the provided point is on the curve. Thus, if we don't have a
2572
+ // signature to verify, we want to skip the parsing step entirely.
2573
+ // This represents a substantial speedup in applying RGS snapshots.
2574
+ node_pubkey =
2575
+ Some ( PublicKey :: from_slice ( node_id) . map_err ( |_| LightningError {
2576
+ err : "Couldn't parse source node pubkey" . to_owned ( ) ,
2577
+ action : ErrorAction :: IgnoreAndLog ( Level :: Debug ) ,
2578
+ } ) ?) ;
2579
+ }
2563
2580
} ,
2564
2581
}
2565
2582
}
2566
2583
2567
- let msg_hash = hash_to_message ! ( & message_sha256d_hash( & msg) [ ..] ) ;
2568
2584
if let Some ( sig) = sig {
2585
+ let msg_hash = hash_to_message ! ( & message_sha256d_hash( & msg) [ ..] ) ;
2586
+ let node_pubkey = if let Some ( pubkey) = node_pubkey {
2587
+ pubkey
2588
+ } else {
2589
+ debug_assert ! ( false , "node_pubkey should have been decoded above" ) ;
2590
+ let err = "node_pubkey wasn't decoded but we need it to check a sig" . to_owned ( ) ;
2591
+ let action = ErrorAction :: IgnoreAndLog ( Level :: Error ) ;
2592
+ return Err ( LightningError { err, action } ) ;
2593
+ } ;
2569
2594
secp_verify_sig ! ( self . secp_ctx, & msg_hash, & sig, & node_pubkey, "channel_update" ) ;
2570
2595
}
2571
2596
0 commit comments