@@ -818,21 +818,19 @@ impl<E: EthSpec> Network<E> {
818818 ///
819819 /// Returns `true` if the subscription was successful and `false` otherwise.
820820 pub fn subscribe ( & mut self , topic : GossipTopic ) -> bool {
821- // update the network globals
822- self . network_globals
823- . gossipsub_subscriptions
824- . write ( )
825- . insert ( topic. clone ( ) ) ;
826-
827- let topic: Topic = topic. into ( ) ;
821+ let libp2p_topic: Topic = topic. clone ( ) . into ( ) ;
828822
829- match self . gossipsub_mut ( ) . subscribe ( & topic ) {
823+ match self . gossipsub_mut ( ) . subscribe ( & libp2p_topic ) {
830824 Err ( e) => {
831825 warn ! ( %topic, error = ?e, "Failed to subscribe to topic" ) ;
832826 false
833827 }
834828 Ok ( _) => {
835829 debug ! ( %topic, "Subscribed to topic" ) ;
830+ self . network_globals
831+ . gossipsub_subscriptions
832+ . write ( )
833+ . insert ( topic) ;
836834 true
837835 }
838836 }
@@ -856,7 +854,12 @@ impl<E: EthSpec> Network<E> {
856854 /// Publishes a list of messages on the pubsub (gossipsub) behaviour, choosing the encoding.
857855 pub fn publish ( & mut self , messages : Vec < PubsubMessage < E > > ) {
858856 for message in messages {
859- for topic in message. topics ( GossipEncoding :: default ( ) , self . enr_fork_id . fork_digest ) {
857+ let fork_digest = gossip_fork_digest_for_publish (
858+ & message,
859+ & self . fork_context ,
860+ self . enr_fork_id . fork_digest ,
861+ ) ;
862+ for topic in message. topics ( GossipEncoding :: default ( ) , fork_digest) {
860863 let message_data = message. encode ( GossipEncoding :: default ( ) ) ;
861864 if let Err ( e) = self
862865 . gossipsub_mut ( )
@@ -2174,3 +2177,98 @@ impl<E: EthSpec> Network<E> {
21742177 }
21752178 }
21762179}
2180+
2181+ /// Fork digest used when publishing a gossip message.
2182+ ///
2183+ /// `ProposerPreferences` uses the digest for `proposal_slot`'s epoch so pre-fork prefs land on the
2184+ /// Gloas topic. All other messages use the current ENR fork digest.
2185+ fn gossip_fork_digest_for_publish < E : EthSpec > (
2186+ message : & PubsubMessage < E > ,
2187+ fork_context : & ForkContext ,
2188+ current_enr_digest : [ u8 ; 4 ] ,
2189+ ) -> [ u8 ; 4 ] {
2190+ match message {
2191+ PubsubMessage :: ProposerPreferences ( prefs) => {
2192+ let epoch = prefs. message . proposal_slot . epoch ( E :: slots_per_epoch ( ) ) ;
2193+ fork_context. context_bytes ( epoch)
2194+ }
2195+ _ => current_enr_digest,
2196+ }
2197+ }
2198+
2199+ #[ cfg( test) ]
2200+ mod gossip_publish_digest_tests {
2201+ use super :: * ;
2202+ use bls:: Signature ;
2203+ use std:: sync:: Arc ;
2204+ use types:: {
2205+ Epoch , Hash256 , MinimalEthSpec , ProposerPreferences , SignedProposerPreferences ,
2206+ SignedVoluntaryExit , VoluntaryExit ,
2207+ } ;
2208+
2209+ type E = MinimalEthSpec ;
2210+
2211+ fn fulu_then_gloas_fork_context ( gloas_epoch : u64 ) -> ForkContext {
2212+ let mut spec = E :: default_spec ( ) ;
2213+ spec. altair_fork_epoch = Some ( Epoch :: new ( 0 ) ) ;
2214+ spec. bellatrix_fork_epoch = Some ( Epoch :: new ( 0 ) ) ;
2215+ spec. capella_fork_epoch = Some ( Epoch :: new ( 0 ) ) ;
2216+ spec. deneb_fork_epoch = Some ( Epoch :: new ( 0 ) ) ;
2217+ spec. electra_fork_epoch = Some ( Epoch :: new ( 0 ) ) ;
2218+ spec. fulu_fork_epoch = Some ( Epoch :: new ( 0 ) ) ;
2219+ spec. gloas_fork_epoch = Some ( Epoch :: new ( gloas_epoch) ) ;
2220+ ForkContext :: new :: < E > ( Slot :: new ( 0 ) , Hash256 :: ZERO , & spec)
2221+ }
2222+
2223+ #[ test]
2224+ fn proposer_preferences_publish_uses_proposal_epoch_digest ( ) {
2225+ let gloas_epoch = 2 ;
2226+ let fork_context = fulu_then_gloas_fork_context ( gloas_epoch) ;
2227+ let fulu_digest = fork_context. context_bytes ( Epoch :: new ( 0 ) ) ;
2228+ let gloas_digest = fork_context. context_bytes ( Epoch :: new ( gloas_epoch) ) ;
2229+ assert_ne ! ( fulu_digest, gloas_digest) ;
2230+ assert_eq ! (
2231+ gloas_digest,
2232+ fork_context
2233+ . spec
2234+ . compute_fork_digest( Hash256 :: ZERO , Epoch :: new( gloas_epoch) )
2235+ ) ;
2236+
2237+ let prefs = SignedProposerPreferences {
2238+ message : ProposerPreferences {
2239+ dependent_root : Hash256 :: ZERO ,
2240+ proposal_slot : Epoch :: new ( gloas_epoch) . start_slot ( E :: slots_per_epoch ( ) ) ,
2241+ validator_index : 1 ,
2242+ fee_recipient : Default :: default ( ) ,
2243+ target_gas_limit : 30_000_000 ,
2244+ } ,
2245+ signature : Signature :: empty ( ) ,
2246+ } ;
2247+ let message = PubsubMessage :: < E > :: ProposerPreferences ( Arc :: new ( prefs) ) ;
2248+
2249+ let digest = gossip_fork_digest_for_publish ( & message, & fork_context, fulu_digest) ;
2250+ assert_eq ! ( digest, gloas_digest) ;
2251+ assert_ne ! ( digest, fulu_digest) ;
2252+ }
2253+
2254+ #[ test]
2255+ fn other_messages_publish_use_current_enr_digest ( ) {
2256+ let fork_context = fulu_then_gloas_fork_context ( 2 ) ;
2257+ let fulu_digest = fork_context. context_bytes ( Epoch :: new ( 0 ) ) ;
2258+ let other_digest = [ 9 , 9 , 9 , 9 ] ;
2259+
2260+ let exit = SignedVoluntaryExit {
2261+ message : VoluntaryExit {
2262+ epoch : Epoch :: new ( 0 ) ,
2263+ validator_index : 0 ,
2264+ } ,
2265+ signature : Signature :: empty ( ) ,
2266+ } ;
2267+ let message = PubsubMessage :: < E > :: VoluntaryExit ( Box :: new ( exit) ) ;
2268+
2269+ let digest = gossip_fork_digest_for_publish ( & message, & fork_context, other_digest) ;
2270+ assert_eq ! ( digest, other_digest) ;
2271+ assert_ne ! ( digest, fork_context. context_bytes( Epoch :: new( 2 ) ) ) ;
2272+ assert_eq ! ( fulu_digest, fork_context. current_fork_digest( ) ) ;
2273+ }
2274+ }
0 commit comments