* State sync

* Importing state fixes

* Bugfixes

* Sync with proof

* Status reporting

* Unsafe sync mode

* Sync test

* Cleanup

* Apply suggestions from code review

Co-authored-by: cheme <emericchevalier.pro@gmail.com>
Co-authored-by: Pierre Krieger <pierre.krieger1708@gmail.com>

* set_genesis_storage

* Extract keys from range proof

* Detect iter completion

* Download and import bodies with fast sync

* Replaced meta updates tuple with a struct

* Fixed reverting finalized state

* Reverted timeout

* Typo

* Doc

* Doc

* Fixed light client test

* Fixed error handling

* Tweaks

* More UpdateMeta changes

* Rename convert_transaction

* Apply suggestions from code review

Co-authored-by: Bastian Köcher <bkchr@users.noreply.github.com>

* Apply suggestions from code review

Co-authored-by: Bastian Köcher <bkchr@users.noreply.github.com>

* Code review suggestions

* Fixed count handling

Co-authored-by: cheme <emericchevalier.pro@gmail.com>
Co-authored-by: Pierre Krieger <pierre.krieger1708@gmail.com>
Co-authored-by: Bastian Köcher <bkchr@users.noreply.github.com>
This commit is contained in:
Arkadiy Paronyan
2021-06-22 11:32:43 +02:00
committed by GitHub
parent 5899eedc8c
commit 77a4b980ae
54 changed files with 2128 additions and 379 deletions
@@ -46,6 +46,8 @@ fn prepare_good_block() -> (TestClient, Hash, u64, PeerId, IncomingBlock<Block>)
origin: Some(peer_id.clone()),
allow_missing_state: false,
import_existing: false,
state: None,
skip_execution: false,
})
}
+40 -5
View File
@@ -29,6 +29,7 @@ use std::{
use libp2p::build_multiaddr;
use log::trace;
use sc_network::block_request_handler::{self, BlockRequestHandler};
use sc_network::state_request_handler::{self, StateRequestHandler};
use sc_network::light_client_requests::{self, handler::LightClientRequestHandler};
use sp_blockchain::{
HeaderBackend, Result as ClientResult,
@@ -55,7 +56,7 @@ use sc_network::{
NetworkWorker, NetworkService, config::{ProtocolId, MultiaddrWithPeerId, NonReservedPeerMode},
Multiaddr,
};
use sc_network::config::{NetworkConfiguration, NonDefaultSetConfig, TransportConfig};
use sc_network::config::{NetworkConfiguration, NonDefaultSetConfig, TransportConfig, SyncMode};
use libp2p::PeerId;
use parking_lot::Mutex;
use sp_core::H256;
@@ -179,6 +180,19 @@ impl PeersClient {
}
}
pub fn has_state_at(&self, block: &BlockId<Block>) -> bool {
let header = match self.header(block).unwrap() {
Some(header) => header,
None => return false,
};
match self {
PeersClient::Full(_client, backend) =>
backend.have_state_at(&header.hash(), *header.number()),
PeersClient::Light(_client, backend) =>
backend.have_state_at(&header.hash(), *header.number()),
}
}
pub fn justifications(&self, block: &BlockId<Block>) -> ClientResult<Option<Justifications>> {
match *self {
PeersClient::Full(ref client, ref _backend) => client.justifications(block),
@@ -235,9 +249,9 @@ impl BlockImport<Block> for PeersClient {
) -> Result<ImportResult, Self::Error> {
match self {
PeersClient::Full(client, _) =>
client.import_block(block.convert_transaction(), cache).await,
client.import_block(block.clear_storage_changes_and_mutate(), cache).await,
PeersClient::Light(client, _) =>
client.import_block(block.convert_transaction(), cache).await,
client.import_block(block.clear_storage_changes_and_mutate(), cache).await,
}
}
}
@@ -584,7 +598,7 @@ impl<I> BlockImport<Block> for BlockImportAdapter<I> where
block: BlockImportParams<Block, ()>,
cache: HashMap<well_known_cache_keys::Id, Vec<u8>>,
) -> Result<ImportResult, Self::Error> {
self.inner.import_block(block.convert_transaction(), cache).await
self.inner.import_block(block.clear_storage_changes_and_mutate(), cache).await
}
}
@@ -644,6 +658,8 @@ pub struct FullPeerConfig {
pub connect_to_peers: Option<Vec<usize>>,
/// Whether the full peer should have the authority role.
pub is_authority: bool,
/// Syncing mode
pub sync_mode: SyncMode,
}
pub trait TestNetFactory: Sized where <Self::BlockImport as BlockImport<Block>>::Transaction: Send {
@@ -699,10 +715,13 @@ pub trait TestNetFactory: Sized where <Self::BlockImport as BlockImport<Block>>:
/// Add a full peer.
fn add_full_peer_with_config(&mut self, config: FullPeerConfig) {
let test_client_builder = match config.keep_blocks {
let mut test_client_builder = match config.keep_blocks {
Some(keep_blocks) => TestClientBuilder::with_pruning_window(keep_blocks),
None => TestClientBuilder::with_default_backend(),
};
if matches!(config.sync_mode, SyncMode::Fast{..}) {
test_client_builder = test_client_builder.set_no_genesis();
}
let backend = test_client_builder.backend();
let (c, longest_chain) = test_client_builder.build_with_longest_chain();
let client = Arc::new(c);
@@ -736,6 +755,7 @@ pub trait TestNetFactory: Sized where <Self::BlockImport as BlockImport<Block>>:
Default::default(),
None,
);
network_config.sync_mode = config.sync_mode;
network_config.transport = TransportConfig::MemoryOnly;
network_config.listen_addresses = vec![listen_addr.clone()];
network_config.allow_non_globals_in_dht = true;
@@ -769,6 +789,16 @@ pub trait TestNetFactory: Sized where <Self::BlockImport as BlockImport<Block>>:
protocol_config
};
let state_request_protocol_config = {
let (handler, protocol_config) = StateRequestHandler::new(
&protocol_id,
client.clone(),
50,
);
self.spawn_task(handler.run().boxed());
protocol_config
};
let light_client_request_protocol_config = {
let (handler, protocol_config) = LightClientRequestHandler::new(&protocol_id, client.clone());
self.spawn_task(handler.run().boxed());
@@ -789,6 +819,7 @@ pub trait TestNetFactory: Sized where <Self::BlockImport as BlockImport<Block>>:
.unwrap_or_else(|| Box::new(DefaultBlockAnnounceValidator)),
metrics_registry: None,
block_request_protocol_config,
state_request_protocol_config,
light_client_request_protocol_config,
}).unwrap();
@@ -862,6 +893,9 @@ pub trait TestNetFactory: Sized where <Self::BlockImport as BlockImport<Block>>:
let block_request_protocol_config = block_request_handler::generate_protocol_config(
&protocol_id,
);
let state_request_protocol_config = state_request_handler::generate_protocol_config(
&protocol_id,
);
let light_client_request_protocol_config =
light_client_requests::generate_protocol_config(&protocol_id);
@@ -879,6 +913,7 @@ pub trait TestNetFactory: Sized where <Self::BlockImport as BlockImport<Block>>:
block_announce_validator: Box::new(DefaultBlockAnnounceValidator),
metrics_registry: None,
block_request_protocol_config,
state_request_protocol_config,
light_client_request_protocol_config,
}).unwrap();
+40
View File
@@ -1087,3 +1087,43 @@ fn syncs_after_missing_announcement() {
net.block_until_sync();
assert!(net.peer(1).client().header(&BlockId::Hash(final_block)).unwrap().is_some());
}
#[test]
fn syncs_state() {
sp_tracing::try_init_simple();
for skip_proofs in &[ false, true ] {
let mut net = TestNet::new(0);
net.add_full_peer_with_config(Default::default());
net.add_full_peer_with_config(FullPeerConfig {
sync_mode: SyncMode::Fast { skip_proofs: *skip_proofs },
..Default::default()
});
net.peer(0).push_blocks(64, false);
// Wait for peer 1 to sync header chain.
net.block_until_sync();
assert!(!net.peer(1).client().has_state_at(&BlockId::Number(64)));
let just = (*b"FRNK", Vec::new());
net.peer(1).client().finalize_block(BlockId::Number(60), Some(just), true).unwrap();
// Wait for state sync.
block_on(futures::future::poll_fn::<(), _>(|cx| {
net.poll(cx);
if net.peer(1).client.info().finalized_state.is_some() {
Poll::Ready(())
} else {
Poll::Pending
}
}));
assert!(!net.peer(1).client().has_state_at(&BlockId::Number(64)));
// Wait for the rest of the states to be imported.
block_on(futures::future::poll_fn::<(), _>(|cx| {
net.poll(cx);
if net.peer(1).client().has_state_at(&BlockId::Number(64)) {
Poll::Ready(())
} else {
Poll::Pending
}
}));
}
}