mirror of
https://github.com/pezkuwichain/pezkuwi-subxt.git
synced 2026-05-30 08:11:03 +00:00
Implement validation data refactor (#1585)
* update primitives * correct parent_head field * make hrmp field pub * refactor validation data: runtime * refactor validation data: messages * add arguments to full_validation_data runtime API * port runtime API * mostly port over candidate validation * remove some parameters from ValidationParams * guide: update candidate validation * update candidate outputs * update ValidationOutputs in primitives * port over candidate validation * add a new test for no-transient behavior * update util runtime API wrappers * candidate backing * fix missing imports * change some fields of validation data around * runtime API impl * update candidate validation * fix backing tests * grumbles from review * fix av-store tests * fix some more crates * fix provisioner tests * fix availability distribution tests * port collation-generation to new validation data * fix overseer tests * Update roadmap/implementers-guide/src/node/utility/candidate-validation.md Co-authored-by: Peter Goodspeed-Niklaus <coriolinus@users.noreply.github.com> Co-authored-by: Peter Goodspeed-Niklaus <coriolinus@users.noreply.github.com>
This commit is contained in:
committed by
GitHub
parent
3395044402
commit
262574fc49
@@ -19,13 +19,12 @@
|
||||
//! Configuration can change only at session boundaries and is buffered until then.
|
||||
|
||||
use sp_std::prelude::*;
|
||||
use primitives::v1::{ValidatorId, GlobalValidationData};
|
||||
use primitives::v1::ValidatorId;
|
||||
use frame_support::{
|
||||
decl_storage, decl_module, decl_error,
|
||||
dispatch::DispatchResult,
|
||||
weights::{DispatchClass, Weight},
|
||||
};
|
||||
use sp_runtime::traits::One;
|
||||
use codec::{Encode, Decode};
|
||||
use frame_system::ensure_root;
|
||||
|
||||
@@ -220,16 +219,6 @@ impl<T: Trait> Module<T> {
|
||||
<Self as Store>::PendingConfig::set(Some(prev));
|
||||
}
|
||||
}
|
||||
|
||||
/// Computes the global validation-data, assuming the context of the parent block.
|
||||
pub(crate) fn global_validation_data() -> GlobalValidationData<T::BlockNumber> {
|
||||
let config = Self::config();
|
||||
GlobalValidationData {
|
||||
max_code_size: config.max_code_size,
|
||||
max_head_data_size: config.max_head_data_size,
|
||||
block_number: <frame_system::Module<T>>::block_number() - One::one(),
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
#[cfg(test)]
|
||||
|
||||
@@ -22,7 +22,6 @@
|
||||
|
||||
use sp_std::prelude::*;
|
||||
use primitives::v1::{
|
||||
validation_data_hash,
|
||||
ValidatorId, CandidateCommitments, CandidateDescriptor, ValidatorIndex, Id as ParaId,
|
||||
AvailabilityBitfield as AvailabilityBitfield, SignedAvailabilityBitfields, SigningContext,
|
||||
BackedCandidate, CoreIndex, GroupIndex, CommittedCandidateReceipt,
|
||||
@@ -435,9 +434,8 @@ impl<T: Trait> Module<T> {
|
||||
|
||||
{
|
||||
// this should never fail because the para is registered
|
||||
let (global_validation_data, local_validation_data) = (
|
||||
<configuration::Module<T>>::global_validation_data(),
|
||||
match <paras::Module<T>>::local_validation_data(para_id) {
|
||||
let persisted_validation_data =
|
||||
match crate::util::make_persisted_validation_data::<T>(para_id) {
|
||||
Some(l) => l,
|
||||
None => {
|
||||
// We don't want to error out here because it will
|
||||
@@ -445,16 +443,12 @@ impl<T: Trait> Module<T> {
|
||||
// doing anything.
|
||||
return Ok(Vec::new());
|
||||
}
|
||||
}
|
||||
);
|
||||
};
|
||||
|
||||
let expected = validation_data_hash(
|
||||
&global_validation_data,
|
||||
&local_validation_data,
|
||||
);
|
||||
let expected = persisted_validation_data.hash();
|
||||
|
||||
ensure!(
|
||||
expected == candidate.descriptor().validation_data_hash,
|
||||
expected == candidate.descriptor().persisted_validation_data_hash,
|
||||
Error::<T>::ValidationDataHashMismatch,
|
||||
);
|
||||
}
|
||||
@@ -722,7 +716,7 @@ mod tests {
|
||||
let payload = primitives::v1::collator_signature_payload(
|
||||
&candidate.descriptor.relay_parent,
|
||||
&candidate.descriptor.para_id,
|
||||
&candidate.descriptor.validation_data_hash,
|
||||
&candidate.descriptor.persisted_validation_data_hash,
|
||||
&candidate.descriptor.pov_hash,
|
||||
);
|
||||
|
||||
@@ -851,7 +845,7 @@ mod tests {
|
||||
head_data: HeadData,
|
||||
pov_hash: Hash,
|
||||
relay_parent: Hash,
|
||||
validation_data_hash: Hash,
|
||||
persisted_validation_data_hash: Hash,
|
||||
new_validation_code: Option<ValidationCode>,
|
||||
}
|
||||
|
||||
@@ -862,7 +856,7 @@ mod tests {
|
||||
para_id: self.para_id,
|
||||
pov_hash: self.pov_hash,
|
||||
relay_parent: self.relay_parent,
|
||||
validation_data_hash: self.validation_data_hash,
|
||||
persisted_validation_data_hash: self.persisted_validation_data_hash,
|
||||
..Default::default()
|
||||
},
|
||||
commitments: CandidateCommitments {
|
||||
@@ -875,9 +869,9 @@ mod tests {
|
||||
}
|
||||
|
||||
fn make_vdata_hash(para_id: ParaId) -> Option<Hash> {
|
||||
let global_validation_data = Configuration::global_validation_data();
|
||||
let local_validation_data = Paras::local_validation_data(para_id)?;
|
||||
Some(validation_data_hash(&global_validation_data, &local_validation_data))
|
||||
let persisted_validation_data
|
||||
= crate::util::make_persisted_validation_data::<Test>(para_id)?;
|
||||
Some(persisted_validation_data.hash())
|
||||
}
|
||||
|
||||
#[test]
|
||||
@@ -1306,7 +1300,7 @@ mod tests {
|
||||
para_id: chain_a,
|
||||
relay_parent: System::parent_hash(),
|
||||
pov_hash: Hash::from([1; 32]),
|
||||
validation_data_hash: make_vdata_hash(chain_a).unwrap(),
|
||||
persisted_validation_data_hash: make_vdata_hash(chain_a).unwrap(),
|
||||
..Default::default()
|
||||
}.build();
|
||||
collator_sign_candidate(
|
||||
@@ -1338,14 +1332,14 @@ mod tests {
|
||||
para_id: chain_a,
|
||||
relay_parent: System::parent_hash(),
|
||||
pov_hash: Hash::from([1; 32]),
|
||||
validation_data_hash: make_vdata_hash(chain_a).unwrap(),
|
||||
persisted_validation_data_hash: make_vdata_hash(chain_a).unwrap(),
|
||||
..Default::default()
|
||||
}.build();
|
||||
let mut candidate_b = TestCandidateBuilder {
|
||||
para_id: chain_b,
|
||||
relay_parent: System::parent_hash(),
|
||||
pov_hash: Hash::from([2; 32]),
|
||||
validation_data_hash: make_vdata_hash(chain_b).unwrap(),
|
||||
persisted_validation_data_hash: make_vdata_hash(chain_b).unwrap(),
|
||||
..Default::default()
|
||||
}.build();
|
||||
|
||||
@@ -1392,7 +1386,7 @@ mod tests {
|
||||
para_id: chain_a,
|
||||
relay_parent: System::parent_hash(),
|
||||
pov_hash: Hash::from([1; 32]),
|
||||
validation_data_hash: make_vdata_hash(chain_a).unwrap(),
|
||||
persisted_validation_data_hash: make_vdata_hash(chain_a).unwrap(),
|
||||
..Default::default()
|
||||
}.build();
|
||||
collator_sign_candidate(
|
||||
@@ -1427,7 +1421,7 @@ mod tests {
|
||||
para_id: chain_a,
|
||||
relay_parent: wrong_parent_hash,
|
||||
pov_hash: Hash::from([1; 32]),
|
||||
validation_data_hash: make_vdata_hash(chain_a).unwrap(),
|
||||
persisted_validation_data_hash: make_vdata_hash(chain_a).unwrap(),
|
||||
..Default::default()
|
||||
}.build();
|
||||
collator_sign_candidate(
|
||||
@@ -1459,7 +1453,7 @@ mod tests {
|
||||
para_id: thread_a,
|
||||
relay_parent: System::parent_hash(),
|
||||
pov_hash: Hash::from([1; 32]),
|
||||
validation_data_hash: make_vdata_hash(thread_a).unwrap(),
|
||||
persisted_validation_data_hash: make_vdata_hash(thread_a).unwrap(),
|
||||
..Default::default()
|
||||
}.build();
|
||||
|
||||
@@ -1497,7 +1491,7 @@ mod tests {
|
||||
para_id: thread_a,
|
||||
relay_parent: System::parent_hash(),
|
||||
pov_hash: Hash::from([1; 32]),
|
||||
validation_data_hash: make_vdata_hash(thread_a).unwrap(),
|
||||
persisted_validation_data_hash: make_vdata_hash(thread_a).unwrap(),
|
||||
..Default::default()
|
||||
}.build();
|
||||
|
||||
@@ -1534,7 +1528,7 @@ mod tests {
|
||||
para_id: chain_a,
|
||||
relay_parent: System::parent_hash(),
|
||||
pov_hash: Hash::from([1; 32]),
|
||||
validation_data_hash: make_vdata_hash(chain_a).unwrap(),
|
||||
persisted_validation_data_hash: make_vdata_hash(chain_a).unwrap(),
|
||||
..Default::default()
|
||||
}.build();
|
||||
|
||||
@@ -1580,7 +1574,7 @@ mod tests {
|
||||
para_id: chain_a,
|
||||
relay_parent: System::parent_hash(),
|
||||
pov_hash: Hash::from([1; 32]),
|
||||
validation_data_hash: make_vdata_hash(chain_a).unwrap(),
|
||||
persisted_validation_data_hash: make_vdata_hash(chain_a).unwrap(),
|
||||
..Default::default()
|
||||
}.build();
|
||||
|
||||
@@ -1619,7 +1613,7 @@ mod tests {
|
||||
relay_parent: System::parent_hash(),
|
||||
pov_hash: Hash::from([1; 32]),
|
||||
new_validation_code: Some(vec![5, 6, 7, 8].into()),
|
||||
validation_data_hash: make_vdata_hash(chain_a).unwrap(),
|
||||
persisted_validation_data_hash: make_vdata_hash(chain_a).unwrap(),
|
||||
..Default::default()
|
||||
}.build();
|
||||
|
||||
@@ -1660,7 +1654,7 @@ mod tests {
|
||||
para_id: chain_a,
|
||||
relay_parent: System::parent_hash(),
|
||||
pov_hash: Hash::from([1; 32]),
|
||||
validation_data_hash: [42u8; 32].into(),
|
||||
persisted_validation_data_hash: [42u8; 32].into(),
|
||||
..Default::default()
|
||||
}.build();
|
||||
|
||||
@@ -1750,7 +1744,7 @@ mod tests {
|
||||
para_id: chain_a,
|
||||
relay_parent: System::parent_hash(),
|
||||
pov_hash: Hash::from([1; 32]),
|
||||
validation_data_hash: make_vdata_hash(chain_a).unwrap(),
|
||||
persisted_validation_data_hash: make_vdata_hash(chain_a).unwrap(),
|
||||
..Default::default()
|
||||
}.build();
|
||||
collator_sign_candidate(
|
||||
@@ -1762,7 +1756,7 @@ mod tests {
|
||||
para_id: chain_b,
|
||||
relay_parent: System::parent_hash(),
|
||||
pov_hash: Hash::from([2; 32]),
|
||||
validation_data_hash: make_vdata_hash(chain_b).unwrap(),
|
||||
persisted_validation_data_hash: make_vdata_hash(chain_b).unwrap(),
|
||||
..Default::default()
|
||||
}.build();
|
||||
collator_sign_candidate(
|
||||
@@ -1774,7 +1768,7 @@ mod tests {
|
||||
para_id: thread_a,
|
||||
relay_parent: System::parent_hash(),
|
||||
pov_hash: Hash::from([3; 32]),
|
||||
validation_data_hash: make_vdata_hash(thread_a).unwrap(),
|
||||
persisted_validation_data_hash: make_vdata_hash(thread_a).unwrap(),
|
||||
..Default::default()
|
||||
}.build();
|
||||
collator_sign_candidate(
|
||||
@@ -1906,7 +1900,7 @@ mod tests {
|
||||
para_id: chain_a,
|
||||
relay_parent: System::parent_hash(),
|
||||
pov_hash: Hash::from([1; 32]),
|
||||
validation_data_hash: make_vdata_hash(chain_a).unwrap(),
|
||||
persisted_validation_data_hash: make_vdata_hash(chain_a).unwrap(),
|
||||
new_validation_code: Some(vec![1, 2, 3].into()),
|
||||
..Default::default()
|
||||
}.build();
|
||||
|
||||
@@ -38,6 +38,8 @@ pub mod validity;
|
||||
|
||||
pub mod runtime_api_impl;
|
||||
|
||||
mod util;
|
||||
|
||||
#[cfg(test)]
|
||||
mod mock;
|
||||
|
||||
|
||||
@@ -26,10 +26,10 @@
|
||||
use sp_std::prelude::*;
|
||||
#[cfg(feature = "std")]
|
||||
use sp_std::marker::PhantomData;
|
||||
use sp_runtime::traits::{One, BlakeTwo256, Hash as HashT, Saturating};
|
||||
use primitives::v1::{
|
||||
Id as ParaId, ValidationCode, HeadData, LocalValidationData,
|
||||
Id as ParaId, ValidationCode, HeadData,
|
||||
};
|
||||
use sp_runtime::traits::One;
|
||||
use frame_support::{
|
||||
decl_storage, decl_module, decl_error,
|
||||
traits::Get,
|
||||
@@ -550,37 +550,6 @@ impl<T: Trait> Module<T> {
|
||||
|
||||
Self::past_code_meta(&id).most_recent_change()
|
||||
}
|
||||
|
||||
/// Compute the local-validation data based on the head of the para. This assumes the
|
||||
/// relay-parent is the parent of the current block.
|
||||
pub(crate) fn local_validation_data(para_id: ParaId) -> Option<LocalValidationData<T::BlockNumber>> {
|
||||
let relay_parent_number = <frame_system::Module<T>>::block_number() - One::one();
|
||||
|
||||
let config = <configuration::Module<T>>::config();
|
||||
let freq = config.validation_upgrade_frequency;
|
||||
let delay = config.validation_upgrade_delay;
|
||||
|
||||
let last_code_upgrade = Self::last_code_upgrade(para_id, true);
|
||||
let can_upgrade_code = last_code_upgrade.map_or(
|
||||
true,
|
||||
|l| { l <= relay_parent_number && relay_parent_number.saturating_sub(l) >= freq },
|
||||
);
|
||||
|
||||
let code_upgrade_allowed = if can_upgrade_code {
|
||||
Some(relay_parent_number + delay)
|
||||
} else {
|
||||
None
|
||||
};
|
||||
|
||||
Some(LocalValidationData {
|
||||
parent_head: Self::para_head(¶_id)?,
|
||||
balance: 0,
|
||||
validation_code_hash: BlakeTwo256::hash_of(
|
||||
&Self::current_code(¶_id)?
|
||||
),
|
||||
code_upgrade_allowed,
|
||||
})
|
||||
}
|
||||
}
|
||||
|
||||
#[cfg(test)]
|
||||
|
||||
@@ -19,10 +19,10 @@
|
||||
|
||||
use sp_std::prelude::*;
|
||||
use primitives::v1::{
|
||||
ValidatorId, ValidatorIndex, GroupRotationInfo, CoreState, GlobalValidationData,
|
||||
Id as ParaId, OccupiedCoreAssumption, LocalValidationData, SessionIndex, ValidationCode,
|
||||
ValidatorId, ValidatorIndex, GroupRotationInfo, CoreState, ValidationData,
|
||||
Id as ParaId, OccupiedCoreAssumption, SessionIndex, ValidationCode,
|
||||
CommittedCandidateReceipt, ScheduledCore, OccupiedCore, CoreOccupied, CoreIndex,
|
||||
GroupIndex, CandidateEvent,
|
||||
GroupIndex, CandidateEvent, PersistedValidationData,
|
||||
};
|
||||
use sp_runtime::traits::Zero;
|
||||
use frame_support::debug;
|
||||
@@ -161,36 +161,61 @@ pub fn availability_cores<T: initializer::Trait>() -> Vec<CoreState<T::BlockNumb
|
||||
core_states
|
||||
}
|
||||
|
||||
/// Implementation for the `global_validation_data` function of the runtime API.
|
||||
pub fn global_validation_data<T: initializer::Trait>()
|
||||
-> GlobalValidationData<T::BlockNumber>
|
||||
{
|
||||
<configuration::Module<T>>::global_validation_data()
|
||||
}
|
||||
|
||||
/// Implementation for the `local_validation_data` function of the runtime API.
|
||||
pub fn local_validation_data<T: initializer::Trait>(
|
||||
fn with_assumption<Trait, T, F>(
|
||||
para_id: ParaId,
|
||||
assumption: OccupiedCoreAssumption,
|
||||
) -> Option<LocalValidationData<T::BlockNumber>> {
|
||||
build: F,
|
||||
) -> Option<T> where
|
||||
Trait: inclusion::Trait,
|
||||
F: FnOnce() -> Option<T>,
|
||||
{
|
||||
match assumption {
|
||||
OccupiedCoreAssumption::Included => {
|
||||
<inclusion::Module<T>>::force_enact(para_id);
|
||||
<paras::Module<T>>::local_validation_data(para_id)
|
||||
<inclusion::Module<Trait>>::force_enact(para_id);
|
||||
build()
|
||||
}
|
||||
OccupiedCoreAssumption::TimedOut => {
|
||||
<paras::Module<T>>::local_validation_data(para_id)
|
||||
build()
|
||||
}
|
||||
OccupiedCoreAssumption::Free => {
|
||||
if <inclusion::Module<T>>::pending_availability(para_id).is_some() {
|
||||
if <inclusion::Module<Trait>>::pending_availability(para_id).is_some() {
|
||||
None
|
||||
} else {
|
||||
<paras::Module<T>>::local_validation_data(para_id)
|
||||
build()
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/// Implementation for the `full_validation_data` function of the runtime API.
|
||||
pub fn full_validation_data<T: initializer::Trait>(
|
||||
para_id: ParaId,
|
||||
assumption: OccupiedCoreAssumption,
|
||||
)
|
||||
-> Option<ValidationData<T::BlockNumber>>
|
||||
{
|
||||
with_assumption::<T, _, _>(
|
||||
para_id,
|
||||
assumption,
|
||||
|| Some(ValidationData {
|
||||
persisted: crate::util::make_persisted_validation_data::<T>(para_id)?,
|
||||
transient: crate::util::make_transient_validation_data::<T>(para_id)?,
|
||||
}),
|
||||
)
|
||||
}
|
||||
|
||||
/// Implementation for the `persisted_validation_data` function of the runtime API.
|
||||
pub fn persisted_validation_data<T: initializer::Trait>(
|
||||
para_id: ParaId,
|
||||
assumption: OccupiedCoreAssumption,
|
||||
) -> Option<PersistedValidationData<T::BlockNumber>> {
|
||||
with_assumption::<T, _, _>(
|
||||
para_id,
|
||||
assumption,
|
||||
|| crate::util::make_persisted_validation_data::<T>(para_id),
|
||||
)
|
||||
}
|
||||
|
||||
/// Implementation for the `session_index_for_child` function of the runtime API.
|
||||
pub fn session_index_for_child<T: initializer::Trait>() -> SessionIndex {
|
||||
// Just returns the session index from `inclusion`. Runtime APIs follow
|
||||
@@ -208,26 +233,11 @@ pub fn validation_code<T: initializer::Trait>(
|
||||
para_id: ParaId,
|
||||
assumption: OccupiedCoreAssumption,
|
||||
) -> Option<ValidationCode> {
|
||||
let fetch = || {
|
||||
<paras::Module<T>>::current_code(¶_id)
|
||||
};
|
||||
|
||||
match assumption {
|
||||
OccupiedCoreAssumption::Included => {
|
||||
<inclusion::Module<T>>::force_enact(para_id);
|
||||
fetch()
|
||||
}
|
||||
OccupiedCoreAssumption::TimedOut => {
|
||||
fetch()
|
||||
}
|
||||
OccupiedCoreAssumption::Free => {
|
||||
if <inclusion::Module<T>>::pending_availability(para_id).is_some() {
|
||||
None
|
||||
} else {
|
||||
fetch()
|
||||
}
|
||||
}
|
||||
}
|
||||
with_assumption::<T, _, _>(
|
||||
para_id,
|
||||
assumption,
|
||||
|| <paras::Module<T>>::current_code(¶_id),
|
||||
)
|
||||
}
|
||||
|
||||
/// Implementation for the `candidate_pending_availability` function of the runtime API.
|
||||
|
||||
@@ -0,0 +1,71 @@
|
||||
// Copyright 2017-2020 Parity Technologies (UK) Ltd.
|
||||
// This file is part of Polkadot.
|
||||
|
||||
// Polkadot is free software: you can redistribute it and/or modify
|
||||
// it under the terms of the GNU General Public License as published by
|
||||
// the Free Software Foundation, either version 3 of the License, or
|
||||
// (at your option) any later version.
|
||||
|
||||
// Polkadot is distributed in the hope that it will be useful,
|
||||
// but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
// GNU General Public License for more details.
|
||||
|
||||
// You should have received a copy of the GNU General Public License
|
||||
// along with Polkadot. If not, see <http://www.gnu.org/licenses/>.
|
||||
|
||||
//! Utilities that don't belong to any particular module but may draw
|
||||
//! on all modules.
|
||||
|
||||
use sp_runtime::traits::{One, Saturating};
|
||||
use primitives::v1::{Id as ParaId, PersistedValidationData, TransientValidationData};
|
||||
use sp_std::prelude::*;
|
||||
|
||||
use crate::{configuration, paras};
|
||||
|
||||
/// Make the persisted validation data for a particular parachain.
|
||||
///
|
||||
/// This ties together the storage of several modules.
|
||||
pub fn make_persisted_validation_data<T: paras::Trait>(
|
||||
para_id: ParaId,
|
||||
) -> Option<PersistedValidationData<T::BlockNumber>> {
|
||||
let relay_parent_number = <frame_system::Module<T>>::block_number() - One::one();
|
||||
|
||||
Some(PersistedValidationData {
|
||||
parent_head: <paras::Module<T>>::para_head(¶_id)?,
|
||||
block_number: relay_parent_number,
|
||||
hrmp_mqc_heads: Vec::new(),
|
||||
})
|
||||
}
|
||||
|
||||
/// Make the transient validation data for a particular parachain.
|
||||
///
|
||||
/// This ties together the storage of several modules.
|
||||
pub fn make_transient_validation_data<T: paras::Trait>(
|
||||
para_id: ParaId,
|
||||
) -> Option<TransientValidationData<T::BlockNumber>> {
|
||||
let config = <configuration::Module<T>>::config();
|
||||
let relay_parent_number = <frame_system::Module<T>>::block_number() - One::one();
|
||||
|
||||
let freq = config.validation_upgrade_frequency;
|
||||
let delay = config.validation_upgrade_delay;
|
||||
|
||||
let last_code_upgrade = <paras::Module<T>>::last_code_upgrade(para_id, true);
|
||||
let can_upgrade_code = last_code_upgrade.map_or(
|
||||
true,
|
||||
|l| { l <= relay_parent_number && relay_parent_number.saturating_sub(l) >= freq },
|
||||
);
|
||||
|
||||
let code_upgrade_allowed = if can_upgrade_code {
|
||||
Some(relay_parent_number + delay)
|
||||
} else {
|
||||
None
|
||||
};
|
||||
|
||||
Some(TransientValidationData {
|
||||
max_code_size: config.max_code_size,
|
||||
max_head_data_size: config.max_head_data_size,
|
||||
balance: 0,
|
||||
code_upgrade_allowed,
|
||||
})
|
||||
}
|
||||
Reference in New Issue
Block a user