@@ -756,6 +756,16 @@ impl Node {
756756 None
757757 } ;
758758
759+ // Create subscription manager for WebSocket subscriptions (eth_subscribe)
760+ // This needs to be shared between the RPC server and the event loop
761+ // so that new blocks can be broadcast to subscribers
762+ let subscription_manager = if rpc_storage. is_some ( ) {
763+ use cipherbft_rpc:: SubscriptionManager ;
764+ Some ( Arc :: new ( SubscriptionManager :: default ( ) ) )
765+ } else {
766+ None
767+ } ;
768+
759769 // Start RPC server if enabled
760770 if let Some ( ref storage) = rpc_storage {
761771 use cipherbft_rpc:: {
@@ -772,8 +782,16 @@ impl Node {
772782 let executor = Arc :: new ( StubExecutionApi :: new ( ) ) ;
773783 let network = Arc :: new ( StubNetworkApi :: new ( ) ) ;
774784
775- let rpc_server =
776- RpcServer :: new ( rpc_config, storage. clone ( ) , mempool, executor, network) ;
785+ // Use with_subscription_manager to share the subscription manager
786+ // between the RPC server and the event loop for broadcasting blocks
787+ let rpc_server = RpcServer :: with_subscription_manager (
788+ rpc_config,
789+ storage. clone ( ) ,
790+ mempool,
791+ executor,
792+ network,
793+ subscription_manager. clone ( ) . unwrap ( ) ,
794+ ) ;
777795
778796 let http_port = self . config . rpc_http_port ;
779797 let ws_port = self . config . rpc_ws_port ;
@@ -819,6 +837,7 @@ impl Node {
819837 & mut decided_rx,
820838 execution_bridge,
821839 rpc_storage,
840+ subscription_manager,
822841 )
823842 . await ;
824843
@@ -840,6 +859,7 @@ impl Node {
840859 }
841860
842861 /// Internal event loop that handles messages and can be cancelled.
862+ #[ allow( clippy:: too_many_arguments) ]
843863 async fn run_event_loop (
844864 cancel_token : CancellationToken ,
845865 primary_incoming_rx : & mut mpsc:: Receiver < ( ValidatorId , DclMessage ) > ,
@@ -848,6 +868,7 @@ impl Node {
848868 decided_rx : & mut mpsc:: Receiver < ( ConsensusHeight , Cut ) > ,
849869 execution_bridge : Option < Arc < ExecutionBridge > > ,
850870 rpc_storage : Option < Arc < cipherbft_rpc:: MdbxRpcStorage < InMemoryProvider > > > ,
871+ subscription_manager : Option < Arc < cipherbft_rpc:: SubscriptionManager > > ,
851872 ) -> Result < ( ) > {
852873 loop {
853874 tokio:: select! {
@@ -940,6 +961,14 @@ impl Node {
940961 error!( "Failed to store block {} to MDBX: {}" , height. 0 , e) ;
941962 } else {
942963 debug!( "Stored block {} to MDBX with hash {}" , height. 0 , block_result. block_hash) ;
964+
965+ // Broadcast to WebSocket subscribers (eth_subscribe("newHeads"))
966+ if let Some ( ref sub_mgr) = subscription_manager {
967+ use cipherbft_rpc:: storage_block_to_rpc_block;
968+ let rpc_block = storage_block_to_rpc_block( block. clone( ) , false ) ;
969+ sub_mgr. broadcast_block( rpc_block) ;
970+ debug!( "Broadcast block {} to WebSocket subscribers" , height. 0 ) ;
971+ }
943972 }
944973
945974 // Store receipts for eth_getBlockReceipts queries
0 commit comments