Network sync refactoring (part 1) (#11303)

* Remove unnecessary imports, move one internal re-export into where it is actually used, make one import explicit

* Move a few data structures down into modules

* Use generic parameters in `sc-network` instead of `chain::Client` trait

* Remove unnecessary bound
This commit is contained in:
Nazar Mokrynskyi
2022-04-29 17:02:03 +03:00
committed by GitHub
parent 887acda7d0
commit af6773aba9
15 changed files with 380 additions and 206 deletions
+26 -42
View File
@@ -39,9 +39,10 @@ use extra_requests::ExtraRequests;
use futures::{stream::FuturesUnordered, task::Poll, Future, FutureExt, StreamExt};
use libp2p::PeerId;
use log::{debug, error, info, trace, warn};
use sc_client_api::{BlockBackend, ProofProvider};
use sc_consensus::{BlockImportError, BlockImportStatus, IncomingBlock};
use sp_arithmetic::traits::Saturating;
use sp_blockchain::{Error as ClientError, HeaderMetadata};
use sp_blockchain::{Error as ClientError, HeaderBackend, HeaderMetadata};
use sp_consensus::{
block_validation::{BlockAnnounceValidator, Validation},
BlockOrigin, BlockStatus,
@@ -54,6 +55,7 @@ use sp_runtime::{
},
EncodedJustification, Justifications,
};
pub use state::StateDownloadProgress;
use state::StateSync;
use std::{
collections::{hash_map::Entry, HashMap, HashSet},
@@ -63,6 +65,7 @@ use std::{
sync::Arc,
};
use warp::{WarpProofRequest, WarpSync, WarpSyncProvider};
pub use warp::{WarpSyncPhase, WarpSyncProgress};
mod blocks;
mod extra_requests;
@@ -194,9 +197,9 @@ struct GapSync<B: BlockT> {
/// The main data structure which contains all the state for a chains
/// active syncing strategy.
pub struct ChainSync<B: BlockT> {
pub struct ChainSync<B: BlockT, Client> {
/// Chain client.
client: Arc<dyn crate::chain::Client<B>>,
client: Arc<Client>,
/// The active peers that we are using to sync and their PeerSync status
peers: HashMap<PeerId, PeerSync<B>>,
/// A `BlockCollection` of blocks that are being downloaded from peers
@@ -228,9 +231,9 @@ pub struct ChainSync<B: BlockT> {
/// Stats per peer about the number of concurrent block announce validations.
block_announce_validation_per_peer_stats: HashMap<PeerId, usize>,
/// State sync in progress, if any.
state_sync: Option<StateSync<B>>,
state_sync: Option<StateSync<B, Client>>,
/// Warp sync in progress, if any.
warp_sync: Option<WarpSync<B>>,
warp_sync: Option<WarpSync<B, Client>>,
/// Warp sync provider.
warp_sync_provider: Option<Arc<dyn WarpSyncProvider<B>>>,
/// Enable importing existing blocks. This is used used after the state download to
@@ -329,30 +332,6 @@ pub enum SyncState {
Downloading,
}
/// Reported state download progress.
#[derive(Clone, Eq, PartialEq, Debug)]
pub struct StateDownloadProgress {
/// Estimated download percentage.
pub percentage: u32,
/// Total state size in bytes downloaded so far.
pub size: u64,
}
/// Reported warp sync phase.
#[derive(Clone, Eq, PartialEq, Debug)]
pub enum WarpSyncPhase<B: BlockT> {
/// Waiting for peers to connect.
AwaitingPeers,
/// Downloading and verifying grandpa warp proofs.
DownloadingWarpProofs,
/// Downloading state data.
DownloadingState,
/// Importing state.
ImportingState,
/// Downloading block history.
DownloadingBlocks(NumberFor<B>),
}
impl<B: BlockT> fmt::Display for WarpSyncPhase<B> {
fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
match self {
@@ -365,15 +344,6 @@ impl<B: BlockT> fmt::Display for WarpSyncPhase<B> {
}
}
/// Reported warp sync progress.
#[derive(Clone, Eq, PartialEq, Debug)]
pub struct WarpSyncProgress<B: BlockT> {
/// Estimated download percentage.
pub phase: WarpSyncPhase<B>,
/// Total bytes downloaded so far.
pub total_bytes: u64,
}
/// Syncing status and statistics.
#[derive(Clone)]
pub struct Status<B: BlockT> {
@@ -534,11 +504,21 @@ enum HasSlotForBlockAnnounceValidation {
MaximumPeerSlotsReached,
}
impl<B: BlockT> ChainSync<B> {
impl<B, Client> ChainSync<B, Client>
where
B: BlockT,
Client: HeaderBackend<B>
+ BlockBackend<B>
+ HeaderMetadata<B, Error = sp_blockchain::Error>
+ ProofProvider<B>
+ Send
+ Sync
+ 'static,
{
/// Create a new instance.
pub fn new(
mode: SyncMode,
client: Arc<dyn crate::chain::Client<B>>,
client: Arc<Client>,
block_announce_validator: Box<dyn BlockAnnounceValidator<B> + Send>,
max_parallel_downloads: u32,
warp_sync_provider: Option<Arc<dyn WarpSyncProvider<B>>>,
@@ -2741,7 +2721,11 @@ mod test {
}
/// Send a block annoucnement for the given `header`.
fn send_block_announce(header: Header, peer_id: &PeerId, sync: &mut ChainSync<Block>) {
fn send_block_announce(
header: Header,
peer_id: &PeerId,
sync: &mut ChainSync<Block, TestClient>,
) {
let block_annnounce = BlockAnnounce {
header: header.clone(),
state: Some(BlockState::Best),
@@ -2780,7 +2764,7 @@ mod test {
/// Get a block request from `sync` and check that is matches the expected request.
fn get_block_request(
sync: &mut ChainSync<Block>,
sync: &mut ChainSync<Block, TestClient>,
from: FromBlock<Hash, u64>,
max: u32,
peer: &PeerId,
@@ -16,14 +16,11 @@
// You should have received a copy of the GNU General Public License
// along with this program. If not, see <https://www.gnu.org/licenses/>.
use super::StateDownloadProgress;
use crate::{
chain::{Client, ImportedState},
schema::v1::{StateEntry, StateRequest, StateResponse},
};
use crate::schema::v1::{StateEntry, StateRequest, StateResponse};
use codec::{Decode, Encode};
use log::debug;
use sc_client_api::CompactProof;
use sc_client_api::{CompactProof, ProofProvider};
use sc_consensus::ImportedState;
use smallvec::SmallVec;
use sp_core::storage::well_known_keys;
use sp_runtime::traits::{Block as BlockT, Header, NumberFor};
@@ -33,18 +30,27 @@ use std::{collections::HashMap, sync::Arc};
/// State sync state machine. Accumulates partial state data until it
/// is ready to be imported.
pub struct StateSync<B: BlockT> {
pub struct StateSync<B: BlockT, Client> {
target_block: B::Hash,
target_header: B::Header,
target_root: B::Hash,
last_key: SmallVec<[Vec<u8>; 2]>,
state: HashMap<Vec<u8>, (Vec<(Vec<u8>, Vec<u8>)>, Vec<Vec<u8>>)>,
complete: bool,
client: Arc<dyn Client<B>>,
client: Arc<Client>,
imported_bytes: u64,
skip_proof: bool,
}
/// Reported state download progress.
#[derive(Clone, Eq, PartialEq, Debug)]
pub struct StateDownloadProgress {
/// Estimated download percentage.
pub percentage: u32,
/// Total state size in bytes downloaded so far.
pub size: u64,
}
/// Import state chunk result.
pub enum ImportResult<B: BlockT> {
/// State is complete and ready for import.
@@ -55,9 +61,13 @@ pub enum ImportResult<B: BlockT> {
BadResponse,
}
impl<B: BlockT> StateSync<B> {
impl<B, Client> StateSync<B, Client>
where
B: BlockT,
Client: ProofProvider<B> + Send + Sync + 'static,
{
/// Create a new instance.
pub fn new(client: Arc<dyn Client<B>>, target: B::Header, skip_proof: bool) -> Self {
pub fn new(client: Arc<Client>, target: B::Header, skip_proof: bool) -> Self {
Self {
client,
target_block: target.hash(),
@@ -71,7 +81,7 @@ impl<B: BlockT> StateSync<B> {
}
}
/// Validate and import a state reponse.
/// Validate and import a state response.
pub fn import(&mut self, response: StateResponse) -> ImportResult<B> {
if response.entries.is_empty() && response.proof.is_empty() {
debug!(target: "sync", "Bad state response");
@@ -17,23 +17,44 @@
// along with this program. If not, see <https://www.gnu.org/licenses/>.
///! Warp sync support.
pub use super::state::ImportResult;
use super::state::StateSync;
use super::state::{ImportResult, StateSync};
use crate::schema::v1::{StateRequest, StateResponse};
pub use crate::warp_request_handler::{
EncodedProof, Request as WarpProofRequest, VerificationResult, WarpSyncProvider,
};
use crate::{
chain::Client,
schema::v1::{StateRequest, StateResponse},
WarpSyncPhase, WarpSyncProgress,
};
use sc_client_api::ProofProvider;
use sp_blockchain::HeaderBackend;
use sp_finality_grandpa::{AuthorityList, SetId};
use sp_runtime::traits::{Block as BlockT, NumberFor, Zero};
use std::sync::Arc;
enum Phase<B: BlockT> {
enum Phase<B: BlockT, Client> {
WarpProof { set_id: SetId, authorities: AuthorityList, last_hash: B::Hash },
State(StateSync<B>),
State(StateSync<B, Client>),
}
/// Reported warp sync phase.
#[derive(Clone, Eq, PartialEq, Debug)]
pub enum WarpSyncPhase<B: BlockT> {
/// Waiting for peers to connect.
AwaitingPeers,
/// Downloading and verifying grandpa warp proofs.
DownloadingWarpProofs,
/// Downloading state data.
DownloadingState,
/// Importing state.
ImportingState,
/// Downloading block history.
DownloadingBlocks(NumberFor<B>),
}
/// Reported warp sync progress.
#[derive(Clone, Eq, PartialEq, Debug)]
pub struct WarpSyncProgress<B: BlockT> {
/// Estimated download percentage.
pub phase: WarpSyncPhase<B>,
/// Total bytes downloaded so far.
pub total_bytes: u64,
}
/// Import warp proof result.
@@ -45,19 +66,20 @@ pub enum WarpProofImportResult {
}
/// Warp sync state machine. Accumulates warp proofs and state.
pub struct WarpSync<B: BlockT> {
phase: Phase<B>,
client: Arc<dyn Client<B>>,
pub struct WarpSync<B: BlockT, Client> {
phase: Phase<B, Client>,
client: Arc<Client>,
warp_sync_provider: Arc<dyn WarpSyncProvider<B>>,
total_proof_bytes: u64,
}
impl<B: BlockT> WarpSync<B> {
impl<B, Client> WarpSync<B, Client>
where
B: BlockT,
Client: HeaderBackend<B> + ProofProvider<B> + 'static,
{
/// Create a new instance.
pub fn new(
client: Arc<dyn Client<B>>,
warp_sync_provider: Arc<dyn WarpSyncProvider<B>>,
) -> Self {
pub fn new(client: Arc<Client>, warp_sync_provider: Arc<dyn WarpSyncProvider<B>>) -> Self {
let last_hash = client.hash(Zero::zero()).unwrap().expect("Genesis header always exists");
let phase = Phase::WarpProof {
set_id: 0,