From d222abcf14da28f6f4ec833341273a14c015192b Mon Sep 17 00:00:00 2001 From: liuchengxu Date: Sun, 27 Oct 2024 08:52:14 +0000 Subject: [PATCH] =?UTF-8?q?Deploying=20to=20gh-pages=20from=20@=20subcoin-?= =?UTF-8?q?project/subcoin@8c5113709d045d3fc33fd278e41d45ae428f24f5=20?= =?UTF-8?q?=F0=9F=9A=80?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- src/subcoin_network/block_downloader.rs.html | 2 +- .../block_downloader/blocks_first.rs.html | 14 +- .../block_downloader/headers_first.rs.html | 16 +- src/subcoin_network/peer_manager.rs.html | 70 ++++- src/subcoin_network/sync.rs.html | 250 +++++++++++------- src/subcoin_network/worker.rs.html | 34 ++- src/subcoin_rpc/network.rs.html | 26 +- subcoin_test_service/fn.new_test_node.html | 2 +- .../fn.new_test_node_and_produce_blocks.html | 2 +- 9 files changed, 247 insertions(+), 169 deletions(-) diff --git a/src/subcoin_network/block_downloader.rs.html b/src/subcoin_network/block_downloader.rs.html index 5cc38f54..5b818aeb 100644 --- a/src/subcoin_network/block_downloader.rs.html +++ b/src/subcoin_network/block_downloader.rs.html @@ -514,7 +514,7 @@ _ => 512, }; - let queued_blocks = self.best_queued_number - best_number; + let queued_blocks = self.best_queued_number.saturating_sub(best_number); if queued_blocks > max_queued_blocks { self.queue_status = ImportQueueStatus::Overloaded; diff --git a/src/subcoin_network/block_downloader/blocks_first.rs.html b/src/subcoin_network/block_downloader/blocks_first.rs.html index f468dc3d..69c6ca5f 100644 --- a/src/subcoin_network/block_downloader/blocks_first.rs.html +++ b/src/subcoin_network/block_downloader/blocks_first.rs.html @@ -513,10 +513,6 @@ 513 514 515 -516 -517 -518 -519
use crate::block_downloader::BlockDownloadManager;
 use crate::peer_store::PeerStore;
 use crate::sync::{LocatorRequest, SyncAction, SyncRequest};
@@ -620,11 +616,7 @@
     }
 
     pub(crate) fn replaceable_sync_peer(&self) -> Option<PeerId> {
-        if self.downloaded_blocks_count > 0 {
-            None
-        } else {
-            Some(self.peer_id)
-        }
+        (self.downloaded_blocks_count == 0).then_some(self.peer_id)
     }
 
     pub(crate) fn replace_sync_peer(&mut self, peer_id: PeerId, target_block_number: u32) {
@@ -663,7 +655,7 @@
 
         if best_number == self.target_block_number {
             self.state = State::Completed;
-            return SyncAction::SwitchToIdle;
+            return SyncAction::SetIdle;
         }
 
         if self.download_manager.is_stalled(self.peer_id) {
@@ -818,7 +810,7 @@
                             "Received block #{block_number},{block_hash} higher than the target block"
                         );
                         self.state = State::Completed;
-                        SyncAction::SwitchToIdle
+                        SyncAction::SetIdle
                     } else {
                         self.state = State::Disconnecting;
                         SyncAction::Disconnect(
diff --git a/src/subcoin_network/block_downloader/headers_first.rs.html b/src/subcoin_network/block_downloader/headers_first.rs.html
index 2b5c1601..75cb386a 100644
--- a/src/subcoin_network/block_downloader/headers_first.rs.html
+++ b/src/subcoin_network/block_downloader/headers_first.rs.html
@@ -688,12 +688,6 @@
 688
 689
 690
-691
-692
-693
-694
-695
-696
 
use crate::block_downloader::BlockDownloadManager;
 use crate::peer_store::PeerStore;
 use crate::sync::{LocatorRequest, SyncAction, SyncRequest};
@@ -824,9 +818,7 @@
     downloaded_headers: DownloadedHeaders,
     downloaded_blocks_count: usize,
     last_locator_start: u32,
-    // TODO: Now it's solely used for the purpose of displaying the sync state.
-    // refactor it later.
-    target_block_number: u32,
+    target_block_number: u32,
     _phantom: PhantomData<Block>,
 }
 
@@ -876,11 +868,7 @@
     }
 
     pub(crate) fn replaceable_sync_peer(&self) -> Option<PeerId> {
-        if self.downloaded_blocks_count > 0 {
-            None
-        } else {
-            Some(self.peer_id)
-        }
+        (self.downloaded_blocks_count == 0).then_some(self.peer_id)
     }
 
     pub(crate) fn replace_sync_peer(&mut self, peer_id: PeerId, target_block_number: u32) {
diff --git a/src/subcoin_network/peer_manager.rs.html b/src/subcoin_network/peer_manager.rs.html
index 1c44426c..29fcdb2d 100644
--- a/src/subcoin_network/peer_manager.rs.html
+++ b/src/subcoin_network/peer_manager.rs.html
@@ -771,6 +771,30 @@
 771
 772
 773
+774
+775
+776
+777
+778
+779
+780
+781
+782
+783
+784
+785
+786
+787
+788
+789
+790
+791
+792
+793
+794
+795
+796
+797
 
use crate::address_book::AddressBook;
 use crate::connection::{ConnectionInitiator, ConnectionWriter, Direction, NewConnection};
 use crate::metrics::Metrics;
@@ -1088,7 +1112,7 @@
         }
     }
 
