Repository: paritytech/substrate
File: client/network/sync/src/engine.rs (Rust)

Code before:

		// poll `ChainSync` last because of a block announcement was received through the
		// event stream between `SyncingEngine` and `Protocol` and the validation finished
		// right after it as queued, the resulting block request (if any) can be sent right away.
		while let Poll::Ready(result) = self.chain_sync.poll(cx) {
			self.process_block_announce_validation_result(result);
		}

		Poll::Pending
	}

	/// Called by peer when it is disconnecting.
	///
	/// Returns a result if the handshake of this peer was indeed accepted.
	pub fn on_sync_peer_disconnected(&mut self, peer: PeerId) -> Result<(), ()> {
		if let Some(info) = self.peers.remove(&peer) {
			if self.important_peers.contains(&peer) {
				log::warn!(target: "sync", "Reserved peer {} disconnected", peer);
			} else {
				log::debug!(target: "sync", "{} disconnected", peer);
			}

			if !self.default_peers_set_no_slot_connected_peers.remove(&peer) &&
				info.inbound && info.info.roles.is_full()
			{
				self.num_in_peers = self.num_in_peers.saturating_sub(1);
			}

			self.chain_sync.peer_disconnected(&peer);
			self.event_streams
				.retain(|stream| stream.unbounded_send(SyncEvent::PeerDisconnected(peer)).is_ok());
			Ok(())
		} else {
			Err(())
		}
	}

	/// Called on the first connection between two peers on the default set, after their exchange
	/// of handshake.
	///
	/// Returns `Ok` if the handshake is accepted and the peer added to the list of peers we sync
	/// from.
	pub fn on_sync_peer_connected(
		&mut self,
		who: PeerId,
		status: &BlockAnnouncesHandshake<B>,
		sink: NotificationsSink,
		inbound: bool,
	) -> Result<(), ()> {
		log::trace!(target: "sync", "New peer {} {:?}", who, status);


Review comment (bug):
May be add a `debug_assert` & `log::error` that the number was non-zero?

Code after:

		// poll `ChainSync` last because of a block announcement was received through the
		// event stream between `SyncingEngine` and `Protocol` and the validation finished
		// right after it as queued, the resulting block request (if any) can be sent right away.
		while let Poll::Ready(result) = self.chain_sync.poll(cx) {
			self.process_block_announce_validation_result(result);
		}

		Poll::Pending
	}

	/// Called by peer when it is disconnecting.
	///
	/// Returns a result if the handshake of this peer was indeed accepted.
	pub fn on_sync_peer_disconnected(&mut self, peer: PeerId) -> Result<(), ()> {
		if let Some(info) = self.peers.remove(&peer) {
			if self.important_peers.contains(&peer) {
				log::warn!(target: "sync", "Reserved peer {} disconnected", peer);
			} else {
				log::debug!(target: "sync", "{} disconnected", peer);
			}

			if !self.default_peers_set_no_slot_connected_peers.remove(&peer) &&
				info.inbound && info.info.roles.is_full()
			{
				match self.num_in_peers.checked_sub(1) {
					Some(value) => {
						self.num_in_peers = value;
					},
					None => {
						log::error!(
							target: "sync",
							"trying to disconnect an inbound node which is not counted as inbound"
						);
						debug_assert!(false);
					},
				}
			}

			self.chain_sync.peer_disconnected(&peer);
			self.event_streams
				.retain(|stream| stream.unbounded_send(SyncEvent::PeerDisconnected(peer)).is_ok());
			Ok(())
		} else {
			Err(())
		}
	}

	/// Called on the first connection between two peers on the default set, after their exchange
	/// of handshake.
	///