ci: add quick-check with rustfmt (#615)

* ci: add quick-check with clippy and rustfmt

* chore: rustfmt round

* chore: set the same rustfmt config than substrate

* chore: fix formatting

* cI: remove clippy

* ci: switch to nightly for the checks

* ci: fix toolchains and naming

* ci: Limit the check to formatting

* chore: fix formatting

* Update .rustfmt.toml

* Update .rustfmt.toml

Co-authored-by: Bastian Köcher <bkchr@users.noreply.github.com>
This commit is contained in:
Chevdor
2021-09-16 16:57:52 +02:00
committed by GitHub
parent 035a576008
commit 1dd000a011
98 changed files with 1244 additions and 1872 deletions
+4 -8
View File
@@ -131,18 +131,14 @@ where
(Some(s), false) => {
seal = Some(s);
false
}
},
}
});
let seal = seal.expect("Could not find an AuRa seal digest!");
let author = Aura::<T>::find_author(
header
.digest()
.logs()
.iter()
.filter_map(|d| d.as_pre_runtime()),
header.digest().logs().iter().filter_map(|d| d.as_pre_runtime()),
)
.expect("Could not find AuRa author index!");
@@ -150,9 +146,9 @@ where
if !authorities
.get(author as usize)
.unwrap_or_else(||
.unwrap_or_else(|| {
panic!("Invalid AuRa author index {} for authorities: {:?}", author, authorities)
)
})
.verify(&pre_hash, &seal)
{
panic!("Invalid AuRa seal");
@@ -19,15 +19,15 @@ use super::*;
#[allow(unused)]
use crate::Pallet as CollatorSelection;
use sp_std::prelude::*;
use frame_benchmarking::{benchmarks, impl_benchmark_test_suite, whitelisted_caller, account};
use frame_system::{RawOrigin, EventRecord};
use frame_benchmarking::{account, benchmarks, impl_benchmark_test_suite, whitelisted_caller};
use frame_support::{
assert_ok,
traits::{Currency, Get, EnsureOrigin},
traits::{Currency, EnsureOrigin, Get},
};
use frame_system::{EventRecord, RawOrigin};
use pallet_authorship::EventHandler;
use pallet_session::SessionManager;
use sp_std::prelude::*;
pub type BalanceOf<T> =
<<T as Config>::Currency as Currency<<T as frame_system::Config>::AccountId>>::Balance;
@@ -38,7 +38,7 @@ const SEED: u32 = 0;
macro_rules! whitelist {
($acc:ident) => {
frame_benchmarking::benchmarking::add_to_whitelist(
frame_system::Account::<T>::hashed_key_for(&$acc).into()
frame_system::Account::<T>::hashed_key_for(&$acc).into(),
);
};
}
+82 -60
View File
@@ -74,29 +74,27 @@ pub mod weights;
#[frame_support::pallet]
pub mod pallet {
pub use crate::weights::WeightInfo;
use core::ops::Div;
use frame_support::{
dispatch::DispatchResultWithPostInfo,
pallet_prelude::*,
inherent::Vec,
traits::{
Currency, ReservableCurrency, EnsureOrigin, ExistenceRequirement::KeepAlive, ValidatorRegistration
},
PalletId,
};
use frame_system::pallet_prelude::*;
use frame_system::Config as SystemConfig;
use frame_support::{
pallet_prelude::*,
sp_runtime::{
traits::{AccountIdConversion, CheckedSub, Saturating, Zero},
RuntimeDebug,
traits::{AccountIdConversion, CheckedSub, Zero, Saturating},
},
traits::{
Currency, EnsureOrigin, ExistenceRequirement::KeepAlive, ReservableCurrency,
ValidatorRegistration,
},
weights::DispatchClass,
PalletId,
};
use sp_runtime::traits::Convert;
use core::ops::Div;
use frame_system::{pallet_prelude::*, Config as SystemConfig};
use pallet_session::SessionManager;
use sp_runtime::traits::Convert;
use sp_staking::SessionIndex;
pub use crate::weights::WeightInfo;
type BalanceOf<T> =
<<T as Config>::Currency as Currency<<T as SystemConfig>::AccountId>>::Balance;
@@ -136,7 +134,6 @@ pub mod pallet {
/// This does not take into account the invulnerables.
type MinCandidates: Get<u32>;
/// Maximum number of invulnerables.
///
/// Used only for benchmarking.
@@ -156,7 +153,6 @@ pub mod pallet {
/// Validate a user is registered
type ValidatorRegistration: ValidatorRegistration<Self::ValidatorId>;
/// The weight information of this pallet.
type WeightInfo: WeightInfo;
}
@@ -182,16 +178,14 @@ pub mod pallet {
/// The (community, limited) collation candidates.
#[pallet::storage]
#[pallet::getter(fn candidates)]
pub type Candidates<T: Config> = StorageValue<
_,
Vec<CandidateInfo<T::AccountId, BalanceOf<T>>>,
ValueQuery,
>;
pub type Candidates<T: Config> =
StorageValue<_, Vec<CandidateInfo<T::AccountId, BalanceOf<T>>>, ValueQuery>;
/// Last block authored by collator.
#[pallet::storage]
#[pallet::getter(fn last_authored_block)]
pub type LastAuthoredBlock<T: Config> = StorageMap<_, Twox64Concat, T::AccountId, T::BlockNumber, ValueQuery>;
pub type LastAuthoredBlock<T: Config> =
StorageMap<_, Twox64Concat, T::AccountId, T::BlockNumber, ValueQuery>;
/// Desired number of candidates.
///
@@ -205,7 +199,6 @@ pub mod pallet {
#[pallet::getter(fn candidacy_bond)]
pub type CandidacyBond<T> = StorageValue<_, BalanceOf<T>, ValueQuery>;
#[pallet::genesis_config]
pub struct GenesisConfig<T: Config> {
pub invulnerables: Vec<T::AccountId>,
@@ -227,9 +220,12 @@ pub mod pallet {
#[pallet::genesis_build]
impl<T: Config> GenesisBuild<T> for GenesisConfig<T> {
fn build(&self) {
let duplicate_invulnerables = self.invulnerables.iter().collect::<std::collections::BTreeSet<_>>();
assert!(duplicate_invulnerables.len() == self.invulnerables.len(), "duplicate invulnerables in genesis.");
let duplicate_invulnerables =
self.invulnerables.iter().collect::<std::collections::BTreeSet<_>>();
assert!(
duplicate_invulnerables.len() == self.invulnerables.len(),
"duplicate invulnerables in genesis."
);
assert!(
T::MaxInvulnerables::get() >= (self.invulnerables.len() as u32),
@@ -276,7 +272,7 @@ pub mod pallet {
/// Account has no associated validator ID
NoAssociatedValidatorId,
/// Validator ID is not yet registered
ValidatorNotRegistered
ValidatorNotRegistered,
}
#[pallet::hooks]
@@ -302,13 +298,14 @@ pub mod pallet {
}
#[pallet::weight(T::WeightInfo::set_desired_candidates())]
pub fn set_desired_candidates(origin: OriginFor<T>, max: u32) -> DispatchResultWithPostInfo {
pub fn set_desired_candidates(
origin: OriginFor<T>,
max: u32,
) -> DispatchResultWithPostInfo {
T::UpdateOrigin::ensure_origin(origin)?;
// we trust origin calls, this is just a for more accurate benchmarking
if max > T::MaxCandidates::get() {
log::warn!(
"max > T::MaxCandidates; you might need to run benchmarks again"
);
log::warn!("max > T::MaxCandidates; you might need to run benchmarks again");
}
<DesiredCandidates<T>>::put(&max);
Self::deposit_event(Event::NewDesiredCandidates(max));
@@ -316,7 +313,10 @@ pub mod pallet {
}
#[pallet::weight(T::WeightInfo::set_candidacy_bond())]
pub fn set_candidacy_bond(origin: OriginFor<T>, bond: BalanceOf<T>) -> DispatchResultWithPostInfo {
pub fn set_candidacy_bond(
origin: OriginFor<T>,
bond: BalanceOf<T>,
) -> DispatchResultWithPostInfo {
T::UpdateOrigin::ensure_origin(origin)?;
<CandidacyBond<T>>::put(&bond);
Self::deposit_event(Event::NewCandidacyBond(bond));
@@ -332,8 +332,12 @@ pub mod pallet {
ensure!((length as u32) < Self::desired_candidates(), Error::<T>::TooManyCandidates);
ensure!(!Self::invulnerables().contains(&who), Error::<T>::AlreadyInvulnerable);
let validator_key = T::ValidatorIdOf::convert(who.clone()).ok_or(Error::<T>::NoAssociatedValidatorId)?;
ensure!(T::ValidatorRegistration::is_registered(&validator_key), Error::<T>::ValidatorNotRegistered);
let validator_key = T::ValidatorIdOf::convert(who.clone())
.ok_or(Error::<T>::NoAssociatedValidatorId)?;
ensure!(
T::ValidatorRegistration::is_registered(&validator_key),
Error::<T>::ValidatorNotRegistered
);
let deposit = Self::candidacy_bond();
// First authored block is current block plus kick threshold to handle session delay
@@ -346,7 +350,10 @@ pub mod pallet {
} else {
T::Currency::reserve(&who, deposit)?;
candidates.push(incoming);
<LastAuthoredBlock<T>>::insert(who.clone(), frame_system::Pallet::<T>::block_number() + T::KickThreshold::get());
<LastAuthoredBlock<T>>::insert(
who.clone(),
frame_system::Pallet::<T>::block_number() + T::KickThreshold::get(),
);
Ok(candidates.len())
}
})?;
@@ -358,7 +365,10 @@ pub mod pallet {
#[pallet::weight(T::WeightInfo::leave_intent(T::MaxCandidates::get()))]
pub fn leave_intent(origin: OriginFor<T>) -> DispatchResultWithPostInfo {
let who = ensure_signed(origin)?;
ensure!(Self::candidates().len() as u32 > T::MinCandidates::get(), Error::<T>::TooFewCandidates);
ensure!(
Self::candidates().len() as u32 > T::MinCandidates::get(),
Error::<T>::TooFewCandidates
);
let current_count = Self::try_remove_candidate(&who)?;
Ok(Some(T::WeightInfo::leave_intent(current_count as u32)).into())
@@ -372,13 +382,17 @@ pub mod pallet {
}
/// Removes a candidate if they exist and sends them back their deposit
fn try_remove_candidate(who: &T::AccountId) -> Result<usize, DispatchError> {
let current_count = <Candidates<T>>::try_mutate(|candidates| -> Result<usize, DispatchError> {
let index = candidates.iter().position(|candidate| candidate.who == *who).ok_or(Error::<T>::NotCandidate)?;
T::Currency::unreserve(&who, candidates[index].deposit);
candidates.remove(index);
<LastAuthoredBlock<T>>::remove(who.clone());
Ok(candidates.len())
})?;
let current_count =
<Candidates<T>>::try_mutate(|candidates| -> Result<usize, DispatchError> {
let index = candidates
.iter()
.position(|candidate| candidate.who == *who)
.ok_or(Error::<T>::NotCandidate)?;
T::Currency::unreserve(&who, candidates[index].deposit);
candidates.remove(index);
<LastAuthoredBlock<T>>::remove(who.clone());
Ok(candidates.len())
})?;
Self::deposit_event(Event::CandidateRemoved(who.clone()));
Ok(current_count)
}
@@ -388,29 +402,34 @@ pub mod pallet {
/// This is done on the fly, as frequent as we are told to do so, as the session manager.
pub fn assemble_collators(candidates: Vec<T::AccountId>) -> Vec<T::AccountId> {
let mut collators = Self::invulnerables();
collators.extend(
candidates.into_iter().collect::<Vec<_>>(),
);
collators.extend(candidates.into_iter().collect::<Vec<_>>());
collators
}
/// Kicks out and candidates that did not produce a block in the kick threshold.
pub fn kick_stale_candidates(candidates: Vec<CandidateInfo<T::AccountId, BalanceOf<T>>>) -> Vec<T::AccountId> {
pub fn kick_stale_candidates(
candidates: Vec<CandidateInfo<T::AccountId, BalanceOf<T>>>,
) -> Vec<T::AccountId> {
let now = frame_system::Pallet::<T>::block_number();
let kick_threshold = T::KickThreshold::get();
let new_candidates = candidates.into_iter().filter_map(|c| {
let last_block = <LastAuthoredBlock<T>>::get(c.who.clone());
let since_last = now.saturating_sub(last_block);
if since_last < kick_threshold || Self::candidates().len() as u32 <= T::MinCandidates::get() {
Some(c.who)
} else {
let outcome = Self::try_remove_candidate(&c.who);
if let Err(why) = outcome {
log::warn!("Failed to remove candidate {:?}", why);
debug_assert!(false, "failed to remove candidate {:?}", why);
let new_candidates = candidates
.into_iter()
.filter_map(|c| {
let last_block = <LastAuthoredBlock<T>>::get(c.who.clone());
let since_last = now.saturating_sub(last_block);
if since_last < kick_threshold ||
Self::candidates().len() as u32 <= T::MinCandidates::get()
{
Some(c.who)
} else {
let outcome = Self::try_remove_candidate(&c.who);
if let Err(why) = outcome {
log::warn!("Failed to remove candidate {:?}", why);
debug_assert!(false, "failed to remove candidate {:?}", why);
}
None
}
None
}
}).collect::<Vec<_>>();
})
.collect::<Vec<_>>();
new_candidates
}
}
@@ -423,7 +442,10 @@ pub mod pallet {
fn note_author(author: T::AccountId) {
let pot = Self::account_id();
// assumes an ED will be sent to pot.
let reward = T::Currency::free_balance(&pot).checked_sub(&T::Currency::minimum_balance()).unwrap_or_else(Zero::zero).div(2u32.into());
let reward = T::Currency::free_balance(&pot)
.checked_sub(&T::Currency::minimum_balance())
.unwrap_or_else(Zero::zero)
.div(2u32.into());
// `reward` is half of pot account minus ED, this should never fail.
let _success = T::Currency::transfer(&pot, &author, reward, KeepAlive);
debug_assert!(_success.is_ok());
+17 -25
View File
@@ -15,19 +15,19 @@
use super::*;
use crate as collator_selection;
use sp_core::H256;
use frame_support::{
parameter_types, ord_parameter_types,
ord_parameter_types, parameter_types,
traits::{FindAuthor, GenesisBuild, ValidatorRegistration},
PalletId
PalletId,
};
use sp_runtime::{
RuntimeAppPublic,
traits::{BlakeTwo256, IdentityLookup, OpaqueKeys},
testing::{Header, UintAuthorityId},
};
use frame_system::{EnsureSignedBy};
use frame_system as system;
use frame_system::EnsureSignedBy;
use sp_core::H256;
use sp_runtime::{
testing::{Header, UintAuthorityId},
traits::{BlakeTwo256, IdentityLookup, OpaqueKeys},
RuntimeAppPublic,
};
type UncheckedExtrinsic = frame_system::mocking::MockUncheckedExtrinsic<Test>;
type Block = frame_system::mocking::MockBlock<Test>;
@@ -100,7 +100,8 @@ impl pallet_balances::Config for Test {
pub struct Author4;
impl FindAuthor<u64> for Author4 {
fn find_author<'a, I>(_digests: I) -> Option<u64>
where I: 'a + IntoIterator<Item = (frame_support::ConsensusEngineId, &'a [u8])>,
where
I: 'a + IntoIterator<Item = (frame_support::ConsensusEngineId, &'a [u8])>,
{
Some(4)
}
@@ -224,22 +225,13 @@ pub fn new_test_ext() -> sp_io::TestExternalities {
sp_tracing::try_init_simple();
let mut t = frame_system::GenesisConfig::default().build_storage::<Test>().unwrap();
let invulnerables = vec![1, 2];
let keys = invulnerables.iter().map(|i|
(
*i,
*i,
MockSessionKeys { aura: UintAuthorityId(*i) },
)
).collect::<Vec<_>>();
let keys = invulnerables
.iter()
.map(|i| (*i, *i, MockSessionKeys { aura: UintAuthorityId(*i) }))
.collect::<Vec<_>>();
let balances = pallet_balances::GenesisConfig::<Test> {
balances: vec![
(1, 100),
(2, 100),
(3, 100),
(4, 100),
(5, 100),
],
balances: vec![(1, 100), (2, 100), (3, 100), (4, 100), (5, 100)],
};
let collator_selection = collator_selection::GenesisConfig::<Test> {
desired_candidates: 2,
@@ -256,7 +248,7 @@ pub fn new_test_ext() -> sp_io::TestExternalities {
}
pub fn initialize_to_block(n: u64) {
for i in System::block_number()+1..=n {
for i in System::block_number() + 1..=n {
System::set_block_number(i);
<AllPallets as frame_support::traits::OnInitialize<u64>>::on_initialize(i);
}
+11 -25
View File
@@ -13,15 +13,14 @@
// See the License for the specific language governing permissions and
// limitations under the License.
use crate as collator_selection;
use crate::{mock::*, Error, CandidateInfo};
use crate::{mock::*, CandidateInfo, Error};
use frame_support::{
assert_noop, assert_ok,
traits::{OnInitialize, Currency, GenesisBuild},
traits::{Currency, GenesisBuild, OnInitialize},
};
use sp_runtime::traits::BadOrigin;
use pallet_balances::Error as BalancesError;
use sp_runtime::traits::BadOrigin;
#[test]
fn basic_setup_works() {
@@ -59,7 +58,10 @@ fn set_desired_candidates_works() {
assert_eq!(CollatorSelection::desired_candidates(), 2);
// can set
assert_ok!(CollatorSelection::set_desired_candidates(Origin::signed(RootAccount::get()), 7));
assert_ok!(CollatorSelection::set_desired_candidates(
Origin::signed(RootAccount::get()),
7
));
assert_eq!(CollatorSelection::desired_candidates(), 7);
// rejects bad origin
@@ -239,11 +241,7 @@ fn authorship_event_handler() {
// triggers `note_author`
Authorship::on_initialize(1);
let collator = CandidateInfo {
who: 4,
deposit: 10,
};
let collator = CandidateInfo { who: 4, deposit: 10 };
assert_eq!(CollatorSelection::candidates(), vec![collator]);
assert_eq!(CollatorSelection::last_authored_block(4), 0);
@@ -268,11 +266,7 @@ fn fees_edgecases() {
// triggers `note_author`
Authorship::on_initialize(1);
let collator = CandidateInfo {
who: 4,
deposit: 10,
};
let collator = CandidateInfo { who: 4, deposit: 10 };
assert_eq!(CollatorSelection::candidates(), vec![collator]);
assert_eq!(CollatorSelection::last_authored_block(4), 0);
@@ -334,10 +328,7 @@ fn kick_mechanism() {
assert_eq!(CollatorSelection::candidates().len(), 1);
// 3 will be kicked after 1 session delay
assert_eq!(SessionHandlerCollators::get(), vec![1, 2, 3, 4]);
let collator = CandidateInfo {
who: 4,
deposit: 10,
};
let collator = CandidateInfo { who: 4, deposit: 10 };
assert_eq!(CollatorSelection::candidates(), vec![collator]);
assert_eq!(CollatorSelection::last_authored_block(4), 20);
initialize_to_block(30);
@@ -362,10 +353,7 @@ fn should_not_kick_mechanism_too_few() {
assert_eq!(CollatorSelection::candidates().len(), 1);
// 3 will be kicked after 1 session delay
assert_eq!(SessionHandlerCollators::get(), vec![1, 2, 3, 5]);
let collator = CandidateInfo {
who: 5,
deposit: 10,
};
let collator = CandidateInfo { who: 5, deposit: 10 };
assert_eq!(CollatorSelection::candidates(), vec![collator]);
assert_eq!(CollatorSelection::last_authored_block(4), 20);
initialize_to_block(30);
@@ -376,7 +364,6 @@ fn should_not_kick_mechanism_too_few() {
});
}
#[test]
#[should_panic = "duplicate invulnerables in genesis."]
fn cannot_set_genesis_value_twice() {
@@ -391,5 +378,4 @@ fn cannot_set_genesis_value_twice() {
};
// collator selection must be initialized before session.
collator_selection.assimilate_storage(&mut t).unwrap();
}
+16 -18
View File
@@ -18,7 +18,10 @@
#![allow(unused_parens)]
#![allow(unused_imports)]
use frame_support::{traits::Get, weights::{Weight, constants::RocksDbWeight}};
use frame_support::{
traits::Get,
weights::{constants::RocksDbWeight, Weight},
};
use sp_std::marker::PhantomData;
// The weight info trait for `pallet_collator_selection`.
@@ -35,28 +38,26 @@ pub trait WeightInfo {
/// Weights for pallet_collator_selection using the Substrate node and recommended hardware.
pub struct SubstrateWeight<T>(PhantomData<T>);
impl<T: frame_system::Config> WeightInfo for SubstrateWeight<T> {
fn set_invulnerables(b: u32, ) -> Weight {
fn set_invulnerables(b: u32) -> Weight {
(18_563_000 as Weight)
// Standard Error: 0
.saturating_add((68_000 as Weight).saturating_mul(b as Weight))
.saturating_add(T::DbWeight::get().writes(1 as Weight))
}
fn set_desired_candidates() -> Weight {
(16_363_000 as Weight)
.saturating_add(T::DbWeight::get().writes(1 as Weight))
(16_363_000 as Weight).saturating_add(T::DbWeight::get().writes(1 as Weight))
}
fn set_candidacy_bond() -> Weight {
(16_840_000 as Weight)
.saturating_add(T::DbWeight::get().writes(1 as Weight))
(16_840_000 as Weight).saturating_add(T::DbWeight::get().writes(1 as Weight))
}
fn register_as_candidate(c: u32, ) -> Weight {
fn register_as_candidate(c: u32) -> Weight {
(71_196_000 as Weight)
// Standard Error: 0
.saturating_add((198_000 as Weight).saturating_mul(c as Weight))
.saturating_add(T::DbWeight::get().reads(4 as Weight))
.saturating_add(T::DbWeight::get().writes(2 as Weight))
}
fn leave_intent(c: u32, ) -> Weight {
fn leave_intent(c: u32) -> Weight {
(55_336_000 as Weight)
// Standard Error: 0
.saturating_add((151_000 as Weight).saturating_mul(c as Weight))
@@ -68,7 +69,7 @@ impl<T: frame_system::Config> WeightInfo for SubstrateWeight<T> {
.saturating_add(T::DbWeight::get().reads(3 as Weight))
.saturating_add(T::DbWeight::get().writes(4 as Weight))
}
fn new_session(r: u32, c: u32, ) -> Weight {
fn new_session(r: u32, c: u32) -> Weight {
(0 as Weight)
// Standard Error: 1_010_000
.saturating_add((109_961_000 as Weight).saturating_mul(r as Weight))
@@ -81,31 +82,28 @@ impl<T: frame_system::Config> WeightInfo for SubstrateWeight<T> {
}
}
// For backwards compatibility and tests
impl WeightInfo for () {
fn set_invulnerables(b: u32, ) -> Weight {
fn set_invulnerables(b: u32) -> Weight {
(18_563_000 as Weight)
// Standard Error: 0
.saturating_add((68_000 as Weight).saturating_mul(b as Weight))
.saturating_add(RocksDbWeight::get().writes(1 as Weight))
}
fn set_desired_candidates() -> Weight {
(16_363_000 as Weight)
.saturating_add(RocksDbWeight::get().writes(1 as Weight))
(16_363_000 as Weight).saturating_add(RocksDbWeight::get().writes(1 as Weight))
}
fn set_candidacy_bond() -> Weight {
(16_840_000 as Weight)
.saturating_add(RocksDbWeight::get().writes(1 as Weight))
(16_840_000 as Weight).saturating_add(RocksDbWeight::get().writes(1 as Weight))
}
fn register_as_candidate(c: u32, ) -> Weight {
fn register_as_candidate(c: u32) -> Weight {
(71_196_000 as Weight)
// Standard Error: 0
.saturating_add((198_000 as Weight).saturating_mul(c as Weight))
.saturating_add(RocksDbWeight::get().reads(4 as Weight))
.saturating_add(RocksDbWeight::get().writes(2 as Weight))
}
fn leave_intent(c: u32, ) -> Weight {
fn leave_intent(c: u32) -> Weight {
(55_336_000 as Weight)
// Standard Error: 0
.saturating_add((151_000 as Weight).saturating_mul(c as Weight))
@@ -117,7 +115,7 @@ impl WeightInfo for () {
.saturating_add(RocksDbWeight::get().reads(3 as Weight))
.saturating_add(RocksDbWeight::get().writes(4 as Weight))
}
fn new_session(r: u32, c: u32, ) -> Weight {
fn new_session(r: u32, c: u32) -> Weight {
(0 as Weight)
// Standard Error: 1_010_000
.saturating_add((109_961_000 as Weight).saturating_mul(r as Weight))
+148 -157
View File
@@ -21,15 +21,16 @@
#![cfg_attr(not(feature = "std"), no_std)]
use scale_info::TypeInfo;
use sp_std::{prelude::*, convert::TryFrom};
use cumulus_primitives_core::relay_chain::BlockNumber as RelayBlockNumber;
use cumulus_primitives_core::DmpMessageHandler;
use codec::{Encode, Decode};
use sp_runtime::RuntimeDebug;
use xcm::{VersionedXcm, latest::prelude::*};
use frame_support::{traits::EnsureOrigin, dispatch::Weight, weights::constants::WEIGHT_PER_MILLIS};
use codec::{Decode, Encode};
use cumulus_primitives_core::{relay_chain::BlockNumber as RelayBlockNumber, DmpMessageHandler};
use frame_support::{
dispatch::Weight, traits::EnsureOrigin, weights::constants::WEIGHT_PER_MILLIS,
};
pub use pallet::*;
use scale_info::TypeInfo;
use sp_runtime::RuntimeDebug;
use sp_std::{convert::TryFrom, prelude::*};
use xcm::{latest::prelude::*, VersionedXcm};
#[derive(Copy, Clone, Eq, PartialEq, Encode, Decode, RuntimeDebug, TypeInfo)]
pub struct ConfigData {
@@ -42,7 +43,7 @@ pub struct ConfigData {
impl Default for ConfigData {
fn default() -> Self {
Self {
max_individual: 10 * WEIGHT_PER_MILLIS, // 10 ms of execution time maximum by default
max_individual: 10 * WEIGHT_PER_MILLIS, // 10 ms of execution time maximum by default
}
}
}
@@ -100,23 +101,13 @@ pub mod pallet {
/// The queue pages.
#[pallet::storage]
pub(super) type Pages<T> = StorageMap<
_,
Blake2_128Concat,
PageCounter,
Vec<(RelayBlockNumber, Vec<u8>)>,
ValueQuery,
>;
pub(super) type Pages<T> =
StorageMap<_, Blake2_128Concat, PageCounter, Vec<(RelayBlockNumber, Vec<u8>)>, ValueQuery>;
/// The overweight messages.
#[pallet::storage]
pub(super) type Overweight<T> = StorageMap<
_,
Blake2_128Concat,
OverweightIndex,
(RelayBlockNumber, Vec<u8>),
OptionQuery,
>;
pub(super) type Overweight<T> =
StorageMap<_, Blake2_128Concat, OverweightIndex, (RelayBlockNumber, Vec<u8>), OptionQuery>;
#[pallet::error]
pub enum Error<T> {
@@ -203,13 +194,14 @@ pub mod pallet {
while page_index.begin_used < page_index.end_used {
let page = Pages::<T>::take(page_index.begin_used);
for (i, &(sent_at, ref data)) in page.iter().enumerate() {
match Self::try_service_message(limit.saturating_sub(used), sent_at, &data[..]) {
match Self::try_service_message(limit.saturating_sub(used), sent_at, &data[..])
{
Ok(w) => used += w,
Err(..) => {
// Too much weight needed - put the remaining messages back and bail
Pages::<T>::insert(page_index.begin_used, &page[i..]);
return used;
}
return used
},
}
}
page_index.begin_used += 1;
@@ -233,8 +225,8 @@ pub mod pallet {
data: &[u8],
) -> Result<Weight, (MessageId, Weight)> {
let id = sp_io::hashing::blake2_256(&data[..]);
let maybe_msg = VersionedXcm::<T::Call>::decode(&mut &data[..])
.map(Xcm::<T::Call>::try_from);
let maybe_msg =
VersionedXcm::<T::Call>::decode(&mut &data[..]).map(Xcm::<T::Call>::try_from);
match maybe_msg {
Err(_) => {
Self::deposit_event(Event::InvalidFormat(id));
@@ -247,14 +239,15 @@ pub mod pallet {
Ok(Ok(x)) => {
let outcome = T::XcmExecutor::execute_xcm(Parent.into(), x, limit);
match outcome {
Outcome::Error(XcmError::WeightLimitReached(required)) => Err((id, required)),
Outcome::Error(XcmError::WeightLimitReached(required)) =>
Err((id, required)),
outcome => {
let weight_used = outcome.weight_used();
Self::deposit_event(Event::ExecutedDownward(id, outcome));
Ok(weight_used)
}
},
}
}
},
}
}
}
@@ -264,7 +257,7 @@ pub mod pallet {
/// the `Parent` location.
impl<T: Config> DmpMessageHandler for Pallet<T> {
fn handle_dmp_messages(
iter: impl Iterator<Item=(RelayBlockNumber, Vec<u8>)>,
iter: impl Iterator<Item = (RelayBlockNumber, Vec<u8>)>,
limit: Weight,
) -> Weight {
let mut page_index = PageIndex::<T>::get();
@@ -290,7 +283,8 @@ pub mod pallet {
match Self::try_service_message(remaining, sent_at, &data[..]) {
Ok(consumed) => used += consumed,
Err((id, required)) =>
// Too much weight required right now.
// Too much weight required right now.
{
if required > config.max_individual {
// overweight - add to overweight queue and continue with
// message execution.
@@ -300,14 +294,17 @@ pub mod pallet {
page_index.overweight_count += 1;
// Not needed for control flow, but only to ensure that the compiler
// understands that we won't attempt to re-use `data` later.
continue;
continue
} else {
// not overweight. stop executing inline and enqueue normally
// from here on.
let item_count_left = item_count.saturating_sub(i);
maybe_enqueue_page = Some(Vec::with_capacity(item_count_left));
Self::deposit_event(Event::WeightExhausted(id, remaining, required));
Self::deposit_event(Event::WeightExhausted(
id, remaining, required,
));
}
}
}
}
// Cannot be an `else` here since the `maybe_enqueue_page` may have changed.
@@ -333,14 +330,17 @@ mod tests {
use super::*;
use crate as dmp_queue;
use std::cell::RefCell;
use codec::Encode;
use cumulus_primitives_core::ParaId;
use frame_support::{parameter_types, assert_noop, traits::OnIdle};
use frame_support::{assert_noop, parameter_types, traits::OnIdle};
use sp_core::H256;
use sp_runtime::{testing::Header, traits::{IdentityLookup, BlakeTwo256}};
use sp_runtime::DispatchError::BadOrigin;
use sp_runtime::{
testing::Header,
traits::{BlakeTwo256, IdentityLookup},
DispatchError::BadOrigin,
};
use sp_version::RuntimeVersion;
use std::cell::RefCell;
use xcm::latest::{MultiLocation, OriginKind};
type UncheckedExtrinsic = frame_system::mocking::MockUncheckedExtrinsic<Test>;
@@ -451,9 +451,12 @@ mod tests {
fn enqueue(enqueued: &[Xcm]) {
if !enqueued.is_empty() {
let mut index = PageIndex::<Test>::get();
Pages::<Test>::insert(index.end_used, enqueued.iter()
.map(|m| (0, VersionedXcm::<Call>::from(m.clone()).encode()))
.collect::<Vec<_>>()
Pages::<Test>::insert(
index.end_used,
enqueued
.iter()
.map(|m| (0, VersionedXcm::<Call>::from(m.clone()).encode()))
.collect::<Vec<_>>(),
);
index.end_used += 1;
PageIndex::<Test>::put(index);
@@ -508,7 +511,7 @@ mod tests {
#[test]
fn service_inline_complete_works() {
new_test_ext().execute_with(|| {
let incoming = vec![ msg(1000), msg(1001) ];
let incoming = vec![msg(1000), msg(1001)];
let weight_used = handle_messages(&incoming, 2500);
assert_eq!(weight_used, 2001);
assert_eq!(take_trace(), vec![msg_complete(1000), msg_complete(1001)]);
@@ -519,41 +522,40 @@ mod tests {
#[test]
fn service_enqueued_works() {
new_test_ext().execute_with(|| {
let enqueued = vec![ msg(1000), msg(1001), msg(1002) ];
let enqueued = vec![msg(1000), msg(1001), msg(1002)];
enqueue(&enqueued);
let weight_used = handle_messages(&[], 2500);
assert_eq!(weight_used, 2001);
assert_eq!(take_trace(), vec![
msg_complete(1000),
msg_complete(1001),
msg_limit_reached(1002),
]);
assert_eq!(
take_trace(),
vec![msg_complete(1000), msg_complete(1001), msg_limit_reached(1002),]
);
});
}
#[test]
fn enqueue_works() {
new_test_ext().execute_with(|| {
let incoming = vec![ msg(1000), msg(1001), msg(1002) ];
let incoming = vec![msg(1000), msg(1001), msg(1002)];
let weight_used = handle_messages(&incoming, 999);
assert_eq!(weight_used, 0);
assert_eq!(PageIndex::<Test>::get(), PageIndexData { begin_used: 0, end_used: 1, overweight_count: 0});
assert_eq!(
PageIndex::<Test>::get(),
PageIndexData { begin_used: 0, end_used: 1, overweight_count: 0 }
);
assert_eq!(Pages::<Test>::get(0).len(), 3);
assert_eq!(take_trace(), vec![ msg_limit_reached(1000) ]);
assert_eq!(take_trace(), vec![msg_limit_reached(1000)]);
let weight_used = handle_messages(&[], 2500);
assert_eq!(weight_used, 2001);
assert_eq!(take_trace(), vec![
msg_complete(1000),
msg_complete(1001),
msg_limit_reached(1002),
]);
assert_eq!(
take_trace(),
vec![msg_complete(1000), msg_complete(1001), msg_limit_reached(1002),]
);
let weight_used = handle_messages(&[], 2500);
assert_eq!(weight_used, 1002);
assert_eq!(take_trace(), vec![
msg_complete(1002),
]);
assert_eq!(take_trace(), vec![msg_complete(1002),]);
assert!(queue_is_empty());
});
}
@@ -561,22 +563,16 @@ mod tests {
#[test]
fn service_inline_then_enqueue_works() {
new_test_ext().execute_with(|| {
let incoming = vec![ msg(1000), msg(1001), msg(1002) ];
let incoming = vec![msg(1000), msg(1001), msg(1002)];
let weight_used = handle_messages(&incoming, 1500);
assert_eq!(weight_used, 1000);
assert_eq!(pages_queued(), 1);
assert_eq!(Pages::<Test>::get(0).len(), 2);
assert_eq!(take_trace(), vec![
msg_complete(1000),
msg_limit_reached(1001),
]);
assert_eq!(take_trace(), vec![msg_complete(1000), msg_limit_reached(1001),]);
let weight_used = handle_messages(&[], 2500);
assert_eq!(weight_used, 2003);
assert_eq!(take_trace(), vec![
msg_complete(1001),
msg_complete(1002),
]);
assert_eq!(take_trace(), vec![msg_complete(1001), msg_complete(1002),]);
assert!(queue_is_empty());
});
}
@@ -584,17 +580,20 @@ mod tests {
#[test]
fn service_enqueued_and_inline_works() {
new_test_ext().execute_with(|| {
let enqueued = vec![ msg(1000), msg(1001) ];
let incoming = vec![ msg(1002), msg(1003) ];
let enqueued = vec![msg(1000), msg(1001)];
let incoming = vec![msg(1002), msg(1003)];
enqueue(&enqueued);
let weight_used = handle_messages(&incoming, 5000);
assert_eq!(weight_used, 4006);
assert_eq!(take_trace(), vec![
msg_complete(1000),
msg_complete(1001),
msg_complete(1002),
msg_complete(1003),
]);
assert_eq!(
take_trace(),
vec![
msg_complete(1000),
msg_complete(1001),
msg_complete(1002),
msg_complete(1003),
]
);
assert!(queue_is_empty());
});
}
@@ -602,32 +601,26 @@ mod tests {
#[test]
fn service_enqueued_partially_and_then_enqueue_works() {
new_test_ext().execute_with(|| {
let enqueued = vec![ msg(1000), msg(10001) ];
let incoming = vec![ msg(1002), msg(1003) ];
let enqueued = vec![msg(1000), msg(10001)];
let incoming = vec![msg(1002), msg(1003)];
enqueue(&enqueued);
let weight_used = handle_messages(&incoming, 5000);
assert_eq!(weight_used, 1000);
assert_eq!(take_trace(), vec![
msg_complete(1000),
msg_limit_reached(10001),
]);
assert_eq!(take_trace(), vec![msg_complete(1000), msg_limit_reached(10001),]);
assert_eq!(pages_queued(), 2);
// 5000 is not enough to process the 10001 blocker, so nothing happens.
let weight_used = handle_messages(&[], 5000);
assert_eq!(weight_used, 0);
assert_eq!(take_trace(), vec![
msg_limit_reached(10001),
]);
assert_eq!(take_trace(), vec![msg_limit_reached(10001),]);
// 20000 is now enough to process everything.
let weight_used = handle_messages(&[], 20000);
assert_eq!(weight_used, 12006);
assert_eq!(take_trace(), vec![
msg_complete(10001),
msg_complete(1002),
msg_complete(1003),
]);
assert_eq!(
take_trace(),
vec![msg_complete(10001), msg_complete(1002), msg_complete(1003),]
);
assert!(queue_is_empty());
});
}
@@ -635,25 +628,21 @@ mod tests {
#[test]
fn service_enqueued_completely_and_then_enqueue_works() {
new_test_ext().execute_with(|| {
let enqueued = vec![ msg(1000), msg(1001) ];
let incoming = vec![ msg(10002), msg(1003) ];
let enqueued = vec![msg(1000), msg(1001)];
let incoming = vec![msg(10002), msg(1003)];
enqueue(&enqueued);
let weight_used = handle_messages(&incoming, 5000);
assert_eq!(weight_used, 2001);
assert_eq!(take_trace(), vec![
msg_complete(1000),
msg_complete(1001),
msg_limit_reached(10002),
]);
assert_eq!(
take_trace(),
vec![msg_complete(1000), msg_complete(1001), msg_limit_reached(10002),]
);
assert_eq!(pages_queued(), 1);
// 20000 is now enough to process everything.
let weight_used = handle_messages(&[], 20000);
assert_eq!(weight_used, 11005);
assert_eq!(take_trace(), vec![
msg_complete(10002),
msg_complete(1003),
]);
assert_eq!(take_trace(), vec![msg_complete(10002), msg_complete(1003),]);
assert!(queue_is_empty());
});
}
@@ -661,25 +650,26 @@ mod tests {
#[test]
fn service_enqueued_then_inline_then_enqueue_works() {
new_test_ext().execute_with(|| {
let enqueued = vec![ msg(1000), msg(1001) ];
let incoming = vec![ msg(1002), msg(10003) ];
let enqueued = vec![msg(1000), msg(1001)];
let incoming = vec![msg(1002), msg(10003)];
enqueue(&enqueued);
let weight_used = handle_messages(&incoming, 5000);
assert_eq!(weight_used, 3003);
assert_eq!(take_trace(), vec![
msg_complete(1000),
msg_complete(1001),
msg_complete(1002),
msg_limit_reached(10003),
]);
assert_eq!(
take_trace(),
vec![
msg_complete(1000),
msg_complete(1001),
msg_complete(1002),
msg_limit_reached(10003),
]
);
assert_eq!(pages_queued(), 1);
// 20000 is now enough to process everything.
let weight_used = handle_messages(&[], 20000);
assert_eq!(weight_used, 10003);
assert_eq!(take_trace(), vec![
msg_complete(10003),
]);
assert_eq!(take_trace(), vec![msg_complete(10003),]);
assert!(queue_is_empty());
});
}
@@ -687,32 +677,23 @@ mod tests {
#[test]
fn page_crawling_works() {
new_test_ext().execute_with(|| {
let enqueued = vec![ msg(1000), msg(1001) ];
let enqueued = vec![msg(1000), msg(1001)];
enqueue(&enqueued);
let weight_used = handle_messages(&vec![ msg(1002) ], 1500);
let weight_used = handle_messages(&vec![msg(1002)], 1500);
assert_eq!(weight_used, 1000);
assert_eq!(take_trace(), vec![
msg_complete(1000),
msg_limit_reached(1001),
]);
assert_eq!(take_trace(), vec![msg_complete(1000), msg_limit_reached(1001),]);
assert_eq!(pages_queued(), 2);
assert_eq!(PageIndex::<Test>::get().begin_used, 0);
let weight_used = handle_messages(&vec![ msg(1003) ], 1500);
let weight_used = handle_messages(&vec![msg(1003)], 1500);
assert_eq!(weight_used, 1001);
assert_eq!(take_trace(), vec![
msg_complete(1001),
msg_limit_reached(1002),
]);
assert_eq!(take_trace(), vec![msg_complete(1001), msg_limit_reached(1002),]);
assert_eq!(pages_queued(), 2);
assert_eq!(PageIndex::<Test>::get().begin_used, 1);
let weight_used = handle_messages(&vec![ msg(1004) ], 1500);
let weight_used = handle_messages(&vec![msg(1004)], 1500);
assert_eq!(weight_used, 1002);
assert_eq!(take_trace(), vec![
msg_complete(1002),
msg_limit_reached(1003),
]);
assert_eq!(take_trace(), vec![msg_complete(1002), msg_limit_reached(1003),]);
assert_eq!(pages_queued(), 2);
assert_eq!(PageIndex::<Test>::get().begin_used, 2);
});
@@ -724,15 +705,14 @@ mod tests {
// Set the overweight threshold to 9999.
Configuration::<Test>::put(ConfigData { max_individual: 9999 });
let incoming = vec![ msg(1000), msg(10001), msg(1002) ];
let incoming = vec![msg(1000), msg(10001), msg(1002)];
let weight_used = handle_messages(&incoming, 2500);
assert_eq!(weight_used, 2002);
assert!(queue_is_empty());
assert_eq!(take_trace(), vec![
msg_complete(1000),
msg_limit_reached(10001),
msg_complete(1002),
]);
assert_eq!(
take_trace(),
vec![msg_complete(1000), msg_limit_reached(10001), msg_complete(1002),]
);
assert_eq!(overweights(), vec![0]);
});
@@ -744,49 +724,60 @@ mod tests {
// Set the overweight threshold to 9999.
Configuration::<Test>::put(ConfigData { max_individual: 9999 });
let incoming = vec![ msg(10000) ];
let incoming = vec![msg(10000)];
let weight_used = handle_messages(&incoming, 2500);
assert_eq!(weight_used, 0);
assert_eq!(take_trace(), vec![ msg_limit_reached(10000) ]);
assert_eq!(take_trace(), vec![msg_limit_reached(10000)]);
assert_eq!(overweights(), vec![0]);
assert_noop!(DmpQueue::service_overweight(Origin::signed(1), 0, 20000), BadOrigin);
assert_noop!(DmpQueue::service_overweight(Origin::root(), 1, 20000), Error::<Test>::Unknown);
assert_noop!(DmpQueue::service_overweight(Origin::root(), 0, 9999), Error::<Test>::OverLimit);
assert_eq!(take_trace(), vec![ msg_limit_reached(10000) ]);
assert_noop!(
DmpQueue::service_overweight(Origin::root(), 1, 20000),
Error::<Test>::Unknown
);
assert_noop!(
DmpQueue::service_overweight(Origin::root(), 0, 9999),
Error::<Test>::OverLimit
);
assert_eq!(take_trace(), vec![msg_limit_reached(10000)]);
let base_weight = super::Call::<Test>::service_overweight {
index: 0,
weight_limit: 0,
}.get_dispatch_info().weight;
let base_weight = super::Call::<Test>::service_overweight { index: 0, weight_limit: 0 }
.get_dispatch_info()
.weight;
use frame_support::weights::GetDispatchInfo;
let info = DmpQueue::service_overweight(Origin::root(), 0, 20000).unwrap();
let actual_weight = info.actual_weight.unwrap();
assert_eq!(actual_weight, base_weight + 10000);
assert_eq!(take_trace(), vec![ msg_complete(10000) ]);
assert_eq!(take_trace(), vec![msg_complete(10000)]);
assert!(overweights().is_empty());
assert_noop!(DmpQueue::service_overweight(Origin::root(), 0, 20000), Error::<Test>::Unknown);
assert_noop!(
DmpQueue::service_overweight(Origin::root(), 0, 20000),
Error::<Test>::Unknown
);
});
}
#[test]
fn on_idle_should_service_queue() {
new_test_ext().execute_with(|| {
enqueue(&vec![ msg(1000), msg(1001) ]);
enqueue(&vec![ msg(1002), msg(1003) ]);
enqueue(&vec![ msg(1004), msg(1005) ]);
enqueue(&vec![msg(1000), msg(1001)]);
enqueue(&vec![msg(1002), msg(1003)]);
enqueue(&vec![msg(1004), msg(1005)]);
let weight_used = DmpQueue::on_idle(1, 6000);
assert_eq!(weight_used, 5010);
assert_eq!(take_trace(), vec![
msg_complete(1000),
msg_complete(1001),
msg_complete(1002),
msg_complete(1003),
msg_complete(1004),
msg_limit_reached(1005),
]);
assert_eq!(
take_trace(),
vec![
msg_complete(1000),
msg_complete(1001),
msg_complete(1002),
msg_complete(1003),
msg_complete(1004),
msg_limit_reached(1005),
]
);
assert_eq!(pages_queued(), 1);
});
}
+5 -11
View File
@@ -69,13 +69,13 @@ impl Parse for Input {
} else if lookahead.peek(keywords::CheckInherents) {
parse_inner::<keywords::CheckInherents>(input, &mut check_inherents)?;
} else {
return Err(lookahead.error());
return Err(lookahead.error())
}
}
let rest = input.parse::<TokenStream>()?;
if !rest.is_empty() {
return Err(Error::new(rest.span(), "Unexpected input data"));
return Err(Error::new(rest.span(), "Unexpected input data"))
}
Ok(Self {
@@ -88,10 +88,8 @@ impl Parse for Input {
fn crate_() -> Result<Ident, Error> {
match crate_name("cumulus-pallet-parachain-system") {
Ok(FoundCrate::Itself) => Ok(syn::Ident::new(
"cumulus_pallet_parachain_system",
Span::call_site(),
)),
Ok(FoundCrate::Itself) =>
Ok(syn::Ident::new("cumulus_pallet_parachain_system", Span::call_site())),
Ok(FoundCrate::Name(name)) => Ok(Ident::new(&name, Span::call_site())),
Err(e) => Err(Error::new(Span::call_site(), e)),
}
@@ -99,11 +97,7 @@ fn crate_() -> Result<Ident, Error> {
#[proc_macro]
pub fn register_validate_block(input: proc_macro::TokenStream) -> proc_macro::TokenStream {
let Input {
runtime,
check_inherents,
block_executor,
} = match syn::parse(input) {
let Input { runtime, check_inherents, block_executor } = match syn::parse(input) {
Ok(t) => t,
Err(e) => return e.into_compile_error().into(),
};
+37 -59
View File
@@ -144,8 +144,8 @@ pub mod pallet {
false,
"host configuration is promised to set until `on_finalize`; qed",
);
return;
}
return
},
};
let relevant_messaging_state = match Self::relevant_messaging_state() {
Some(ok) => ok,
@@ -155,8 +155,8 @@ pub mod pallet {
"relevant messaging state is promised to be set until `on_finalize`; \
qed",
);
return;
}
return
},
};
<PendingUpwardMessages<T>>::mutate(|up| {
@@ -172,19 +172,16 @@ pub mod pallet {
// available_capacity and available_size.
let num = up
.iter()
.scan(
(available_capacity as usize, available_size as usize),
|state, msg| {
let (cap_left, size_left) = *state;
match (cap_left.checked_sub(1), size_left.checked_sub(msg.len())) {
(Some(new_cap), Some(new_size)) => {
*state = (new_cap, new_size);
Some(())
}
_ => None,
}
},
)
.scan((available_capacity as usize, available_size as usize), |state, msg| {
let (cap_left, size_left) = *state;
match (cap_left.checked_sub(1), size_left.checked_sub(msg.len())) {
(Some(new_cap), Some(new_size)) => {
*state = (new_cap, new_size);
Some(())
},
_ => None,
}
})
.count();
// TODO: #274 Return back messages that do not longer fit into the queue.
@@ -366,10 +363,7 @@ pub mod pallet {
vfp.relay_parent_number,
);
Ok(PostDispatchInfo {
actual_weight: Some(total_weight),
pays_fee: Pays::No,
})
Ok(PostDispatchInfo { actual_weight: Some(total_weight), pays_fee: Pays::No })
}
#[pallet::weight((1_000, DispatchClass::Operational))]
@@ -572,11 +566,10 @@ pub mod pallet {
cumulus_primitives_parachain_inherent::INHERENT_IDENTIFIER;
fn create_inherent(data: &InherentData) -> Option<Self::Call> {
let data: ParachainInherentData = data
.get_data(&Self::INHERENT_IDENTIFIER)
.ok()
.flatten()
.expect("validation function params are always injected into inherent data; qed");
let data: ParachainInherentData =
data.get_data(&Self::INHERENT_IDENTIFIER).ok().flatten().expect(
"validation function params are always injected into inherent data; qed",
);
Some(Call::set_validation_data { data })
}
@@ -611,11 +604,11 @@ pub mod pallet {
provides: vec![hash.as_ref().to_vec()],
longevity: TransactionLongevity::max_value(),
propagate: true,
});
})
}
}
if let Call::set_validation_data { .. } = call {
return Ok(Default::default());
return Ok(Default::default())
}
Err(InvalidTransaction::Call.into())
}
@@ -650,8 +643,8 @@ impl<T: Config> GetChannelInfo for Pallet<T> {
let channels = match Self::relevant_messaging_state() {
None => {
log::warn!("calling `get_channel_status` with no RelevantMessagingState?!");
return ChannelStatus::Closed;
}
return ChannelStatus::Closed
},
Some(d) => d.egress_channels,
};
// ^^^ NOTE: This storage field should carry over from the previous block. So if it's
@@ -667,7 +660,7 @@ impl<T: Config> GetChannelInfo for Pallet<T> {
let meta = &channels[index].1;
if meta.msg_count + 1 > meta.max_capacity {
// The channel is at its capacity. Skip it for now.
return ChannelStatus::Full;
return ChannelStatus::Full
}
let max_size_now = meta.max_total_size - meta.total_size;
let max_size_ever = meta.max_message_size;
@@ -771,9 +764,7 @@ impl<T: Config> Pallet<T> {
// A violation of the assertion below indicates that one of the messages submitted
// by the collator was sent from a sender that doesn't have a channel opened to
// this parachain, according to the relay-parent state.
assert!(ingress_channels
.binary_search_by_key(sender, |&(s, _)| s)
.is_ok(),);
assert!(ingress_channels.binary_search_by_key(sender, |&(s, _)| s).is_ok(),);
}
// Second, prepare horizontal messages for a more convenient processing:
@@ -787,9 +778,7 @@ impl<T: Config> Pallet<T> {
let mut horizontal_messages = horizontal_messages
.into_iter()
.flat_map(|(sender, channel_contents)| {
channel_contents
.into_iter()
.map(move |message| (sender, message))
channel_contents.into_iter().map(move |message| (sender, message))
})
.collect::<Vec<_>>();
horizontal_messages.sort_by(|a, b| {
@@ -806,10 +795,7 @@ impl<T: Config> Pallet<T> {
{
for (sender, ref horizontal_message) in &horizontal_messages {
if hrmp_watermark
.map(|w| w < horizontal_message.sent_at)
.unwrap_or(true)
{
if hrmp_watermark.map(|w| w < horizontal_message.sent_at).unwrap_or(true) {
hrmp_watermark = Some(horizontal_message.sent_at);
}
@@ -882,16 +868,15 @@ impl<T: Config> Pallet<T> {
) -> Option<relay_chain::BlockNumber> {
if <PendingRelayChainBlockNumber<T>>::get().is_some() {
// There is already upgrade scheduled. Upgrade is not allowed.
return None;
return None
}
let relay_blocks_since_last_upgrade = vfp
.relay_parent_number
.saturating_sub(<LastUpgrade<T>>::get());
let relay_blocks_since_last_upgrade =
vfp.relay_parent_number.saturating_sub(<LastUpgrade<T>>::get());
if relay_blocks_since_last_upgrade <= cfg.validation_upgrade_frequency {
// The cooldown after the last upgrade hasn't elapsed yet. Upgrade is not allowed.
return None;
return None
}
Some(vfp.relay_parent_number + cfg.validation_upgrade_delay)
@@ -899,16 +884,10 @@ impl<T: Config> Pallet<T> {
/// The implementation of the runtime upgrade functionality for parachains.
fn set_code_impl(validation_function: Vec<u8>) -> DispatchResult {
ensure!(
!<PendingValidationCode<T>>::exists(),
Error::<T>::OverlappingUpgrades
);
ensure!(!<PendingValidationCode<T>>::exists(), Error::<T>::OverlappingUpgrades);
let vfp = Self::validation_data().ok_or(Error::<T>::ValidationDataNotAvailable)?;
let cfg = Self::host_configuration().ok_or(Error::<T>::HostConfigurationNotAvailable)?;
ensure!(
validation_function.len() <= cfg.max_code_size as usize,
Error::<T>::TooBig
);
ensure!(validation_function.len() <= cfg.max_code_size as usize, Error::<T>::TooBig);
let apply_block =
Self::code_upgrade_allowed(&vfp, &cfg).ok_or(Error::<T>::ProhibitedByPolkadot)?;
@@ -1002,11 +981,10 @@ impl<T: Config> Pallet<T> {
//
// However, changing this setting is expected to be rare.
match Self::host_configuration() {
Some(cfg) => {
Some(cfg) =>
if message.len() > cfg.max_upward_message_size as usize {
return Err(MessageSendError::TooBig);
}
}
return Err(MessageSendError::TooBig)
},
None => {
// This storage field should carry over from the previous block. So if it's None
// then it must be that this is an edge-case where a message is attempted to be
@@ -1017,7 +995,7 @@ impl<T: Config> Pallet<T> {
// returned back to the sender.
//
// Thus fall through here.
}
},
};
<PendingUpwardMessages<T>>::append(message);
Ok(0)
@@ -19,11 +19,10 @@ use cumulus_primitives_core::{
relay_chain, AbridgedHostConfiguration, AbridgedHrmpChannel, ParaId,
};
use scale_info::TypeInfo;
use sp_trie::{MemoryDB, HashDBT, EMPTY_PREFIX};
use sp_runtime::traits::HashFor;
use sp_state_machine::{Backend, TrieBackend};
use sp_std::vec::Vec;
use sp_trie::StorageProof;
use sp_trie::{HashDBT, MemoryDB, StorageProof, EMPTY_PREFIX};
/// A snapshot of some messaging related state of relay chain pertaining to the current parachain.
///
@@ -130,14 +129,11 @@ impl RelayChainStateProof {
) -> Result<Self, Error> {
let db = proof.into_memory_db::<HashFor<relay_chain::Block>>();
if !db.contains(&relay_parent_storage_root, EMPTY_PREFIX) {
return Err(Error::RootMismatch);
return Err(Error::RootMismatch)
}
let trie_backend = TrieBackend::new(db, relay_parent_storage_root);
Ok(Self {
para_id,
trie_backend,
})
Ok(Self { para_id, trie_backend })
}
/// Read the [`MessagingStateSnapshot`] from the relay chain state proof.
@@ -174,10 +170,7 @@ impl RelayChainStateProof {
let mut ingress_channels = Vec::with_capacity(ingress_channel_index.len());
for sender in ingress_channel_index {
let channel_id = relay_chain::v1::HrmpChannelId {
sender,
recipient: self.para_id,
};
let channel_id = relay_chain::v1::HrmpChannelId { sender, recipient: self.para_id };
let hrmp_channel: AbridgedHrmpChannel = read_entry(
&self.trie_backend,
&relay_chain::well_known_keys::hrmp_channels(channel_id),
@@ -189,10 +182,7 @@ impl RelayChainStateProof {
let mut egress_channels = Vec::with_capacity(egress_channel_index.len());
for recipient in egress_channel_index {
let channel_id = relay_chain::v1::HrmpChannelId {
sender: self.para_id,
recipient,
};
let channel_id = relay_chain::v1::HrmpChannelId { sender: self.para_id, recipient };
let hrmp_channel: AbridgedHrmpChannel = read_entry(
&self.trie_backend,
&relay_chain::well_known_keys::hrmp_channels(channel_id),
@@ -226,6 +216,7 @@ impl RelayChainStateProof {
///
/// Returns an error if anything failed at reading or decoding.
pub fn read_slot(&self) -> Result<relay_chain::v1::Slot, Error> {
read_entry(&self.trie_backend, relay_chain::well_known_keys::CURRENT_SLOT, None).map_err(Error::Slot)
read_entry(&self.trie_backend, relay_chain::well_known_keys::CURRENT_SLOT, None)
.map_err(Error::Slot)
}
}
+53 -119
View File
@@ -17,17 +17,17 @@ use super::*;
use codec::Encode;
use cumulus_primitives_core::{
AbridgedHrmpChannel, InboundDownwardMessage, InboundHrmpMessage, PersistedValidationData,
relay_chain::BlockNumber as RelayBlockNumber,
relay_chain::BlockNumber as RelayBlockNumber, AbridgedHrmpChannel, InboundDownwardMessage,
InboundHrmpMessage, PersistedValidationData,
};
use cumulus_test_relay_sproof_builder::RelayStateSproofBuilder;
use frame_support::{
assert_ok,
dispatch::UnfilteredDispatchable,
inherent::{InherentData, ProvideInherent},
parameter_types,
traits::{OnFinalize, OnInitialize},
weights::Weight,
inherent::{InherentData, ProvideInherent},
};
use frame_system::{InitKind, RawOrigin};
use hex_literal::hex;
@@ -113,10 +113,7 @@ std::thread_local! {
static SENT_MESSAGES: RefCell<Vec<(ParaId, Vec<u8>)>> = RefCell::new(Vec::new());
}
fn send_message(
dest: ParaId,
message: Vec<u8>,
) {
fn send_message(dest: ParaId, message: Vec<u8>) {
SENT_MESSAGES.with(|m| m.borrow_mut().push((dest, message)));
}
@@ -125,9 +122,9 @@ impl XcmpMessageSource for FromThreadLocal {
let mut ids = std::collections::BTreeSet::<ParaId>::new();
let mut taken = 0;
let mut result = Vec::new();
SENT_MESSAGES.with(|ms| ms.borrow_mut()
.retain(|m| {
let status = <Pallet::<Test> as GetChannelInfo>::get_channel_status(m.0);
SENT_MESSAGES.with(|ms| {
ms.borrow_mut().retain(|m| {
let status = <Pallet<Test> as GetChannelInfo>::get_channel_status(m.0);
let ready = matches!(status, ChannelStatus::Ready(..));
if ready && !ids.contains(&m.0) && taken < maximum_channels {
ids.insert(m.0);
@@ -138,14 +135,14 @@ impl XcmpMessageSource for FromThreadLocal {
true
}
})
);
});
result
}
}
impl DmpMessageHandler for SaveIntoThreadLocal {
fn handle_dmp_messages(
iter: impl Iterator<Item=(RelayBlockNumber, Vec<u8>)>,
iter: impl Iterator<Item = (RelayBlockNumber, Vec<u8>)>,
_max_weight: Weight,
) -> Weight {
HANDLED_DMP_MESSAGES.with(|m| {
@@ -158,7 +155,7 @@ impl DmpMessageHandler for SaveIntoThreadLocal {
}
impl XcmpMessageHandler for SaveIntoThreadLocal {
fn handle_xcmp_messages<'a, I: Iterator<Item=(ParaId, RelayBlockNumber, &'a [u8])>>(
fn handle_xcmp_messages<'a, I: Iterator<Item = (ParaId, RelayBlockNumber, &'a [u8])>>(
iter: I,
_max_weight: Weight,
) -> Weight {
@@ -177,10 +174,7 @@ fn new_test_ext() -> sp_io::TestExternalities {
HANDLED_DMP_MESSAGES.with(|m| m.borrow_mut().clear());
HANDLED_XCMP_MESSAGES.with(|m| m.borrow_mut().clear());
frame_system::GenesisConfig::default()
.build_storage::<Test>()
.unwrap()
.into()
frame_system::GenesisConfig::default().build_storage::<Test>().unwrap().into()
}
struct ReadRuntimeVersion(Vec<u8>);
@@ -204,9 +198,9 @@ fn wasm_ext() -> sp_io::TestExternalities {
};
let mut ext = new_test_ext();
ext.register_extension(sp_core::traits::ReadRuntimeVersionExt::new(
ReadRuntimeVersion(version.encode()),
));
ext.register_extension(sp_core::traits::ReadRuntimeVersionExt::new(ReadRuntimeVersion(
version.encode(),
)));
ext
}
@@ -247,11 +241,7 @@ impl BlockTests {
where
F: 'static + Fn(),
{
self.add_raw(BlockTest {
n,
within_block: Box::new(within_block),
after_block: None,
})
self.add_raw(BlockTest { n, within_block: Box::new(within_block), after_block: None })
}
fn add_with_post_test<F1, F2>(
@@ -299,12 +289,7 @@ impl BlockTests {
fn run(&mut self) {
self.ran = true;
wasm_ext().execute_with(|| {
for BlockTest {
n,
within_block,
after_block,
} in self.tests.iter()
{
for BlockTest { n, within_block, after_block } in self.tests.iter() {
// clear pending updates, as applicable
if let Some(upgrade_block) = self.pending_upgrade {
if n >= &upgrade_block.into() {
@@ -313,12 +298,7 @@ impl BlockTests {
}
// begin initialization
System::initialize(
&n,
&Default::default(),
&Default::default(),
InitKind::Full,
);
System::initialize(&n, &Default::default(), &Default::default(), InitKind::Full);
// now mess with the storage the way validate_block does
let mut sproof_builder = RelayStateSproofBuilder::default();
@@ -398,9 +378,7 @@ impl Drop for BlockTests {
#[test]
#[should_panic]
fn block_tests_run_on_drop() {
BlockTests::new().add(123, || {
panic!("if this test passes, block tests run properly")
});
BlockTests::new().add(123, || panic!("if this test passes, block tests run properly"));
}
#[test]
@@ -412,10 +390,7 @@ fn events() {
.add_with_post_test(
123,
|| {
assert_ok!(System::set_code(
RawOrigin::Root.into(),
Default::default()
));
assert_ok!(System::set_code(RawOrigin::Root.into(), Default::default()));
},
|| {
let events = System::events();
@@ -445,10 +420,7 @@ fn non_overlapping() {
builder.host_config.validation_upgrade_delay = 1000;
})
.add(123, || {
assert_ok!(System::set_code(
RawOrigin::Root.into(),
Default::default()
));
assert_ok!(System::set_code(RawOrigin::Root.into(), Default::default()));
})
.add(234, || {
assert_eq!(
@@ -466,14 +438,8 @@ fn manipulates_storage() {
!<PendingValidationCode<Test>>::exists(),
"validation function must not exist yet"
);
assert_ok!(System::set_code(
RawOrigin::Root.into(),
Default::default()
));
assert!(
<PendingValidationCode<Test>>::exists(),
"validation function must now exist"
);
assert_ok!(System::set_code(RawOrigin::Root.into(), Default::default()));
assert!(<PendingValidationCode<Test>>::exists(), "validation function must now exist");
})
.add_with_post_test(
1234,
@@ -573,10 +539,7 @@ fn send_hrmp_message_buffer_channel_close() {
sproof.para_id = ParaId::from(200);
sproof.hrmp_egress_channel_index = Some(vec![ParaId::from(300), ParaId::from(400)]);
sproof.hrmp_channels.insert(
HrmpChannelId {
sender: ParaId::from(200),
recipient: ParaId::from(300),
},
HrmpChannelId { sender: ParaId::from(200), recipient: ParaId::from(300) },
AbridgedHrmpChannel {
max_capacity: 1,
msg_count: 1, // <- 1/1 means the channel is full
@@ -587,10 +550,7 @@ fn send_hrmp_message_buffer_channel_close() {
},
);
sproof.hrmp_channels.insert(
HrmpChannelId {
sender: ParaId::from(200),
recipient: ParaId::from(400),
},
HrmpChannelId { sender: ParaId::from(200), recipient: ParaId::from(400) },
AbridgedHrmpChannel {
max_capacity: 1,
msg_count: 1,
@@ -605,8 +565,8 @@ fn send_hrmp_message_buffer_channel_close() {
// Adjustment according to block
//
match relay_block_num {
1 => {}
2 => {}
1 => {},
2 => {},
3 => {
// The channel 200->400 ceases to exist at the relay chain block 3
sproof
@@ -628,21 +588,15 @@ fn send_hrmp_message_buffer_channel_close() {
})
.unwrap()
.msg_count = 0;
}
},
_ => unreachable!(),
}
})
.add_with_post_test(
1,
|| {
send_message(
ParaId::from(300),
b"1".to_vec(),
);
send_message(
ParaId::from(400),
b"2".to_vec(),
);
send_message(ParaId::from(300), b"1".to_vec());
send_message(ParaId::from(400), b"2".to_vec());
},
|| {},
)
@@ -662,10 +616,7 @@ fn send_hrmp_message_buffer_channel_close() {
let v = HrmpOutboundMessages::<Test>::get();
assert_eq!(
v,
vec![OutboundHrmpMessage {
recipient: ParaId::from(300),
data: b"1".to_vec(),
}]
vec![OutboundHrmpMessage { recipient: ParaId::from(300), data: b"1".to_vec() }]
);
},
);
@@ -682,27 +633,15 @@ fn message_queue_chain() {
// These cases are taken from https://github.com/paritytech/polkadot/pull/2351
assert_eq!(
MessageQueueChain::default()
.extend_downward(&InboundDownwardMessage {
sent_at: 2,
msg: vec![1, 2, 3],
})
.extend_downward(&InboundDownwardMessage {
sent_at: 3,
msg: vec![4, 5, 6],
})
.extend_downward(&InboundDownwardMessage { sent_at: 2, msg: vec![1, 2, 3] })
.extend_downward(&InboundDownwardMessage { sent_at: 3, msg: vec![4, 5, 6] })
.head(),
hex!["88dc00db8cc9d22aa62b87807705831f164387dfa49f80a8600ed1cbe1704b6b"].into(),
);
assert_eq!(
MessageQueueChain::default()
.extend_hrmp(&InboundHrmpMessage {
sent_at: 2,
data: vec![1, 2, 3],
})
.extend_hrmp(&InboundHrmpMessage {
sent_at: 3,
data: vec![4, 5, 6],
})
.extend_hrmp(&InboundHrmpMessage { sent_at: 2, data: vec![1, 2, 3] })
.extend_hrmp(&InboundHrmpMessage { sent_at: 3, data: vec![4, 5, 6] })
.head(),
hex!["88dc00db8cc9d22aa62b87807705831f164387dfa49f80a8600ed1cbe1704b6b"].into(),
);
@@ -722,13 +661,13 @@ fn receive_dmp() {
1 => {
sproof.dmq_mqc_head =
Some(MessageQueueChain::default().extend_downward(&MSG).head());
}
},
_ => unreachable!(),
})
.with_inherent_data(|_, relay_block_num, data| match relay_block_num {
1 => {
data.downward_messages.push(MSG.clone());
}
},
_ => unreachable!(),
})
.add(1, || {
@@ -771,7 +710,7 @@ fn receive_hrmp() {
// 300 - one new message
sproof.upsert_inbound_channel(ParaId::from(300)).mqc_head =
Some(MessageQueueChain::default().extend_hrmp(&MSG_1).head());
}
},
2 => {
// 200 - two new messages
// 300 - now present with one message.
@@ -784,20 +723,19 @@ fn receive_hrmp() {
.extend_hrmp(&MSG_3)
.head(),
);
}
},
3 => {
// 200 - no new messages
// 300 - is gone
sproof.upsert_inbound_channel(ParaId::from(200)).mqc_head =
Some(MessageQueueChain::default().extend_hrmp(&MSG_4).head());
}
},
_ => unreachable!(),
})
.with_inherent_data(|_, relay_block_num, data| match relay_block_num {
1 => {
data.horizontal_messages
.insert(ParaId::from(300), vec![MSG_1.clone()]);
}
data.horizontal_messages.insert(ParaId::from(300), vec![MSG_1.clone()]);
},
2 => {
data.horizontal_messages.insert(
ParaId::from(300),
@@ -809,10 +747,9 @@ fn receive_hrmp() {
MSG_3.clone(),
],
);
data.horizontal_messages
.insert(ParaId::from(200), vec![MSG_4.clone()]);
}
3 => {}
data.horizontal_messages.insert(ParaId::from(200), vec![MSG_4.clone()]);
},
3 => {},
_ => unreachable!(),
})
.add(1, || {
@@ -845,12 +782,12 @@ fn receive_hrmp_empty_channel() {
.with_relay_sproof_builder(|_, relay_block_num, sproof| match relay_block_num {
1 => {
// no channels
}
},
2 => {
// one new channel
sproof.upsert_inbound_channel(ParaId::from(300)).mqc_head =
Some(MessageQueueChain::default().head());
}
},
_ => unreachable!(),
})
.add(1, || {})
@@ -878,33 +815,30 @@ fn receive_hrmp_after_pause() {
1 => {
sproof.upsert_inbound_channel(ALICE).mqc_head =
Some(MessageQueueChain::default().extend_hrmp(&MSG_1).head());
}
},
2 => {
// 300 - no new messages, mqc stayed the same.
sproof.upsert_inbound_channel(ALICE).mqc_head =
Some(MessageQueueChain::default().extend_hrmp(&MSG_1).head());
}
},
3 => {
// 300 - new message.
sproof.upsert_inbound_channel(ALICE).mqc_head = Some(
MessageQueueChain::default()
.extend_hrmp(&MSG_1)
.extend_hrmp(&MSG_2)
.head(),
MessageQueueChain::default().extend_hrmp(&MSG_1).extend_hrmp(&MSG_2).head(),
);
}
},
_ => unreachable!(),
})
.with_inherent_data(|_, relay_block_num, data| match relay_block_num {
1 => {
data.horizontal_messages.insert(ALICE, vec![MSG_1.clone()]);
}
},
2 => {
// no new messages
}
},
3 => {
data.horizontal_messages.insert(ALICE, vec![MSG_2.clone()]);
}
},
_ => unreachable!(),
})
.add(1, || {
@@ -16,7 +16,7 @@
//! The actual implementation of the validate block functionality.
use frame_support::traits::{ExecuteBlock, ExtrinsicCall, IsSubType, Get};
use frame_support::traits::{ExecuteBlock, ExtrinsicCall, Get, IsSubType};
use sp_runtime::traits::{Block as BlockT, Extrinsic, HashFor, Header as HeaderT, NumberFor};
use sp_io::KillStorageResult;
@@ -64,10 +64,7 @@ where
let head_data = HeadData(header.encode());
let block = B::new(header, extrinsics);
assert!(
parent_head.hash() == *block.header().parent_hash(),
"Invalid parent hash",
);
assert!(parent_head.hash() == *block.header().parent_hash(), "Invalid parent hash",);
// Uncompress
let mut db = MemoryDB::default();
@@ -128,7 +125,8 @@ where
.iter()
.filter_map(|e| e.call().is_sub_type())
.find_map(|c| match c {
crate::Call::set_validation_data { data: validation_data } => Some(validation_data.clone()),
crate::Call::set_validation_data { data: validation_data } =>
Some(validation_data.clone()),
_ => None,
})
.expect("Could not find `set_validation_data` inherent");
@@ -196,7 +194,7 @@ fn host_storage_read(key: &[u8], value_out: &mut [u8], value_offset: u32) -> Opt
let written = sp_std::cmp::min(data.len(), value_out.len());
value_out[..written].copy_from_slice(&data[..written]);
Some(value.len() as u32)
}
},
None => None,
}
}
@@ -276,7 +274,7 @@ fn host_default_child_storage_read(
let written = sp_std::cmp::min(data.len(), value_out.len());
value_out[..written].copy_from_slice(&data[..written]);
Some(value.len() as u32)
}
},
None => None,
}
}
@@ -312,7 +310,11 @@ fn host_default_child_storage_exists(storage_key: &[u8], key: &[u8]) -> bool {
with_externalities(|ext| ext.exists_child_storage(&child_info, key))
}
fn host_default_child_storage_clear_prefix(storage_key: &[u8], prefix: &[u8], limit: Option<u32>) -> KillStorageResult {
fn host_default_child_storage_clear_prefix(
storage_key: &[u8],
prefix: &[u8],
limit: Option<u32>,
) -> KillStorageResult {
let child_info = ChildInfo::new_default(storage_key);
with_externalities(|ext| {
let (all_removed, num_removed) = ext.clear_child_prefix(&child_info, prefix, limit);
@@ -79,16 +79,11 @@ fn build_block_with_witness(
validation_data.relay_parent_storage_root = relay_parent_storage_root;
extra_extrinsics
.into_iter()
.for_each(|e| builder.push(e).unwrap());
extra_extrinsics.into_iter().for_each(|e| builder.push(e).unwrap());
let block = builder.build_parachain_block(*parent_head.state_root());
TestBlockData {
block,
validation_data,
}
TestBlockData { block, validation_data }
}
#[test]
@@ -96,18 +91,13 @@ fn validate_block_no_extra_extrinsics() {
sp_tracing::try_init_simple();
let (client, parent_head) = create_test_client();
let TestBlockData {
block,
validation_data,
} = build_block_with_witness(&client, vec![], parent_head.clone(), Default::default());
let TestBlockData { block, validation_data } =
build_block_with_witness(&client, vec![], parent_head.clone(), Default::default());
let header = block.header().clone();
let res_header = call_validate_block(
parent_head,
block,
validation_data.relay_parent_storage_root,
)
.expect("Calls `validate_block`");
let res_header =
call_validate_block(parent_head, block, validation_data.relay_parent_storage_root)
.expect("Calls `validate_block`");
assert_eq!(header, res_header);
}
@@ -122,10 +112,7 @@ fn validate_block_with_extra_extrinsics() {
transfer(&client, Charlie, Alice, 500),
];
let TestBlockData {
block,
validation_data,
} = build_block_with_witness(
let TestBlockData { block, validation_data } = build_block_with_witness(
&client,
extra_extrinsics,
parent_head.clone(),
@@ -133,12 +120,9 @@ fn validate_block_with_extra_extrinsics() {
);
let header = block.header().clone();
let res_header = call_validate_block(
parent_head,
block,
validation_data.relay_parent_storage_root,
)
.expect("Calls `validate_block`");
let res_header =
call_validate_block(parent_head, block, validation_data.relay_parent_storage_root)
.expect("Calls `validate_block`");
assert_eq!(header, res_header);
}
@@ -148,20 +132,14 @@ fn validate_block_invalid_parent_hash() {
if env::var("RUN_TEST").is_ok() {
let (client, parent_head) = create_test_client();
let TestBlockData {
block,
validation_data,
} = build_block_with_witness(&client, vec![], parent_head.clone(), Default::default());
let TestBlockData { block, validation_data } =
build_block_with_witness(&client, vec![], parent_head.clone(), Default::default());
let (mut header, extrinsics, witness) = block.deconstruct();
header.set_parent_hash(Hash::from_low_u64_be(1));
let block_data = ParachainBlockData::new(header, extrinsics, witness);
call_validate_block(
parent_head,
block_data,
validation_data.relay_parent_storage_root,
)
.unwrap_err();
call_validate_block(parent_head, block_data, validation_data.relay_parent_storage_root)
.unwrap_err();
} else {
let output = Command::new(env::current_exe().unwrap())
.args(&["validate_block_invalid_parent_hash", "--", "--nocapture"])
@@ -186,11 +164,7 @@ fn validate_block_fails_on_invalid_validation_data() {
call_validate_block(parent_head, block, Hash::random()).unwrap_err();
} else {
let output = Command::new(env::current_exe().unwrap())
.args(&[
"validate_block_fails_on_invalid_validation_data",
"--",
"--nocapture",
])
.args(&["validate_block_fails_on_invalid_validation_data", "--", "--nocapture"])
.env("RUN_TEST", "1")
.output()
.expect("Runs the test");
@@ -208,32 +182,18 @@ fn check_inherent_fails_on_validate_block_as_expected() {
if env::var("RUN_TEST").is_ok() {
let (client, parent_head) = create_test_client();
let TestBlockData {
block,
validation_data,
} = build_block_with_witness(
let TestBlockData { block, validation_data } = build_block_with_witness(
&client,
vec![],
parent_head.clone(),
RelayStateSproofBuilder {
current_slot: 1337.into(),
..Default::default()
},
RelayStateSproofBuilder { current_slot: 1337.into(), ..Default::default() },
);
call_validate_block(
parent_head,
block,
validation_data.relay_parent_storage_root,
)
.unwrap_err();
call_validate_block(parent_head, block, validation_data.relay_parent_storage_root)
.unwrap_err();
} else {
let output = Command::new(env::current_exe().unwrap())
.args(&[
"check_inherent_fails_on_validate_block_as_expected",
"--",
"--nocapture",
])
.args(&["check_inherent_fails_on_validate_block_as_expected", "--", "--nocapture"])
.env("RUN_TEST", "1")
.output()
.expect("Runs the test");
+3 -10
View File
@@ -16,16 +16,14 @@
//! Benchmarking setup for pallet-session
#![cfg_attr(not(feature = "std"), no_std)]
#![cfg(feature = "runtime-benchmarks")]
use sp_std::prelude::*;
use sp_std::vec;
use sp_std::{prelude::*, vec};
use frame_benchmarking::{benchmarks, impl_benchmark_test_suite, whitelisted_caller};
use frame_system::{RawOrigin};
use frame_system::RawOrigin;
use pallet_session::*;
pub struct Pallet<T: Config>(pallet_session::Pallet<T>);
pub trait Config: pallet_session::Config {}
benchmarks! {
set_keys {
let caller: T::AccountId = whitelisted_caller();
@@ -43,9 +41,4 @@ benchmarks! {
}: _(RawOrigin::Signed(caller))
}
impl_benchmark_test_suite!(
Pallet,
crate::mock::new_test_ext(),
crate::mock::Test,
extra = false,
);
impl_benchmark_test_suite!(Pallet, crate::mock::new_test_ext(), crate::mock::Test, extra = false,);
+22 -19
View File
@@ -20,15 +20,19 @@
#![cfg_attr(not(feature = "std"), no_std)]
use sp_std::{prelude::*, convert::TryFrom};
use cumulus_primitives_core::{ParaId, DmpMessageHandler};
use cumulus_primitives_core::relay_chain::BlockNumber as RelayBlockNumber;
use codec::{Encode, Decode};
use scale_info::TypeInfo;
use sp_runtime::traits::BadOrigin;
use xcm::{VersionedXcm, latest::{Xcm, Outcome, Parent, ExecuteXcm}};
use codec::{Decode, Encode};
use cumulus_primitives_core::{
relay_chain::BlockNumber as RelayBlockNumber, DmpMessageHandler, ParaId,
};
use frame_support::dispatch::Weight;
pub use pallet::*;
use scale_info::TypeInfo;
use sp_runtime::traits::BadOrigin;
use sp_std::{convert::TryFrom, prelude::*};
use xcm::{
latest::{ExecuteXcm, Outcome, Parent, Xcm},
VersionedXcm,
};
#[frame_support::pallet]
pub mod pallet {
@@ -50,8 +54,7 @@ pub mod pallet {
}
#[pallet::error]
pub enum Error<T> {
}
pub enum Error<T> {}
#[pallet::hooks]
impl<T: Config> Hooks<BlockNumberFor<T>> for Pallet<T> {}
@@ -106,14 +109,13 @@ pub mod pallet {
pub struct UnlimitedDmpExecution<T>(sp_std::marker::PhantomData<T>);
impl<T: Config> DmpMessageHandler for UnlimitedDmpExecution<T> {
fn handle_dmp_messages(
iter: impl Iterator<Item=(RelayBlockNumber, Vec<u8>)>,
iter: impl Iterator<Item = (RelayBlockNumber, Vec<u8>)>,
limit: Weight,
) -> Weight {
let mut used = 0;
for (_sent_at, data) in iter {
let id = sp_io::hashing::twox_64(&data[..]);
let msg = VersionedXcm::<T::Call>::decode(&mut &data[..])
.map(Xcm::<T::Call>::try_from);
let msg = VersionedXcm::<T::Call>::decode(&mut &data[..]).map(Xcm::<T::Call>::try_from);
match msg {
Err(_) => Pallet::<T>::deposit_event(Event::InvalidFormat(id)),
Ok(Err(())) => Pallet::<T>::deposit_event(Event::UnsupportedVersion(id)),
@@ -121,7 +123,7 @@ impl<T: Config> DmpMessageHandler for UnlimitedDmpExecution<T> {
let outcome = T::XcmExecutor::execute_xcm(Parent.into(), x, limit);
used += outcome.weight_used();
Pallet::<T>::deposit_event(Event::ExecutedDownward(id, outcome));
}
},
}
}
used
@@ -136,14 +138,13 @@ impl<T: Config> DmpMessageHandler for UnlimitedDmpExecution<T> {
pub struct LimitAndDropDmpExecution<T>(sp_std::marker::PhantomData<T>);
impl<T: Config> DmpMessageHandler for LimitAndDropDmpExecution<T> {
fn handle_dmp_messages(
iter: impl Iterator<Item=(RelayBlockNumber, Vec<u8>)>,
iter: impl Iterator<Item = (RelayBlockNumber, Vec<u8>)>,
limit: Weight,
) -> Weight {
let mut used = 0;
for (_sent_at, data) in iter {
let id = sp_io::hashing::twox_64(&data[..]);
let msg = VersionedXcm::<T::Call>::decode(&mut &data[..])
.map(Xcm::<T::Call>::try_from);
let msg = VersionedXcm::<T::Call>::decode(&mut &data[..]).map(Xcm::<T::Call>::try_from);
match msg {
Err(_) => Pallet::<T>::deposit_event(Event::InvalidFormat(id)),
Ok(Err(())) => Pallet::<T>::deposit_event(Event::UnsupportedVersion(id)),
@@ -152,7 +153,7 @@ impl<T: Config> DmpMessageHandler for LimitAndDropDmpExecution<T> {
let outcome = T::XcmExecutor::execute_xcm(Parent.into(), x, weight_limit);
used += outcome.weight_used();
Pallet::<T>::deposit_event(Event::ExecutedDownward(id, outcome));
}
},
}
}
used
@@ -162,7 +163,8 @@ impl<T: Config> DmpMessageHandler for LimitAndDropDmpExecution<T> {
/// Ensure that the origin `o` represents a sibling parachain.
/// Returns `Ok` with the parachain ID of the sibling or an `Err` otherwise.
pub fn ensure_sibling_para<OuterOrigin>(o: OuterOrigin) -> Result<ParaId, BadOrigin>
where OuterOrigin: Into<Result<Origin, OuterOrigin>>
where
OuterOrigin: Into<Result<Origin, OuterOrigin>>,
{
match o.into() {
Ok(Origin::SiblingParachain(id)) => Ok(id),
@@ -173,7 +175,8 @@ pub fn ensure_sibling_para<OuterOrigin>(o: OuterOrigin) -> Result<ParaId, BadOri
/// Ensure that the origin `o` represents is the relay chain.
/// Returns `Ok` if it does or an `Err` otherwise.
pub fn ensure_relay<OuterOrigin>(o: OuterOrigin) -> Result<(), BadOrigin>
where OuterOrigin: Into<Result<Origin, OuterOrigin>>
where
OuterOrigin: Into<Result<Origin, OuterOrigin>>,
{
match o.into() {
Ok(Origin::Relay) => Ok(()),
+54 -84
View File
@@ -34,7 +34,7 @@ mod tests;
use codec::{Decode, Encode};
use cumulus_primitives_core::{
relay_chain::BlockNumber as RelayBlockNumber, ChannelStatus, GetChannelInfo, MessageSendError,
ParaId, XcmpMessageHandler, XcmpMessageSource, XcmpMessageFormat,
ParaId, XcmpMessageFormat, XcmpMessageHandler, XcmpMessageSource,
};
use frame_support::weights::Weight;
use rand_chacha::{
@@ -43,8 +43,8 @@ use rand_chacha::{
};
use scale_info::TypeInfo;
use sp_runtime::{traits::Hash, RuntimeDebug};
use sp_std::{prelude::*, convert::TryFrom};
use xcm::{latest::prelude::*, WrapVersion, VersionedXcm};
use sp_std::{convert::TryFrom, prelude::*};
use xcm::{latest::prelude::*, VersionedXcm, WrapVersion};
pub use pallet::*;
@@ -126,11 +126,7 @@ pub mod pallet {
#[pallet::storage]
pub(super) type InboundXcmpStatus<T: Config> = StorageValue<
_,
Vec<(
ParaId,
InboundStatus,
Vec<(RelayBlockNumber, XcmpMessageFormat)>,
)>,
Vec<(ParaId, InboundStatus, Vec<(RelayBlockNumber, XcmpMessageFormat)>)>,
ValueQuery,
>;
@@ -242,28 +238,25 @@ impl<T: Config> Pallet<T> {
let max_message_size =
T::ChannelInfo::get_channel_max(recipient).ok_or(MessageSendError::NoChannel)?;
if data.len() > max_message_size {
return Err(MessageSendError::TooBig);
return Err(MessageSendError::TooBig)
}
let mut s = <OutboundXcmpStatus<T>>::get();
let index = s
.iter()
.position(|item| item.0 == recipient)
.unwrap_or_else(|| {
s.push((recipient, OutboundStatus::Ok, false, 0, 0));
s.len() - 1
});
let index = s.iter().position(|item| item.0 == recipient).unwrap_or_else(|| {
s.push((recipient, OutboundStatus::Ok, false, 0, 0));
s.len() - 1
});
let have_active = s[index].4 > s[index].3;
let appended = have_active
&& <OutboundXcmpMessages<T>>::mutate(recipient, s[index].4 - 1, |s| {
let appended = have_active &&
<OutboundXcmpMessages<T>>::mutate(recipient, s[index].4 - 1, |s| {
if XcmpMessageFormat::decode(&mut &s[..]) != Ok(format) {
return false;
return false
}
if s.len() + data.len() > max_message_size {
return false;
return false
}
s.extend_from_slice(&data[..]);
return true;
return true
});
if appended {
Ok((s[index].4 - s[index].3 - 1) as u32)
@@ -316,10 +309,9 @@ impl<T: Config> Pallet<T> {
// Create a shuffled order for use to iterate through.
// Not a great random seed, but good enough for our purposes.
let seed = frame_system::Pallet::<T>::parent_hash();
let seed = <[u8; 32]>::decode(&mut sp_runtime::traits::TrailingZeroInput::new(
seed.as_ref(),
))
.expect("input is padded with zeroes; qed");
let seed =
<[u8; 32]>::decode(&mut sp_runtime::traits::TrailingZeroInput::new(seed.as_ref()))
.expect("input is padded with zeroes; qed");
let mut rng = ChaChaRng::from_seed(seed);
let mut shuffled = (0..len).collect::<Vec<_>>();
for i in 0..len {
@@ -359,11 +351,8 @@ impl<T: Config> Pallet<T> {
// we just report the weight used.
Outcome::Incomplete(w, e) => (Ok(w), Event::Fail(Some(hash), e)),
}
}
Err(()) => (
Err(XcmError::UnhandledXcmVersion),
Event::BadVersion(Some(hash)),
),
},
Err(()) => (Err(XcmError::UnhandledXcmVersion), Event::BadVersion(Some(hash))),
};
Self::deposit_event(event);
result
@@ -390,18 +379,18 @@ impl<T: Config> Pallet<T> {
// That message didn't get processed this time because of being
// too heavy. We leave it around for next time and bail.
remaining_fragments = last_remaining_fragments;
break;
}
break
},
Err(_) => {
// Message looks invalid; don't attempt to retry
}
},
}
} else {
debug_assert!(false, "Invalid incoming XCMP message data");
remaining_fragments = &b""[..];
}
}
}
},
XcmpMessageFormat::ConcatenatedEncodedBlob => {
while !remaining_fragments.is_empty() {
last_remaining_fragments = remaining_fragments;
@@ -413,22 +402,22 @@ impl<T: Config> Pallet<T> {
// That message didn't get processed this time because of being
// too heavy. We leave it around for next time and bail.
remaining_fragments = last_remaining_fragments;
break;
}
break
},
Err(false) => {
// Message invalid; don't attempt to retry
}
},
}
} else {
debug_assert!(false, "Invalid incoming blob message data");
remaining_fragments = &b""[..];
}
}
}
},
XcmpMessageFormat::Signals => {
debug_assert!(false, "All signals are handled immediately; qed");
remaining_fragments = &b""[..];
}
},
}
let is_empty = remaining_fragments.is_empty();
if is_empty {
@@ -469,15 +458,11 @@ impl<T: Config> Pallet<T> {
fn service_xcmp_queue(max_weight: Weight) -> Weight {
let mut status = <InboundXcmpStatus<T>>::get(); // <- sorted.
if status.len() == 0 {
return 0;
return 0
}
let QueueConfigData {
resume_threshold,
threshold_weight,
weight_restrict_decay,
..
} = <QueueConfig<T>>::get();
let QueueConfigData { resume_threshold, threshold_weight, weight_restrict_decay, .. } =
<QueueConfig<T>>::get();
let mut shuffled = Self::create_shuffle(status.len());
let mut weight_used = 0;
@@ -492,8 +477,8 @@ impl<T: Config> Pallet<T> {
// send more, heavier messages.
let mut shuffle_index = 0;
while shuffle_index < shuffled.len()
&& max_weight.saturating_sub(weight_used) >= threshold_weight
while shuffle_index < shuffled.len() &&
max_weight.saturating_sub(weight_used) >= threshold_weight
{
let index = shuffled[shuffle_index];
let sender = status[index].0;
@@ -514,10 +499,7 @@ impl<T: Config> Pallet<T> {
}
let weight_processed = if status[index].2.is_empty() {
debug_assert!(
false,
"channel exists in status; there must be messages; qed"
);
debug_assert!(false, "channel exists in status; there must be messages; qed");
0
} else {
// Process up to one block's worth for now.
@@ -531,26 +513,24 @@ impl<T: Config> Pallet<T> {
};
weight_used += weight_processed;
if status[index].2.len() as u32 <= resume_threshold
&& status[index].1 == InboundStatus::Suspended
if status[index].2.len() as u32 <= resume_threshold &&
status[index].1 == InboundStatus::Suspended
{
// Resume
let r = Self::send_signal(sender, ChannelSignal::Resume);
debug_assert!(
r.is_ok(),
"WARNING: Failed sending resume into suspended channel"
);
debug_assert!(r.is_ok(), "WARNING: Failed sending resume into suspended channel");
status[index].1 = InboundStatus::Ok;
}
// If there are more and we're making progress, we process them after we've given the
// other channels a look in. If we've still not unlocked all weight, then we set them
// up for processing a second time anyway.
if !status[index].2.is_empty() && (weight_processed > 0 || weight_available != max_weight)
if !status[index].2.is_empty() &&
(weight_processed > 0 || weight_available != max_weight)
{
if shuffle_index + 1 == shuffled.len() {
// Only this queue left. Just run around this loop once more.
continue;
continue
}
shuffled.push(index);
}
@@ -590,10 +570,7 @@ impl<T: Config> Pallet<T> {
s[index].1 = OutboundStatus::Ok;
}
} else {
debug_assert!(
false,
"WARNING: Attempt to resume channel that was not suspended."
);
debug_assert!(false, "WARNING: Attempt to resume channel that was not suspended.");
}
});
}
@@ -606,11 +583,7 @@ impl<T: Config> XcmpMessageHandler for Pallet<T> {
) -> Weight {
let mut status = <InboundXcmpStatus<T>>::get();
let QueueConfigData {
suspend_threshold,
drop_threshold,
..
} = <QueueConfig<T>>::get();
let QueueConfigData { suspend_threshold, drop_threshold, .. } = <QueueConfig<T>>::get();
for (sender, sent_at, data) in iter {
// Figure out the message format.
@@ -618,12 +591,9 @@ impl<T: Config> XcmpMessageHandler for Pallet<T> {
let format = match XcmpMessageFormat::decode(&mut data_ref) {
Ok(f) => f,
Err(_) => {
debug_assert!(
false,
"Unknown XCMP message format. Silently dropping message"
);
continue;
}
debug_assert!(false, "Unknown XCMP message format. Silently dropping message");
continue
},
};
if format == XcmpMessageFormat::Signals {
while !data_ref.is_empty() {
@@ -656,7 +626,7 @@ impl<T: Config> XcmpMessageHandler for Pallet<T> {
"XCMP channel queue full. Silently dropping message"
);
}
}
},
Err(_) => status.push((sender, InboundStatus::Ok, vec![(sent_at, format)])),
}
// Queue the payload for later execution.
@@ -686,10 +656,10 @@ impl<T: Config> XcmpMessageSource for Pallet<T> {
if result.len() == max_message_count {
// We check this condition in the beginning of the loop so that we don't include
// a message where the limit is 0.
break;
break
}
if outbound_status == OutboundStatus::Suspended {
continue;
continue
}
let (max_size_now, max_size_ever) = match T::ChannelInfo::get_channel_status(para_id) {
ChannelStatus::Closed => {
@@ -702,8 +672,8 @@ impl<T: Config> XcmpMessageSource for Pallet<T> {
<SignalMessages<T>>::remove(para_id);
}
*status = (para_id, OutboundStatus::Ok, false, 0, 0);
continue;
}
continue
},
ChannelStatus::Full => continue,
ChannelStatus::Ready(n, e) => (n, e),
};
@@ -715,7 +685,7 @@ impl<T: Config> XcmpMessageSource for Pallet<T> {
signalling = false;
page
} else {
continue;
continue
}
} else if end > begin {
let page = <OutboundXcmpMessages<T>>::get(para_id, begin);
@@ -724,10 +694,10 @@ impl<T: Config> XcmpMessageSource for Pallet<T> {
begin += 1;
page
} else {
continue;
continue
}
} else {
continue;
continue
};
if begin == end {
begin = 0;
@@ -789,7 +759,7 @@ impl<T: Config> SendXcm for Pallet<T> {
.map_err(|e| SendError::Transport(<&'static str>::from(e)))?;
Self::deposit_event(Event::XcmpMessageSent(Some(hash)));
Ok(())
}
},
// Anything else is unhandled. This includes a message this is meant for us.
_ => Err(SendError::CannotReachDestination(dest, msg)),
}
+7 -7
View File
@@ -15,12 +15,14 @@
use super::*;
use crate as xcmp_queue;
use sp_core::H256;
use frame_support::parameter_types;
use sp_runtime::{traits::{BlakeTwo256, IdentityLookup}, testing::Header};
use sp_core::H256;
use sp_runtime::{
testing::Header,
traits::{BlakeTwo256, IdentityLookup},
};
use xcm_builder::{
FixedWeightBounds, IsConcrete, LocationInverter, NativeAsset, CurrencyAdapter,
ParentIsDefault,
CurrencyAdapter, FixedWeightBounds, IsConcrete, LocationInverter, NativeAsset, ParentIsDefault,
};
type UncheckedExtrinsic = frame_system::mocking::MockUncheckedExtrinsic<Test>;
@@ -124,9 +126,7 @@ pub type LocalAssetTransactor = CurrencyAdapter<
(),
>;
pub type LocationToAccountId = (
ParentIsDefault<AccountId>,
);
pub type LocationToAccountId = (ParentIsDefault<AccountId>,);
pub struct XcmConfig;
impl xcm_executor::Config for XcmConfig {
+3 -12
View File
@@ -14,25 +14,16 @@
// limitations under the License.
use super::*;
use mock::{new_test_ext, XcmpQueue};
use cumulus_primitives_core::XcmpMessageHandler;
use mock::{new_test_ext, XcmpQueue};
#[test]
fn one_message_does_not_panic() {
new_test_ext().execute_with(|| {
let message_format = XcmpMessageFormat::ConcatenatedVersionedXcm.encode();
let messages = vec![
(
Default::default(),
1u32.into(),
message_format.as_slice(),
),
];
let messages = vec![(Default::default(), 1u32.into(), message_format.as_slice())];
// This shouldn't cause a panic
XcmpQueue::handle_xcmp_messages(
messages.into_iter(),
Weight::max_value(),
);
XcmpQueue::handle_xcmp_messages(messages.into_iter(), Weight::max_value());
})
}