-    pub(crate) fn on_tick(&mut self) -> Option<SlowPeer> {
+    pub(crate) fn on_tick(&mut self) -> (Vec<PeerId>, Option<SlowPeer>) {
         let mut timeout_peers = vec![];
         let mut should_ping_peers = vec![];
 
@@ -1107,10 +1131,6 @@
             self.send_pings(should_ping_peers);
         }
 
-        for peer_id in timeout_peers {
-            self.disconnect(peer_id, Error::PingTimeout);
-        }
-
         let outbound_peers_count = self
             .connected_peers
             .values()
@@ -1133,6 +1153,13 @@
                 .set(self.address_book.available_addresses_count() as u64);
         }
 
+        let maybe_slow_peer = self.manage_outbound_connections(outbound_peers_count);
+
+        (timeout_peers, maybe_slow_peer)
+    }
+
+    /// Manages outbound connections by initiating new connections or evicting slow peers.
+    fn manage_outbound_connections(&mut self, outbound_peers_count: usize) -> Option<SlowPeer> {
         if outbound_peers_count < self.max_outbound_peers {
             if let Some(addr) = self.address_book.pop() {
                 if !self.connections.contains_key(&addr) {
@@ -1215,7 +1242,19 @@
         }
     }
 
-    /// Disconnect from a peer with given reason, do nothing if the peer is persistent.
+    /// Disconnects from a specified peer, unless it is designated as persistent, with a given reason.
+    ///
+    /// # Important Notes
+    ///
+    /// - **Syncing Components:** This function, as well as [`Self::evict`], should not be invoked
+    ///   directly within the peer manager module without triggering a notification. For example,
+    ///   chain sync might depend on receiving a disconnect notification to correctly update their
+    ///   internal state, which helps maintain a consistent peer set between the peer manager and
+    ///   other modules.
+    ///
+    /// - **Potential for Inconsistent State:** Bypassing notifications may lead to inconsistency
+    ///   between the peer manager and modules that rely on peer status, resulting in unexpected
+    ///   issues in the peer set or other connected components.
     pub(crate) fn disconnect(&mut self, peer_id: PeerId, reason: Error) {
         if self.config.persistent.contains(&peer_id) {
             return;
@@ -1238,6 +1277,20 @@
         self.connected_peers.remove(&peer_id);
     }
 
+    /// Evicts a peer, disconnecting it with a specified reason and updating the eviction timestamp.
+    ///
+    /// This function internally calls [`Self::disconnect`] to carry out the disconnection
+    /// process and subsequently records the current time as the `last_eviction` timestamp.
+    ///
+    /// # Important Note
+    ///
+    /// Just like with `disconnect`, any call to `evict` should be accompanied by necessary
+    /// notifications to avoid state inconsistencies.
+    pub(crate) fn evict(&mut self, peer_id: PeerId, reason: Error) {
+        self.disconnect(peer_id, reason);
+        self.last_eviction = Instant::now();
+    }
+
     /// Sets the prefer addrv2 flag for a peer.
     pub(crate) fn set_want_addrv2(&mut self, peer_id: PeerId) {
         self.connected_peers.entry(peer_id).and_modify(|info| {
@@ -1252,11 +1305,6 @@
         });
     }
 
-    pub(crate) fn evict(&mut self, peer_id: PeerId, reason: Error) {
-        self.disconnect(peer_id, reason);
-        self.last_eviction = Instant::now();
-    }
-
     /// Checks if a peer is connected.
     pub(crate) fn is_connected(&self, peer_id: PeerId) -> bool {
         self.connected_peers.contains_key(&peer_id)
diff --git a/src/subcoin_network/sync.rs.html b/src/subcoin_network/sync.rs.html
index fcf5466d..550a2d18 100644
--- a/src/subcoin_network/sync.rs.html
+++ b/src/subcoin_network/sync.rs.html
@@ -739,6 +739,30 @@
 739
 740
 741
+742
+743
+744
+745
+746
+747
+748
+749
+750
+751
+752
+753
+754
+755
+756
+757
+758
+759
+760
+761
+762
+763
+764
+765
 
use crate::block_downloader::{BlocksFirstDownloader, HeadersFirstDownloader};
 use crate::peer_manager::NewPeer;
 use crate::peer_store::PeerStore;
@@ -846,20 +870,26 @@
 pub(crate) enum SyncAction {
     /// Fetch headers, blocks and data.
     Request(SyncRequest),
-    /// Headers-First sync completed, use the Blocks-First sync
-    /// to download the recent blocks.
+    /// Transitions to a Blocks-First sync after Headers-First sync
+    /// compltes, to fetch the most recent blocks.
     SwitchToBlocksFirstSync,
     /// Disconnect from the peer for the given reason.
     Disconnect(PeerId, Error),
-    /// Make this peer as deprioritized and restart the current syncing
-    /// process using other sync candidates if there are any.
+    /// Deprioritize the specified peer, restarting the current sync
+    /// with other candidates if available.
     RestartSyncWithStalledPeer(PeerId),
-    /// Blocks-First sync finished, switch syncing state to idle.
-    SwitchToIdle,
+    /// Blocks-First sync finished and sets the syncing state to idle.
+    SetIdle,
     /// No action needed.
     None,
 }
 
+#[derive(Debug)]
+pub(crate) enum RestartReason {
+    Stalled,
+    Disconnected,
+}
+
 // This enum encapsulates the various strategies and states a node
 // might be in during the sync process.
 enum Syncing<Block, Client> {
@@ -970,80 +1000,112 @@
             .collect()
     }
 
-    /// Attempts to restart the sync due to the stalled peer.
-    ///
-    /// Returns `true` if the sync is restarted with a new peer.
-    pub(super) fn restart_sync(&mut self, stalled_peer: PeerId) -> bool {
-        let our_best = self.client.best_number();
+    /// Removes the given peer from peers of chain sync.
+    pub(super) fn disconnect(&mut self, peer_id: PeerId) {
+        if let Some(removed_peer) = self.peers.remove(&peer_id) {
+            // We currently support only one syncing peer, this logic needs to be
+            // refactored once multiple syncing peers are supported.
+            if matches!(removed_peer.state, PeerSyncState::DownloadingNew { .. }) {
+                self.restart_sync(removed_peer.peer_id, RestartReason::Disconnected);
+            }
+        }
+    }
 
-        // First, try to find the best available peer for syncing.
-        let new_available_peer = self
-            .peers
-            .values_mut()
+    /// Attempt to find the best available peer, falling back to a random choice if needed
+    fn select_next_peer_for_sync(
+        &mut self,
+        our_best: u32,
+        excluded_peer: PeerId,
+    ) -> Option<PeerId> {
+        self.peers
+            .values()
             .filter(|peer| {
-                peer.peer_id != stalled_peer
+                peer.peer_id != excluded_peer
                     && peer.best_number > our_best
                     && peer.state.is_available()
             })
-            .max_by_key(|peer| peer.best_number);
-
-        let new_peer = match new_available_peer {
-            Some(peer) => peer,
-            None => {
+            .max_by_key(|peer| peer.best_number)
+            .map(|peer| peer.peer_id)
+            .or_else(|| {
                 let sync_candidates = self
                     .peers
-                    .values_mut()
-                    .filter(|peer| peer.peer_id != stalled_peer && peer.best_number > our_best)
+                    .values()
+                    .filter(|peer| peer.peer_id != excluded_peer && peer.best_number > our_best)
                     .collect::<Vec<_>>();
 
-                if sync_candidates.is_empty() {
-                    if let Some(median_seen_block) = self.median_seen() {
-                        let best_seen_block = self.peers.values().map(|p| p.best_number).max();
-
-                        if median_seen_block <= our_best {
-                            // We are synced to the median block seen by our peers, but this may
-                            // not be the network's tip.
-                            //
-                            // Transition to idle unless more blocks are announced.
-                            tracing::debug!(
-                                best_seen_block,
-                                median_seen_block,
-                                our_best,
-                                "Synced to the majority of peers, no new blocks to sync"
-                            );
-                            self.syncing = Syncing::Idle;
-                            return false;
-                        }
-                    }
+                // Pick a random peer, even if it's marked as deprioritized.
+                self.rng.choice(sync_candidates).map(|peer| peer.peer_id)
+            })
+    }
 
-                    // No new sync candidate, keep it as is.
-                    // TODO: handle this properly.
-                    tracing::debug!(?stalled_peer, "⚠️ Sync stalled, but no new sync candidates");
+    /// Attempts to restart the sync based on the reason provided.
+    ///
+    /// Returns `true` if the sync is restarted with a new peer.
+    pub(super) fn restart_sync(&mut self, prior_peer_id: PeerId, reason: RestartReason) {
+        let our_best = self.client.best_number();
 
-                    return false;
+        let Some(new_peer_id) = self.select_next_peer_for_sync(our_best, prior_peer_id) else {
+            if let Some(median_seen_block) = self.median_seen() {
+                if median_seen_block <= our_best {
+                    let best_seen_block = self.peers.values().map(|p| p.best_number).max();
+
+                    // We are synced to the median block seen by our peers, but this may
+                    // not be the network's tip.
+                    //
+                    // Transition to idle unless more blocks are announced.
+                    tracing::debug!(
+                        best_seen_block,
+                        median_seen_block,
+                        our_best,
+                        "Synced to the majority of peers, switching to Idle"
+                    );
+                    self.update_syncing_state(Syncing::Idle);
+                    return;
                 }
-
-                // Pick a random peer, even if it's marked as deprioritized.
-                self.rng
-                    .choice(sync_candidates)
-                    .expect("Sync candidates must be non-empty as checked; qed")
             }
+
+            // No new sync candidate, keep it as is.
+            // TODO: handle this properly.
+            tracing::debug!(
+                ?prior_peer_id,
+                "⚠️ Attempting to restart sync, but no new sync candidate available"
+            );
+
+            return;
         };
 
-        tracing::debug!(?stalled_peer, ?new_peer, "🔄 Sync stalled, restarting");
+        {
+            let Some(new_peer) = self.peers.get_mut(&new_peer_id) else {
+                tracing::error!("Corrupted state, next peer {new_peer_id} missing from peer list");
+                return;
+            };
 
-        new_peer.state = PeerSyncState::DownloadingNew { start: our_best };
+            tracing::debug!(?reason, ?prior_peer_id, ?new_peer, "🔄 Sync restarted");
+            new_peer.state = PeerSyncState::DownloadingNew { start: our_best };
 
-        match &mut self.syncing {
-            Syncing::BlocksFirst(downloader) => {
-                downloader.restart(new_peer.peer_id, new_peer.best_number);
-                true
-            }
-            Syncing::HeadersFirst(downloader) => {
-                downloader.restart(new_peer.peer_id, new_peer.best_number);
-                true
+            match &mut self.syncing {
+                Syncing::BlocksFirst(downloader) => {
+                    downloader.restart(new_peer.peer_id, new_peer.best_number);
+                }
+                Syncing::HeadersFirst(downloader) => {
+                    downloader.restart(new_peer.peer_id, new_peer.best_number);
+                }
+                Syncing::Idle => {}
+            }
+        }
+
+        match reason {
+            RestartReason::Stalled => {
+                self.peers.entry(prior_peer_id).and_modify(|p| {
+                    let current_stalled_count = p.state.stalled_count();
+                    p.state = PeerSyncState::Deprioritized {
+                        stalled_count: current_stalled_count + 1,
+                    };
+                });
+            }
+            RestartReason::Disconnected => {
+                // Nothing to be done, peer is already removed from the peer list.
             }
-            Syncing::Idle => false,
         }
     }
 
@@ -1064,20 +1126,6 @@
         }
     }
 
-    pub(super) fn note_peer_stalled(&mut self, stalled_peer: PeerId) {
-        self.peers.entry(stalled_peer).and_modify(|p| {
-            let current_stalled_count = p.state.stalled_count();
-            p.state = PeerSyncState::Deprioritized {
-                stalled_count: current_stalled_count + 1,
-            };
-        });
-    }
-
-    pub(super) fn remove_peer(&mut self, peer_id: PeerId) {
-        // TODO: handle the situation that the peer is being involved in the downloader.
-        self.peers.remove(&peer_id);
-    }
-
     pub(super) fn update_peer_latency(&mut self, peer_id: PeerId, avg_latency: Latency) {
         self.peers.entry(peer_id).and_modify(|peer| {
             peer.latency = avg_latency;
@@ -1087,9 +1135,9 @@
 
     pub(super) fn update_sync_peer_on_lower_latency(&mut self) {
         let maybe_sync_peer_id = match &self.syncing {
+            Syncing::Idle => return,
             Syncing::BlocksFirst(downloader) => downloader.replaceable_sync_peer(),
             Syncing::HeadersFirst(downloader) => downloader.replaceable_sync_peer(),
-            Syncing::Idle => return,
         };
 
         let Some(current_sync_peer_id) = maybe_sync_peer_id else {
@@ -1155,6 +1203,9 @@
                 self.peers.entry(current_sync_peer_id).and_modify(|peer| {
                     peer.state = PeerSyncState::Available;
                 });
+                self.peers.entry(peer_id).and_modify(|peer| {
+                    peer.state = PeerSyncState::DownloadingNew { start: our_best };
+                });
             }
         }
     }
@@ -1291,13 +1342,12 @@
     }
 
     fn update_syncing_state(&mut self, new: Syncing<Block, Client>) {
-        let is_major_syncing = new.is_major_syncing();
         self.syncing = new;
         self.is_major_syncing
-            .store(is_major_syncing, Ordering::Relaxed);
+            .store(self.syncing.is_major_syncing(), Ordering::Relaxed);
     }
 
-    pub(super) fn switch_to_idle(&mut self) {
+    pub(super) fn set_idle(&mut self) {
         tracing::debug!(
             best_number = self.client.best_number(),
             "Blocks-First sync completed, switching to Syncing::Idle"
@@ -1346,7 +1396,7 @@
                 if inventories.len() == 1 {
                     if let Inventory::Block(block_hash) = inventories[0] {
                         if !self.inflight_announced_blocks.contains(&block_hash) {
-                            // A new block maybe broadcasted via `inv` message.
+                            // A new block is broadcasted via `inv` message.
                             tracing::trace!(
                                 "Requesting a new block {block_hash} announced from {from:?}"
                             );
@@ -1361,22 +1411,6 @@
         }
     }
 
-    pub(super) fn on_block(&mut self, block: BitcoinBlock, from: PeerId) -> SyncAction {
-        if self.inflight_announced_blocks.remove(&block.block_hash()) {
-            self.import_queue.import_blocks(ImportBlocks {
-                origin: BlockOrigin::NetworkBroadcast,
-                blocks: vec![block],
-            });
-            return SyncAction::None;
-        }
-
-        match &mut self.syncing {
-            Syncing::Idle => SyncAction::None,
-            Syncing::BlocksFirst(downloader) => downloader.on_block(block, from),
-            Syncing::HeadersFirst(downloader) => downloader.on_block(block, from),
-        }
-    }
-
     fn announced_blocks_request(
         &mut self,
         block_hashes: impl IntoIterator<Item = BlockHash>,
@@ -1396,6 +1430,22 @@
         SyncAction::Request(data_request)
     }
 
+    pub(super) fn on_block(&mut self, block: BitcoinBlock, from: PeerId) -> SyncAction {
+        match &mut self.syncing {
+            Syncing::Idle => {
+                if self.inflight_announced_blocks.remove(&block.block_hash()) {
+                    self.import_queue.import_blocks(ImportBlocks {
+                        origin: BlockOrigin::NetworkBroadcast,
+                        blocks: vec![block],
+                    });
+                }
+                SyncAction::None
+            }
+            Syncing::BlocksFirst(downloader) => downloader.on_block(block, from),
+            Syncing::HeadersFirst(downloader) => downloader.on_block(block, from),
+        }
+    }
+
     pub(super) fn on_headers(&mut self, headers: Vec<BitcoinHeader>, from: PeerId) -> SyncAction {
         match &mut self.syncing {
             Syncing::HeadersFirst(downloader) => downloader.on_headers(headers, from),
@@ -1421,10 +1471,8 @@
                         }
                     }
 
-                    return self.announced_blocks_request(
-                        headers.into_iter().map(|header| header.block_hash()),
-                        from,
-                    );
+                    let new_blocks = headers.into_iter().map(|header| header.block_hash());
+                    return self.announced_blocks_request(new_blocks, from);
                 }
 
                 tracing::debug!(
diff --git a/src/subcoin_network/worker.rs.html b/src/subcoin_network/worker.rs.html
index f7b0864a..84c329a7 100644
--- a/src/subcoin_network/worker.rs.html
+++ b/src/subcoin_network/worker.rs.html
@@ -530,6 +530,10 @@
 530
 531
 532
+533
+534
+535
+536
 
use crate::connection::{ConnectionInitiator, Direction, NewConnection};
 use crate::metrics::Metrics;
 use crate::network::{
@@ -537,7 +541,7 @@
 };
 use crate::peer_manager::{Config, NewPeer, PeerManager, SlowPeer, PEER_LATENCY_THRESHOLD};
 use crate::peer_store::PeerStore;
-use crate::sync::{ChainSync, LocatorRequest, SyncAction, SyncRequest};
+use crate::sync::{ChainSync, LocatorRequest, RestartReason, SyncAction, SyncRequest};
 use crate::transaction_manager::TransactionManager;
 use crate::{Bandwidth, Error, PeerId, SyncStrategy};
 use bitcoin::p2p::message::{NetworkMessage, MAX_INV_SIZE};
@@ -714,7 +718,7 @@
             }
             Event::Disconnect { peer_addr, reason } => {
                 self.peer_manager.disconnect(peer_addr, reason);
-                self.chain_sync.remove_peer(peer_addr);
+                self.chain_sync.disconnect(peer_addr);
                 self.peer_store.remove_peer(peer_addr);
             }
             Event::PeerMessage {
@@ -749,13 +753,18 @@
 
         for peer in self.chain_sync.unreliable_peers() {
             self.peer_manager.disconnect(peer, Error::UnreliablePeer);
-            self.chain_sync.remove_peer(peer);
+            self.chain_sync.disconnect(peer);
             self.peer_store.remove_peer(peer);
         }
 
-        if let Some(SlowPeer { peer_id, latency }) = self.peer_manager.on_tick() {
+        let (timeout_peers, maybe_slow_peer) = self.peer_manager.on_tick();
+        timeout_peers.into_iter().for_each(|peer_id| {
+            self.peer_manager.disconnect(peer_id, Error::PingTimeout);
+            self.chain_sync.disconnect(peer_id);
+        });
+        if let Some(SlowPeer { peer_id, latency }) = maybe_slow_peer {
             self.peer_manager.evict(peer_id, Error::SlowPeer(latency));
-            self.chain_sync.remove_peer(peer_id);
+            self.chain_sync.disconnect(peer_id);
         }
 
         let connected_peers = self.peer_manager.connected_peers();
@@ -879,7 +888,7 @@
                         if avg_latency > PEER_LATENCY_THRESHOLD {
                             self.peer_manager
                                 .disconnect(from, Error::PingLatencyTooHigh(avg_latency));
-                            self.chain_sync.remove_peer(from);
+                            self.chain_sync.disconnect(from);
                             self.peer_store.remove_peer(from);
                         } else {
                             if self.chain_sync.peers.contains_key(&from) {
@@ -899,7 +908,7 @@
                     }
                     Err(err) => {
                         self.peer_manager.disconnect(from, err);
-                        self.chain_sync.remove_peer(from);
+                        self.chain_sync.disconnect(from);
                         self.peer_store.remove_peer(from);
                     }
                 }
@@ -982,17 +991,16 @@
                     self.send_get_blocks_request(request);
                 }
             }
-            SyncAction::SwitchToIdle => {
-                self.chain_sync.switch_to_idle();
+            SyncAction::SetIdle => {
+                self.chain_sync.set_idle();
             }
             SyncAction::RestartSyncWithStalledPeer(stalled_peer_id) => {
-                if self.chain_sync.restart_sync(stalled_peer_id) {
-                    self.chain_sync.note_peer_stalled(stalled_peer_id);
-                }
+                self.chain_sync
+                    .restart_sync(stalled_peer_id, RestartReason::Stalled);
             }
             SyncAction::Disconnect(peer_id, reason) => {
                 self.peer_manager.disconnect(peer_id, reason);
-                self.chain_sync.remove_peer(peer_id);
+                self.chain_sync.disconnect(peer_id);
             }
             SyncAction::None => {}
         }
diff --git a/src/subcoin_rpc/network.rs.html b/src/subcoin_rpc/network.rs.html
index c6398617..a5662e37 100644
--- a/src/subcoin_rpc/network.rs.html
+++ b/src/subcoin_rpc/network.rs.html
@@ -107,9 +107,6 @@
 107
 108
 109
-110
-111
-112
 
use crate::error::Error;
 use jsonrpsee::proc_macros::rpc;
 use sc_client_api::{AuxStore, BlockBackend, HeaderBackend};
@@ -129,11 +126,12 @@
     DownloadingNew,
 }
 
-#[derive(Clone, Serialize, Deserialize)]
+/// Overview of peers in chain sync.
+#[derive(Clone, Serialize, Deserialize)]
 #[serde(rename_all = "camelCase")]
-pub struct NetworkPeers {
+pub struct SyncPeers {
     /// A map containing the count of peers in each sync state (e.g., syncing, idle).
-    sync_state_counts: BTreeMap<SyncState, usize>,
+    peer_counts: BTreeMap<SyncState, usize>,
     /// The highest block height known across all peers in the network.
     best_known_block: Option<u32>,
     /// Detailed synchronization information for each peer.
@@ -143,8 +141,8 @@
 #[rpc(client, server)]
 pub trait NetworkApi {
     /// Get the sync peers.
-    #[method(name = "network_peers")]
-    async fn network_peers(&self) -> Result<NetworkPeers, Error>;
+    #[method(name = "network_syncPeers")]
+    async fn network_sync_peers(&self) -> Result<SyncPeers, Error>;
 
     /// Get overall network status.
     #[method(name = "network_status")]
@@ -180,7 +178,7 @@
     Block: BlockT + 'static,
     Client: HeaderBackend<Block> + BlockBackend<Block> + AuxStore + 'static,
 {
-    async fn network_peers(&self) -> Result<NetworkPeers, Error> {
+    async fn network_sync_peers(&self) -> Result<SyncPeers, Error> {
         let mut sync_peers = self.network_handle.sync_peers().await;
 
         let mut available = 0;
@@ -203,17 +201,13 @@
 
         sync_peers.sort_by_key(|x| x.latency);
 
-        Ok(NetworkPeers {
-            sync_state_counts: BTreeMap::from([
+        Ok(SyncPeers {
+            peer_counts: BTreeMap::from([
                 (SyncState::Available, available),
                 (SyncState::Deprioritized, deprioritized),
                 (SyncState::DownloadingNew, downloading_new),
             ]),
-            best_known_block: if best_known_block > 0 {
-                Some(best_known_block)
-            } else {
-                None
-            },
+            best_known_block: (best_known_block > 0).then_some(best_known_block),
             peer_sync_details: sync_peers,
         })
     }
diff --git a/subcoin_test_service/fn.new_test_node.html b/subcoin_test_service/fn.new_test_node.html
index a5799302..a603fb5f 100644
--- a/subcoin_test_service/fn.new_test_node.html
+++ b/subcoin_test_service/fn.new_test_node.html
@@ -1 +1 @@
-new_test_node in subcoin_test_service - Rust

Function subcoin_test_service::new_test_node

source ·
pub fn new_test_node(tokio_handle: Handle) -> Result<NodeComponents, Error>
\ No newline at end of file +new_test_node in subcoin_test_service - Rust

Function subcoin_test_service::new_test_node

source ·
pub fn new_test_node(tokio_handle: Handle) -> Result<NodeComponents, Error>
\ No newline at end of file diff --git a/subcoin_test_service/fn.new_test_node_and_produce_blocks.html b/subcoin_test_service/fn.new_test_node_and_produce_blocks.html index 54afbf0f..6cc8ecac 100644 --- a/subcoin_test_service/fn.new_test_node_and_produce_blocks.html +++ b/subcoin_test_service/fn.new_test_node_and_produce_blocks.html @@ -1,4 +1,4 @@ new_test_node_and_produce_blocks in subcoin_test_service - Rust
pub async fn new_test_node_and_produce_blocks(
     config: &Configuration,
     up_to: u32,
-) -> Arc<FullClient>
\ No newline at end of file +) -> Arc<FullClient>
\ No newline at end of file