From f9f30c6f8a132e77cdc89595c30d25607abbf013 Mon Sep 17 00:00:00 2001 From: Chris Sosnin Date: Thu, 26 Aug 2021 16:18:03 +0300 Subject: [PATCH 1/7] Introduce new Runtime API endpoint `persisted_validation_data_with_code_hash` that will be used by the candidate validation subsystem in order to decrease amount of runtime API requests. --- node/core/runtime-api/src/tests.rs | 7 ++++ primitives/src/v1/mod.rs | 8 ++++ runtime/kusama/src/lib.rs | 10 +++++ runtime/parachains/src/paras.rs | 7 +++- runtime/parachains/src/runtime_api_impl/v1.rs | 40 ++++++++++++++++--- runtime/polkadot/src/lib.rs | 7 ++++ runtime/rococo/src/lib.rs | 10 +++++ runtime/test-runtime/src/lib.rs | 10 +++++ runtime/westend/src/lib.rs | 10 +++++ 9 files changed, 103 insertions(+), 6 deletions(-) diff --git a/node/core/runtime-api/src/tests.rs b/node/core/runtime-api/src/tests.rs index 18906e196b82..ee673880f24b 100644 --- a/node/core/runtime-api/src/tests.rs +++ b/node/core/runtime-api/src/tests.rs @@ -89,6 +89,13 @@ sp_api::mock_impl_runtime_apis! { self.validation_data.get(¶).cloned() } + fn persisted_validation_data_with_code_hash( + _para_id: ParaId, + _expected_persisted_validation_data_hash: Hash + ) -> Option<(PersistedValidationData, ValidationCodeHash)> { + None + } + fn check_validation_outputs( &self, para_id: ParaId, diff --git a/primitives/src/v1/mod.rs b/primitives/src/v1/mod.rs index dec17ca915a7..8a99970f2466 100644 --- a/primitives/src/v1/mod.rs +++ b/primitives/src/v1/mod.rs @@ -953,6 +953,14 @@ sp_api::decl_runtime_apis! { fn persisted_validation_data(para_id: Id, assumption: OccupiedCoreAssumption) -> Option>; + /// Returns the persisted validation data for the given `ParaId` along with the corresponding + /// validation code hash. Instead of accepting assumption about the para, matches the validation + /// data hash against an expected one and yields `None` if they're not equal. + fn persisted_validation_data_with_code_hash( + para_id: Id, + expected_persisted_validation_data_hash: Hash, + ) -> Option<(PersistedValidationData, ValidationCodeHash)>; + /// Checks if the given validation outputs pass the acceptance criteria. fn check_validation_outputs(para_id: Id, outputs: CandidateCommitments) -> bool; diff --git a/runtime/kusama/src/lib.rs b/runtime/kusama/src/lib.rs index ede28280b21a..bb1ae6fb82d9 100644 --- a/runtime/kusama/src/lib.rs +++ b/runtime/kusama/src/lib.rs @@ -1579,6 +1579,16 @@ sp_api::impl_runtime_apis! { parachains_runtime_api_impl::persisted_validation_data::(para_id, assumption) } + fn persisted_validation_data_with_code_hash( + para_id: ParaId, + expected_persisted_validation_data_hash: Hash, + ) -> Option<(PersistedValidationData, ValidationCodeHash)> { + parachains_runtime_api_impl::persisted_validation_data_with_code_hash::( + para_id, + expected_persisted_validation_data_hash + ) + } + fn check_validation_outputs( para_id: ParaId, outputs: primitives::v1::CandidateCommitments, diff --git a/runtime/parachains/src/paras.rs b/runtime/parachains/src/paras.rs index 170914d8f518..e4c45979ca4b 100644 --- a/runtime/parachains/src/paras.rs +++ b/runtime/parachains/src/paras.rs @@ -587,9 +587,14 @@ impl Pallet { outgoing_paras } + /// The validation code hash of live para. + pub(crate) fn current_code_hash(para_id: &ParaId) -> Option { + CurrentCodeHash::::get(para_id) + } + /// The validation code of live para. pub(crate) fn current_code(para_id: &ParaId) -> Option { - CurrentCodeHash::::get(para_id).and_then(|code_hash| { + Self::current_code_hash(para_id).and_then(|code_hash| { let code = CodeByHash::::get(&code_hash); if code.is_none() { log::error!( diff --git a/runtime/parachains/src/runtime_api_impl/v1.rs b/runtime/parachains/src/runtime_api_impl/v1.rs index 3dd0be084886..0a3518976ab4 100644 --- a/runtime/parachains/src/runtime_api_impl/v1.rs +++ b/runtime/parachains/src/runtime_api_impl/v1.rs @@ -22,7 +22,7 @@ use crate::{ }; use primitives::v1::{ AuthorityDiscoveryId, CandidateEvent, CommittedCandidateReceipt, CoreIndex, CoreOccupied, - CoreState, GroupIndex, GroupRotationInfo, Id as ParaId, InboundDownwardMessage, + CoreState, GroupIndex, GroupRotationInfo, Hash, Id as ParaId, InboundDownwardMessage, InboundHrmpMessage, OccupiedCore, OccupiedCoreAssumption, PersistedValidationData, ScheduledCore, SessionIndex, SessionInfo, ValidationCode, ValidationCodeHash, ValidatorId, ValidatorIndex, @@ -172,6 +172,16 @@ pub fn availability_cores() -> Vec( +) -> (::BlockNumber, ::Hash) { + use parity_scale_codec::Decode as _; + let relay_parent_number = >::block_number(); + let relay_parent_storage_root = T::Hash::decode(&mut &sp_io::storage::root()[..]) + .expect("storage root must decode to the Hash type; qed"); + (relay_parent_number, relay_parent_storage_root) +} + fn with_assumption( para_id: ParaId, assumption: OccupiedCoreAssumption, @@ -202,10 +212,7 @@ pub fn persisted_validation_data( para_id: ParaId, assumption: OccupiedCoreAssumption, ) -> Option> { - use parity_scale_codec::Decode as _; - let relay_parent_number = >::block_number(); - let relay_parent_storage_root = T::Hash::decode(&mut &sp_io::storage::root()[..]) - .expect("storage root must decode to the Hash type; qed"); + let (relay_parent_number, relay_parent_storage_root) = current_relay_parent::(); with_assumption::(para_id, assumption, || { crate::util::make_persisted_validation_data::( para_id, @@ -215,6 +222,29 @@ pub fn persisted_validation_data( }) } +/// Implementation for the `persisted_validation_data_with_code_hash` function of the runtime API. +pub fn persisted_validation_data_with_code_hash( + para_id: ParaId, + expected_persisted_validation_data_hash: Hash, +) -> Option<(PersistedValidationData, ValidationCodeHash)> { + let (relay_parent_number, relay_parent_storage_root) = current_relay_parent::(); + let make_validation_data = || { + crate::util::make_persisted_validation_data::( + para_id, + relay_parent_number, + relay_parent_storage_root, + ) + .filter(|validation_data| validation_data.hash() == expected_persisted_validation_data_hash) + }; + let persisted_validation_data = make_validation_data().or_else(|| { + >::pending_availability(para_id).and_then(|_| { + >::force_enact(para_id); + make_validation_data() + }) + }); + persisted_validation_data.zip(>::current_code_hash(¶_id)) +} + /// Implementation for the `check_validation_outputs` function of the runtime API. pub fn check_validation_outputs( para_id: ParaId, diff --git a/runtime/polkadot/src/lib.rs b/runtime/polkadot/src/lib.rs index 8e5eb2776856..1223497686b7 100644 --- a/runtime/polkadot/src/lib.rs +++ b/runtime/polkadot/src/lib.rs @@ -1219,6 +1219,13 @@ sp_api::impl_runtime_apis! { None } + fn persisted_validation_data_with_code_hash( + _: Id, + _: Hash, + ) -> Option<(PersistedValidationData, ValidationCodeHash)> { + None + } + fn check_validation_outputs(_: Id, _: primitives::v1::CandidateCommitments) -> bool { false } diff --git a/runtime/rococo/src/lib.rs b/runtime/rococo/src/lib.rs index 35d78487eca9..736c57cb2eea 100644 --- a/runtime/rococo/src/lib.rs +++ b/runtime/rococo/src/lib.rs @@ -1174,6 +1174,16 @@ sp_api::impl_runtime_apis! { runtime_api_impl::persisted_validation_data::(para_id, assumption) } + fn persisted_validation_data_with_code_hash( + para_id: ParaId, + expected_persisted_validation_data_hash: Hash, + ) -> Option<(PersistedValidationData, ValidationCodeHash)> { + runtime_api_impl::persisted_validation_data_with_code_hash::( + para_id, + expected_persisted_validation_data_hash + ) + } + fn check_validation_outputs( para_id: Id, outputs: primitives::v1::CandidateCommitments, diff --git a/runtime/test-runtime/src/lib.rs b/runtime/test-runtime/src/lib.rs index 1ca04fbf1184..a1186e9489f3 100644 --- a/runtime/test-runtime/src/lib.rs +++ b/runtime/test-runtime/src/lib.rs @@ -695,6 +695,16 @@ sp_api::impl_runtime_apis! { runtime_impl::persisted_validation_data::(para_id, assumption) } + fn persisted_validation_data_with_code_hash( + para_id: ParaId, + expected_persisted_validation_data_hash: Hash, + ) -> Option<(PersistedValidationData, ValidationCodeHash)> { + runtime_impl::persisted_validation_data_with_code_hash::( + para_id, + expected_persisted_validation_data_hash + ) + } + fn check_validation_outputs( para_id: ParaId, outputs: primitives::v1::CandidateCommitments, diff --git a/runtime/westend/src/lib.rs b/runtime/westend/src/lib.rs index 8910e306d54c..a5f75e2ac011 100644 --- a/runtime/westend/src/lib.rs +++ b/runtime/westend/src/lib.rs @@ -1164,6 +1164,16 @@ sp_api::impl_runtime_apis! { parachains_runtime_api_impl::persisted_validation_data::(para_id, assumption) } + fn persisted_validation_data_with_code_hash( + para_id: ParaId, + expected_persisted_validation_data_hash: Hash, + ) -> Option<(PersistedValidationData, ValidationCodeHash)> { + parachains_runtime_api_impl::persisted_validation_data_with_code_hash::( + para_id, + expected_persisted_validation_data_hash + ) + } + fn check_validation_outputs( para_id: ParaId, outputs: primitives::v1::CandidateCommitments, From 7ecb4d5d4075088b20f5c5b60b7093259e393e28 Mon Sep 17 00:00:00 2001 From: Chris Sosnin Date: Thu, 26 Aug 2021 17:53:22 +0300 Subject: [PATCH 2/7] Node-side part of new runtime API request --- node/core/runtime-api/src/cache.rs | 29 +++++++++++++ node/core/runtime-api/src/lib.rs | 36 ++++++++++++++++ node/core/runtime-api/src/tests.rs | 62 ++++++++++++++++++++++++++-- node/subsystem-types/src/messages.rs | 7 ++++ 4 files changed, 131 insertions(+), 3 deletions(-) diff --git a/node/core/runtime-api/src/cache.rs b/node/core/runtime-api/src/cache.rs index 962959a23841..4f246b3d91d9 100644 --- a/node/core/runtime-api/src/cache.rs +++ b/node/core/runtime-api/src/cache.rs @@ -32,6 +32,7 @@ const VALIDATORS_CACHE_SIZE: usize = 64 * 1024; const VALIDATOR_GROUPS_CACHE_SIZE: usize = 64 * 1024; const AVAILABILITY_CORES_CACHE_SIZE: usize = 64 * 1024; const PERSISTED_VALIDATION_DATA_CACHE_SIZE: usize = 64 * 1024; +const PERSISTED_VALIDATION_DATA_WITH_CODE_HASH_CACHE_SIZE: usize = 64 * 1024; const CHECK_VALIDATION_OUTPUTS_CACHE_SIZE: usize = 64 * 1024; const SESSION_INDEX_FOR_CHILD_CACHE_SIZE: usize = 64 * 1024; const VALIDATION_CODE_CACHE_SIZE: usize = 10 * 1024 * 1024; @@ -78,6 +79,10 @@ pub(crate) struct RequestResultCache { (Hash, ParaId, OccupiedCoreAssumption), ResidentSizeOf>, >, + persisted_validation_data_with_code_hash: MemoryLruCache< + (ParaId, Hash), + ResidentSizeOf>, + >, check_validation_outputs: MemoryLruCache<(Hash, ParaId, CandidateCommitments), ResidentSizeOf>, session_index_for_child: MemoryLruCache>, @@ -108,6 +113,9 @@ impl Default for RequestResultCache { validator_groups: MemoryLruCache::new(VALIDATOR_GROUPS_CACHE_SIZE), availability_cores: MemoryLruCache::new(AVAILABILITY_CORES_CACHE_SIZE), persisted_validation_data: MemoryLruCache::new(PERSISTED_VALIDATION_DATA_CACHE_SIZE), + persisted_validation_data_with_code_hash: MemoryLruCache::new( + PERSISTED_VALIDATION_DATA_WITH_CODE_HASH_CACHE_SIZE, + ), check_validation_outputs: MemoryLruCache::new(CHECK_VALIDATION_OUTPUTS_CACHE_SIZE), session_index_for_child: MemoryLruCache::new(SESSION_INDEX_FOR_CHILD_CACHE_SIZE), validation_code: MemoryLruCache::new(VALIDATION_CODE_CACHE_SIZE), @@ -186,6 +194,21 @@ impl RequestResultCache { self.persisted_validation_data.insert(key, ResidentSizeOf(data)); } + pub(crate) fn persisted_validation_data_with_code_hash( + &mut self, + key: (Hash, ParaId, Hash), + ) -> Option<&Option<(PersistedValidationData, ValidationCodeHash)>> { + self.persisted_validation_data_with_code_hash.get(&(key.1, key.2)).map(|v| &v.0) + } + + pub(crate) fn cache_persisted_validation_data_with_code_hash( + &mut self, + key: (ParaId, Hash), + data: Option<(PersistedValidationData, ValidationCodeHash)>, + ) { + self.persisted_validation_data_with_code_hash.insert(key, ResidentSizeOf(data)); + } + pub(crate) fn check_validation_outputs( &mut self, key: (Hash, ParaId, CandidateCommitments), @@ -328,6 +351,12 @@ pub(crate) enum RequestResult { ValidatorGroups(Hash, (Vec>, GroupRotationInfo)), AvailabilityCores(Hash, Vec), PersistedValidationData(Hash, ParaId, OccupiedCoreAssumption, Option), + PersistedValidationDataWithCodeHash( + Hash, + ParaId, + Hash, + Option<(PersistedValidationData, ValidationCodeHash)>, + ), CheckValidationOutputs(Hash, ParaId, CandidateCommitments, bool), SessionIndexForChild(Hash, SessionIndex), ValidationCode(Hash, ParaId, OccupiedCoreAssumption, Option), diff --git a/node/core/runtime-api/src/lib.rs b/node/core/runtime-api/src/lib.rs index cf2ec719c8e5..9f9e58cd03ab 100644 --- a/node/core/runtime-api/src/lib.rs +++ b/node/core/runtime-api/src/lib.rs @@ -119,6 +119,15 @@ where PersistedValidationData(relay_parent, para_id, assumption, data) => self .requests_cache .cache_persisted_validation_data((relay_parent, para_id, assumption), data), + PersistedValidationDataWithCodeHash( + _relay_parent, + para_id, + expected_persisted_validation_data_hash, + data, + ) => self.requests_cache.cache_persisted_validation_data_with_code_hash( + (para_id, expected_persisted_validation_data_hash), + data, + ), CheckValidationOutputs(relay_parent, para_id, commitments, b) => self .requests_cache .cache_check_validation_outputs((relay_parent, para_id, commitments), b), @@ -184,6 +193,24 @@ where Request::PersistedValidationData(para, assumption, sender) => query!(persisted_validation_data(para, assumption), sender) .map(|sender| Request::PersistedValidationData(para, assumption, sender)), + Request::PersistedValidationDataWithCodeHash( + para, + expected_persisted_validation_data_hash, + sender, + ) => query!( + persisted_validation_data_with_code_hash( + para, + expected_persisted_validation_data_hash + ), + sender + ) + .map(|sender| { + Request::PersistedValidationDataWithCodeHash( + para, + expected_persisted_validation_data_hash, + sender, + ) + }), Request::CheckValidationOutputs(para, commitments, sender) => query!(check_validation_outputs(para, commitments), sender) .map(|sender| Request::CheckValidationOutputs(para, commitments, sender)), @@ -326,6 +353,15 @@ where query!(AvailabilityCores, availability_cores(), sender), Request::PersistedValidationData(para, assumption, sender) => query!(PersistedValidationData, persisted_validation_data(para, assumption), sender), + Request::PersistedValidationDataWithCodeHash( + para, + expected_persisted_validation_data_hash, + sender, + ) => query!( + PersistedValidationDataWithCodeHash, + persisted_validation_data_with_code_hash(para, expected_persisted_validation_data_hash), + sender + ), Request::CheckValidationOutputs(para, commitments, sender) => query!(CheckValidationOutputs, check_validation_outputs(para, commitments), sender), Request::SessionIndexForChild(sender) => diff --git a/node/core/runtime-api/src/tests.rs b/node/core/runtime-api/src/tests.rs index ee673880f24b..2c435c8b038c 100644 --- a/node/core/runtime-api/src/tests.rs +++ b/node/core/runtime-api/src/tests.rs @@ -90,10 +90,14 @@ sp_api::mock_impl_runtime_apis! { } fn persisted_validation_data_with_code_hash( - _para_id: ParaId, - _expected_persisted_validation_data_hash: Hash + para_id: ParaId, + expected_persisted_validation_data_hash: Hash, ) -> Option<(PersistedValidationData, ValidationCodeHash)> { - None + self.validation_data + .get(¶_id) + .cloned() + .filter(|data| data.hash() == expected_persisted_validation_data_hash) + .zip(self.validation_code.get(¶_id).map(|code| code.hash())) } fn check_validation_outputs( @@ -347,6 +351,58 @@ fn requests_persisted_validation_data() { futures::executor::block_on(future::join(subsystem_task, test_task)); } +#[test] +fn requests_persisted_validation_data_with_code_hash() { + let (ctx, mut ctx_handle) = test_helpers::make_subsystem_context(TaskExecutor::new()); + let relay_parent = [1; 32].into(); + let para_a = 5.into(); + let para_b = 6.into(); + let spawner = sp_core::testing::TaskExecutor::new(); + + let validation_code = ValidationCode(vec![1, 2, 3]); + let expected_data_hash = ::default().hash(); + let expected_code_hash = validation_code.hash(); + + let mut runtime_api = MockRuntimeApi::default(); + runtime_api.validation_data.insert(para_a, Default::default()); + runtime_api.validation_code.insert(para_a, validation_code); + runtime_api.validation_data.insert(para_b, Default::default()); + let runtime_api = Arc::new(runtime_api); + + let subsystem = RuntimeApiSubsystem::new(runtime_api.clone(), Metrics(None), spawner); + let subsystem_task = run(ctx, subsystem).map(|x| x.unwrap()); + let test_task = async move { + let (tx, rx) = oneshot::channel(); + + ctx_handle + .send(FromOverseer::Communication { + msg: RuntimeApiMessage::Request( + relay_parent, + Request::PersistedValidationDataWithCodeHash(para_a, expected_data_hash, tx), + ), + }) + .await; + + assert_eq!(rx.await.unwrap().unwrap(), Some((Default::default(), expected_code_hash))); + + let (tx, rx) = oneshot::channel(); + ctx_handle + .send(FromOverseer::Communication { + msg: RuntimeApiMessage::Request( + relay_parent, + Request::PersistedValidationDataWithCodeHash(para_a, Hash::zero(), tx), + ), + }) + .await; + + assert_eq!(rx.await.unwrap().unwrap(), None); + + ctx_handle.send(FromOverseer::Signal(OverseerSignal::Conclude)).await; + }; + + futures::executor::block_on(future::join(subsystem_task, test_task)); +} + #[test] fn requests_check_validation_outputs() { let (ctx, mut ctx_handle) = test_helpers::make_subsystem_context(TaskExecutor::new()); diff --git a/node/subsystem-types/src/messages.rs b/node/subsystem-types/src/messages.rs index 147074fa1b1d..d1d34ca06eb5 100644 --- a/node/subsystem-types/src/messages.rs +++ b/node/subsystem-types/src/messages.rs @@ -594,6 +594,13 @@ pub enum RuntimeApiRequest { OccupiedCoreAssumption, RuntimeApiSender>, ), + /// Get the persisted validation data for a particular para along with the current validation code + /// hash, matching the data hash against an expected one without any assumptions. + PersistedValidationDataWithCodeHash( + ParaId, + Hash, + RuntimeApiSender>, + ), /// Sends back `true` if the validation outputs pass all acceptance criteria checks. CheckValidationOutputs( ParaId, From 8a67b2bc01ef4e1d6f365cc06f51737347a077fc Mon Sep 17 00:00:00 2001 From: Chris Sosnin Date: Fri, 27 Aug 2021 17:06:39 +0300 Subject: [PATCH 3/7] Define code hash getter via macro --- runtime/parachains/src/paras.rs | 6 +----- 1 file changed, 1 insertion(+), 5 deletions(-) diff --git a/runtime/parachains/src/paras.rs b/runtime/parachains/src/paras.rs index e4c45979ca4b..b303240a11ef 100644 --- a/runtime/parachains/src/paras.rs +++ b/runtime/parachains/src/paras.rs @@ -331,6 +331,7 @@ pub mod pallet { /// /// Corresponding code can be retrieved with [`CodeByHash`]. #[pallet::storage] + #[pallet::getter(fn current_code_hash)] pub(super) type CurrentCodeHash = StorageMap<_, Twox64Concat, ParaId, ValidationCodeHash>; @@ -587,11 +588,6 @@ impl Pallet { outgoing_paras } - /// The validation code hash of live para. - pub(crate) fn current_code_hash(para_id: &ParaId) -> Option { - CurrentCodeHash::::get(para_id) - } - /// The validation code of live para. pub(crate) fn current_code(para_id: &ParaId) -> Option { Self::current_code_hash(para_id).and_then(|code_hash| { From a9d6ceaeec34c2f05c901a0de1461e0baa3856eb Mon Sep 17 00:00:00 2001 From: Chris Sosnin Date: Fri, 27 Aug 2021 17:33:49 +0300 Subject: [PATCH 4/7] Rename new endpoint to `assumed_validation_data` --- node/core/runtime-api/src/cache.rs | 18 ++++++------ node/core/runtime-api/src/lib.rs | 28 ++++++++----------- node/core/runtime-api/src/tests.rs | 8 +++--- node/subsystem-types/src/messages.rs | 4 +-- primitives/src/v1/mod.rs | 2 +- runtime/kusama/src/lib.rs | 6 ++-- runtime/parachains/src/runtime_api_impl/v1.rs | 4 +-- runtime/polkadot/src/lib.rs | 2 +- runtime/rococo/src/lib.rs | 6 ++-- runtime/test-runtime/src/lib.rs | 6 ++-- runtime/westend/src/lib.rs | 6 ++-- 11 files changed, 41 insertions(+), 49 deletions(-) diff --git a/node/core/runtime-api/src/cache.rs b/node/core/runtime-api/src/cache.rs index 4f246b3d91d9..b30f3138c416 100644 --- a/node/core/runtime-api/src/cache.rs +++ b/node/core/runtime-api/src/cache.rs @@ -32,7 +32,7 @@ const VALIDATORS_CACHE_SIZE: usize = 64 * 1024; const VALIDATOR_GROUPS_CACHE_SIZE: usize = 64 * 1024; const AVAILABILITY_CORES_CACHE_SIZE: usize = 64 * 1024; const PERSISTED_VALIDATION_DATA_CACHE_SIZE: usize = 64 * 1024; -const PERSISTED_VALIDATION_DATA_WITH_CODE_HASH_CACHE_SIZE: usize = 64 * 1024; +const ASSUMED_VALIDATION_DATA_CACHE_SIZE: usize = 64 * 1024; const CHECK_VALIDATION_OUTPUTS_CACHE_SIZE: usize = 64 * 1024; const SESSION_INDEX_FOR_CHILD_CACHE_SIZE: usize = 64 * 1024; const VALIDATION_CODE_CACHE_SIZE: usize = 10 * 1024 * 1024; @@ -79,7 +79,7 @@ pub(crate) struct RequestResultCache { (Hash, ParaId, OccupiedCoreAssumption), ResidentSizeOf>, >, - persisted_validation_data_with_code_hash: MemoryLruCache< + assumed_validation_data: MemoryLruCache< (ParaId, Hash), ResidentSizeOf>, >, @@ -113,9 +113,7 @@ impl Default for RequestResultCache { validator_groups: MemoryLruCache::new(VALIDATOR_GROUPS_CACHE_SIZE), availability_cores: MemoryLruCache::new(AVAILABILITY_CORES_CACHE_SIZE), persisted_validation_data: MemoryLruCache::new(PERSISTED_VALIDATION_DATA_CACHE_SIZE), - persisted_validation_data_with_code_hash: MemoryLruCache::new( - PERSISTED_VALIDATION_DATA_WITH_CODE_HASH_CACHE_SIZE, - ), + assumed_validation_data: MemoryLruCache::new(ASSUMED_VALIDATION_DATA_CACHE_SIZE), check_validation_outputs: MemoryLruCache::new(CHECK_VALIDATION_OUTPUTS_CACHE_SIZE), session_index_for_child: MemoryLruCache::new(SESSION_INDEX_FOR_CHILD_CACHE_SIZE), validation_code: MemoryLruCache::new(VALIDATION_CODE_CACHE_SIZE), @@ -194,19 +192,19 @@ impl RequestResultCache { self.persisted_validation_data.insert(key, ResidentSizeOf(data)); } - pub(crate) fn persisted_validation_data_with_code_hash( + pub(crate) fn assumed_validation_data( &mut self, key: (Hash, ParaId, Hash), ) -> Option<&Option<(PersistedValidationData, ValidationCodeHash)>> { - self.persisted_validation_data_with_code_hash.get(&(key.1, key.2)).map(|v| &v.0) + self.assumed_validation_data.get(&(key.1, key.2)).map(|v| &v.0) } - pub(crate) fn cache_persisted_validation_data_with_code_hash( + pub(crate) fn cache_assumed_validation_data( &mut self, key: (ParaId, Hash), data: Option<(PersistedValidationData, ValidationCodeHash)>, ) { - self.persisted_validation_data_with_code_hash.insert(key, ResidentSizeOf(data)); + self.assumed_validation_data.insert(key, ResidentSizeOf(data)); } pub(crate) fn check_validation_outputs( @@ -351,7 +349,7 @@ pub(crate) enum RequestResult { ValidatorGroups(Hash, (Vec>, GroupRotationInfo)), AvailabilityCores(Hash, Vec), PersistedValidationData(Hash, ParaId, OccupiedCoreAssumption, Option), - PersistedValidationDataWithCodeHash( + AssumedValidationData( Hash, ParaId, Hash, diff --git a/node/core/runtime-api/src/lib.rs b/node/core/runtime-api/src/lib.rs index 9f9e58cd03ab..dfa5cc76eedf 100644 --- a/node/core/runtime-api/src/lib.rs +++ b/node/core/runtime-api/src/lib.rs @@ -119,12 +119,12 @@ where PersistedValidationData(relay_parent, para_id, assumption, data) => self .requests_cache .cache_persisted_validation_data((relay_parent, para_id, assumption), data), - PersistedValidationDataWithCodeHash( + AssumedValidationData( _relay_parent, para_id, expected_persisted_validation_data_hash, data, - ) => self.requests_cache.cache_persisted_validation_data_with_code_hash( + ) => self.requests_cache.cache_assumed_validation_data( (para_id, expected_persisted_validation_data_hash), data, ), @@ -193,19 +193,16 @@ where Request::PersistedValidationData(para, assumption, sender) => query!(persisted_validation_data(para, assumption), sender) .map(|sender| Request::PersistedValidationData(para, assumption, sender)), - Request::PersistedValidationDataWithCodeHash( + Request::AssumedValidationData( para, expected_persisted_validation_data_hash, sender, ) => query!( - persisted_validation_data_with_code_hash( - para, - expected_persisted_validation_data_hash - ), + assumed_validation_data(para, expected_persisted_validation_data_hash), sender ) .map(|sender| { - Request::PersistedValidationDataWithCodeHash( + Request::AssumedValidationData( para, expected_persisted_validation_data_hash, sender, @@ -353,15 +350,12 @@ where query!(AvailabilityCores, availability_cores(), sender), Request::PersistedValidationData(para, assumption, sender) => query!(PersistedValidationData, persisted_validation_data(para, assumption), sender), - Request::PersistedValidationDataWithCodeHash( - para, - expected_persisted_validation_data_hash, - sender, - ) => query!( - PersistedValidationDataWithCodeHash, - persisted_validation_data_with_code_hash(para, expected_persisted_validation_data_hash), - sender - ), + Request::AssumedValidationData(para, expected_persisted_validation_data_hash, sender) => + query!( + AssumedValidationData, + assumed_validation_data(para, expected_persisted_validation_data_hash), + sender + ), Request::CheckValidationOutputs(para, commitments, sender) => query!(CheckValidationOutputs, check_validation_outputs(para, commitments), sender), Request::SessionIndexForChild(sender) => diff --git a/node/core/runtime-api/src/tests.rs b/node/core/runtime-api/src/tests.rs index 2c435c8b038c..93ef6f186fb4 100644 --- a/node/core/runtime-api/src/tests.rs +++ b/node/core/runtime-api/src/tests.rs @@ -89,7 +89,7 @@ sp_api::mock_impl_runtime_apis! { self.validation_data.get(¶).cloned() } - fn persisted_validation_data_with_code_hash( + fn assumed_validation_data( para_id: ParaId, expected_persisted_validation_data_hash: Hash, ) -> Option<(PersistedValidationData, ValidationCodeHash)> { @@ -352,7 +352,7 @@ fn requests_persisted_validation_data() { } #[test] -fn requests_persisted_validation_data_with_code_hash() { +fn requests_assumed_validation_data() { let (ctx, mut ctx_handle) = test_helpers::make_subsystem_context(TaskExecutor::new()); let relay_parent = [1; 32].into(); let para_a = 5.into(); @@ -378,7 +378,7 @@ fn requests_persisted_validation_data_with_code_hash() { .send(FromOverseer::Communication { msg: RuntimeApiMessage::Request( relay_parent, - Request::PersistedValidationDataWithCodeHash(para_a, expected_data_hash, tx), + Request::AssumedValidationData(para_a, expected_data_hash, tx), ), }) .await; @@ -390,7 +390,7 @@ fn requests_persisted_validation_data_with_code_hash() { .send(FromOverseer::Communication { msg: RuntimeApiMessage::Request( relay_parent, - Request::PersistedValidationDataWithCodeHash(para_a, Hash::zero(), tx), + Request::AssumedValidationData(para_a, Hash::zero(), tx), ), }) .await; diff --git a/node/subsystem-types/src/messages.rs b/node/subsystem-types/src/messages.rs index d1d34ca06eb5..cb5233c98b6f 100644 --- a/node/subsystem-types/src/messages.rs +++ b/node/subsystem-types/src/messages.rs @@ -595,8 +595,8 @@ pub enum RuntimeApiRequest { RuntimeApiSender>, ), /// Get the persisted validation data for a particular para along with the current validation code - /// hash, matching the data hash against an expected one without any assumptions. - PersistedValidationDataWithCodeHash( + /// hash, matching the data hash against an expected one. + AssumedValidationData( ParaId, Hash, RuntimeApiSender>, diff --git a/primitives/src/v1/mod.rs b/primitives/src/v1/mod.rs index 8a99970f2466..94df973d0348 100644 --- a/primitives/src/v1/mod.rs +++ b/primitives/src/v1/mod.rs @@ -956,7 +956,7 @@ sp_api::decl_runtime_apis! { /// Returns the persisted validation data for the given `ParaId` along with the corresponding /// validation code hash. Instead of accepting assumption about the para, matches the validation /// data hash against an expected one and yields `None` if they're not equal. - fn persisted_validation_data_with_code_hash( + fn assumed_validation_data( para_id: Id, expected_persisted_validation_data_hash: Hash, ) -> Option<(PersistedValidationData, ValidationCodeHash)>; diff --git a/runtime/kusama/src/lib.rs b/runtime/kusama/src/lib.rs index bb1ae6fb82d9..f4c1b448c5ef 100644 --- a/runtime/kusama/src/lib.rs +++ b/runtime/kusama/src/lib.rs @@ -1579,13 +1579,13 @@ sp_api::impl_runtime_apis! { parachains_runtime_api_impl::persisted_validation_data::(para_id, assumption) } - fn persisted_validation_data_with_code_hash( + fn assumed_validation_data( para_id: ParaId, expected_persisted_validation_data_hash: Hash, ) -> Option<(PersistedValidationData, ValidationCodeHash)> { - parachains_runtime_api_impl::persisted_validation_data_with_code_hash::( + parachains_runtime_api_impl::assumed_validation_data::( para_id, - expected_persisted_validation_data_hash + expected_persisted_validation_data_hash, ) } diff --git a/runtime/parachains/src/runtime_api_impl/v1.rs b/runtime/parachains/src/runtime_api_impl/v1.rs index 0a3518976ab4..2a6d77b92278 100644 --- a/runtime/parachains/src/runtime_api_impl/v1.rs +++ b/runtime/parachains/src/runtime_api_impl/v1.rs @@ -222,8 +222,8 @@ pub fn persisted_validation_data( }) } -/// Implementation for the `persisted_validation_data_with_code_hash` function of the runtime API. -pub fn persisted_validation_data_with_code_hash( +/// Implementation for the `assumed_validation_data` function of the runtime API. +pub fn assumed_validation_data( para_id: ParaId, expected_persisted_validation_data_hash: Hash, ) -> Option<(PersistedValidationData, ValidationCodeHash)> { diff --git a/runtime/polkadot/src/lib.rs b/runtime/polkadot/src/lib.rs index 1223497686b7..613e69b68a5b 100644 --- a/runtime/polkadot/src/lib.rs +++ b/runtime/polkadot/src/lib.rs @@ -1219,7 +1219,7 @@ sp_api::impl_runtime_apis! { None } - fn persisted_validation_data_with_code_hash( + fn assumed_validation_data( _: Id, _: Hash, ) -> Option<(PersistedValidationData, ValidationCodeHash)> { diff --git a/runtime/rococo/src/lib.rs b/runtime/rococo/src/lib.rs index 736c57cb2eea..f39c473e4a9d 100644 --- a/runtime/rococo/src/lib.rs +++ b/runtime/rococo/src/lib.rs @@ -1174,13 +1174,13 @@ sp_api::impl_runtime_apis! { runtime_api_impl::persisted_validation_data::(para_id, assumption) } - fn persisted_validation_data_with_code_hash( + fn assumed_validation_data( para_id: ParaId, expected_persisted_validation_data_hash: Hash, ) -> Option<(PersistedValidationData, ValidationCodeHash)> { - runtime_api_impl::persisted_validation_data_with_code_hash::( + runtime_api_impl::assumed_validation_data::( para_id, - expected_persisted_validation_data_hash + expected_persisted_validation_data_hash, ) } diff --git a/runtime/test-runtime/src/lib.rs b/runtime/test-runtime/src/lib.rs index a1186e9489f3..20a518c08aeb 100644 --- a/runtime/test-runtime/src/lib.rs +++ b/runtime/test-runtime/src/lib.rs @@ -695,13 +695,13 @@ sp_api::impl_runtime_apis! { runtime_impl::persisted_validation_data::(para_id, assumption) } - fn persisted_validation_data_with_code_hash( + fn assumed_validation_data( para_id: ParaId, expected_persisted_validation_data_hash: Hash, ) -> Option<(PersistedValidationData, ValidationCodeHash)> { - runtime_impl::persisted_validation_data_with_code_hash::( + runtime_impl::assumed_validation_data::( para_id, - expected_persisted_validation_data_hash + expected_persisted_validation_data_hash, ) } diff --git a/runtime/westend/src/lib.rs b/runtime/westend/src/lib.rs index a5f75e2ac011..cd7c887118e4 100644 --- a/runtime/westend/src/lib.rs +++ b/runtime/westend/src/lib.rs @@ -1164,13 +1164,13 @@ sp_api::impl_runtime_apis! { parachains_runtime_api_impl::persisted_validation_data::(para_id, assumption) } - fn persisted_validation_data_with_code_hash( + fn assumed_validation_data( para_id: ParaId, expected_persisted_validation_data_hash: Hash, ) -> Option<(PersistedValidationData, ValidationCodeHash)> { - parachains_runtime_api_impl::persisted_validation_data_with_code_hash::( + parachains_runtime_api_impl::assumed_validation_data::( para_id, - expected_persisted_validation_data_hash + expected_persisted_validation_data_hash, ) } From 7cece5f5e4bcfb8301840b6c8cec17837754d0a3 Mon Sep 17 00:00:00 2001 From: Chris Sosnin Date: Fri, 27 Aug 2021 17:42:55 +0300 Subject: [PATCH 5/7] Docs for runtime API impl of new endpoint --- runtime/parachains/src/runtime_api_impl/v1.rs | 6 ++++++ 1 file changed, 6 insertions(+) diff --git a/runtime/parachains/src/runtime_api_impl/v1.rs b/runtime/parachains/src/runtime_api_impl/v1.rs index 2a6d77b92278..2b96b5bf19d2 100644 --- a/runtime/parachains/src/runtime_api_impl/v1.rs +++ b/runtime/parachains/src/runtime_api_impl/v1.rs @@ -228,6 +228,8 @@ pub fn assumed_validation_data( expected_persisted_validation_data_hash: Hash, ) -> Option<(PersistedValidationData, ValidationCodeHash)> { let (relay_parent_number, relay_parent_storage_root) = current_relay_parent::(); + // This closure obtains the `persisted_validation_data` for the given `para_id` and matches + // its hash against an expected one. let make_validation_data = || { crate::util::make_persisted_validation_data::( para_id, @@ -236,12 +238,16 @@ pub fn assumed_validation_data( ) .filter(|validation_data| validation_data.hash() == expected_persisted_validation_data_hash) }; + let persisted_validation_data = make_validation_data().or_else(|| { + // Try again with force enacting the core. This check only makes sense if + // the core is occupied. >::pending_availability(para_id).and_then(|_| { >::force_enact(para_id); make_validation_data() }) }); + // If we were successful, also query current validation code hash. persisted_validation_data.zip(>::current_code_hash(¶_id)) } From 5816c34e238cae0e992edde677bea7ce930a6a28 Mon Sep 17 00:00:00 2001 From: Chris Sosnin Date: Fri, 27 Aug 2021 17:48:18 +0300 Subject: [PATCH 6/7] AssumedValidationData specialized request function --- node/subsystem-util/src/lib.rs | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/node/subsystem-util/src/lib.rs b/node/subsystem-util/src/lib.rs index 0c5e35d1abc8..27be7424955c 100644 --- a/node/subsystem-util/src/lib.rs +++ b/node/subsystem-util/src/lib.rs @@ -53,7 +53,7 @@ use polkadot_primitives::v1::{ AuthorityDiscoveryId, CandidateEvent, CommittedCandidateReceipt, CoreState, EncodeAs, GroupIndex, GroupRotationInfo, Hash, Id as ParaId, OccupiedCoreAssumption, PersistedValidationData, SessionIndex, SessionInfo, Signed, SigningContext, ValidationCode, - ValidatorId, ValidatorIndex, + ValidationCodeHash, ValidatorId, ValidatorIndex, }; use sp_application_crypto::AppKey; use sp_core::{traits::SpawnNamed, Public}; @@ -206,6 +206,7 @@ specialize_requests! { fn request_validator_groups() -> (Vec>, GroupRotationInfo); ValidatorGroups; fn request_availability_cores() -> Vec; AvailabilityCores; fn request_persisted_validation_data(para_id: ParaId, assumption: OccupiedCoreAssumption) -> Option; PersistedValidationData; + fn request_assumed_validation_data(para_id: ParaId, expected_persisted_validation_data_hash: Hash) -> Option<(PersistedValidationData, ValidationCodeHash)>; AssumedValidationData; fn request_session_index_for_child() -> SessionIndex; SessionIndexForChild; fn request_validation_code(para_id: ParaId, assumption: OccupiedCoreAssumption) -> Option; ValidationCode; fn request_candidate_pending_availability(para_id: ParaId) -> Option; CandidatePendingAvailability; From 5a82f59643d2b11b126ee8d9b3203646f9b55d20 Mon Sep 17 00:00:00 2001 From: Chris Sosnin Date: Thu, 21 Oct 2021 16:26:38 +0300 Subject: [PATCH 7/7] fmt --- runtime/kusama/src/lib.rs | 4 +--- 1 file changed, 1 insertion(+), 3 deletions(-) diff --git a/runtime/kusama/src/lib.rs b/runtime/kusama/src/lib.rs index a270a0d0d571..147531946673 100644 --- a/runtime/kusama/src/lib.rs +++ b/runtime/kusama/src/lib.rs @@ -49,9 +49,7 @@ use authority_discovery_primitives::AuthorityId as AuthorityDiscoveryId; use beefy_primitives::crypto::AuthorityId as BeefyId; use frame_support::{ construct_runtime, parameter_types, - traits::{ - Contains, Everything, InstanceFilter, KeyOwnerProofSystem, LockIdentifier, Nothing, - }, + traits::{Contains, Everything, InstanceFilter, KeyOwnerProofSystem, LockIdentifier, Nothing}, weights::Weight, PalletId, RuntimeDebug, };