diff --git a/full-node/src/run/consensus_service.rs b/full-node/src/run/consensus_service.rs index 1247f389d0..1e26dac9b1 100644 --- a/full-node/src/run/consensus_service.rs +++ b/full-node/src/run/consensus_service.rs @@ -1099,7 +1099,8 @@ impl SyncBackground { (self, false) } all::ProcessOne::VerifyWarpSyncFragment(_) - | all::ProcessOne::WarpSyncError { .. } + | all::ProcessOne::WarpSyncBuildRuntime(_) + | all::ProcessOne::WarpSyncBuildChainInformation(_) | all::ProcessOne::WarpSyncFinished { .. } => unreachable!(), all::ProcessOne::VerifyBodyHeader(verify) => { let hash_to_verify = verify.hash(); diff --git a/lib/src/sync/all.rs b/lib/src/sync/all.rs index b2c0c7ba8b..21cff80a9e 100644 --- a/lib/src/sync/all.rs +++ b/lib/src/sync/all.rs @@ -32,7 +32,7 @@ use crate::{ chain::{blocks_tree, chain_information}, - executor::{host, storage_diff, vm::ExecHint}, + executor::{host, storage_diff}, header, sync::{all_forks, optimistic, warp_sync}, verify, @@ -46,6 +46,7 @@ use core::{ time::Duration, }; +pub use crate::executor::vm::ExecHint; pub use optimistic::TrieEntryVersion; pub use warp_sync::{FragmentError as WarpSyncFragmentError, WarpSyncFragment}; @@ -179,7 +180,9 @@ impl AllSync { sources_capacity: config.sources_capacity, requests_capacity: config.sources_capacity, // TODO: ?! add as config? }) { - Ok(inner) => AllSyncInner::GrandpaWarpSync { inner }, + Ok(inner) => AllSyncInner::GrandpaWarpSync { + inner: warp_sync::WarpSync::InProgress(inner), + }, Err(( chain_information, warp_sync::WarpSyncInitError::NotGrandpa @@ -216,12 +219,7 @@ impl AllSync { /// Returns the value that was initially passed in [`Config::block_number_bytes`]. pub fn block_number_bytes(&self) -> usize { - match &self.inner { - AllSyncInner::AllForks(sync) => sync.block_number_bytes(), - AllSyncInner::GrandpaWarpSync { inner: sync } => sync.block_number_bytes(), - AllSyncInner::Optimistic { inner } => inner.block_number_bytes(), - AllSyncInner::Poisoned => unreachable!(), - } + self.shared.block_number_bytes } /// Builds a [`chain_information::ChainInformationRef`] struct corresponding to the current @@ -229,7 +227,12 @@ impl AllSync { pub fn as_chain_information(&self) -> chain_information::ValidChainInformationRef { match &self.inner { AllSyncInner::AllForks(sync) => sync.as_chain_information(), - AllSyncInner::GrandpaWarpSync { inner: sync } => sync.as_chain_information(), + AllSyncInner::GrandpaWarpSync { + inner: warp_sync::WarpSync::InProgress(sync), + } => sync.as_chain_information(), + AllSyncInner::GrandpaWarpSync { + inner: warp_sync::WarpSync::Finished(sync), + } => (&sync.chain_information).into(), AllSyncInner::Optimistic { inner } => inner.as_chain_information(), AllSyncInner::Poisoned => unreachable!(), } @@ -239,7 +242,9 @@ impl AllSync { pub fn status(&self) -> Status { match &self.inner { AllSyncInner::AllForks(_) => Status::Sync, - AllSyncInner::GrandpaWarpSync { inner: sync } => match sync.status() { + AllSyncInner::GrandpaWarpSync { + inner: warp_sync::WarpSync::InProgress(sync), + } => match sync.status() { warp_sync::Status::Fragments { source: None, finalized_block_hash, @@ -268,6 +273,9 @@ impl AllSync { finalized_block_number, }, }, + AllSyncInner::GrandpaWarpSync { + inner: warp_sync::WarpSync::Finished(_), + } => Status::Sync, AllSyncInner::Optimistic { .. } => Status::Sync, // TODO: right now we don't differentiate between AllForks and Optimistic, as they're kind of similar anyway AllSyncInner::Poisoned => unreachable!(), } @@ -278,9 +286,12 @@ impl AllSync { match &self.inner { AllSyncInner::AllForks(sync) => sync.finalized_block_header(), AllSyncInner::Optimistic { inner } => inner.finalized_block_header(), - AllSyncInner::GrandpaWarpSync { inner: sync } => { - sync.as_chain_information().as_ref().finalized_block_header - } + AllSyncInner::GrandpaWarpSync { + inner: warp_sync::WarpSync::InProgress(sync), + } => sync.as_chain_information().as_ref().finalized_block_header, + AllSyncInner::GrandpaWarpSync { + inner: warp_sync::WarpSync::Finished(sync), + } => sync.chain_information.as_ref().finalized_block_header, AllSyncInner::Poisoned => unreachable!(), } } @@ -319,9 +330,9 @@ impl AllSync { match &self.inner { AllSyncInner::AllForks(sync) => sync.best_block_hash(), AllSyncInner::Optimistic { inner } => inner.best_block_hash(), - AllSyncInner::GrandpaWarpSync { inner, .. } => { - self.best_block_header().hash(inner.block_number_bytes()) - } + AllSyncInner::GrandpaWarpSync { .. } => self + .best_block_header() + .hash(self.shared.block_number_bytes), AllSyncInner::Poisoned => unreachable!(), } } @@ -400,7 +411,7 @@ impl AllSync { // `inner` is temporarily replaced with `Poisoned`. A new value must be put back before // returning. match mem::replace(&mut self.inner, AllSyncInner::Poisoned) { - AllSyncInner::GrandpaWarpSync { inner: mut sync } => { + AllSyncInner::GrandpaWarpSync { mut inner } => { let outer_source_id_entry = self.shared.sources.vacant_entry(); let outer_source_id = SourceId(outer_source_id_entry.key()); @@ -412,11 +423,23 @@ impl AllSync { finalized_block_height: None, }; - let inner_source_id = sync.add_source(source_extra); + let inner_source_id = match &mut inner { + warp_sync::WarpSync::InProgress(sync) => sync.add_source(source_extra), + warp_sync::WarpSync::Finished(sync) => { + let new_id = sync.sources_ordered.last().map_or( + warp_sync::SourceId::min_value(), + |(id, _)| { + id.checked_add(1).unwrap_or_else(|| panic!()) // TODO: don't panic? + }, + ); + sync.sources_ordered.push((new_id, source_extra)); + new_id + } + }; outer_source_id_entry.insert(SourceMapping::GrandpaWarpSync(inner_source_id)); - self.inner = AllSyncInner::GrandpaWarpSync { inner: sync }; + self.inner = AllSyncInner::GrandpaWarpSync { inner }; outer_source_id } AllSyncInner::AllForks(mut all_forks) => { @@ -541,7 +564,29 @@ impl AllSync { AllSyncInner::GrandpaWarpSync { inner }, SourceMapping::GrandpaWarpSync(source_id), ) => { - let (user_data, requests) = inner.remove_source(source_id); + let (user_data, requests) = match inner { + warp_sync::WarpSync::InProgress(inner) => { + let (ud, requests) = inner.remove_source(source_id); + (ud, either::Left(requests)) + } + warp_sync::WarpSync::Finished(inner) => { + let index = inner + .sources_ordered + .binary_search_by_key(&source_id, |(id, _)| *id) + .unwrap_or_else(|_| panic!()); + let (_, user_data) = inner.sources_ordered.remove(index); + let (requests_of_source, requests_back) = + mem::take(&mut inner.in_progress_requests) + .into_iter() + .partition(|(s, ..)| *s == source_id); + inner.in_progress_requests = requests_back; + let requests_of_source = requests_of_source + .into_iter() + .map(|(_, rq_id, ud, _)| (rq_id, ud)); + (user_data, either::Right(requests_of_source)) + } + }; + let requests = requests .map(|(_inner_request_id, request_inner_user_data)| { debug_assert!(self @@ -586,17 +631,28 @@ impl AllSync { /// Returns the list of sources in this state machine. pub fn sources(&'_ self) -> impl Iterator + '_ { match &self.inner { - AllSyncInner::GrandpaWarpSync { inner: sync } => { + AllSyncInner::GrandpaWarpSync { + inner: warp_sync::WarpSync::InProgress(sync), + } => { let iter = sync.sources().map(move |id| sync[id].outer_source_id); either::Left(either::Left(iter)) } + AllSyncInner::GrandpaWarpSync { + inner: warp_sync::WarpSync::Finished(sync), + } => { + let iter = sync + .sources_ordered + .iter() + .map(move |(_, ud)| ud.outer_source_id); + either::Left(either::Right(iter)) + } AllSyncInner::Optimistic { inner: sync } => { let iter = sync.sources().map(move |id| sync[id].outer_source_id); - either::Left(either::Right(iter)) + either::Right(either::Left(iter)) } AllSyncInner::AllForks(sync) => { let iter = sync.sources().map(move |id| sync[id].outer_source_id); - either::Right(iter) + either::Right(either::Right(iter)) } AllSyncInner::Poisoned => unreachable!(), } @@ -664,12 +720,27 @@ impl AllSync { (height, hash) } ( - AllSyncInner::GrandpaWarpSync { inner: sync }, + AllSyncInner::GrandpaWarpSync { + inner: warp_sync::WarpSync::InProgress(sync), + }, SourceMapping::GrandpaWarpSync(src), ) => { let ud = &sync[*src]; (ud.best_block_number, &ud.best_block_hash) } + ( + AllSyncInner::GrandpaWarpSync { + inner: warp_sync::WarpSync::Finished(sync), + }, + SourceMapping::GrandpaWarpSync(src), + ) => { + let index = sync + .sources_ordered + .binary_search_by_key(src, |(id, _)| *id) + .unwrap_or_else(|_| panic!()); + let user_data = &sync.sources_ordered[index].1; + (user_data.best_block_number, &user_data.best_block_hash) + } (AllSyncInner::Poisoned, _) => unreachable!(), // Invalid combinations of syncing state machine and source id. @@ -711,7 +782,9 @@ impl AllSync { inner.source_best_block(*src) >= height } ( - AllSyncInner::GrandpaWarpSync { inner: sync }, + AllSyncInner::GrandpaWarpSync { + inner: warp_sync::WarpSync::InProgress(sync), + }, SourceMapping::GrandpaWarpSync(src), ) => { assert!( @@ -726,6 +799,28 @@ impl AllSync { let user_data = &sync[*src]; user_data.best_block_hash == *hash && user_data.best_block_number == height } + ( + AllSyncInner::GrandpaWarpSync { + inner: warp_sync::WarpSync::Finished(sync), + }, + SourceMapping::GrandpaWarpSync(src), + ) => { + assert!( + height + > sync + .chain_information + .as_ref() + .finalized_block_header + .number + ); + + let index = sync + .sources_ordered + .binary_search_by_key(src, |(id, _)| *id) + .unwrap_or_else(|_| panic!()); + let user_data = &sync.sources_ordered[index].1; + user_data.best_block_hash == *hash && user_data.best_block_number == height + } (AllSyncInner::Poisoned, _) => unreachable!(), // Invalid combinations of syncing state machine and source id. @@ -755,7 +850,9 @@ impl AllSync { hash: &[u8; 32], ) -> impl Iterator + '_ { match &self.inner { - AllSyncInner::GrandpaWarpSync { inner: sync } => { + AllSyncInner::GrandpaWarpSync { + inner: warp_sync::WarpSync::InProgress(sync), + } => { assert!( height > sync @@ -776,11 +873,34 @@ impl AllSync { either::Right(either::Left(iter)) } + AllSyncInner::GrandpaWarpSync { + inner: warp_sync::WarpSync::Finished(sync), + } => { + assert!( + height + > sync + .chain_information + .as_ref() + .finalized_block_header + .number + ); + + let hash = *hash; + let iter = sync + .sources_ordered + .iter() + .filter(move |(_, user_data)| { + user_data.best_block_hash == hash && user_data.best_block_number == height + }) + .map(move |(_, ud)| ud.outer_source_id); + + either::Right(either::Right(iter)) + } AllSyncInner::AllForks(sync) => { let iter = sync .knows_non_finalized_block(height, hash) .map(move |id| sync[id].outer_source_id); - either::Left(iter) + either::Left(either::Left(iter)) } AllSyncInner::Optimistic { inner } => { // TODO: is this correct? @@ -788,7 +908,7 @@ impl AllSync { .sources() .filter(move |source_id| inner.source_best_block(*source_id) >= height) .map(move |source_id| inner[source_id].outer_source_id); - either::Right(either::Right(iter)) + either::Left(either::Right(iter)) } AllSyncInner::Poisoned => unreachable!(), } @@ -855,9 +975,11 @@ impl AllSync { ) }); - either::Right(iter) + either::Right(either::Left(iter)) } - AllSyncInner::GrandpaWarpSync { inner } => { + AllSyncInner::GrandpaWarpSync { + inner: warp_sync::WarpSync::InProgress(inner), + } => { let iter = inner .desired_requests() .map(move |(_, src_user_data, rq_detail)| { @@ -896,6 +1018,9 @@ impl AllSync { either::Left(either::Left(iter)) } + AllSyncInner::GrandpaWarpSync { + inner: warp_sync::WarpSync::Finished(_), + } => either::Right(either::Right(iter::empty())), AllSyncInner::Poisoned => unreachable!(), } } @@ -984,7 +1109,9 @@ impl AllSync { return outer_request_id; } ( - AllSyncInner::GrandpaWarpSync { inner }, + AllSyncInner::GrandpaWarpSync { + inner: warp_sync::WarpSync::InProgress(inner), + }, RequestDetail::GrandpaWarpSync { sync_start_block_hash, }, @@ -1012,7 +1139,9 @@ impl AllSync { return outer_request_id; } ( - AllSyncInner::GrandpaWarpSync { inner }, + AllSyncInner::GrandpaWarpSync { + inner: warp_sync::WarpSync::InProgress(inner), + }, RequestDetail::StorageGet { block_hash, keys }, ) => { let inner_source_id = match self.shared.sources.get(source_id.0).unwrap() { @@ -1039,7 +1168,9 @@ impl AllSync { return outer_request_id; } ( - AllSyncInner::GrandpaWarpSync { inner }, + AllSyncInner::GrandpaWarpSync { + inner: warp_sync::WarpSync::InProgress(inner), + }, RequestDetail::RuntimeCallMerkleProof { block_hash, function_name, @@ -1130,68 +1261,52 @@ impl AllSync { /// [`AllSync`] is yielded back at the end of this process. pub fn process_one(mut self) -> ProcessOne { match self.inner { - AllSyncInner::GrandpaWarpSync { inner } => { - match inner.process_one() { - warp_sync::ProcessOne::Idle(inner) => { - self.inner = AllSyncInner::GrandpaWarpSync { inner }; - ProcessOne::AllSync(self) - } - warp_sync::ProcessOne::VerifyWarpSyncFragment(inner) => { - ProcessOne::VerifyWarpSyncFragment(WarpSyncFragmentVerify { - inner, - shared: self.shared, - marker: marker::PhantomData, - }) - } - warp_sync::ProcessOne::BuildRuntime(inner) => { - // TODO: errors not reported to upper layer - // TODO: make these parameters configurable - match inner.build(ExecHint::CompileAheadOfTime, false).0 { - warp_sync::WarpSync::InProgress(inner) => { - self.inner = AllSyncInner::GrandpaWarpSync { inner }; - ProcessOne::AllSync(self) - } - warp_sync::WarpSync::Finished(success) => { - let ( - new_inner, - finalized_block_runtime, - finalized_storage_code, - finalized_storage_heap_pages, - ) = self.shared.transition_grandpa_warp_sync_all_forks(success); - self.inner = AllSyncInner::AllForks(new_inner); - ProcessOne::WarpSyncFinished { - sync: self, - finalized_block_runtime, - finalized_storage_code, - finalized_storage_heap_pages, - } - } - } - } - warp_sync::ProcessOne::BuildChainInformation(inner) => { - match inner.build().0 { - // TODO: errors not reported to upper layer - warp_sync::WarpSync::InProgress(inner) => { - self.inner = AllSyncInner::GrandpaWarpSync { inner }; - ProcessOne::AllSync(self) - } - warp_sync::WarpSync::Finished(success) => { - let ( - new_inner, - finalized_block_runtime, - finalized_storage_code, - finalized_storage_heap_pages, - ) = self.shared.transition_grandpa_warp_sync_all_forks(success); - self.inner = AllSyncInner::AllForks(new_inner); - ProcessOne::WarpSyncFinished { - sync: self, - finalized_block_runtime, - finalized_storage_code, - finalized_storage_heap_pages, - } - } - } - } + AllSyncInner::GrandpaWarpSync { + inner: warp_sync::WarpSync::InProgress(inner), + } => match inner.process_one() { + warp_sync::ProcessOne::Idle(inner) => { + self.inner = AllSyncInner::GrandpaWarpSync { + inner: warp_sync::WarpSync::InProgress(inner), + }; + ProcessOne::AllSync(self) + } + warp_sync::ProcessOne::VerifyWarpSyncFragment(inner) => { + ProcessOne::VerifyWarpSyncFragment(WarpSyncFragmentVerify { + inner, + shared: self.shared, + marker: marker::PhantomData, + }) + } + warp_sync::ProcessOne::BuildRuntime(inner) => { + ProcessOne::WarpSyncBuildRuntime(WarpSyncBuildRuntime { + inner, + shared: self.shared, + marker: marker::PhantomData, + }) + } + warp_sync::ProcessOne::BuildChainInformation(inner) => { + ProcessOne::WarpSyncBuildChainInformation(WarpSyncBuildChainInformation { + inner, + shared: self.shared, + marker: marker::PhantomData, + }) + } + }, + AllSyncInner::GrandpaWarpSync { + inner: warp_sync::WarpSync::Finished(success), + } => { + let ( + new_inner, + finalized_block_runtime, + finalized_storage_code, + finalized_storage_heap_pages, + ) = self.shared.transition_grandpa_warp_sync_all_forks(success); + self.inner = AllSyncInner::AllForks(new_inner); + ProcessOne::WarpSyncFinished { + sync: self, + finalized_block_runtime, + finalized_storage_code, + finalized_storage_heap_pages, } } AllSyncInner::AllForks(sync) => match sync.process_one() { @@ -1283,20 +1398,31 @@ impl AllSync { } } ( - AllSyncInner::GrandpaWarpSync { inner: sync }, + AllSyncInner::GrandpaWarpSync { inner }, &SourceMapping::GrandpaWarpSync(source_id), ) => { - let block_number_bytes = sync.block_number_bytes(); - match header::decode(&announced_scale_encoded_header, block_number_bytes) { + match header::decode( + &announced_scale_encoded_header, + self.shared.block_number_bytes, + ) { Err(err) => BlockAnnounceOutcome::InvalidHeader(err), Ok(header) => { // If GrandPa warp syncing is in progress, the best block of the source is stored // in the user data. It will be useful later when transitioning to another // syncing strategy. if is_best { - let mut user_data = &mut sync[source_id]; + let mut user_data = match inner { + warp_sync::WarpSync::InProgress(sync) => &mut sync[source_id], + warp_sync::WarpSync::Finished(sync) => { + let index = sync + .sources_ordered + .binary_search_by_key(&source_id, |(id, _)| *id) + .unwrap_or_else(|_| panic!()); + &mut sync.sources_ordered[index].1 + } + }; user_data.best_block_number = header.number; - user_data.best_block_hash = header.hash(block_number_bytes); + user_data.best_block_hash = header.hash(self.shared.block_number_bytes); } BlockAnnounceOutcome::Discarded @@ -1336,7 +1462,9 @@ impl AllSync { } (AllSyncInner::Optimistic { .. }, _) => {} // TODO: the optimistic sync could get some help from the finalized block ( - AllSyncInner::GrandpaWarpSync { inner }, + AllSyncInner::GrandpaWarpSync { + inner: warp_sync::WarpSync::InProgress(inner), + }, SourceMapping::GrandpaWarpSync(source_id), ) => { // TODO: the warp syncing algorithm could maybe be interested in the finalized block height @@ -1345,6 +1473,22 @@ impl AllSync { cmp::max(b, finalized_block_height) })); } + ( + AllSyncInner::GrandpaWarpSync { + inner: warp_sync::WarpSync::Finished(sync), + }, + SourceMapping::GrandpaWarpSync(src), + ) => { + let index = sync + .sources_ordered + .binary_search_by_key(src, |(id, _)| *id) + .unwrap_or_else(|_| panic!()); + // TODO: the warp syncing algorithm could maybe be interested in the finalized block height + let n = &mut sync.sources_ordered[index].1.finalized_block_height; + *n = Some(n.map_or(finalized_block_height, |b| { + cmp::max(b, finalized_block_height) + })); + } // Invalid internal states. (AllSyncInner::AllForks(_), _) => unreachable!(), @@ -1565,7 +1709,9 @@ impl AllSync { match (&mut self.inner, request) { ( - AllSyncInner::GrandpaWarpSync { inner: grandpa }, + AllSyncInner::GrandpaWarpSync { + inner: warp_sync::WarpSync::InProgress(grandpa), + }, RequestMapping::WarpSync(request_id), ) => { let user_data = if let Some((fragments, is_finished)) = response { @@ -1610,22 +1756,29 @@ impl AllSync { request, ) { ( - AllSyncInner::GrandpaWarpSync { inner: mut sync }, + AllSyncInner::GrandpaWarpSync { + inner: warp_sync::WarpSync::InProgress(mut sync), + }, Ok(response), RequestMapping::WarpSync(request_id), ) => { let user_data = sync.storage_get_success(request_id, response); - self.inner = AllSyncInner::GrandpaWarpSync { inner: sync }; + self.inner = AllSyncInner::GrandpaWarpSync { + inner: warp_sync::WarpSync::InProgress(sync), + }; (user_data.user_data, ResponseOutcome::Queued) } ( - AllSyncInner::GrandpaWarpSync { inner: mut sync }, + AllSyncInner::GrandpaWarpSync { + inner: warp_sync::WarpSync::InProgress(mut sync), + }, Err(_), RequestMapping::WarpSync(request_id), ) => { let user_data = sync.fail_request(request_id).user_data; - // TODO: notify user of the problem - self.inner = AllSyncInner::GrandpaWarpSync { inner: sync }; + self.inner = AllSyncInner::GrandpaWarpSync { + inner: warp_sync::WarpSync::InProgress(sync), + }; (user_data, ResponseOutcome::Queued) } // Only the GrandPa warp syncing ever starts GrandPa warp sync requests. @@ -1664,22 +1817,30 @@ impl AllSync { request, ) { ( - AllSyncInner::GrandpaWarpSync { inner: mut sync }, + AllSyncInner::GrandpaWarpSync { + inner: warp_sync::WarpSync::InProgress(mut sync), + }, Ok(response), RequestMapping::WarpSync(request_id), ) => { let user_data = sync.runtime_call_merkle_proof_success(request_id, response); - self.inner = AllSyncInner::GrandpaWarpSync { inner: sync }; + self.inner = AllSyncInner::GrandpaWarpSync { + inner: warp_sync::WarpSync::InProgress(sync), + }; (user_data.user_data, ResponseOutcome::Queued) } ( - AllSyncInner::GrandpaWarpSync { inner: mut sync }, + AllSyncInner::GrandpaWarpSync { + inner: warp_sync::WarpSync::InProgress(mut sync), + }, Err(_), RequestMapping::WarpSync(request_id), ) => { let user_data = sync.fail_request(request_id); // TODO: notify user of the problem - self.inner = AllSyncInner::GrandpaWarpSync { inner: sync }; + self.inner = AllSyncInner::GrandpaWarpSync { + inner: warp_sync::WarpSync::InProgress(sync), + }; (user_data.user_data, ResponseOutcome::Queued) } // Only the GrandPa warp syncing ever starts call proof requests. @@ -1707,9 +1868,23 @@ impl ops::Index for AllSync { &inner[*src].user_data } ( - AllSyncInner::GrandpaWarpSync { inner: sync }, + AllSyncInner::GrandpaWarpSync { + inner: warp_sync::WarpSync::InProgress(sync), + }, SourceMapping::GrandpaWarpSync(src), ) => &sync[*src].user_data, + ( + AllSyncInner::GrandpaWarpSync { + inner: warp_sync::WarpSync::Finished(sync), + }, + SourceMapping::GrandpaWarpSync(src), + ) => { + let index = sync + .sources_ordered + .binary_search_by_key(src, |(id, _)| *id) + .unwrap_or_else(|_| panic!()); + &sync.sources_ordered[index].1.user_data + } (AllSyncInner::Poisoned, _) => unreachable!(), // Invalid combinations of syncing state machine and source id. @@ -1740,9 +1915,23 @@ impl ops::IndexMut for AllSync { &mut inner[*src].user_data } ( - AllSyncInner::GrandpaWarpSync { inner: sync }, + AllSyncInner::GrandpaWarpSync { + inner: warp_sync::WarpSync::InProgress(sync), + }, SourceMapping::GrandpaWarpSync(src), ) => &mut sync[*src].user_data, + ( + AllSyncInner::GrandpaWarpSync { + inner: warp_sync::WarpSync::Finished(sync), + }, + SourceMapping::GrandpaWarpSync(src), + ) => { + let index = sync + .sources_ordered + .binary_search_by_key(src, |(id, _)| *id) + .unwrap_or_else(|_| panic!()); + &mut sync.sources_ordered[index].1.user_data + } (AllSyncInner::Poisoned, _) => unreachable!(), // Invalid combinations of syncing state machine and source id. @@ -2033,13 +2222,11 @@ pub enum ProcessOne { /// No block ready to be processed. AllSync(AllSync), - /// Content of the response is erroneous in the context of warp syncing. - WarpSyncError { - sync: AllSync, + /// Building the runtime is necessary in order for the warp syncing to continue. + WarpSyncBuildRuntime(WarpSyncBuildRuntime), - /// Error that happened. - error: warp_sync::Error, - }, + /// Building the chain information is necessary in order for the warp syncing to continue. + WarpSyncBuildChainInformation(WarpSyncBuildChainInformation), /// Response has made it possible to finish warp syncing. WarpSyncFinished { @@ -2404,7 +2591,7 @@ impl WarpSyncFragmentVerify { ( AllSync { inner: AllSyncInner::GrandpaWarpSync { - inner: next_grandpa_warp_sync, + inner: warp_sync::WarpSync::InProgress(next_grandpa_warp_sync), }, shared: self.shared, }, @@ -2413,6 +2600,75 @@ impl WarpSyncFragmentVerify { } } +/// Compiling a new runtime is necessary for the warp sync process. +#[must_use] +pub struct WarpSyncBuildRuntime { + inner: + warp_sync::BuildRuntime, GrandpaWarpSyncRequestExtra>, + shared: Shared, + marker: marker::PhantomData>, +} + +impl WarpSyncBuildRuntime { + /// Builds the runtime. + /// + /// Assuming that the warp syncing goes to completion, the provided parameters are used to + /// compile the runtime that will be yielded in + /// [`ProcessOne::WarpSyncFinished::finalized_block_runtime`]. + // TODO: better error type + pub fn build( + self, + exec_hint: ExecHint, + allow_unresolved_imports: bool, + ) -> (AllSync, Result<(), warp_sync::Error>) { + let (warp_sync_status, error) = self.inner.build(exec_hint, allow_unresolved_imports); + + ( + AllSync { + inner: AllSyncInner::GrandpaWarpSync { + inner: warp_sync_status, + }, + shared: self.shared, + }, + match error { + Some(err) => Err(err), + None => Ok(()), + }, + ) + } +} + +/// Building the chain information is necessary for the warp sync process. +#[must_use] +pub struct WarpSyncBuildChainInformation { + inner: warp_sync::BuildChainInformation< + GrandpaWarpSyncSourceExtra, + GrandpaWarpSyncRequestExtra, + >, + shared: Shared, + marker: marker::PhantomData>, +} + +impl WarpSyncBuildChainInformation { + /// Builds the chain information. + // TODO: better error type + pub fn build(self) -> (AllSync, Result<(), warp_sync::Error>) { + let (warp_sync_status, error) = self.inner.build(); + ( + AllSync { + inner: AllSyncInner::GrandpaWarpSync { + inner: warp_sync_status, + }, + shared: self.shared, + }, + match error { + Some(err) => Err(err), + None => Ok(()), + }, + ) + } +} + pub struct HeaderBodyVerify { inner: HeaderBodyVerifyInner, shared: Shared, @@ -2525,7 +2781,7 @@ pub enum BlockVerification { ParentStorageNextKey(StorageNextKey), /// Compiling a runtime is required in order to continue. - RuntimeCompilation(RuntimeCompilation), + RuntimeCompilation(BlockVerificationRuntimeCompilation), } /// Error that can happen when verifying a block body. @@ -2632,7 +2888,7 @@ impl BlockVerification { }) } optimistic::BlockVerification::RuntimeCompilation(inner) => { - BlockVerification::RuntimeCompilation(RuntimeCompilation { + BlockVerification::RuntimeCompilation(BlockVerificationRuntimeCompilation { inner, shared, user_data, @@ -2734,7 +2990,7 @@ impl StorageNextKey { /// Compiling a new runtime is necessary as part of the verification. #[must_use] -pub struct RuntimeCompilation { +pub struct BlockVerificationRuntimeCompilation { inner: optimistic::RuntimeCompilation< OptimisticRequestExtra, OptimisticSourceExtra, @@ -2744,7 +3000,7 @@ pub struct RuntimeCompilation { user_data: TBl, } -impl RuntimeCompilation { +impl BlockVerificationRuntimeCompilation { /// Builds the runtime. pub fn build(self) -> BlockVerification { let inner = self.inner.build(); @@ -2754,10 +3010,8 @@ impl RuntimeCompilation { enum AllSyncInner { GrandpaWarpSync { - inner: warp_sync::InProgressWarpSync< - GrandpaWarpSyncSourceExtra, - GrandpaWarpSyncRequestExtra, - >, + inner: + warp_sync::WarpSync, GrandpaWarpSyncRequestExtra>, }, Optimistic { inner: optimistic::OptimisticSync< @@ -2905,7 +3159,7 @@ impl Shared { RequestMapping::Inline(SourceId(source_id), detail, user_data); } - for source in grandpa.sources { + for (_, source) in grandpa.sources_ordered { let source_user_data = AllForksSourceExtra { user_data: source.user_data, outer_source_id: source.outer_source_id, diff --git a/lib/src/sync/warp_sync.rs b/lib/src/sync/warp_sync.rs index 079ae74457..6c4994974c 100644 --- a/lib/src/sync/warp_sync.rs +++ b/lib/src/sync/warp_sync.rs @@ -209,6 +209,17 @@ pub enum WarpSyncInitError { #[derive(Debug, Copy, Clone, Ord, PartialOrd, Eq, PartialEq, Hash)] pub struct SourceId(usize); +impl SourceId { + /// Returns the smallest possible [`SourceId`]. It is always inferior or equal to any other. + pub fn min_value() -> Self { + SourceId(usize::min_value()) + } + + pub fn checked_add(&self, n: u8) -> Option { + Some(SourceId(self.0.checked_add(usize::from(n))?)) + } +} + /// The result of a successful warp sync. pub struct Success { /// The synced chain information. @@ -225,7 +236,8 @@ pub struct Success { pub finalized_storage_heap_pages: Option>, /// The list of sources that were added to the state machine. - pub sources: Vec, + /// The list is ordered by [`SourceId`]. + pub sources_ordered: Vec<(SourceId, TSrc)>, /// The list of requests that were added to the state machine. pub in_progress_requests: Vec<(SourceId, RequestId, TRq, RequestDetail)>, @@ -1319,11 +1331,9 @@ impl BuildRuntime { finalized_storage_code: Some(finalized_storage_code.to_owned()), finalized_storage_heap_pages: finalized_storage_heappages .map(|v| v.to_vec()), - sources: self - .inner - .sources - .drain() - .map(|source| source.user_data) + sources_ordered: mem::take(&mut self.inner.sources) + .into_iter() + .map(|(id, source)| (SourceId(id), source.user_data)) .collect(), in_progress_requests: mem::take(&mut self.inner.in_progress_requests) .into_iter() @@ -1470,11 +1480,9 @@ impl BuildChainInformation { finalized_storage_code: downloaded_runtime.storage_code, finalized_storage_heap_pages: downloaded_runtime .storage_heap_pages, - sources: self - .inner - .sources - .drain() - .map(|source| source.user_data) + sources_ordered: mem::take(&mut self.inner.sources) + .into_iter() + .map(|(id, source)| (SourceId(id), source.user_data)) .collect(), in_progress_requests: mem::take( &mut self.inner.in_progress_requests, diff --git a/light-base/src/sync_service/standalone.rs b/light-base/src/sync_service/standalone.rs index 739f83f26c..103f73626d 100644 --- a/light-base/src/sync_service/standalone.rs +++ b/light-base/src/sync_service/standalone.rs @@ -595,13 +595,35 @@ impl Task { return (self, false); } - all::ProcessOne::WarpSyncError { sync, error } => { - self.sync = sync; - log::warn!( - target: &self.log_target, - "Error during GrandPa warp syncing: {}", - error - ); + all::ProcessOne::WarpSyncBuildRuntime(req) => { + // Warp syncing compiles the runtime. The compiled runtime will later be yielded + // in the `WarpSyncFinished` variant, which is then provided as an event. + let (new_sync, error) = req.build(all::ExecHint::CompileAheadOfTime, true); + match error { + Ok(()) => { + log::debug!(target: &self.log_target, "Sync => WarpSyncRuntimeBuild(success=true)") + } + Err(err) => { + log::debug!(target: &self.log_target, "Sync => WarpSyncRuntimeBuild(error={})", err); + log::warn!(target: &self.log_target, "Failed to compile runtime during warp syncing process: {}", err); + } + }; + self.sync = new_sync; + return (self, true); + } + + all::ProcessOne::WarpSyncBuildChainInformation(req) => { + let (new_sync, error) = req.build(); + match error { + Ok(()) => { + log::debug!(target: &self.log_target, "Sync => WarpSyncBuildChainInformation(success=true)") + } + Err(err) => { + log::debug!(target: &self.log_target, "Sync => WarpSyncBuildChainInformation(error={})", err); + log::warn!(target: &self.log_target, "Failed to build the chain information during warp syncing process: {}", err); + } + }; + self.sync = new_sync; return (self, true); } diff --git a/wasm-node/CHANGELOG.md b/wasm-node/CHANGELOG.md index 54be9ca331..16d392f564 100644 --- a/wasm-node/CHANGELOG.md +++ b/wasm-node/CHANGELOG.md @@ -5,6 +5,7 @@ ### Changed - The parameter of `chainHead_unstable_follow` has been renamed from `runtimeUpdates` to `withRuntime` in accordance with the latest JSON-RPC specification changes. ([#624](https://github.com/smol-dot/smoldot/pull/624)) +- Errors while building the runtime and errors while building the consensus-related information that can happen during the warp syncing process are now printed in the logs. ([#644](https://github.com/smol-dot/smoldot/pull/644)) ### Fixed