cargo +nightly fmt (#3540)

* cargo +nightly fmt

* add cargo-fmt check to ci

* update ci

* fmt

* fmt

* skip macro

* ignore bridges
This commit is contained in:
Shawn Tabrizi
2021-08-02 12:47:33 +02:00
committed by GitHub
parent 30e3012270
commit ff5d56fb76
350 changed files with 20617 additions and 21266 deletions
+193 -133
View File
@@ -18,13 +18,13 @@
//!
//! Configuration can change only at session boundaries and is buffered until then.
use sp_std::prelude::*;
use primitives::v1::{Balance, SessionIndex, MAX_CODE_SIZE, MAX_POV_SIZE};
use parity_scale_codec::{Encode, Decode};
use frame_system::pallet_prelude::*;
use frame_support::pallet_prelude::*;
use sp_runtime::traits::Zero;
use crate::shared;
use frame_support::pallet_prelude::*;
use frame_system::pallet_prelude::*;
use parity_scale_codec::{Decode, Encode};
use primitives::v1::{Balance, SessionIndex, MAX_CODE_SIZE, MAX_POV_SIZE};
use sp_runtime::traits::Zero;
use sp_std::prelude::*;
pub use pallet::*;
@@ -38,7 +38,6 @@ pub struct HostConfiguration<BlockNumber> {
// A parachain requested this struct can only depend on the subset of this struct. Specifically,
// only a first few fields can be depended upon. These fields cannot be changed without
// corresponding migration of the parachains.
/**
* The parameters that are required for the parachains.
*/
@@ -244,8 +243,7 @@ impl<BlockNumber: Zero> HostConfiguration<BlockNumber> {
if self.max_code_size > MAX_CODE_SIZE {
panic!(
"`max_code_size` ({}) is bigger than allowed by the client ({})",
self.max_code_size,
MAX_CODE_SIZE,
self.max_code_size, MAX_CODE_SIZE,
)
}
@@ -275,32 +273,23 @@ pub mod pallet {
/// The active configuration for the current session.
#[pallet::storage]
#[pallet::getter(fn config)]
pub(crate) type ActiveConfig<T: Config> = StorageValue<
_,
HostConfiguration<T::BlockNumber>,
ValueQuery
>;
pub(crate) type ActiveConfig<T: Config> =
StorageValue<_, HostConfiguration<T::BlockNumber>, ValueQuery>;
/// Pending configuration (if any) for the next session.
#[pallet::storage]
pub(crate) type PendingConfig<T: Config> = StorageMap<
_,
Twox64Concat,
SessionIndex,
HostConfiguration<T::BlockNumber>
>;
pub(crate) type PendingConfig<T: Config> =
StorageMap<_, Twox64Concat, SessionIndex, HostConfiguration<T::BlockNumber>>;
#[pallet::genesis_config]
pub struct GenesisConfig<T: Config> {
pub config: HostConfiguration<T::BlockNumber>
pub config: HostConfiguration<T::BlockNumber>,
}
#[cfg(feature = "std")]
impl<T: Config> Default for GenesisConfig<T> {
fn default() -> Self {
GenesisConfig {
config: Default::default()
}
GenesisConfig { config: Default::default() }
}
}
@@ -316,7 +305,10 @@ pub mod pallet {
impl<T: Config> Pallet<T> {
/// Set the validation upgrade frequency.
#[pallet::weight((1_000, DispatchClass::Operational))]
pub fn set_validation_upgrade_frequency(origin: OriginFor<T>, new: T::BlockNumber) -> DispatchResult {
pub fn set_validation_upgrade_frequency(
origin: OriginFor<T>,
new: T::BlockNumber,
) -> DispatchResult {
ensure_root(origin)?;
Self::update_config_member(|config| {
sp_std::mem::replace(&mut config.validation_upgrade_frequency, new) != new
@@ -326,7 +318,10 @@ pub mod pallet {
/// Set the validation upgrade delay.
#[pallet::weight((1_000, DispatchClass::Operational))]
pub fn set_validation_upgrade_delay(origin: OriginFor<T>, new: T::BlockNumber) -> DispatchResult {
pub fn set_validation_upgrade_delay(
origin: OriginFor<T>,
new: T::BlockNumber,
) -> DispatchResult {
ensure_root(origin)?;
Self::update_config_member(|config| {
sp_std::mem::replace(&mut config.validation_upgrade_delay, new) != new
@@ -336,7 +331,10 @@ pub mod pallet {
/// Set the acceptance period for an included candidate.
#[pallet::weight((1_000, DispatchClass::Operational))]
pub fn set_code_retention_period(origin: OriginFor<T>, new: T::BlockNumber) -> DispatchResult {
pub fn set_code_retention_period(
origin: OriginFor<T>,
new: T::BlockNumber,
) -> DispatchResult {
ensure_root(origin)?;
Self::update_config_member(|config| {
sp_std::mem::replace(&mut config.code_retention_period, new) != new
@@ -396,10 +394,12 @@ pub mod pallet {
Ok(())
}
/// Set the parachain validator-group rotation frequency
#[pallet::weight((1_000, DispatchClass::Operational))]
pub fn set_group_rotation_frequency(origin: OriginFor<T>, new: T::BlockNumber) -> DispatchResult {
pub fn set_group_rotation_frequency(
origin: OriginFor<T>,
new: T::BlockNumber,
) -> DispatchResult {
ensure_root(origin)?;
ensure!(!new.is_zero(), Error::<T>::InvalidNewValue);
@@ -412,7 +412,10 @@ pub mod pallet {
/// Set the availability period for parachains.
#[pallet::weight((1_000, DispatchClass::Operational))]
pub fn set_chain_availability_period(origin: OriginFor<T>, new: T::BlockNumber) -> DispatchResult {
pub fn set_chain_availability_period(
origin: OriginFor<T>,
new: T::BlockNumber,
) -> DispatchResult {
ensure_root(origin)?;
ensure!(!new.is_zero(), Error::<T>::InvalidNewValue);
@@ -425,7 +428,10 @@ pub mod pallet {
/// Set the availability period for parathreads.
#[pallet::weight((1_000, DispatchClass::Operational))]
pub fn set_thread_availability_period(origin: OriginFor<T>, new: T::BlockNumber) -> DispatchResult {
pub fn set_thread_availability_period(
origin: OriginFor<T>,
new: T::BlockNumber,
) -> DispatchResult {
ensure_root(origin)?;
ensure!(!new.is_zero(), Error::<T>::InvalidNewValue);
@@ -448,7 +454,10 @@ pub mod pallet {
/// Set the maximum number of validators to assign to any core.
#[pallet::weight((1_000, DispatchClass::Operational))]
pub fn set_max_validators_per_core(origin: OriginFor<T>, new: Option<u32>) -> DispatchResult {
pub fn set_max_validators_per_core(
origin: OriginFor<T>,
new: Option<u32>,
) -> DispatchResult {
ensure_root(origin)?;
Self::update_config_member(|config| {
sp_std::mem::replace(&mut config.max_validators_per_core, new) != new
@@ -484,7 +493,8 @@ pub mod pallet {
) -> DispatchResult {
ensure_root(origin)?;
Self::update_config_member(|config| {
sp_std::mem::replace(&mut config.dispute_post_conclusion_acceptance_period, new) != new
sp_std::mem::replace(&mut config.dispute_post_conclusion_acceptance_period, new) !=
new
});
Ok(())
}
@@ -501,9 +511,10 @@ pub mod pallet {
/// Set the dispute conclusion by time out period.
#[pallet::weight((1_000, DispatchClass::Operational))]
pub fn set_dispute_conclusion_by_time_out_period(origin: OriginFor<T>, new: T::BlockNumber)
-> DispatchResult
{
pub fn set_dispute_conclusion_by_time_out_period(
origin: OriginFor<T>,
new: T::BlockNumber,
) -> DispatchResult {
ensure_root(origin)?;
Self::update_config_member(|config| {
sp_std::mem::replace(&mut config.dispute_conclusion_by_time_out_period, new) != new
@@ -617,7 +628,10 @@ pub mod pallet {
/// Sets the maximum number of messages that a candidate can contain.
#[pallet::weight((1_000, DispatchClass::Operational))]
pub fn set_max_upward_message_num_per_candidate(origin: OriginFor<T>, new: u32) -> DispatchResult {
pub fn set_max_upward_message_num_per_candidate(
origin: OriginFor<T>,
new: u32,
) -> DispatchResult {
ensure_root(origin)?;
Self::update_config_member(|config| {
sp_std::mem::replace(&mut config.max_upward_message_num_per_candidate, new) != new
@@ -678,7 +692,10 @@ pub mod pallet {
/// Sets the maximum number of inbound HRMP channels a parachain is allowed to accept.
#[pallet::weight((1_000, DispatchClass::Operational))]
pub fn set_hrmp_max_parachain_inbound_channels(origin: OriginFor<T>, new: u32) -> DispatchResult {
pub fn set_hrmp_max_parachain_inbound_channels(
origin: OriginFor<T>,
new: u32,
) -> DispatchResult {
ensure_root(origin)?;
Self::update_config_member(|config| {
sp_std::mem::replace(&mut config.hrmp_max_parachain_inbound_channels, new) != new
@@ -688,7 +705,10 @@ pub mod pallet {
/// Sets the maximum number of inbound HRMP channels a parathread is allowed to accept.
#[pallet::weight((1_000, DispatchClass::Operational))]
pub fn set_hrmp_max_parathread_inbound_channels(origin: OriginFor<T>, new: u32) -> DispatchResult {
pub fn set_hrmp_max_parathread_inbound_channels(
origin: OriginFor<T>,
new: u32,
) -> DispatchResult {
ensure_root(origin)?;
Self::update_config_member(|config| {
sp_std::mem::replace(&mut config.hrmp_max_parathread_inbound_channels, new) != new
@@ -708,7 +728,10 @@ pub mod pallet {
/// Sets the maximum number of outbound HRMP channels a parachain is allowed to open.
#[pallet::weight((1_000, DispatchClass::Operational))]
pub fn set_hrmp_max_parachain_outbound_channels(origin: OriginFor<T>, new: u32) -> DispatchResult {
pub fn set_hrmp_max_parachain_outbound_channels(
origin: OriginFor<T>,
new: u32,
) -> DispatchResult {
ensure_root(origin)?;
Self::update_config_member(|config| {
sp_std::mem::replace(&mut config.hrmp_max_parachain_outbound_channels, new) != new
@@ -718,7 +741,10 @@ pub mod pallet {
/// Sets the maximum number of outbound HRMP channels a parathread is allowed to open.
#[pallet::weight((1_000, DispatchClass::Operational))]
pub fn set_hrmp_max_parathread_outbound_channels(origin: OriginFor<T>, new: u32) -> DispatchResult {
pub fn set_hrmp_max_parathread_outbound_channels(
origin: OriginFor<T>,
new: u32,
) -> DispatchResult {
ensure_root(origin)?;
Self::update_config_member(|config| {
sp_std::mem::replace(&mut config.hrmp_max_parathread_outbound_channels, new) != new
@@ -728,7 +754,10 @@ pub mod pallet {
/// Sets the maximum number of outbound HRMP messages can be sent by a candidate.
#[pallet::weight((1_000, DispatchClass::Operational))]
pub fn set_hrmp_max_message_num_per_candidate(origin: OriginFor<T>, new: u32) -> DispatchResult {
pub fn set_hrmp_max_message_num_per_candidate(
origin: OriginFor<T>,
new: u32,
) -> DispatchResult {
ensure_root(origin)?;
Self::update_config_member(|config| {
sp_std::mem::replace(&mut config.hrmp_max_message_num_per_candidate, new) != new
@@ -745,12 +774,10 @@ impl<T: Config> Pallet<T> {
}
/// Called by the initializer to finalize the configuration module.
pub(crate) fn initializer_finalize() { }
pub(crate) fn initializer_finalize() {}
/// Called by the initializer to note that a new session has started.
pub(crate) fn initializer_on_new_session(
session_index: &SessionIndex,
) {
pub(crate) fn initializer_on_new_session(session_index: &SessionIndex) {
if let Some(pending) = <Self as Store>::PendingConfig::take(session_index) {
<Self as Store>::ActiveConfig::set(pending);
}
@@ -773,9 +800,7 @@ impl<T: Config> Pallet<T> {
// duplicated code (making this function to show up in the top of heaviest functions) only for
// the sake of essentially avoiding an indirect call. Doesn't worth it.
#[inline(never)]
fn update_config_member(
updater: impl FnOnce(&mut HostConfiguration<T::BlockNumber>) -> bool,
) {
fn update_config_member(updater: impl FnOnce(&mut HostConfiguration<T::BlockNumber>) -> bool) {
let scheduled_session = Self::scheduled_session();
let pending = <Self as Store>::PendingConfig::get(scheduled_session);
let mut prev = pending.unwrap_or_else(Self::config);
@@ -867,138 +892,172 @@ mod tests {
assert!(<Configuration as Store>::PendingConfig::get(shared::SESSION_DELAY).is_none());
Configuration::set_validation_upgrade_frequency(
Origin::root(), new_config.validation_upgrade_frequency,
).unwrap();
Origin::root(),
new_config.validation_upgrade_frequency,
)
.unwrap();
Configuration::set_validation_upgrade_delay(
Origin::root(), new_config.validation_upgrade_delay,
).unwrap();
Origin::root(),
new_config.validation_upgrade_delay,
)
.unwrap();
Configuration::set_code_retention_period(
Origin::root(), new_config.code_retention_period,
).unwrap();
Configuration::set_max_code_size(
Origin::root(), new_config.max_code_size,
).unwrap();
Configuration::set_max_pov_size(
Origin::root(), new_config.max_pov_size,
).unwrap();
Configuration::set_max_head_data_size(
Origin::root(), new_config.max_head_data_size,
).unwrap();
Configuration::set_parathread_cores(
Origin::root(), new_config.parathread_cores,
).unwrap();
Configuration::set_parathread_retries(
Origin::root(), new_config.parathread_retries,
).unwrap();
Origin::root(),
new_config.code_retention_period,
)
.unwrap();
Configuration::set_max_code_size(Origin::root(), new_config.max_code_size).unwrap();
Configuration::set_max_pov_size(Origin::root(), new_config.max_pov_size).unwrap();
Configuration::set_max_head_data_size(Origin::root(), new_config.max_head_data_size)
.unwrap();
Configuration::set_parathread_cores(Origin::root(), new_config.parathread_cores)
.unwrap();
Configuration::set_parathread_retries(Origin::root(), new_config.parathread_retries)
.unwrap();
Configuration::set_group_rotation_frequency(
Origin::root(), new_config.group_rotation_frequency,
).unwrap();
Origin::root(),
new_config.group_rotation_frequency,
)
.unwrap();
Configuration::set_chain_availability_period(
Origin::root(), new_config.chain_availability_period,
).unwrap();
Origin::root(),
new_config.chain_availability_period,
)
.unwrap();
Configuration::set_thread_availability_period(
Origin::root(), new_config.thread_availability_period,
).unwrap();
Origin::root(),
new_config.thread_availability_period,
)
.unwrap();
Configuration::set_scheduling_lookahead(
Origin::root(), new_config.scheduling_lookahead,
).unwrap();
Origin::root(),
new_config.scheduling_lookahead,
)
.unwrap();
Configuration::set_max_validators_per_core(
Origin::root(), new_config.max_validators_per_core,
).unwrap();
Configuration::set_max_validators(
Origin::root(), new_config.max_validators,
).unwrap();
Configuration::set_dispute_period(
Origin::root(), new_config.dispute_period,
).unwrap();
Origin::root(),
new_config.max_validators_per_core,
)
.unwrap();
Configuration::set_max_validators(Origin::root(), new_config.max_validators).unwrap();
Configuration::set_dispute_period(Origin::root(), new_config.dispute_period).unwrap();
Configuration::set_dispute_post_conclusion_acceptance_period(
Origin::root(), new_config.dispute_post_conclusion_acceptance_period,
).unwrap();
Origin::root(),
new_config.dispute_post_conclusion_acceptance_period,
)
.unwrap();
Configuration::set_dispute_max_spam_slots(
Origin::root(), new_config.dispute_max_spam_slots,
).unwrap();
Origin::root(),
new_config.dispute_max_spam_slots,
)
.unwrap();
Configuration::set_dispute_conclusion_by_time_out_period(
Origin::root(), new_config.dispute_conclusion_by_time_out_period,
).unwrap();
Configuration::set_no_show_slots(
Origin::root(), new_config.no_show_slots,
).unwrap();
Configuration::set_n_delay_tranches(
Origin::root(), new_config.n_delay_tranches,
).unwrap();
Origin::root(),
new_config.dispute_conclusion_by_time_out_period,
)
.unwrap();
Configuration::set_no_show_slots(Origin::root(), new_config.no_show_slots).unwrap();
Configuration::set_n_delay_tranches(Origin::root(), new_config.n_delay_tranches)
.unwrap();
Configuration::set_zeroth_delay_tranche_width(
Origin::root(), new_config.zeroth_delay_tranche_width,
).unwrap();
Configuration::set_needed_approvals(
Origin::root(), new_config.needed_approvals,
).unwrap();
Origin::root(),
new_config.zeroth_delay_tranche_width,
)
.unwrap();
Configuration::set_needed_approvals(Origin::root(), new_config.needed_approvals)
.unwrap();
Configuration::set_relay_vrf_modulo_samples(
Origin::root(), new_config.relay_vrf_modulo_samples,
).unwrap();
Origin::root(),
new_config.relay_vrf_modulo_samples,
)
.unwrap();
Configuration::set_max_upward_queue_count(
Origin::root(), new_config.max_upward_queue_count,
).unwrap();
Origin::root(),
new_config.max_upward_queue_count,
)
.unwrap();
Configuration::set_max_upward_queue_size(
Origin::root(), new_config.max_upward_queue_size,
).unwrap();
Origin::root(),
new_config.max_upward_queue_size,
)
.unwrap();
Configuration::set_max_downward_message_size(
Origin::root(), new_config.max_downward_message_size,
).unwrap();
Origin::root(),
new_config.max_downward_message_size,
)
.unwrap();
Configuration::set_ump_service_total_weight(
Origin::root(), new_config.ump_service_total_weight,
).unwrap();
Origin::root(),
new_config.ump_service_total_weight,
)
.unwrap();
Configuration::set_max_upward_message_size(
Origin::root(), new_config.max_upward_message_size,
).unwrap();
Origin::root(),
new_config.max_upward_message_size,
)
.unwrap();
Configuration::set_max_upward_message_num_per_candidate(
Origin::root(), new_config.max_upward_message_num_per_candidate,
).unwrap();
Origin::root(),
new_config.max_upward_message_num_per_candidate,
)
.unwrap();
Configuration::set_hrmp_open_request_ttl(
Origin::root(),
new_config.hrmp_open_request_ttl,
).unwrap();
Configuration::set_hrmp_sender_deposit(
Origin::root(),
new_config.hrmp_sender_deposit,
).unwrap();
)
.unwrap();
Configuration::set_hrmp_sender_deposit(Origin::root(), new_config.hrmp_sender_deposit)
.unwrap();
Configuration::set_hrmp_recipient_deposit(
Origin::root(),
new_config.hrmp_recipient_deposit,
).unwrap();
)
.unwrap();
Configuration::set_hrmp_channel_max_capacity(
Origin::root(),
new_config.hrmp_channel_max_capacity,
).unwrap();
)
.unwrap();
Configuration::set_hrmp_channel_max_total_size(
Origin::root(),
new_config.hrmp_channel_max_total_size,
).unwrap();
)
.unwrap();
Configuration::set_hrmp_max_parachain_inbound_channels(
Origin::root(),
new_config.hrmp_max_parachain_inbound_channels,
).unwrap();
)
.unwrap();
Configuration::set_hrmp_max_parathread_inbound_channels(
Origin::root(),
new_config.hrmp_max_parathread_inbound_channels,
).unwrap();
)
.unwrap();
Configuration::set_hrmp_channel_max_message_size(
Origin::root(),
new_config.hrmp_channel_max_message_size,
).unwrap();
)
.unwrap();
Configuration::set_hrmp_max_parachain_outbound_channels(
Origin::root(),
new_config.hrmp_max_parachain_outbound_channels,
).unwrap();
)
.unwrap();
Configuration::set_hrmp_max_parathread_outbound_channels(
Origin::root(),
new_config.hrmp_max_parathread_outbound_channels,
).unwrap();
)
.unwrap();
Configuration::set_hrmp_max_message_num_per_candidate(
Origin::root(),
new_config.hrmp_max_message_num_per_candidate,
).unwrap();
)
.unwrap();
assert_eq!(<Configuration as Store>::PendingConfig::get(shared::SESSION_DELAY), Some(new_config));
assert_eq!(
<Configuration as Store>::PendingConfig::get(shared::SESSION_DELAY),
Some(new_config)
);
})
}
@@ -1012,7 +1071,8 @@ mod tests {
#[test]
fn setting_config_to_same_as_current_is_noop() {
new_test_ext(Default::default()).execute_with(|| {
Configuration::set_validation_upgrade_delay(Origin::root(), Default::default()).unwrap();
Configuration::set_validation_upgrade_delay(Origin::root(), Default::default())
.unwrap();
assert!(<Configuration as Store>::PendingConfig::get(shared::SESSION_DELAY).is_none())
});
}
File diff suppressed because it is too large Load Diff
+21 -33
View File
@@ -19,9 +19,9 @@ use crate::{
initializer,
};
use frame_support::pallet_prelude::*;
use sp_std::{fmt, prelude::*};
use primitives::v1::{DownwardMessage, Hash, Id as ParaId, InboundDownwardMessage};
use sp_runtime::traits::{BlakeTwo256, Hash as HashT, SaturatedConversion};
use primitives::v1::{Id as ParaId, DownwardMessage, InboundDownwardMessage, Hash};
use sp_std::{fmt, prelude::*};
use xcm::v0::Error as XcmError;
pub use pallet::*;
@@ -47,24 +47,16 @@ pub enum ProcessedDownwardMessagesAcceptanceErr {
/// If there are pending messages then `processed_downward_messages` should be at least 1,
AdvancementRule,
/// `processed_downward_messages` should not be greater than the number of pending messages.
Underflow {
processed_downward_messages: u32,
dmq_length: u32,
},
Underflow { processed_downward_messages: u32, dmq_length: u32 },
}
impl fmt::Debug for ProcessedDownwardMessagesAcceptanceErr {
fn fmt(&self, fmt: &mut fmt::Formatter) -> fmt::Result {
use ProcessedDownwardMessagesAcceptanceErr::*;
match *self {
AdvancementRule => write!(
fmt,
"DMQ is not empty, but processed_downward_messages is 0",
),
Underflow {
processed_downward_messages,
dmq_length,
} => write!(
AdvancementRule =>
write!(fmt, "DMQ is not empty, but processed_downward_messages is 0",),
Underflow { processed_downward_messages, dmq_length } => write!(
fmt,
"processed_downward_messages = {}, but dmq_length is only {}",
processed_downward_messages, dmq_length,
@@ -91,7 +83,7 @@ pub mod pallet {
Twox64Concat,
ParaId,
Vec<InboundDownwardMessage<T::BlockNumber>>,
ValueQuery
ValueQuery,
>;
/// A mapping that stores the downward message queue MQC head for each para.
@@ -102,13 +94,8 @@ pub mod pallet {
/// - `B`: is the relay-chain block number in which a message was appended.
/// - `H(M)`: is the hash of the message being appended.
#[pallet::storage]
pub(crate) type DownwardMessageQueueHeads<T: Config> = StorageMap<
_,
Twox64Concat,
ParaId,
Hash,
ValueQuery,
>;
pub(crate) type DownwardMessageQueueHeads<T: Config> =
StorageMap<_, Twox64Concat, ParaId, Hash, ValueQuery>;
#[pallet::call]
impl<T: Config> Pallet<T> {}
@@ -161,13 +148,11 @@ impl<T: Config> Pallet<T> {
) -> Result<(), QueueDownwardMessageError> {
let serialized_len = msg.len() as u32;
if serialized_len > config.max_downward_message_size {
return Err(QueueDownwardMessageError::ExceedsMaxMessageSize);
return Err(QueueDownwardMessageError::ExceedsMaxMessageSize)
}
let inbound = InboundDownwardMessage {
msg,
sent_at: <frame_system::Pallet<T>>::block_number(),
};
let inbound =
InboundDownwardMessage { msg, sent_at: <frame_system::Pallet<T>>::block_number() };
// obtain the new link in the MQC and update the head.
<Self as Store>::DownwardMessageQueueHeads::mutate(para, |head| {
@@ -191,13 +176,13 @@ impl<T: Config> Pallet<T> {
let dmq_length = Self::dmq_length(para);
if dmq_length > 0 && processed_downward_messages == 0 {
return Err(ProcessedDownwardMessagesAcceptanceErr::AdvancementRule);
return Err(ProcessedDownwardMessagesAcceptanceErr::AdvancementRule)
}
if dmq_length < processed_downward_messages {
return Err(ProcessedDownwardMessagesAcceptanceErr::Underflow {
processed_downward_messages,
dmq_length,
});
})
}
Ok(())
@@ -245,10 +230,10 @@ impl<T: Config> Pallet<T> {
#[cfg(test)]
mod tests {
use super::*;
use crate::mock::{new_test_ext, Configuration, Dmp, MockGenesisConfig, Paras, System};
use hex_literal::hex;
use primitives::v1::BlockNumber;
use parity_scale_codec::Encode;
use crate::mock::{Configuration, new_test_ext, System, Dmp, MockGenesisConfig, Paras};
use primitives::v1::BlockNumber;
pub(crate) fn run_to_block(to: BlockNumber, new_session: Option<Vec<BlockNumber>>) {
while System::block_number() < to {
@@ -413,8 +398,8 @@ mod tests {
#[test]
fn verify_dmq_mqc_head_is_externally_accessible() {
use primitives::v1::well_known_keys;
use hex_literal::hex;
use primitives::v1::well_known_keys;
let a = ParaId::from(2020);
@@ -427,7 +412,10 @@ mod tests {
let head = sp_io::storage::get(&well_known_keys::dmq_mqc_head(a));
assert_eq!(
head,
Some(hex!["434f8579a2297dfea851bf6be33093c83a78b655a53ae141a7894494c0010589"].to_vec())
Some(
hex!["434f8579a2297dfea851bf6be33093c83a78b655a53ae141a7894494c0010589"]
.to_vec()
)
);
});
}
+139 -338
View File
@@ -15,22 +15,20 @@
// along with Polkadot. If not, see <http://www.gnu.org/licenses/>.
use crate::{
ensure_parachain,
configuration::{self, HostConfiguration},
initializer, paras, dmp,
dmp, ensure_parachain, initializer, paras,
};
use parity_scale_codec::{Decode, Encode};
use frame_support::pallet_prelude::*;
use frame_support::traits::ReservableCurrency;
use frame_support::{pallet_prelude::*, traits::ReservableCurrency};
use frame_system::pallet_prelude::*;
use parity_scale_codec::{Decode, Encode};
use primitives::v1::{
Balance, Hash, HrmpChannelId, Id as ParaId, InboundHrmpMessage, OutboundHrmpMessage,
SessionIndex,
};
use sp_runtime::traits::{UniqueSaturatedInto, AccountIdConversion, BlakeTwo256, Hash as HashT};
use sp_runtime::traits::{AccountIdConversion, BlakeTwo256, Hash as HashT, UniqueSaturatedInto};
use sp_std::{
mem, fmt,
collections::{btree_map::BTreeMap, btree_set::BTreeSet},
fmt, mem,
prelude::*,
};
@@ -63,7 +61,6 @@ pub struct HrmpChannel {
// A parachain requested this struct can only depend on the subset of this struct. Specifically,
// only a first few fields can be depended upon (See `AbridgedHrmpChannel`). These fields cannot
// be changed without corresponding migration of parachains.
/// The maximum number of messages that can be pending in the channel at once.
pub max_capacity: u32,
/// The maximum total size of the messages that can be pending in the channel at once.
@@ -93,48 +90,20 @@ pub struct HrmpChannel {
/// An error returned by [`check_hrmp_watermark`] that indicates an acceptance criteria check
/// didn't pass.
pub enum HrmpWatermarkAcceptanceErr<BlockNumber> {
AdvancementRule {
new_watermark: BlockNumber,
last_watermark: BlockNumber,
},
AheadRelayParent {
new_watermark: BlockNumber,
relay_chain_parent_number: BlockNumber,
},
LandsOnBlockWithNoMessages {
new_watermark: BlockNumber,
},
AdvancementRule { new_watermark: BlockNumber, last_watermark: BlockNumber },
AheadRelayParent { new_watermark: BlockNumber, relay_chain_parent_number: BlockNumber },
LandsOnBlockWithNoMessages { new_watermark: BlockNumber },
}
/// An error returned by [`check_outbound_hrmp`] that indicates an acceptance criteria check
/// didn't pass.
pub enum OutboundHrmpAcceptanceErr {
MoreMessagesThanPermitted {
sent: u32,
permitted: u32,
},
NotSorted {
idx: u32,
},
NoSuchChannel {
idx: u32,
channel_id: HrmpChannelId,
},
MaxMessageSizeExceeded {
idx: u32,
msg_size: u32,
max_size: u32,
},
TotalSizeExceeded {
idx: u32,
total_size: u32,
limit: u32,
},
CapacityExceeded {
idx: u32,
count: u32,
limit: u32,
},
MoreMessagesThanPermitted { sent: u32, permitted: u32 },
NotSorted { idx: u32 },
NoSuchChannel { idx: u32, channel_id: HrmpChannelId },
MaxMessageSizeExceeded { idx: u32, msg_size: u32, max_size: u32 },
TotalSizeExceeded { idx: u32, total_size: u32, limit: u32 },
CapacityExceeded { idx: u32, count: u32, limit: u32 },
}
impl<BlockNumber> fmt::Debug for HrmpWatermarkAcceptanceErr<BlockNumber>
@@ -144,18 +113,12 @@ where
fn fmt(&self, fmt: &mut fmt::Formatter) -> fmt::Result {
use HrmpWatermarkAcceptanceErr::*;
match self {
AdvancementRule {
new_watermark,
last_watermark,
} => write!(
AdvancementRule { new_watermark, last_watermark } => write!(
fmt,
"the HRMP watermark is not advanced relative to the last watermark ({:?} > {:?})",
new_watermark, last_watermark,
),
AheadRelayParent {
new_watermark,
relay_chain_parent_number,
} => write!(
AheadRelayParent { new_watermark, relay_chain_parent_number } => write!(
fmt,
"the HRMP watermark is ahead the relay-parent ({:?} > {:?})",
new_watermark, relay_chain_parent_number
@@ -178,30 +141,19 @@ impl fmt::Debug for OutboundHrmpAcceptanceErr {
"more HRMP messages than permitted by config ({} > {})",
sent, permitted,
),
NotSorted { idx } => write!(
fmt,
"the HRMP messages are not sorted (first unsorted is at index {})",
idx,
),
NotSorted { idx } =>
write!(fmt, "the HRMP messages are not sorted (first unsorted is at index {})", idx,),
NoSuchChannel { idx, channel_id } => write!(
fmt,
"the HRMP message at index {} is sent to a non existent channel {:?}->{:?}",
idx, channel_id.sender, channel_id.recipient,
),
MaxMessageSizeExceeded {
idx,
msg_size,
max_size,
} => write!(
MaxMessageSizeExceeded { idx, msg_size, max_size } => write!(
fmt,
"the HRMP message at index {} exceeds the negotiated channel maximum message size ({} > {})",
idx, msg_size, max_size,
),
TotalSizeExceeded {
idx,
total_size,
limit,
} => write!(
TotalSizeExceeded { idx, total_size, limit } => write!(
fmt,
"sending the HRMP message at index {} would exceed the neogitiated channel total size ({} > {})",
idx, total_size, limit,
@@ -219,13 +171,14 @@ impl fmt::Debug for OutboundHrmpAcceptanceErr {
pub mod pallet {
use super::*;
#[pallet::pallet]
#[pallet::generate_store(pub(super) trait Store)]
pub struct Pallet<T>(_);
#[pallet::config]
pub trait Config: frame_system::Config + configuration::Config + paras::Config + dmp::Config {
pub trait Config:
frame_system::Config + configuration::Config + paras::Config + dmp::Config
{
/// The outer event type.
type Event: From<Event<Self>> + IsType<<Self as frame_system::Config>::Event>;
@@ -294,39 +247,26 @@ pub mod pallet {
/// Invariant:
/// - There are no channels that exists in list but not in the set and vice versa.
#[pallet::storage]
pub type HrmpOpenChannelRequests<T: Config> = StorageMap<
_,
Twox64Concat,
HrmpChannelId,
HrmpOpenChannelRequest
>;
pub type HrmpOpenChannelRequests<T: Config> =
StorageMap<_, Twox64Concat, HrmpChannelId, HrmpOpenChannelRequest>;
#[pallet::storage]
pub type HrmpOpenChannelRequestsList<T: Config> = StorageValue<_, Vec<HrmpChannelId>, ValueQuery>;
pub type HrmpOpenChannelRequestsList<T: Config> =
StorageValue<_, Vec<HrmpChannelId>, ValueQuery>;
/// This mapping tracks how many open channel requests are initiated by a given sender para.
/// Invariant: `HrmpOpenChannelRequests` should contain the same number of items that has `(X, _)`
/// as the number of `HrmpOpenChannelRequestCount` for `X`.
#[pallet::storage]
pub type HrmpOpenChannelRequestCount<T: Config> = StorageMap<
_,
Twox64Concat,
ParaId,
u32,
ValueQuery
>;
pub type HrmpOpenChannelRequestCount<T: Config> =
StorageMap<_, Twox64Concat, ParaId, u32, ValueQuery>;
/// This mapping tracks how many open channel requests were accepted by a given recipient para.
/// Invariant: `HrmpOpenChannelRequests` should contain the same number of items `(_, X)` with
/// `confirmed` set to true, as the number of `HrmpAcceptedChannelRequestCount` for `X`.
#[pallet::storage]
pub type HrmpAcceptedChannelRequestCount<T: Config> = StorageMap<
_,
Twox64Concat,
ParaId,
u32,
ValueQuery
>;
pub type HrmpAcceptedChannelRequestCount<T: Config> =
StorageMap<_, Twox64Concat, ParaId, u32, ValueQuery>;
/// A set of pending HRMP close channel requests that are going to be closed during the session change.
/// Used for checking if a given channel is registered for closure.
@@ -339,7 +279,8 @@ pub mod pallet {
pub type HrmpCloseChannelRequests<T: Config> = StorageMap<_, Twox64Concat, HrmpChannelId, ()>;
#[pallet::storage]
pub type HrmpCloseChannelRequestsList<T: Config> = StorageValue<_, Vec<HrmpChannelId>, ValueQuery>;
pub type HrmpCloseChannelRequestsList<T: Config> =
StorageValue<_, Vec<HrmpChannelId>, ValueQuery>;
/// The HRMP watermark associated with each para.
/// Invariant:
@@ -367,24 +308,14 @@ pub mod pallet {
/// - there should be no other dangling channels in `HrmpChannels`.
/// - the vectors are sorted.
#[pallet::storage]
pub type HrmpIngressChannelsIndex<T: Config> = StorageMap<
_,
Twox64Concat,
ParaId,
Vec<ParaId>,
ValueQuery
>;
pub type HrmpIngressChannelsIndex<T: Config> =
StorageMap<_, Twox64Concat, ParaId, Vec<ParaId>, ValueQuery>;
// NOTE that this field is used by parachains via merkle storage proofs, therefore changing
// the format will require migration of parachains.
#[pallet::storage]
pub type HrmpEgressChannelsIndex<T: Config> = StorageMap<
_,
Twox64Concat,
ParaId,
Vec<ParaId>,
ValueQuery
>;
pub type HrmpEgressChannelsIndex<T: Config> =
StorageMap<_, Twox64Concat, ParaId, Vec<ParaId>, ValueQuery>;
/// Storage for the messages for each channel.
/// Invariant: cannot be non-empty if the corresponding channel in `HrmpChannels` is `None`.
@@ -394,7 +325,7 @@ pub mod pallet {
Twox64Concat,
HrmpChannelId,
Vec<InboundHrmpMessage<T::BlockNumber>>,
ValueQuery
ValueQuery,
>;
/// Maintains a mapping that can be used to answer the question:
@@ -405,13 +336,8 @@ pub mod pallet {
/// - The outer vector is sorted ascending by block number and cannot store two items with the same
/// block number.
#[pallet::storage]
pub type HrmpChannelDigests<T: Config> = StorageMap<
_,
Twox64Concat,
ParaId,
Vec<(T::BlockNumber, Vec<ParaId>)>,
ValueQuery
>;
pub type HrmpChannelDigests<T: Config> =
StorageMap<_, Twox64Concat, ParaId, Vec<(T::BlockNumber, Vec<ParaId>)>, ValueQuery>;
/// Preopen the given HRMP channels.
///
@@ -432,9 +358,7 @@ pub mod pallet {
#[cfg(feature = "std")]
impl Default for GenesisConfig {
fn default() -> Self {
GenesisConfig {
preopen_hrmp_channels: Default::default(),
}
GenesisConfig { preopen_hrmp_channels: Default::default() }
}
}
@@ -469,13 +393,13 @@ pub mod pallet {
origin,
recipient,
proposed_max_capacity,
proposed_max_message_size
proposed_max_message_size,
)?;
Self::deposit_event(Event::OpenChannelRequested(
origin,
recipient,
proposed_max_capacity,
proposed_max_message_size
proposed_max_message_size,
));
Ok(())
}
@@ -496,7 +420,10 @@ pub mod pallet {
///
/// The closure can only happen on a session change.
#[pallet::weight(0)]
pub fn hrmp_close_channel(origin: OriginFor<T>, channel_id: HrmpChannelId) -> DispatchResult {
pub fn hrmp_close_channel(
origin: OriginFor<T>,
channel_id: HrmpChannelId,
) -> DispatchResult {
let origin = ensure_parachain(<T as Config>::Origin::from(origin))?;
Self::close_channel(origin, channel_id.clone())?;
Self::deposit_event(Event::ChannelClosed(origin, channel_id));
@@ -544,7 +471,9 @@ pub mod pallet {
fn initialize_storage<T: Config>(preopen_hrmp_channels: &[(ParaId, ParaId, u32, u32)]) {
let host_config = configuration::Pallet::<T>::config();
for &(sender, recipient, max_capacity, max_message_size) in preopen_hrmp_channels {
if let Err(err) = preopen_hrmp_channel::<T>(sender, recipient, max_capacity, max_message_size) {
if let Err(err) =
preopen_hrmp_channel::<T>(sender, recipient, max_capacity, max_message_size)
{
panic!("failed to initialize the genesis storage: {:?}", err);
}
}
@@ -556,14 +485,9 @@ fn preopen_hrmp_channel<T: Config>(
sender: ParaId,
recipient: ParaId,
max_capacity: u32,
max_message_size: u32
max_message_size: u32,
) -> DispatchResult {
<Pallet<T>>::init_open_channel(
sender,
recipient,
max_capacity,
max_message_size,
)?;
<Pallet<T>>::init_open_channel(sender, recipient, max_capacity, max_message_size)?;
<Pallet<T>>::accept_open_channel(recipient, sender)?;
Ok(())
}
@@ -603,16 +527,10 @@ impl<T: Config> Pallet<T> {
let ingress = <Self as Store>::HrmpIngressChannelsIndex::take(outgoing_para)
.into_iter()
.map(|sender| HrmpChannelId {
sender,
recipient: outgoing_para.clone(),
});
.map(|sender| HrmpChannelId { sender, recipient: outgoing_para.clone() });
let egress = <Self as Store>::HrmpEgressChannelsIndex::take(outgoing_para)
.into_iter()
.map(|recipient| HrmpChannelId {
sender: outgoing_para.clone(),
recipient,
});
.map(|recipient| HrmpChannelId { sender: outgoing_para.clone(), recipient });
let mut to_close = ingress.chain(egress).collect::<Vec<_>>();
to_close.sort();
to_close.dedup();
@@ -629,7 +547,7 @@ impl<T: Config> Pallet<T> {
fn process_hrmp_open_channel_requests(config: &HostConfiguration<T::BlockNumber>) {
let mut open_req_channels = <Self as Store>::HrmpOpenChannelRequestsList::get();
if open_req_channels.is_empty() {
return;
return
}
// iterate the vector starting from the end making our way to the beginning. This way we
@@ -638,7 +556,7 @@ impl<T: Config> Pallet<T> {
loop {
// bail if we've iterated over all items.
if idx == 0 {
break;
break
}
idx -= 1;
@@ -648,8 +566,8 @@ impl<T: Config> Pallet<T> {
);
if request.confirmed {
if <paras::Pallet<T>>::is_valid_para(channel_id.sender)
&& <paras::Pallet<T>>::is_valid_para(channel_id.recipient)
if <paras::Pallet<T>>::is_valid_para(channel_id.sender) &&
<paras::Pallet<T>>::is_valid_para(channel_id.recipient)
{
<Self as Store>::HrmpChannels::insert(
&channel_id,
@@ -745,11 +663,8 @@ impl<T: Config> Pallet<T> {
/// This function is idempotent, meaning that after the first application it should have no
/// effect (i.e. it won't return the deposits twice).
fn close_hrmp_channel(channel_id: &HrmpChannelId) {
if let Some(HrmpChannel {
sender_deposit,
recipient_deposit,
..
}) = <Self as Store>::HrmpChannels::take(channel_id)
if let Some(HrmpChannel { sender_deposit, recipient_deposit, .. }) =
<Self as Store>::HrmpChannels::take(channel_id)
{
T::Currency::unreserve(
&channel_id.sender.into_account(),
@@ -793,14 +708,14 @@ impl<T: Config> Pallet<T> {
return Err(HrmpWatermarkAcceptanceErr::AdvancementRule {
new_watermark: new_hrmp_watermark,
last_watermark,
});
})
}
}
if new_hrmp_watermark > relay_chain_parent_number {
return Err(HrmpWatermarkAcceptanceErr::AheadRelayParent {
new_watermark: new_hrmp_watermark,
relay_chain_parent_number,
});
})
}
// Second, check where the watermark CAN land. It's one of the following:
@@ -817,7 +732,7 @@ impl<T: Config> Pallet<T> {
{
return Err(HrmpWatermarkAcceptanceErr::LandsOnBlockWithNoMessages {
new_watermark: new_hrmp_watermark,
});
})
}
Ok(())
}
@@ -832,36 +747,28 @@ impl<T: Config> Pallet<T> {
return Err(OutboundHrmpAcceptanceErr::MoreMessagesThanPermitted {
sent: out_hrmp_msgs.len() as u32,
permitted: config.hrmp_max_message_num_per_candidate,
});
})
}
let mut last_recipient = None::<ParaId>;
for (idx, out_msg) in out_hrmp_msgs
.iter()
.enumerate()
.map(|(idx, out_msg)| (idx as u32, out_msg))
for (idx, out_msg) in
out_hrmp_msgs.iter().enumerate().map(|(idx, out_msg)| (idx as u32, out_msg))
{
match last_recipient {
// the messages must be sorted in ascending order and there must be no two messages sent
// to the same recipient. Thus we can check that every recipient is strictly greater than
// the previous one.
Some(last_recipient) if out_msg.recipient <= last_recipient => {
return Err(OutboundHrmpAcceptanceErr::NotSorted { idx });
}
Some(last_recipient) if out_msg.recipient <= last_recipient =>
return Err(OutboundHrmpAcceptanceErr::NotSorted { idx }),
_ => last_recipient = Some(out_msg.recipient),
}
let channel_id = HrmpChannelId {
sender,
recipient: out_msg.recipient,
};
let channel_id = HrmpChannelId { sender, recipient: out_msg.recipient };
let channel = match <Self as Store>::HrmpChannels::get(&channel_id) {
Some(channel) => channel,
None => {
return Err(OutboundHrmpAcceptanceErr::NoSuchChannel { channel_id, idx });
}
None => return Err(OutboundHrmpAcceptanceErr::NoSuchChannel { channel_id, idx }),
};
let msg_size = out_msg.data.len() as u32;
@@ -870,7 +777,7 @@ impl<T: Config> Pallet<T> {
idx,
msg_size,
max_size: channel.max_message_size,
});
})
}
let new_total_size = channel.total_size + out_msg.data.len() as u32;
@@ -879,7 +786,7 @@ impl<T: Config> Pallet<T> {
idx,
total_size: new_total_size,
limit: channel.max_total_size,
});
})
}
let new_msg_count = channel.msg_count + 1;
@@ -888,7 +795,7 @@ impl<T: Config> Pallet<T> {
idx,
count: new_msg_count,
limit: channel.max_capacity,
});
})
}
}
@@ -916,9 +823,8 @@ impl<T: Config> Pallet<T> {
weight += T::DbWeight::get().reads_writes(1, 1);
// having all senders we can trivially find out the channels which we need to prune.
let channels_to_prune = senders
.into_iter()
.map(|sender| HrmpChannelId { sender, recipient });
let channels_to_prune =
senders.into_iter().map(|sender| HrmpChannelId { sender, recipient });
for channel_id in channels_to_prune {
// prune each channel up to the new watermark keeping track how many messages we removed
// and what is the total byte size of them.
@@ -968,24 +874,18 @@ impl<T: Config> Pallet<T> {
let now = <frame_system::Pallet<T>>::block_number();
for out_msg in out_hrmp_msgs {
let channel_id = HrmpChannelId {
sender,
recipient: out_msg.recipient,
};
let channel_id = HrmpChannelId { sender, recipient: out_msg.recipient };
let mut channel = match <Self as Store>::HrmpChannels::get(&channel_id) {
Some(channel) => channel,
None => {
// apparently, that since acceptance of this candidate the recipient was
// offboarded and the channel no longer exists.
continue;
}
continue
},
};
let inbound = InboundHrmpMessage {
sent_at: now,
data: out_msg.data,
};
let inbound = InboundHrmpMessage { sent_at: now, data: out_msg.data };
// book keeping
channel.msg_count += 1;
@@ -1052,27 +952,18 @@ impl<T: Config> Pallet<T> {
);
let config = <configuration::Pallet<T>>::config();
ensure!(
proposed_max_capacity > 0,
Error::<T>::OpenHrmpChannelZeroCapacity,
);
ensure!(proposed_max_capacity > 0, Error::<T>::OpenHrmpChannelZeroCapacity,);
ensure!(
proposed_max_capacity <= config.hrmp_channel_max_capacity,
Error::<T>::OpenHrmpChannelCapacityExceedsLimit,
);
ensure!(
proposed_max_message_size > 0,
Error::<T>::OpenHrmpChannelZeroMessageSize,
);
ensure!(proposed_max_message_size > 0, Error::<T>::OpenHrmpChannelZeroMessageSize,);
ensure!(
proposed_max_message_size <= config.hrmp_channel_max_message_size,
Error::<T>::OpenHrmpChannelMessageSizeExceedsLimit,
);
let channel_id = HrmpChannelId {
sender: origin,
recipient,
};
let channel_id = HrmpChannelId { sender: origin, recipient };
ensure!(
<Self as Store>::HrmpOpenChannelRequests::get(&channel_id).is_none(),
Error::<T>::OpenHrmpChannelAlreadyExists,
@@ -1115,8 +1006,8 @@ impl<T: Config> Pallet<T> {
<Self as Store>::HrmpOpenChannelRequestsList::append(channel_id);
let notification_bytes = {
use xcm::opaque::{v0::Xcm, VersionedXcm};
use parity_scale_codec::Encode as _;
use xcm::opaque::{v0::Xcm, VersionedXcm};
VersionedXcm::from(Xcm::HrmpNewChannelOpenRequest {
sender: u32::from(origin),
@@ -1141,16 +1032,10 @@ impl<T: Config> Pallet<T> {
/// Basically the same as [`hrmp_accept_open_channel`](Pallet::hrmp_accept_open_channel) but
/// intendend for calling directly from other pallets rather than dispatched.
pub fn accept_open_channel(origin: ParaId, sender: ParaId) -> DispatchResult {
let channel_id = HrmpChannelId {
sender,
recipient: origin,
};
let channel_id = HrmpChannelId { sender, recipient: origin };
let mut channel_req = <Self as Store>::HrmpOpenChannelRequests::get(&channel_id)
.ok_or(Error::<T>::AcceptHrmpChannelDoesntExist)?;
ensure!(
!channel_req.confirmed,
Error::<T>::AcceptHrmpChannelAlreadyConfirmed,
);
ensure!(!channel_req.confirmed, Error::<T>::AcceptHrmpChannelAlreadyConfirmed,);
// check if by accepting this open channel request, this parachain would exceed the
// number of inbound channels.
@@ -1183,10 +1068,7 @@ impl<T: Config> Pallet<T> {
use parity_scale_codec::Encode as _;
use xcm::opaque::{v0::Xcm, VersionedXcm};
VersionedXcm::from(Xcm::HrmpChannelAccepted {
recipient: u32::from(origin),
})
.encode()
VersionedXcm::from(Xcm::HrmpChannelAccepted { recipient: u32::from(origin) }).encode()
};
if let Err(dmp::QueueDownwardMessageError::ExceedsMaxMessageSize) =
<dmp::Pallet<T>>::queue_downward_message(&config, sender, notification_bytes)
@@ -1233,11 +1115,8 @@ impl<T: Config> Pallet<T> {
})
.encode()
};
let opposite_party = if origin == channel_id.sender {
channel_id.recipient
} else {
channel_id.sender
};
let opposite_party =
if origin == channel_id.sender { channel_id.recipient } else { channel_id.sender };
if let Err(dmp::QueueDownwardMessageError::ExceedsMaxMessageSize) =
<dmp::Pallet<T>>::queue_downward_message(&config, opposite_party, notification_bytes)
{
@@ -1292,15 +1171,14 @@ impl<T: Config> Pallet<T> {
mod tests {
use super::*;
use crate::mock::{
new_test_ext, Test, Configuration, Paras, ParasShared, Hrmp, System, MockGenesisConfig,
Event as MockEvent,
new_test_ext, Configuration, Event as MockEvent, Hrmp, MockGenesisConfig, Paras,
ParasShared, System, Test,
};
use frame_support::{assert_noop, assert_ok, traits::Currency as _};
use primitives::v1::BlockNumber;
use std::collections::{BTreeMap, HashSet};
fn run_to_block(to: BlockNumber, new_session: Option<Vec<BlockNumber>>) {
let config = Configuration::config();
while System::block_number() < to {
let b = System::block_number();
@@ -1500,9 +1378,7 @@ mod tests {
// An entry in `HrmpChannels` indicates that the channel is open. Only open channels can
// have contents.
for (non_empty_channel, contents) in <Hrmp as Store>::HrmpChannelContents::iter() {
assert!(<Hrmp as Store>::HrmpChannels::contains_key(
&non_empty_channel
));
assert!(<Hrmp as Store>::HrmpChannels::contains_key(&non_empty_channel));
// pedantic check: there should be no empty vectors in storage, those should be modeled
// by a removed kv pair.
@@ -1544,10 +1420,7 @@ mod tests {
let channel_set_ground_truth = <Hrmp as Store>::HrmpChannels::iter()
.map(|(k, _)| (k.sender, k.recipient))
.collect::<HashSet<_>>();
assert_eq!(
channel_set_derived_from_ingress,
channel_set_derived_from_egress
);
assert_eq!(channel_set_derived_from_ingress, channel_set_derived_from_egress);
assert_eq!(channel_set_derived_from_egress, channel_set_ground_truth);
<Hrmp as Store>::HrmpIngressChannelsIndex::iter()
@@ -1583,22 +1456,13 @@ mod tests {
fn assert_contains_only_onboarded(iter: impl Iterator<Item = ParaId>, cause: &str) {
for para in iter {
assert!(
Paras::is_valid_para(para),
"{}: {} para is offboarded",
cause,
para
);
assert!(Paras::is_valid_para(para), "{}: {} para is offboarded", cause, para);
}
}
}
fn assert_is_sorted<T: Ord>(slice: &[T], id: &str) {
assert!(
slice.windows(2).all(|xs| xs[0] <= xs[1]),
"{} supposed to be sorted",
id
);
assert!(slice.windows(2).all(|xs| xs[0] <= xs[1]), "{} supposed to be sorted", id);
}
#[test]
@@ -1623,15 +1487,13 @@ mod tests {
run_to_block(5, Some(vec![4, 5]));
Hrmp::hrmp_init_open_channel(para_a_origin.into(), para_b, 2, 8).unwrap();
assert_storage_consistency_exhaustive();
assert!(System::events().iter().any(|record|
record.event == MockEvent::Hrmp(Event::OpenChannelRequested(para_a, para_b, 2, 8))
));
assert!(System::events().iter().any(|record| record.event ==
MockEvent::Hrmp(Event::OpenChannelRequested(para_a, para_b, 2, 8))));
Hrmp::hrmp_accept_open_channel(para_b_origin.into(), para_a).unwrap();
assert_storage_consistency_exhaustive();
assert!(System::events().iter().any(|record|
record.event == MockEvent::Hrmp(Event::OpenChannelAccepted(para_a, para_b))
));
assert!(System::events().iter().any(|record| record.event ==
MockEvent::Hrmp(Event::OpenChannelAccepted(para_a, para_b))));
// Advance to a block 6, but without session change. That means that the channel has
// not been created yet.
@@ -1664,10 +1526,7 @@ mod tests {
// Close the channel. The effect is not immediate, but rather deferred to the next
// session change.
let channel_id = HrmpChannelId {
sender: para_a,
recipient: para_b,
};
let channel_id = HrmpChannelId { sender: para_a, recipient: para_b };
Hrmp::hrmp_close_channel(para_b_origin.into(), channel_id.clone()).unwrap();
assert!(channel_exists(para_a, para_b));
assert_storage_consistency_exhaustive();
@@ -1676,9 +1535,8 @@ mod tests {
run_to_block(8, Some(vec![8]));
assert!(!channel_exists(para_a, para_b));
assert_storage_consistency_exhaustive();
assert!(System::events().iter().any(|record|
record.event == MockEvent::Hrmp(Event::ChannelClosed(para_b, channel_id.clone()))
));
assert!(System::events().iter().any(|record| record.event ==
MockEvent::Hrmp(Event::ChannelClosed(para_b, channel_id.clone()))));
});
}
@@ -1732,27 +1590,31 @@ mod tests {
register_parachain(para_a);
register_parachain(para_b);
run_to_block(2, Some(vec![1,2]));
run_to_block(2, Some(vec![1, 2]));
Hrmp::init_open_channel(para_a, para_b, 2, 20).unwrap();
Hrmp::accept_open_channel(para_b, para_a).unwrap();
run_to_block(3, Some(vec![3]));
let _ = Hrmp::queue_outbound_hrmp(para_a, vec![OutboundHrmpMessage {
recipient: para_b,
data: vec![1, 2, 3],
}]);
let _ = Hrmp::queue_outbound_hrmp(
para_a,
vec![OutboundHrmpMessage { recipient: para_b, data: vec![1, 2, 3] }],
);
run_to_block(4, None);
let _ = Hrmp::queue_outbound_hrmp(para_a, vec![OutboundHrmpMessage {
recipient: para_b,
data: vec![4, 5, 6],
}]);
let _ = Hrmp::queue_outbound_hrmp(
para_a,
vec![OutboundHrmpMessage { recipient: para_b, data: vec![4, 5, 6] }],
);
assert_eq!(
Hrmp::hrmp_mqc_heads(para_b),
vec![
(para_a, hex_literal::hex!["a964fd3b4f3d3ce92a0e25e576b87590d92bb5cb7031909c7f29050e1f04a375"].into()),
],
vec![(
para_a,
hex_literal::hex![
"a964fd3b4f3d3ce92a0e25e576b87590d92bb5cb7031909c7f29050e1f04a375"
]
.into()
),],
);
});
}
@@ -1803,10 +1665,7 @@ mod tests {
run_to_block(6, Some(vec![6]));
assert!(Paras::is_valid_para(para_a));
let msgs = vec![OutboundHrmpMessage {
recipient: para_b,
data: b"knock".to_vec(),
}];
let msgs = vec![OutboundHrmpMessage { recipient: para_b, data: b"knock".to_vec() }];
let config = Configuration::config();
assert!(Hrmp::check_outbound_hrmp(&config, para_a, &msgs).is_ok());
let _ = Hrmp::queue_outbound_hrmp(para_a, msgs.clone());
@@ -1817,13 +1676,7 @@ mod tests {
assert_eq!(
contents,
vec![
(
para_a,
vec![InboundHrmpMessage {
sent_at: 6,
data: b"knock".to_vec(),
}]
),
(para_a, vec![InboundHrmpMessage { sent_at: 6, data: b"knock".to_vec() }]),
(para_c, vec![])
]
.into_iter()
@@ -1891,29 +1744,19 @@ mod tests {
);
let raw_ingress_index =
sp_io::storage::get(
&well_known_keys::hrmp_ingress_channel_index(para_b),
)
.expect("the ingress index must be present for para_b");
sp_io::storage::get(&well_known_keys::hrmp_ingress_channel_index(para_b))
.expect("the ingress index must be present for para_b");
let ingress_index = <Vec<ParaId>>::decode(&mut &raw_ingress_index[..])
.expect("ingress indexx should be decodable as a list of para ids");
assert_eq!(
ingress_index,
vec![para_a],
);
assert_eq!(ingress_index, vec![para_a],);
// Now, verify that we can access and decode the egress index.
let raw_egress_index =
sp_io::storage::get(
&well_known_keys::hrmp_egress_channel_index(para_a)
)
.expect("the egress index must be present for para_a");
sp_io::storage::get(&well_known_keys::hrmp_egress_channel_index(para_a))
.expect("the egress index must be present for para_a");
let egress_index = <Vec<ParaId>>::decode(&mut &raw_egress_index[..])
.expect("egress index should be decodable as a list of para ids");
assert_eq!(
egress_index,
vec![para_b],
);
assert_eq!(egress_index, vec![para_b],);
});
}
@@ -1962,34 +1805,16 @@ mod tests {
run_to_block(5, Some(vec![4, 5]));
Hrmp::init_open_channel(para_a, para_b, 2, 8).unwrap();
Hrmp::accept_open_channel(para_b, para_a).unwrap();
assert_eq!(
<Test as Config>::Currency::free_balance(&para_a.into_account()),
80
);
assert_eq!(
<Test as Config>::Currency::free_balance(&para_b.into_account()),
95
);
assert_eq!(<Test as Config>::Currency::free_balance(&para_a.into_account()), 80);
assert_eq!(<Test as Config>::Currency::free_balance(&para_b.into_account()), 95);
run_to_block(8, Some(vec![8]));
// Now, we close the channel and wait until the next session.
Hrmp::close_channel(
para_b,
HrmpChannelId {
sender: para_a,
recipient: para_b,
},
)
.unwrap();
Hrmp::close_channel(para_b, HrmpChannelId { sender: para_a, recipient: para_b })
.unwrap();
run_to_block(10, Some(vec![10]));
assert_eq!(
<Test as Config>::Currency::free_balance(&para_a.into_account()),
100
);
assert_eq!(
<Test as Config>::Currency::free_balance(&para_b.into_account()),
110
);
assert_eq!(<Test as Config>::Currency::free_balance(&para_a.into_account()), 100);
assert_eq!(<Test as Config>::Currency::free_balance(&para_b.into_account()), 110);
});
}
@@ -2009,28 +1834,16 @@ mod tests {
register_parachain_with_balance(para_b, 110);
run_to_block(5, Some(vec![4, 5]));
Hrmp::init_open_channel(para_a, para_b, 2, 8).unwrap();
assert_eq!(
<Test as Config>::Currency::free_balance(&para_a.into_account()),
80
);
assert_eq!(
<Test as Config>::Currency::free_balance(&para_b.into_account()),
110
);
assert_eq!(<Test as Config>::Currency::free_balance(&para_a.into_account()), 80);
assert_eq!(<Test as Config>::Currency::free_balance(&para_b.into_account()), 110);
// Request age is 1 out of 2
run_to_block(10, Some(vec![10]));
assert_eq!(
<Test as Config>::Currency::free_balance(&para_a.into_account()),
80
);
assert_eq!(<Test as Config>::Currency::free_balance(&para_a.into_account()), 80);
// Request age is 2 out of 2. The request should expire.
run_to_block(20, Some(vec![20]));
assert_eq!(
<Test as Config>::Currency::free_balance(&para_a.into_account()),
100
);
assert_eq!(<Test as Config>::Currency::free_balance(&para_a.into_account()), 100);
});
}
@@ -2049,14 +1862,8 @@ mod tests {
run_to_block(5, Some(vec![4, 5]));
Hrmp::init_open_channel(para_a, para_b, 2, 8).unwrap();
Hrmp::accept_open_channel(para_b, para_a).unwrap();
assert_eq!(
<Test as Config>::Currency::free_balance(&para_a.into_account()),
80
);
assert_eq!(
<Test as Config>::Currency::free_balance(&para_b.into_account()),
95
);
assert_eq!(<Test as Config>::Currency::free_balance(&para_a.into_account()), 80);
assert_eq!(<Test as Config>::Currency::free_balance(&para_b.into_account()), 95);
run_to_block(8, Some(vec![8]));
assert!(channel_exists(para_a, para_b));
@@ -2069,14 +1876,8 @@ mod tests {
assert!(!channel_exists(para_a, para_b));
assert_storage_consistency_exhaustive();
assert_eq!(
<Test as Config>::Currency::free_balance(&para_a.into_account()),
100
);
assert_eq!(
<Test as Config>::Currency::free_balance(&para_b.into_account()),
110
);
assert_eq!(<Test as Config>::Currency::free_balance(&para_a.into_account()), 100);
assert_eq!(<Test as Config>::Currency::free_balance(&para_b.into_account()), 110);
});
}
}
File diff suppressed because it is too large Load Diff
+40 -46
View File
@@ -19,15 +19,15 @@
//!
//! This module can throw fatal errors if session-change notifications are received after initialization.
use sp_std::prelude::*;
use primitives::v1::{ValidatorId, SessionIndex, ConsensusLog, BlockNumber};
use frame_support::traits::{Randomness, OneSessionHandler};
use parity_scale_codec::{Encode, Decode};
use crate::{
configuration::{self, HostConfiguration},
disputes::DisputesHandler,
shared, paras, scheduler, inclusion, session_info, dmp, ump, hrmp,
dmp, hrmp, inclusion, paras, scheduler, session_info, shared, ump,
};
use frame_support::traits::{OneSessionHandler, Randomness};
use parity_scale_codec::{Decode, Encode};
use primitives::v1::{BlockNumber, ConsensusLog, SessionIndex, ValidatorId};
use sp_std::prelude::*;
pub use pallet::*;
@@ -70,9 +70,9 @@ struct BufferedSessionChange {
#[frame_support::pallet]
pub mod pallet {
use super::*;
use frame_support::pallet_prelude::*;
use frame_system::pallet_prelude::*;
use super::*;
#[pallet::pallet]
#[pallet::generate_store(pub(super) trait Store)]
@@ -97,7 +97,6 @@ pub mod pallet {
type ForceOrigin: EnsureOrigin<<Self as frame_system::Config>::Origin>;
}
/// Whether the parachains modules have been initialized within this block.
///
/// Semantically a `bool`, but this guarantees it should never hit the trie,
@@ -117,7 +116,8 @@ pub mod pallet {
/// However this is a `Vec` regardless to handle various edge cases that may occur at runtime
/// upgrade boundaries or if governance intervenes.
#[pallet::storage]
pub(super) type BufferedSessionChanges<T: Config> = StorageValue<_, Vec<BufferedSessionChange>, ValueQuery>;
pub(super) type BufferedSessionChanges<T: Config> =
StorageValue<_, Vec<BufferedSessionChange>, ValueQuery>;
#[pallet::hooks]
impl<T: Config> Hooks<BlockNumberFor<T>> for Pallet<T> {
@@ -165,11 +165,8 @@ pub mod pallet {
// next block will observe the next session.
//
// Note that we only apply the last session as all others lasted less than a block (weirdly).
if let Some(BufferedSessionChange {
session_index,
validators,
queued,
}) = BufferedSessionChanges::<T>::take().pop()
if let Some(BufferedSessionChange { session_index, validators, queued }) =
BufferedSessionChanges::<T>::take().pop()
{
Self::apply_new_session(session_index, validators, queued);
}
@@ -250,8 +247,8 @@ impl<T: Config> Pallet<T> {
session_index: SessionIndex,
validators: I,
queued: Option<I>,
)
where I: Iterator<Item=(&'a T::AccountId, ValidatorId)>
) where
I: Iterator<Item = (&'a T::AccountId, ValidatorId)>,
{
let validators: Vec<_> = validators.map(|(_, v)| v).collect();
let queued: Vec<_> = if let Some(queued) = queued {
@@ -264,13 +261,10 @@ impl<T: Config> Pallet<T> {
// Genesis session should be immediately enacted.
Self::apply_new_session(0, validators, queued);
} else {
BufferedSessionChanges::<T>::mutate(|v| v.push(BufferedSessionChange {
validators,
queued,
session_index,
}));
BufferedSessionChanges::<T>::mutate(|v| {
v.push(BufferedSessionChange { validators, queued, session_index })
});
}
}
// Allow to trigger on_new_session in tests, this is needed as long as pallet_session is not
@@ -281,8 +275,8 @@ impl<T: Config> Pallet<T> {
session_index: SessionIndex,
validators: I,
queued: Option<I>,
)
where I: Iterator<Item=(&'a T::AccountId, ValidatorId)>
) where
I: Iterator<Item = (&'a T::AccountId, ValidatorId)>,
{
Self::on_new_session(changed, session_index, validators, queued)
}
@@ -296,29 +290,31 @@ impl<T: pallet_session::Config + Config> OneSessionHandler<T::AccountId> for Pal
type Key = ValidatorId;
fn on_genesis_session<'a, I: 'a>(validators: I)
where I: Iterator<Item=(&'a T::AccountId, Self::Key)>
where
I: Iterator<Item = (&'a T::AccountId, Self::Key)>,
{
<Pallet<T>>::on_new_session(false, 0, validators, None);
}
fn on_new_session<'a, I: 'a>(changed: bool, validators: I, queued: I)
where I: Iterator<Item=(&'a T::AccountId, Self::Key)>
where
I: Iterator<Item = (&'a T::AccountId, Self::Key)>,
{
let session_index = <pallet_session::Pallet<T>>::current_index();
<Pallet<T>>::on_new_session(changed, session_index, validators, Some(queued));
}
fn on_disabled(_i: usize) { }
fn on_disabled(_i: usize) {}
}
#[cfg(test)]
mod tests {
use super::*;
use primitives::v1::{Id as ParaId};
use crate::mock::{
new_test_ext,
Initializer, System, Dmp, Paras, Configuration, SessionInfo, MockGenesisConfig,
new_test_ext, Configuration, Dmp, Initializer, MockGenesisConfig, Paras, SessionInfo,
System,
};
use primitives::v1::Id as ParaId;
use frame_support::{
assert_ok,
@@ -409,26 +405,24 @@ mod tests {
validation_code: Default::default(),
};
new_test_ext(
MockGenesisConfig {
configuration: crate::configuration::GenesisConfig {
config: crate::configuration::HostConfiguration {
max_downward_message_size: 1024,
..Default::default()
},
},
paras: crate::paras::GenesisConfig {
paras: vec![
(a, mock_genesis.clone()),
(b, mock_genesis.clone()),
(c, mock_genesis.clone()),
],
new_test_ext(MockGenesisConfig {
configuration: crate::configuration::GenesisConfig {
config: crate::configuration::HostConfiguration {
max_downward_message_size: 1024,
..Default::default()
},
},
paras: crate::paras::GenesisConfig {
paras: vec![
(a, mock_genesis.clone()),
(b, mock_genesis.clone()),
(c, mock_genesis.clone()),
],
..Default::default()
}
).execute_with(|| {
},
..Default::default()
})
.execute_with(|| {
// enqueue downward messages to A, B and C.
assert_ok!(Dmp::queue_downward_message(&Configuration::config(), a, vec![1, 2, 3]));
assert_ok!(Dmp::queue_downward_message(&Configuration::config(), b, vec![4, 5, 6]));
+7 -7
View File
@@ -24,18 +24,18 @@
pub mod configuration;
pub mod disputes;
pub mod shared;
pub mod dmp;
pub mod hrmp;
pub mod inclusion;
pub mod initializer;
pub mod origin;
pub mod paras;
pub mod paras_inherent;
pub mod reward_points;
pub mod scheduler;
pub mod session_info;
pub mod origin;
pub mod dmp;
pub mod shared;
pub mod ump;
pub mod hrmp;
pub mod reward_points;
pub mod runtime_api_impl;
@@ -44,9 +44,9 @@ mod util;
#[cfg(test)]
mod mock;
pub use origin::{Origin, ensure_parachain};
use primitives::v1::Id as ParaId;
pub use origin::{ensure_parachain, Origin};
pub use paras::ParaLifecycle;
use primitives::v1::Id as ParaId;
/// Schedule a para to be initialized at the start of the next session with the given genesis data.
pub fn schedule_para_initialize<T: paras::Config>(
+21 -25
View File
@@ -16,23 +16,19 @@
//! Mocks for all the traits.
use sp_io::TestExternalities;
use sp_core::H256;
use sp_runtime::traits::{
BlakeTwo256, IdentityLookup,
};
use primitives::v1::{
AuthorityDiscoveryId, Balance, BlockNumber, Header, ValidatorIndex, SessionIndex,
};
use frame_support::parameter_types;
use frame_support::traits::GenesisBuild;
use frame_support_test::TestRandomness;
use std::cell::RefCell;
use std::collections::HashMap;
use crate::{
inclusion, scheduler, dmp, ump, hrmp, session_info, paras, configuration,
initializer, shared, disputes,
configuration, disputes, dmp, hrmp, inclusion, initializer, paras, scheduler, session_info,
shared, ump,
};
use frame_support::{parameter_types, traits::GenesisBuild};
use frame_support_test::TestRandomness;
use primitives::v1::{
AuthorityDiscoveryId, Balance, BlockNumber, Header, SessionIndex, ValidatorIndex,
};
use sp_core::H256;
use sp_io::TestExternalities;
use sp_runtime::traits::{BlakeTwo256, IdentityLookup};
use std::{cell::RefCell, collections::HashMap};
type UncheckedExtrinsic = frame_system::mocking::MockUncheckedExtrinsic<Test>;
type Block = frame_system::mocking::MockBlock<Test>;
@@ -114,16 +110,16 @@ impl crate::initializer::Config for Test {
type ForceOrigin = frame_system::EnsureRoot<u64>;
}
impl crate::configuration::Config for Test { }
impl crate::configuration::Config for Test {}
impl crate::shared::Config for Test { }
impl crate::shared::Config for Test {}
impl crate::paras::Config for Test {
type Origin = Origin;
type Event = Event;
}
impl crate::dmp::Config for Test { }
impl crate::dmp::Config for Test {}
parameter_types! {
pub const FirstMessageFactorPercent: u64 = 100;
@@ -157,7 +153,7 @@ thread_local! {
impl crate::disputes::RewardValidators for Test {
fn reward_dispute_statement(
session: SessionIndex,
validators: impl IntoIterator<Item=ValidatorIndex>
validators: impl IntoIterator<Item = ValidatorIndex>,
) {
REWARD_VALIDATORS.with(|r| r.borrow_mut().push((session, validators.into_iter().collect())))
}
@@ -166,7 +162,7 @@ impl crate::disputes::RewardValidators for Test {
impl crate::disputes::PunishValidators for Test {
fn punish_for_invalid(
session: SessionIndex,
validators: impl IntoIterator<Item=ValidatorIndex>,
validators: impl IntoIterator<Item = ValidatorIndex>,
) {
PUNISH_VALIDATORS_FOR
.with(|r| r.borrow_mut().push((session, validators.into_iter().collect())))
@@ -174,7 +170,7 @@ impl crate::disputes::PunishValidators for Test {
fn punish_against_valid(
session: SessionIndex,
validators: impl IntoIterator<Item=ValidatorIndex>,
validators: impl IntoIterator<Item = ValidatorIndex>,
) {
PUNISH_VALIDATORS_AGAINST
.with(|r| r.borrow_mut().push((session, validators.into_iter().collect())))
@@ -182,14 +178,14 @@ impl crate::disputes::PunishValidators for Test {
fn punish_inconclusive(
session: SessionIndex,
validators: impl IntoIterator<Item=ValidatorIndex>,
validators: impl IntoIterator<Item = ValidatorIndex>,
) {
PUNISH_VALIDATORS_INCONCLUSIVE
.with(|r| r.borrow_mut().push((session, validators.into_iter().collect())))
}
}
impl crate::scheduler::Config for Test { }
impl crate::scheduler::Config for Test {}
impl crate::inclusion::Config for Test {
type Event = Event;
@@ -197,9 +193,9 @@ impl crate::inclusion::Config for Test {
type RewardValidators = TestRewardValidators;
}
impl crate::paras_inherent::Config for Test { }
impl crate::paras_inherent::Config for Test {}
impl crate::session_info::Config for Test { }
impl crate::session_info::Config for Test {}
thread_local! {
pub static DISCOVERY_AUTHORITIES: RefCell<Vec<AuthorityDiscoveryId>> = RefCell::new(Vec::new());
+5 -4
View File
@@ -16,16 +16,17 @@
//! Declaration of the parachain specific origin and a pallet that hosts it.
use sp_std::result;
use sp_runtime::traits::BadOrigin;
use primitives::v1::Id as ParaId;
use sp_runtime::traits::BadOrigin;
use sp_std::result;
pub use pallet::*;
/// Ensure that the origin `o` represents a parachain.
/// Returns `Ok` with the parachain ID that effected the extrinsic or an `Err` otherwise.
pub fn ensure_parachain<OuterOrigin>(o: OuterOrigin) -> result::Result<ParaId, BadOrigin>
where OuterOrigin: Into<result::Result<Origin, OuterOrigin>>
where
OuterOrigin: Into<result::Result<Origin, OuterOrigin>>,
{
match o.into() {
Ok(Origin::Parachain(id)) => Ok(id),
@@ -41,8 +42,8 @@ pub fn ensure_parachain<OuterOrigin>(o: OuterOrigin) -> result::Result<ParaId, B
// ideally, though, the `construct_runtime` should support a free-standing origin.
#[frame_support::pallet]
pub mod pallet {
use frame_support::pallet_prelude::*;
use super::*;
use frame_support::pallet_prelude::*;
#[pallet::pallet]
#[pallet::generate_store(pub(super) trait Store)]
+223 -213
View File
@@ -23,20 +23,19 @@
//! A para is not considered live until it is registered and activated in this pallet. Activation can
//! only occur at session boundaries.
use sp_std::prelude::*;
use sp_std::result;
use primitives::v1::{
Id as ParaId, ValidationCode, ValidationCodeHash, HeadData, SessionIndex, ConsensusLog,
};
use sp_runtime::{traits::One, DispatchResult, SaturatedConversion};
use frame_system::pallet_prelude::*;
use crate::{configuration, initializer::SessionChangeNotification, shared};
use frame_support::pallet_prelude::*;
use parity_scale_codec::{Encode, Decode};
use crate::{configuration, shared, initializer::SessionChangeNotification};
use frame_system::pallet_prelude::*;
use parity_scale_codec::{Decode, Encode};
use primitives::v1::{
ConsensusLog, HeadData, Id as ParaId, SessionIndex, ValidationCode, ValidationCodeHash,
};
use sp_core::RuntimeDebug;
use sp_runtime::{traits::One, DispatchResult, SaturatedConversion};
use sp_std::{prelude::*, result};
#[cfg(feature = "std")]
use serde::{Serialize, Deserialize};
use serde::{Deserialize, Serialize};
pub use crate::Origin as ParachainOrigin;
@@ -123,10 +122,11 @@ impl ParaLifecycle {
/// This also includes transitioning states, so you may want to combine
/// this check with `is_stable` if you specifically want `Paralifecycle::Parachain`.
pub fn is_parachain(&self) -> bool {
matches!(self,
matches!(
self,
ParaLifecycle::Parachain |
ParaLifecycle::DowngradingParachain |
ParaLifecycle::OffboardingParachain
ParaLifecycle::DowngradingParachain |
ParaLifecycle::OffboardingParachain
)
}
@@ -134,10 +134,11 @@ impl ParaLifecycle {
/// This also includes transitioning states, so you may want to combine
/// this check with `is_stable` if you specifically want `Paralifecycle::Parathread`.
pub fn is_parathread(&self) -> bool {
matches!(self,
matches!(
self,
ParaLifecycle::Parathread |
ParaLifecycle::UpgradingParathread |
ParaLifecycle::OffboardingParathread
ParaLifecycle::UpgradingParathread |
ParaLifecycle::OffboardingParathread
)
}
@@ -196,8 +197,8 @@ impl<N: Ord + Copy + PartialEq> ParaPastCodeMeta<N> {
// The earliest stored code replacement needs to be special-cased, since we need to check
// against the pruning state to see if this replacement represents the correct code, or
// is simply after a replacement that actually represents the correct code, but has been pruned.
let was_pruned = replaced_after_pos == 0
&& self.last_pruned.map_or(false, |t| t >= para_at);
let was_pruned =
replaced_after_pos == 0 && self.last_pruned.map_or(false, |t| t >= para_at);
if was_pruned {
None
@@ -210,10 +211,12 @@ impl<N: Ord + Copy + PartialEq> ParaPastCodeMeta<N> {
// we don't know the code necessary anymore. Compare against `last_pruned` to determine.
self.last_pruned.as_ref().map_or(
Some(UseCodeAt::Current), // nothing pruned, use current
|earliest_activation| if &para_at < earliest_activation {
None
} else {
Some(UseCodeAt::Current)
|earliest_activation| {
if &para_at < earliest_activation {
None
} else {
Some(UseCodeAt::Current)
}
},
)
}
@@ -235,7 +238,7 @@ impl<N: Ord + Copy + PartialEq> ParaPastCodeMeta<N> {
//
// returns an iterator of block numbers at which code was replaced, where the replaced
// code should be now pruned, in ascending order.
fn prune_up_to(&'_ mut self, max: N) -> impl Iterator<Item=N> + '_ {
fn prune_up_to(&'_ mut self, max: N) -> impl Iterator<Item = N> + '_ {
let to_prune = self.upgrade_times.iter().take_while(|t| t.activated_at <= max).count();
let drained = if to_prune == 0 {
// no-op prune.
@@ -271,11 +274,7 @@ pub mod pallet {
pub struct Pallet<T>(_);
#[pallet::config]
pub trait Config:
frame_system::Config +
configuration::Config +
shared::Config
{
pub trait Config: frame_system::Config + configuration::Config + shared::Config {
/// The outer origin type.
type Origin: From<Origin>
+ From<<Self as frame_system::Config>::Origin>
@@ -331,32 +330,24 @@ pub mod pallet {
///
/// Corresponding code can be retrieved with [`CodeByHash`].
#[pallet::storage]
pub(super) type CurrentCodeHash<T: Config> = StorageMap<_, Twox64Concat, ParaId, ValidationCodeHash>;
pub(super) type CurrentCodeHash<T: Config> =
StorageMap<_, Twox64Concat, ParaId, ValidationCodeHash>;
/// Actual past code hash, indicated by the para id as well as the block number at which it
/// became outdated.
///
/// Corresponding code can be retrieved with [`CodeByHash`].
#[pallet::storage]
pub(super) type PastCodeHash<T: Config> = StorageMap<
_,
Twox64Concat,
(ParaId, T::BlockNumber),
ValidationCodeHash
>;
pub(super) type PastCodeHash<T: Config> =
StorageMap<_, Twox64Concat, (ParaId, T::BlockNumber), ValidationCodeHash>;
/// Past code of parachains. The parachains themselves may not be registered anymore,
/// but we also keep their code on-chain for the same amount of time as outdated code
/// to keep it available for secondary checkers.
#[pallet::storage]
#[pallet::getter(fn past_code_meta)]
pub(super) type PastCodeMeta<T: Config> = StorageMap<
_,
Twox64Concat,
ParaId,
ParaPastCodeMeta<T::BlockNumber>,
ValueQuery
>;
pub(super) type PastCodeMeta<T: Config> =
StorageMap<_, Twox64Concat, ParaId, ParaPastCodeMeta<T::BlockNumber>, ValueQuery>;
/// Which paras have past code that needs pruning and the relay-chain block at which the code was replaced.
/// Note that this is the actual height of the included block, not the expected height at which the
@@ -365,33 +356,39 @@ pub mod pallet {
/// from the time at which the parachain perceives a code upgrade as having occurred.
/// Multiple entries for a single para are permitted. Ordered ascending by block number.
#[pallet::storage]
pub(super) type PastCodePruning<T: Config> = StorageValue<_, Vec<(ParaId, T::BlockNumber)>, ValueQuery>;
pub(super) type PastCodePruning<T: Config> =
StorageValue<_, Vec<(ParaId, T::BlockNumber)>, ValueQuery>;
/// The block number at which the planned code change is expected for a para.
/// The change will be applied after the first parablock for this ID included which executes
/// in the context of a relay chain block with a number >= `expected_at`.
#[pallet::storage]
#[pallet::getter(fn future_code_upgrade_at)]
pub(super) type FutureCodeUpgrades<T: Config> = StorageMap<_, Twox64Concat, ParaId, T::BlockNumber>;
pub(super) type FutureCodeUpgrades<T: Config> =
StorageMap<_, Twox64Concat, ParaId, T::BlockNumber>;
/// The actual future code hash of a para.
///
/// Corresponding code can be retrieved with [`CodeByHash`].
#[pallet::storage]
pub(super) type FutureCodeHash<T: Config> = StorageMap<_, Twox64Concat, ParaId, ValidationCodeHash>;
pub(super) type FutureCodeHash<T: Config> =
StorageMap<_, Twox64Concat, ParaId, ValidationCodeHash>;
/// The actions to perform during the start of a specific session index.
#[pallet::storage]
#[pallet::getter(fn actions_queue)]
pub(super) type ActionsQueue<T: Config> = StorageMap<_, Twox64Concat, SessionIndex, Vec<ParaId>, ValueQuery>;
pub(super) type ActionsQueue<T: Config> =
StorageMap<_, Twox64Concat, SessionIndex, Vec<ParaId>, ValueQuery>;
/// Upcoming paras instantiation arguments.
#[pallet::storage]
pub(super) type UpcomingParasGenesis<T: Config> = StorageMap<_, Twox64Concat, ParaId, ParaGenesisArgs>;
pub(super) type UpcomingParasGenesis<T: Config> =
StorageMap<_, Twox64Concat, ParaId, ParaGenesisArgs>;
/// The number of reference on the validation code in [`CodeByHash`] storage.
#[pallet::storage]
pub(super) type CodeByHashRefs<T: Config> = StorageMap<_, Identity, ValidationCodeHash, u32, ValueQuery>;
pub(super) type CodeByHashRefs<T: Config> =
StorageMap<_, Identity, ValidationCodeHash, u32, ValueQuery>;
/// Validation code stored by its hash.
///
@@ -399,7 +396,8 @@ pub mod pallet {
/// [`PastCodeHash`].
#[pallet::storage]
#[pallet::getter(fn code_by_hash)]
pub(super) type CodeByHash<T: Config> = StorageMap<_, Identity, ValidationCodeHash, ValidationCode>;
pub(super) type CodeByHash<T: Config> =
StorageMap<_, Identity, ValidationCodeHash, ValidationCode>;
#[pallet::genesis_config]
pub struct GenesisConfig {
@@ -409,16 +407,15 @@ pub mod pallet {
#[cfg(feature = "std")]
impl Default for GenesisConfig {
fn default() -> Self {
GenesisConfig {
paras: Default::default(),
}
GenesisConfig { paras: Default::default() }
}
}
#[pallet::genesis_build]
impl<T: Config> GenesisBuild<T> for GenesisConfig {
fn build(&self) {
let mut parachains: Vec<_> = self.paras
let mut parachains: Vec<_> = self
.paras
.iter()
.filter(|(_, args)| args.parachain)
.map(|&(ref id, _)| id)
@@ -451,7 +448,11 @@ pub mod pallet {
impl<T: Config> Pallet<T> {
/// Set the storage for the parachain validation code immediately.
#[pallet::weight(0)]
pub fn force_set_current_code(origin: OriginFor<T>, para: ParaId, new_code: ValidationCode) -> DispatchResult {
pub fn force_set_current_code(
origin: OriginFor<T>,
para: ParaId,
new_code: ValidationCode,
) -> DispatchResult {
ensure_root(origin)?;
let prior_code_hash = <Self as Store>::CurrentCodeHash::get(&para).unwrap_or_default();
let new_code_hash = new_code.hash();
@@ -466,7 +467,11 @@ pub mod pallet {
/// Set the storage for the current parachain head data immediately.
#[pallet::weight(0)]
pub fn force_set_current_head(origin: OriginFor<T>, para: ParaId, new_head: HeadData) -> DispatchResult {
pub fn force_set_current_head(
origin: OriginFor<T>,
para: ParaId,
new_head: HeadData,
) -> DispatchResult {
ensure_root(origin)?;
<Self as Store>::Heads::insert(&para, new_head);
Self::deposit_event(Event::CurrentHeadUpdated(para));
@@ -479,7 +484,7 @@ pub mod pallet {
origin: OriginFor<T>,
para: ParaId,
new_code: ValidationCode,
expected_at: T::BlockNumber
expected_at: T::BlockNumber,
) -> DispatchResult {
ensure_root(origin)?;
Self::schedule_code_upgrade(para, new_code, expected_at);
@@ -489,7 +494,11 @@ pub mod pallet {
/// Note a new block head for para within the context of the current block.
#[pallet::weight(0)]
pub fn force_note_new_head(origin: OriginFor<T>, para: ParaId, new_head: HeadData) -> DispatchResult {
pub fn force_note_new_head(
origin: OriginFor<T>,
para: ParaId,
new_head: HeadData,
) -> DispatchResult {
ensure_root(origin)?;
let now = frame_system::Pallet::<T>::block_number();
Self::note_new_head(para, new_head, now);
@@ -522,12 +531,14 @@ impl<T: Config> Pallet<T> {
}
/// Called by the initializer to finalize the configuration pallet.
pub(crate) fn initializer_finalize() { }
pub(crate) fn initializer_finalize() {}
/// Called by the initializer to note that a new session has started.
///
/// Returns the list of outgoing paras from the actions queue.
pub(crate) fn initializer_on_new_session(notification: &SessionChangeNotification<T::BlockNumber>) -> Vec<ParaId> {
pub(crate) fn initializer_on_new_session(
notification: &SessionChangeNotification<T::BlockNumber>,
) -> Vec<ParaId> {
let outgoing_paras = Self::apply_actions_queue(notification.session_index);
outgoing_paras
}
@@ -564,7 +575,8 @@ impl<T: Config> Pallet<T> {
for para in actions {
let lifecycle = ParaLifecycles::<T>::get(&para);
match lifecycle {
None | Some(ParaLifecycle::Parathread) | Some(ParaLifecycle::Parachain) => { /* Nothing to do... */ },
None | Some(ParaLifecycle::Parathread) | Some(ParaLifecycle::Parachain) => { /* Nothing to do... */
},
// Onboard a new parathread or parachain.
Some(ParaLifecycle::Onboarding) => {
if let Some(genesis_data) = <Self as Store>::UpcomingParasGenesis::take(&para) {
@@ -598,7 +610,8 @@ impl<T: Config> Pallet<T> {
ParaLifecycles::<T>::insert(&para, ParaLifecycle::Parathread);
},
// Offboard a parathread or parachain from the system
Some(ParaLifecycle::OffboardingParachain) | Some(ParaLifecycle::OffboardingParathread) => {
Some(ParaLifecycle::OffboardingParachain) |
Some(ParaLifecycle::OffboardingParathread) => {
if let Ok(i) = parachains.binary_search(&para) {
parachains.remove(i);
}
@@ -648,8 +661,8 @@ impl<T: Config> Pallet<T> {
// Schedule pruning for this past-code to be removed as soon as it
// exits the slashing window.
<Self as Store>::PastCodePruning::mutate(|pruning| {
let insert_idx = pruning.binary_search_by_key(&at, |&(_, b)| b)
.unwrap_or_else(|idx| idx);
let insert_idx =
pruning.binary_search_by_key(&at, |&(_, b)| b).unwrap_or_else(|idx| idx);
pruning.insert(insert_idx, (id, now));
});
@@ -663,19 +676,18 @@ impl<T: Config> Pallet<T> {
let code_retention_period = config.code_retention_period;
if now <= code_retention_period {
let weight = T::DbWeight::get().reads_writes(1, 0);
return weight;
return weight
}
// The height of any changes we no longer should keep around.
let pruning_height = now - (code_retention_period + One::one());
let pruning_tasks_done =
<Self as Store>::PastCodePruning::mutate(|pruning_tasks: &mut Vec<(_, T::BlockNumber)>| {
let pruning_tasks_done = <Self as Store>::PastCodePruning::mutate(
|pruning_tasks: &mut Vec<(_, T::BlockNumber)>| {
let (pruning_tasks_done, pruning_tasks_to_do) = {
// find all past code that has just exited the pruning window.
let up_to_idx = pruning_tasks.iter()
.take_while(|&(_, at)| at <= &pruning_height)
.count();
let up_to_idx =
pruning_tasks.iter().take_while(|&(_, at)| at <= &pruning_height).count();
(up_to_idx, pruning_tasks.drain(..up_to_idx))
};
@@ -707,7 +719,8 @@ impl<T: Config> Pallet<T> {
}
pruning_tasks_done as u64
});
},
);
// 1 read for the meta for each pruning task, 1 read for the config
// 2 writes: updating the meta and pruning the code
@@ -751,9 +764,7 @@ impl<T: Config> Pallet<T> {
let lifecycle = ParaLifecycles::<T>::get(&id);
match lifecycle {
// If para is not registered, nothing to do!
None => {
return Ok(())
},
None => return Ok(()),
Some(ParaLifecycle::Parathread) => {
ParaLifecycles::<T>::insert(&id, ParaLifecycle::OffboardingParathread);
},
@@ -864,12 +875,7 @@ impl<T: Config> Pallet<T> {
// `now` is only used for registering pruning as part of `fn note_past_code`
let now = <frame_system::Pallet<T>>::block_number();
let weight = Self::note_past_code(
id,
expected_at,
now,
prior_code_hash,
);
let weight = Self::note_past_code(id, expected_at, now, prior_code_hash);
// add 1 to writes due to heads update.
weight + T::DbWeight::get().reads_writes(3, 1 + 3)
@@ -897,7 +903,7 @@ impl<T: Config> Pallet<T> {
assume_intermediate: Option<T::BlockNumber>,
) -> Option<ValidationCodeHash> {
if assume_intermediate.as_ref().map_or(false, |i| &at <= i) {
return None;
return None
}
let planned_upgrade = <Self as Store>::FutureCodeUpgrades::get(&id);
@@ -912,7 +918,8 @@ impl<T: Config> Pallet<T> {
match Self::past_code_meta(&id).code_at(at) {
None => None,
Some(UseCodeAt::Current) => CurrentCodeHash::<T>::get(&id),
Some(UseCodeAt::ReplacedAt(replaced)) => <Self as Store>::PastCodeHash::get(&(id, replaced)),
Some(UseCodeAt::ReplacedAt(replaced)) =>
<Self as Store>::PastCodeHash::get(&(id, replaced)),
}
}
}
@@ -960,7 +967,7 @@ impl<T: Config> Pallet<T> {
pub(crate) fn last_code_upgrade(id: ParaId, include_future: bool) -> Option<T::BlockNumber> {
if include_future {
if let Some(at) = Self::future_code_upgrade_at(id) {
return Some(at);
return Some(at)
}
}
@@ -1013,11 +1020,13 @@ impl<T: Config> Pallet<T> {
#[cfg(test)]
mod tests {
use super::*;
use primitives::v1::BlockNumber;
use frame_support::assert_ok;
use primitives::v1::BlockNumber;
use crate::mock::{new_test_ext, Paras, ParasShared, System, MockGenesisConfig};
use crate::configuration::HostConfiguration;
use crate::{
configuration::HostConfiguration,
mock::{new_test_ext, MockGenesisConfig, Paras, ParasShared, System},
};
fn run_to_block(to: BlockNumber, new_session: Option<Vec<BlockNumber>>) {
while System::block_number() < to {
@@ -1045,7 +1054,10 @@ mod tests {
}
}
fn upgrade_at(expected_at: BlockNumber, activated_at: BlockNumber) -> ReplacementTimes<BlockNumber> {
fn upgrade_at(
expected_at: BlockNumber,
activated_at: BlockNumber,
) -> ReplacementTimes<BlockNumber> {
ReplacementTimes { expected_at, activated_at }
}
@@ -1103,7 +1115,6 @@ mod tests {
assert_eq!(past_code.code_at(24), Some(UseCodeAt::ReplacedAt(20)));
assert_eq!(past_code.code_at(25), Some(UseCodeAt::ReplacedAt(30)));
assert_eq!(past_code.code_at(30), Some(UseCodeAt::Current));
}
#[test]
@@ -1118,66 +1129,80 @@ mod tests {
assert_eq!(old, past_code);
assert_eq!(past_code.prune_up_to(10).collect::<Vec<_>>(), vec![10]);
assert_eq!(past_code, ParaPastCodeMeta {
upgrade_times: vec![upgrade_at(20, 25), upgrade_at(30, 35)],
last_pruned: Some(10),
});
assert_eq!(
past_code,
ParaPastCodeMeta {
upgrade_times: vec![upgrade_at(20, 25), upgrade_at(30, 35)],
last_pruned: Some(10),
}
);
assert!(past_code.prune_up_to(21).collect::<Vec<_>>().is_empty());
assert_eq!(past_code.prune_up_to(26).collect::<Vec<_>>(), vec![20]);
assert_eq!(past_code, ParaPastCodeMeta {
upgrade_times: vec![upgrade_at(30, 35)],
last_pruned: Some(25),
});
assert_eq!(
past_code,
ParaPastCodeMeta { upgrade_times: vec![upgrade_at(30, 35)], last_pruned: Some(25) }
);
past_code.note_replacement(40, 42);
past_code.note_replacement(50, 53);
past_code.note_replacement(60, 66);
assert_eq!(past_code, ParaPastCodeMeta {
upgrade_times: vec![upgrade_at(30, 35), upgrade_at(40, 42), upgrade_at(50, 53), upgrade_at(60, 66)],
last_pruned: Some(25),
});
assert_eq!(
past_code,
ParaPastCodeMeta {
upgrade_times: vec![
upgrade_at(30, 35),
upgrade_at(40, 42),
upgrade_at(50, 53),
upgrade_at(60, 66)
],
last_pruned: Some(25),
}
);
assert_eq!(past_code.prune_up_to(60).collect::<Vec<_>>(), vec![30, 40, 50]);
assert_eq!(past_code, ParaPastCodeMeta {
upgrade_times: vec![upgrade_at(60, 66)],
last_pruned: Some(53),
});
assert_eq!(
past_code,
ParaPastCodeMeta { upgrade_times: vec![upgrade_at(60, 66)], last_pruned: Some(53) }
);
assert_eq!(past_code.most_recent_change(), Some(60));
assert_eq!(past_code.prune_up_to(66).collect::<Vec<_>>(), vec![60]);
assert_eq!(past_code, ParaPastCodeMeta {
upgrade_times: Vec::new(),
last_pruned: Some(66),
});
assert_eq!(
past_code,
ParaPastCodeMeta { upgrade_times: Vec::new(), last_pruned: Some(66) }
);
}
#[test]
fn para_past_code_pruning_in_initialize() {
let code_retention_period = 10;
let paras = vec![
(0u32.into(), ParaGenesisArgs {
parachain: true,
genesis_head: Default::default(),
validation_code: Default::default(),
}),
(1u32.into(), ParaGenesisArgs {
parachain: false,
genesis_head: Default::default(),
validation_code: Default::default(),
}),
(
0u32.into(),
ParaGenesisArgs {
parachain: true,
genesis_head: Default::default(),
validation_code: Default::default(),
},
),
(
1u32.into(),
ParaGenesisArgs {
parachain: false,
genesis_head: Default::default(),
validation_code: Default::default(),
},
),
];
let genesis_config = MockGenesisConfig {
paras: GenesisConfig { paras, ..Default::default() },
configuration: crate::configuration::GenesisConfig {
config: HostConfiguration {
code_retention_period,
..Default::default()
},
config: HostConfiguration { code_retention_period, ..Default::default() },
..Default::default()
},
..Default::default()
@@ -1200,11 +1225,17 @@ mod tests {
}
let pruned_at: BlockNumber = included_block + code_retention_period + 1;
assert_eq!(<Paras as Store>::PastCodeHash::get(&(id, at_block)), Some(validation_code.hash()));
assert_eq!(
<Paras as Store>::PastCodeHash::get(&(id, at_block)),
Some(validation_code.hash())
);
check_code_is_stored(&validation_code);
run_to_block(pruned_at - 1, None);
assert_eq!(<Paras as Store>::PastCodeHash::get(&(id, at_block)), Some(validation_code.hash()));
assert_eq!(
<Paras as Store>::PastCodeHash::get(&(id, at_block)),
Some(validation_code.hash())
);
assert_eq!(Paras::past_code_meta(&id).most_recent_change(), Some(at_block));
check_code_is_stored(&validation_code);
@@ -1218,21 +1249,19 @@ mod tests {
#[test]
fn note_new_head_sets_head() {
let code_retention_period = 10;
let paras = vec![
(0u32.into(), ParaGenesisArgs {
let paras = vec![(
0u32.into(),
ParaGenesisArgs {
parachain: true,
genesis_head: Default::default(),
validation_code: Default::default(),
}),
];
},
)];
let genesis_config = MockGenesisConfig {
paras: GenesisConfig { paras, ..Default::default() },
configuration: crate::configuration::GenesisConfig {
config: HostConfiguration {
code_retention_period,
..Default::default()
},
config: HostConfiguration { code_retention_period, ..Default::default() },
..Default::default()
},
..Default::default()
@@ -1253,25 +1282,28 @@ mod tests {
fn note_past_code_sets_up_pruning_correctly() {
let code_retention_period = 10;
let paras = vec![
(0u32.into(), ParaGenesisArgs {
parachain: true,
genesis_head: Default::default(),
validation_code: Default::default(),
}),
(1u32.into(), ParaGenesisArgs {
parachain: false,
genesis_head: Default::default(),
validation_code: Default::default(),
}),
(
0u32.into(),
ParaGenesisArgs {
parachain: true,
genesis_head: Default::default(),
validation_code: Default::default(),
},
),
(
1u32.into(),
ParaGenesisArgs {
parachain: false,
genesis_head: Default::default(),
validation_code: Default::default(),
},
),
];
let genesis_config = MockGenesisConfig {
paras: GenesisConfig { paras, ..Default::default() },
configuration: crate::configuration::GenesisConfig {
config: HostConfiguration {
code_retention_period,
..Default::default()
},
config: HostConfiguration { code_retention_period, ..Default::default() },
..Default::default()
},
..Default::default()
@@ -1287,17 +1319,11 @@ mod tests {
assert_eq!(<Paras as Store>::PastCodePruning::get(), vec![(id_a, 12), (id_b, 23)]);
assert_eq!(
Paras::past_code_meta(&id_a),
ParaPastCodeMeta {
upgrade_times: vec![upgrade_at(10, 12)],
last_pruned: None,
}
ParaPastCodeMeta { upgrade_times: vec![upgrade_at(10, 12)], last_pruned: None }
);
assert_eq!(
Paras::past_code_meta(&id_b),
ParaPastCodeMeta {
upgrade_times: vec![upgrade_at(20, 23)],
last_pruned: None,
}
ParaPastCodeMeta { upgrade_times: vec![upgrade_at(20, 23)], last_pruned: None }
);
});
}
@@ -1308,13 +1334,14 @@ mod tests {
let validation_upgrade_delay = 5;
let original_code = ValidationCode(vec![1, 2, 3]);
let paras = vec![
(0u32.into(), ParaGenesisArgs {
let paras = vec![(
0u32.into(),
ParaGenesisArgs {
parachain: true,
genesis_head: Default::default(),
validation_code: original_code.clone(),
}),
];
},
)];
let genesis_config = MockGenesisConfig {
paras: GenesisConfig { paras, ..Default::default() },
@@ -1376,10 +1403,7 @@ mod tests {
{
Paras::note_new_head(para_id, Default::default(), expected_at);
assert_eq!(
Paras::past_code_meta(&para_id).most_recent_change(),
Some(expected_at),
);
assert_eq!(Paras::past_code_meta(&para_id).most_recent_change(), Some(expected_at),);
assert_eq!(
<Paras as Store>::PastCodeHash::get(&(para_id, expected_at)),
Some(original_code.hash()),
@@ -1399,13 +1423,14 @@ mod tests {
let validation_upgrade_delay = 5;
let original_code = ValidationCode(vec![1, 2, 3]);
let paras = vec![
(0u32.into(), ParaGenesisArgs {
let paras = vec![(
0u32.into(),
ParaGenesisArgs {
parachain: true,
genesis_head: Default::default(),
validation_code: original_code.clone(),
}),
];
},
)];
let genesis_config = MockGenesisConfig {
paras: GenesisConfig { paras, ..Default::default() },
@@ -1448,10 +1473,7 @@ mod tests {
{
Paras::note_new_head(para_id, Default::default(), expected_at + 4);
assert_eq!(
Paras::past_code_meta(&para_id).most_recent_change(),
Some(expected_at),
);
assert_eq!(Paras::past_code_meta(&para_id).most_recent_change(), Some(expected_at),);
// Some hypothetical block which would have triggered the code change
// should still use the old code.
@@ -1489,21 +1511,19 @@ mod tests {
fn submit_code_change_when_not_allowed_is_err() {
let code_retention_period = 10;
let paras = vec![
(0u32.into(), ParaGenesisArgs {
let paras = vec![(
0u32.into(),
ParaGenesisArgs {
parachain: true,
genesis_head: Default::default(),
validation_code: vec![1, 2, 3].into(),
}),
];
},
)];
let genesis_config = MockGenesisConfig {
paras: GenesisConfig { paras, ..Default::default() },
configuration: crate::configuration::GenesisConfig {
config: HostConfiguration {
code_retention_period,
..Default::default()
},
config: HostConfiguration { code_retention_period, ..Default::default() },
..Default::default()
},
..Default::default()
@@ -1533,21 +1553,19 @@ mod tests {
let code_retention_period = 10;
let original_code = ValidationCode(vec![1, 2, 3]);
let paras = vec![
(0u32.into(), ParaGenesisArgs {
let paras = vec![(
0u32.into(),
ParaGenesisArgs {
parachain: true,
genesis_head: Default::default(),
validation_code: original_code.clone(),
}),
];
},
)];
let genesis_config = MockGenesisConfig {
paras: GenesisConfig { paras, ..Default::default() },
configuration: crate::configuration::GenesisConfig {
config: HostConfiguration {
code_retention_period,
..Default::default()
},
config: HostConfiguration { code_retention_period, ..Default::default() },
..Default::default()
},
..Default::default()
@@ -1600,12 +1618,15 @@ mod tests {
}
// run to block #4, with a 2 session changes at the end of the block 2 & 3.
run_to_block(4, Some(vec![3,4]));
run_to_block(4, Some(vec![3, 4]));
// cleaning up the parachain should place the current parachain code
// into the past code buffer & schedule cleanup.
assert_eq!(Paras::past_code_meta(&para_id).most_recent_change(), Some(3));
assert_eq!(<Paras as Store>::PastCodeHash::get(&(para_id, 3)), Some(original_code.hash()));
assert_eq!(
<Paras as Store>::PastCodeHash::get(&(para_id, 3)),
Some(original_code.hash())
);
assert_eq!(<Paras as Store>::PastCodePruning::get(), vec![(para_id, 3)]);
check_code_is_stored(&original_code);
@@ -1688,9 +1709,8 @@ mod tests {
assert_eq!(<Paras as Store>::ParaLifecycles::get(&b), Some(ParaLifecycle::Onboarding));
assert_eq!(<Paras as Store>::ParaLifecycles::get(&c), Some(ParaLifecycle::Onboarding));
// Two sessions pass, so action queue is triggered
run_to_block(4, Some(vec![3,4]));
run_to_block(4, Some(vec![3, 4]));
assert_eq!(Paras::parachains(), vec![c, b]);
assert_eq!(<Paras as Store>::ActionsQueue::get(Paras::scheduled_session()), Vec::new());
@@ -1710,21 +1730,19 @@ mod tests {
fn code_hash_at_with_intermediate() {
let code_retention_period = 10;
let paras = vec![
(0u32.into(), ParaGenesisArgs {
let paras = vec![(
0u32.into(),
ParaGenesisArgs {
parachain: true,
genesis_head: Default::default(),
validation_code: vec![1, 2, 3].into(),
}),
];
},
)];
let genesis_config = MockGenesisConfig {
paras: GenesisConfig { paras, ..Default::default() },
configuration: crate::configuration::GenesisConfig {
config: HostConfiguration {
code_retention_period,
..Default::default()
},
config: HostConfiguration { code_retention_period, ..Default::default() },
..Default::default()
},
..Default::default()
@@ -1762,21 +1780,19 @@ mod tests {
fn code_hash_at_returns_up_to_end_of_code_retention_period() {
let code_retention_period = 10;
let paras = vec![
(0u32.into(), ParaGenesisArgs {
let paras = vec![(
0u32.into(),
ParaGenesisArgs {
parachain: true,
genesis_head: Default::default(),
validation_code: vec![1, 2, 3].into(),
}),
];
},
)];
let genesis_config = MockGenesisConfig {
paras: GenesisConfig { paras, ..Default::default() },
configuration: crate::configuration::GenesisConfig {
config: HostConfiguration {
code_retention_period,
..Default::default()
},
config: HostConfiguration { code_retention_period, ..Default::default() },
..Default::default()
},
..Default::default()
@@ -1791,10 +1807,7 @@ mod tests {
run_to_block(10, None);
Paras::note_new_head(para_id, Default::default(), 7);
assert_eq!(
Paras::past_code_meta(&para_id).upgrade_times,
vec![upgrade_at(2, 10)],
);
assert_eq!(Paras::past_code_meta(&para_id).upgrade_times, vec![upgrade_at(2, 10)],);
assert_eq!(fetch_validation_code_at(para_id, 2, None), Some(old_code.clone()));
assert_eq!(fetch_validation_code_at(para_id, 3, None), Some(old_code.clone()));
@@ -1814,10 +1827,7 @@ mod tests {
assert_eq!(
Paras::past_code_meta(&para_id),
ParaPastCodeMeta {
upgrade_times: Vec::new(),
last_pruned: Some(10),
},
ParaPastCodeMeta { upgrade_times: Vec::new(), last_pruned: Some(10) },
);
assert_eq!(fetch_validation_code_at(para_id, 2, None), None); // pruned :(
@@ -21,26 +21,26 @@
//! as it has no initialization logic and its finalization logic depends only on the details of
//! this module.
use sp_std::prelude::*;
use sp_runtime::traits::Header as HeaderT;
use primitives::v1::{
BackedCandidate, PARACHAINS_INHERENT_IDENTIFIER, InherentData as ParachainsInherentData,
};
use frame_support::{
decl_error, decl_module, decl_storage, ensure,
dispatch::DispatchResultWithPostInfo,
weights::{DispatchClass, Weight},
traits::Get,
inherent::{InherentIdentifier, InherentData, MakeFatalError, ProvideInherent},
};
use frame_system::ensure_none;
use crate::{
disputes::DisputesHandler,
inclusion,
scheduler::{self, FreedReason},
shared,
ump,
shared, ump,
};
use frame_support::{
decl_error, decl_module, decl_storage,
dispatch::DispatchResultWithPostInfo,
ensure,
inherent::{InherentData, InherentIdentifier, MakeFatalError, ProvideInherent},
traits::Get,
weights::{DispatchClass, Weight},
};
use frame_system::ensure_none;
use primitives::v1::{
BackedCandidate, InherentData as ParachainsInherentData, PARACHAINS_INHERENT_IDENTIFIER,
};
use sp_runtime::traits::Header as HeaderT;
use sp_std::prelude::*;
const LOG_TARGET: &str = "runtime::inclusion-inherent";
// In the future, we should benchmark these consts; these are all untested assumptions for now.
@@ -249,7 +249,7 @@ fn limit_backed_candidates<T: Config>(
return false
}
code_upgrades +=1;
code_upgrades += 1;
}
true
@@ -258,7 +258,9 @@ fn limit_backed_candidates<T: Config>(
// the weight of the paras inherent is already included in the current block weight,
// so our operation is simple: if the block is currently overloaded, make this intrinsic smaller
if frame_system::Pallet::<T>::block_weight().total() > <T as frame_system::Config>::BlockWeights::get().max_block {
if frame_system::Pallet::<T>::block_weight().total() >
<T as frame_system::Config>::BlockWeights::get().max_block
{
Vec::new()
} else {
backed_candidates
@@ -271,47 +273,41 @@ impl<T: Config> ProvideInherent for Module<T> {
const INHERENT_IDENTIFIER: InherentIdentifier = PARACHAINS_INHERENT_IDENTIFIER;
fn create_inherent(data: &InherentData) -> Option<Self::Call> {
let mut inherent_data: ParachainsInherentData<T::Header>
= match data.get_data(&Self::INHERENT_IDENTIFIER)
{
Ok(Some(d)) => d,
Ok(None) => return None,
Err(_) => {
log::warn!(
target: LOG_TARGET,
"ParachainsInherentData failed to decode",
);
let mut inherent_data: ParachainsInherentData<T::Header> =
match data.get_data(&Self::INHERENT_IDENTIFIER) {
Ok(Some(d)) => d,
Ok(None) => return None,
Err(_) => {
log::warn!(target: LOG_TARGET, "ParachainsInherentData failed to decode",);
return None;
}
};
return None
},
};
// filter out any unneeded dispute statements
T::DisputesHandler::filter_multi_dispute_data(&mut inherent_data.disputes);
// Sanity check: session changes can invalidate an inherent, and we _really_ don't want that to happen.
// See github.com/paritytech/polkadot/issues/1327
let inherent_data = match Self::enter(
frame_system::RawOrigin::None.into(),
inherent_data.clone(),
) {
Ok(_) => inherent_data,
Err(err) => {
log::warn!(
target: LOG_TARGET,
"dropping signed_bitfields and backed_candidates because they produced \
let inherent_data =
match Self::enter(frame_system::RawOrigin::None.into(), inherent_data.clone()) {
Ok(_) => inherent_data,
Err(err) => {
log::warn!(
target: LOG_TARGET,
"dropping signed_bitfields and backed_candidates because they produced \
an invalid paras inherent: {:?}",
err,
);
err,
);
ParachainsInherentData {
bitfields: Vec::new(),
backed_candidates: Vec::new(),
disputes: Vec::new(),
parent_header: inherent_data.parent_header,
}
}
};
ParachainsInherentData {
bitfields: Vec::new(),
backed_candidates: Vec::new(),
disputes: Vec::new(),
parent_header: inherent_data.parent_header,
}
},
};
Some(Call::enter(inherent_data))
}
@@ -325,9 +321,7 @@ impl<T: Config> ProvideInherent for Module<T> {
mod tests {
use super::*;
use crate::mock::{
new_test_ext, System, MockGenesisConfig, Test
};
use crate::mock::{new_test_ext, MockGenesisConfig, System, Test};
mod limit_backed_candidates {
use super::*;
@@ -345,7 +339,8 @@ mod tests {
fn does_not_truncate_on_exactly_full_block() {
new_test_ext(MockGenesisConfig::default()).execute_with(|| {
let backed_candidates = vec![BackedCandidate::default()];
let max_block_weight = <Test as frame_system::Config>::BlockWeights::get().max_block;
let max_block_weight =
<Test as frame_system::Config>::BlockWeights::get().max_block;
// if the consumed resources are precisely equal to the max block weight, we do not truncate.
System::set_block_consumed_resources(max_block_weight, 0);
assert_eq!(limit_backed_candidates::<Test>(backed_candidates).len(), 1);
@@ -356,7 +351,8 @@ mod tests {
fn truncates_on_over_full_block() {
new_test_ext(MockGenesisConfig::default()).execute_with(|| {
let backed_candidates = vec![BackedCandidate::default()];
let max_block_weight = <Test as frame_system::Config>::BlockWeights::get().max_block;
let max_block_weight =
<Test as frame_system::Config>::BlockWeights::get().max_block;
// if the consumed resources are precisely equal to the max block weight, we do not truncate.
System::set_block_consumed_resources(max_block_weight + 1, 0);
assert_eq!(limit_backed_candidates::<Test>(backed_candidates).len(), 0);
@@ -367,7 +363,8 @@ mod tests {
fn all_backed_candidates_get_truncated() {
new_test_ext(MockGenesisConfig::default()).execute_with(|| {
let backed_candidates = vec![BackedCandidate::default(); 10];
let max_block_weight = <Test as frame_system::Config>::BlockWeights::get().max_block;
let max_block_weight =
<Test as frame_system::Config>::BlockWeights::get().max_block;
// if the consumed resources are precisely equal to the max block weight, we do not truncate.
System::set_block_consumed_resources(max_block_weight + 1, 0);
assert_eq!(limit_backed_candidates::<Test>(backed_candidates).len(), 0);
@@ -388,9 +385,7 @@ mod tests {
mod paras_inherent_weight {
use super::*;
use crate::mock::{
new_test_ext, System, MockGenesisConfig, Test
};
use crate::mock::{new_test_ext, MockGenesisConfig, System, Test};
use primitives::v1::Header;
use frame_support::traits::UnfilteredDispatchable;
@@ -425,7 +420,8 @@ mod tests {
(backed_candidates.len() as Weight * BACKED_CANDIDATE_WEIGHT);
// we've used half the block weight; there's plenty of margin
let max_block_weight = <Test as frame_system::Config>::BlockWeights::get().max_block;
let max_block_weight =
<Test as frame_system::Config>::BlockWeights::get().max_block;
let used_block_weight = max_block_weight / 2;
System::set_block_consumed_resources(used_block_weight, 0);
@@ -436,7 +432,9 @@ mod tests {
disputes: Vec::new(),
parent_header: default_header(),
})
.dispatch_bypass_filter(None.into()).unwrap_err().post_info;
.dispatch_bypass_filter(None.into())
.unwrap_err()
.post_info;
// we don't directly check the block's weight post-call. Instead, we check that the
// call has returned the appropriate post-dispatch weight for refund, and trust
@@ -470,7 +468,8 @@ mod tests {
let expected_weight = MINIMAL_INCLUSION_INHERENT_WEIGHT;
// oops, looks like this mandatory call pushed the block weight over the limit
let max_block_weight = <Test as frame_system::Config>::BlockWeights::get().max_block;
let max_block_weight =
<Test as frame_system::Config>::BlockWeights::get().max_block;
let used_block_weight = max_block_weight + 1;
System::set_block_consumed_resources(used_block_weight, 0);
@@ -481,15 +480,13 @@ mod tests {
disputes: Vec::new(),
parent_header: header,
})
.dispatch_bypass_filter(None.into()).unwrap();
.dispatch_bypass_filter(None.into())
.unwrap();
// we don't directly check the block's weight post-call. Instead, we check that the
// call has returned the appropriate post-dispatch weight for refund, and trust
// Substrate to do the right thing with that information.
assert_eq!(
post_info.actual_weight.unwrap(),
expected_weight,
);
assert_eq!(post_info.actual_weight.unwrap(), expected_weight,);
});
}
}
@@ -21,9 +21,9 @@
//! which doesn't currently mention availability bitfields. As such, we don't reward them
//! for the time being, although we will build schemes to do so in the future.
use primitives::v1::ValidatorIndex;
use pallet_staking::SessionInterface;
use crate::shared;
use pallet_staking::SessionInterface;
use primitives::v1::ValidatorIndex;
/// The amount of era points given by backing a candidate that is included.
pub const BACKING_POINTS: u32 = 20;
@@ -31,21 +31,27 @@ pub const BACKING_POINTS: u32 = 20;
/// Rewards validators for participating in parachains with era points in pallet-staking.
pub struct RewardValidatorsWithEraPoints<C>(sp_std::marker::PhantomData<C>);
fn validators_to_reward<C, T, I>(validators: &'_ [T], indirect_indices: I) -> impl IntoIterator<Item=&'_ T> where
fn validators_to_reward<C, T, I>(
validators: &'_ [T],
indirect_indices: I,
) -> impl IntoIterator<Item = &'_ T>
where
C: shared::Config,
I: IntoIterator<Item = ValidatorIndex>
I: IntoIterator<Item = ValidatorIndex>,
{
let validator_indirection = <shared::Pallet<C>>::active_validator_indices();
indirect_indices.into_iter()
indirect_indices
.into_iter()
.filter_map(move |i| validator_indirection.get(i.0 as usize).map(|v| v.clone()))
.filter_map(move |i| validators.get(i.0 as usize))
}
impl<C> crate::inclusion::RewardValidators for RewardValidatorsWithEraPoints<C>
where C: pallet_staking::Config + shared::Config,
where
C: pallet_staking::Config + shared::Config,
{
fn reward_backing(indirect_indices: impl IntoIterator<Item=ValidatorIndex>) {
fn reward_backing(indirect_indices: impl IntoIterator<Item = ValidatorIndex>) {
// Fetch the validators from the _session_ because sessions are offset from eras
// and we are rewarding for behavior in current session.
let validators = C::SessionInterface::validators();
@@ -57,16 +63,18 @@ impl<C> crate::inclusion::RewardValidators for RewardValidatorsWithEraPoints<C>
<pallet_staking::Pallet<C>>::reward_by_ids(rewards);
}
fn reward_bitfields(_validators: impl IntoIterator<Item=ValidatorIndex>) { }
fn reward_bitfields(_validators: impl IntoIterator<Item = ValidatorIndex>) {}
}
#[cfg(test)]
mod tests {
use super::*;
use primitives::v1::ValidatorId;
use crate::configuration::HostConfiguration;
use crate::mock::{new_test_ext, MockGenesisConfig, ParasShared, Test};
use crate::{
configuration::HostConfiguration,
mock::{new_test_ext, MockGenesisConfig, ParasShared, Test},
};
use keyring::Sr25519Keyring;
use primitives::v1::ValidatorId;
#[test]
fn rewards_based_on_indirection() {
@@ -88,12 +96,8 @@ mod tests {
let pubkeys = validator_pubkeys(&validators);
let shuffled_pubkeys = ParasShared::initializer_on_new_session(
1,
[1; 32],
&config,
pubkeys,
);
let shuffled_pubkeys =
ParasShared::initializer_on_new_session(1, [1; 32], &config, pubkeys);
assert_eq!(
shuffled_pubkeys,
@@ -121,7 +125,10 @@ mod tests {
validators_to_reward::<Test, _, _>(
&validators,
vec![ValidatorIndex(0), ValidatorIndex(1), ValidatorIndex(2)],
).into_iter().copied().collect::<Vec<_>>(),
)
.into_iter()
.copied()
.collect::<Vec<_>>(),
vec![Sr25519Keyring::Ferdie, Sr25519Keyring::Bob, Sr25519Keyring::Charlie],
);
})
@@ -17,9 +17,9 @@
//! Runtimes implementing the v1 runtime API are recommended to forward directly to these
//! functions.
use sp_std::prelude::*;
use sp_std::collections::btree_map::BTreeMap;
use sp_runtime::traits::One;
use crate::{
configuration, dmp, hrmp, inclusion, initializer, paras, scheduler, session_info, shared,
};
use primitives::v1::{
AuthorityDiscoveryId, CandidateEvent, CommittedCandidateReceipt, CoreIndex, CoreOccupied,
CoreState, GroupIndex, GroupRotationInfo, Id as ParaId, InboundDownwardMessage,
@@ -27,8 +27,8 @@ use primitives::v1::{
ScheduledCore, SessionIndex, SessionInfo, ValidationCode, ValidationCodeHash, ValidatorId,
ValidatorIndex,
};
use crate::{initializer, inclusion, scheduler, configuration, paras, session_info, dmp, hrmp, shared};
use sp_runtime::traits::One;
use sp_std::{collections::btree_map::BTreeMap, prelude::*};
/// Implementation for the `validators` function of the runtime API.
pub fn validators<T: initializer::Config>() -> Vec<ValidatorId> {
@@ -36,10 +36,8 @@ pub fn validators<T: initializer::Config>() -> Vec<ValidatorId> {
}
/// Implementation for the `validator_groups` function of the runtime API.
pub fn validator_groups<T: initializer::Config>() -> (
Vec<Vec<ValidatorIndex>>,
GroupRotationInfo<T::BlockNumber>,
) {
pub fn validator_groups<T: initializer::Config>(
) -> (Vec<Vec<ValidatorIndex>>, GroupRotationInfo<T::BlockNumber>) {
let now = <frame_system::Pallet<T>>::block_number() + One::one();
let groups = <scheduler::Pallet<T>>::validator_groups();
@@ -80,10 +78,13 @@ pub fn availability_cores<T: initializer::Config>() -> Vec<CoreState<T::Hash, T:
}
};
let group_responsible_for = |backed_in_number, core_index| {
match <scheduler::Pallet<T>>::group_assigned_to_core(core_index, backed_in_number) {
let group_responsible_for =
|backed_in_number, core_index| match <scheduler::Pallet<T>>::group_assigned_to_core(
core_index,
backed_in_number,
) {
Some(g) => g,
None => {
None => {
log::warn!(
target: "runtime::polkadot-api::v1",
"Could not determine the group responsible for core extracted \
@@ -91,23 +92,24 @@ pub fn availability_cores<T: initializer::Config>() -> Vec<CoreState<T::Hash, T:
);
GroupIndex(0)
}
}
};
},
};
let mut core_states: Vec<_> = cores.into_iter().enumerate().map(|(i, core)| match core {
Some(occupied) => {
CoreState::Occupied(match occupied {
let mut core_states: Vec<_> = cores
.into_iter()
.enumerate()
.map(|(i, core)| match core {
Some(occupied) => CoreState::Occupied(match occupied {
CoreOccupied::Parachain => {
let para_id = parachains[i];
let pending_availability = <inclusion::Pallet<T>>
::pending_availability(para_id)
.expect("Occupied core always has pending availability; qed");
let pending_availability =
<inclusion::Pallet<T>>::pending_availability(para_id)
.expect("Occupied core always has pending availability; qed");
let backed_in_number = pending_availability.backed_in_number().clone();
OccupiedCore {
next_up_on_available: <scheduler::Pallet<T>>::next_up_on_available(
CoreIndex(i as u32)
CoreIndex(i as u32),
),
occupied_since: backed_in_number,
time_out_at: time_out_at(
@@ -115,7 +117,7 @@ pub fn availability_cores<T: initializer::Config>() -> Vec<CoreState<T::Hash, T:
config.chain_availability_period,
),
next_up_on_time_out: <scheduler::Pallet<T>>::next_up_on_time_out(
CoreIndex(i as u32)
CoreIndex(i as u32),
),
availability: pending_availability.availability_votes().clone(),
group_responsible: group_responsible_for(
@@ -125,17 +127,17 @@ pub fn availability_cores<T: initializer::Config>() -> Vec<CoreState<T::Hash, T:
candidate_hash: pending_availability.candidate_hash(),
candidate_descriptor: pending_availability.candidate_descriptor().clone(),
}
}
},
CoreOccupied::Parathread(p) => {
let para_id = p.claim.0;
let pending_availability = <inclusion::Pallet<T>>
::pending_availability(para_id)
.expect("Occupied core always has pending availability; qed");
let pending_availability =
<inclusion::Pallet<T>>::pending_availability(para_id)
.expect("Occupied core always has pending availability; qed");
let backed_in_number = pending_availability.backed_in_number().clone();
OccupiedCore {
next_up_on_available: <scheduler::Pallet<T>>::next_up_on_available(
CoreIndex(i as u32)
CoreIndex(i as u32),
),
occupied_since: backed_in_number,
time_out_at: time_out_at(
@@ -143,7 +145,7 @@ pub fn availability_cores<T: initializer::Config>() -> Vec<CoreState<T::Hash, T:
config.thread_availability_period,
),
next_up_on_time_out: <scheduler::Pallet<T>>::next_up_on_time_out(
CoreIndex(i as u32)
CoreIndex(i as u32),
),
availability: pending_availability.availability_votes().clone(),
group_responsible: group_responsible_for(
@@ -153,11 +155,11 @@ pub fn availability_cores<T: initializer::Config>() -> Vec<CoreState<T::Hash, T:
candidate_hash: pending_availability.candidate_hash(),
candidate_descriptor: pending_availability.candidate_descriptor().clone(),
}
}
})
}
None => CoreState::Free,
}).collect();
},
}),
None => CoreState::Free,
})
.collect();
// This will overwrite only `Free` cores if the scheduler module is working as intended.
for scheduled in <scheduler::Pallet<T>>::scheduled() {
@@ -174,7 +176,8 @@ fn with_assumption<Config, T, F>(
para_id: ParaId,
assumption: OccupiedCoreAssumption,
build: F,
) -> Option<T> where
) -> Option<T>
where
Config: inclusion::Config,
F: FnOnce() -> Option<T>,
{
@@ -182,17 +185,15 @@ fn with_assumption<Config, T, F>(
OccupiedCoreAssumption::Included => {
<inclusion::Pallet<Config>>::force_enact(para_id);
build()
}
OccupiedCoreAssumption::TimedOut => {
build()
}
},
OccupiedCoreAssumption::TimedOut => build(),
OccupiedCoreAssumption::Free => {
if <inclusion::Pallet<Config>>::pending_availability(para_id).is_some() {
None
} else {
build()
}
}
},
}
}
@@ -237,7 +238,8 @@ pub fn session_index_for_child<T: initializer::Config>() -> SessionIndex {
/// Implementation for the `AuthorityDiscoveryApi::authorities()` function of the runtime API.
/// It is a heavy call, but currently only used for authority discovery, so it is fine.
/// Gets next, current and some historical authority ids using `session_info` module.
pub fn relevant_authority_ids<T: initializer::Config + pallet_authority_discovery::Config>() -> Vec<AuthorityDiscoveryId> {
pub fn relevant_authority_ids<T: initializer::Config + pallet_authority_discovery::Config>(
) -> Vec<AuthorityDiscoveryId> {
let current_session_index = session_index_for_child::<T>();
let earliest_stored_session = <session_info::Pallet<T>>::earliest_stored_session();
@@ -267,17 +269,13 @@ pub fn validation_code<T: initializer::Config>(
para_id: ParaId,
assumption: OccupiedCoreAssumption,
) -> Option<ValidationCode> {
with_assumption::<T, _, _>(
para_id,
assumption,
|| <paras::Pallet<T>>::current_code(&para_id),
)
with_assumption::<T, _, _>(para_id, assumption, || <paras::Pallet<T>>::current_code(&para_id))
}
/// Implementation for the `candidate_pending_availability` function of the runtime API.
pub fn candidate_pending_availability<T: initializer::Config>(para_id: ParaId)
-> Option<CommittedCandidateReceipt<T::Hash>>
{
pub fn candidate_pending_availability<T: initializer::Config>(
para_id: ParaId,
) -> Option<CommittedCandidateReceipt<T::Hash>> {
<inclusion::Pallet<T>>::candidate_pending_availability(para_id)
}
@@ -291,17 +289,17 @@ where
{
use inclusion::Event as RawEvent;
<frame_system::Pallet<T>>::events().into_iter()
<frame_system::Pallet<T>>::events()
.into_iter()
.filter_map(|record| extract_event(record.event))
.map(|event| match event {
RawEvent::<T>::CandidateBacked(c, h, core, group)
=> CandidateEvent::CandidateBacked(c, h, core, group),
RawEvent::<T>::CandidateIncluded(c, h, core, group)
=> CandidateEvent::CandidateIncluded(c, h, core, group),
RawEvent::<T>::CandidateTimedOut(c, h, core)
=> CandidateEvent::CandidateTimedOut(c, h, core),
RawEvent::<T>::__Ignore(_, _)
=> unreachable!("__Ignore cannot be used"),
RawEvent::<T>::CandidateBacked(c, h, core, group) =>
CandidateEvent::CandidateBacked(c, h, core, group),
RawEvent::<T>::CandidateIncluded(c, h, core, group) =>
CandidateEvent::CandidateIncluded(c, h, core, group),
RawEvent::<T>::CandidateTimedOut(c, h, core) =>
CandidateEvent::CandidateTimedOut(c, h, core),
RawEvent::<T>::__Ignore(_, _) => unreachable!("__Ignore cannot be used"),
})
.collect()
}
File diff suppressed because it is too large Load Diff
+30 -39
View File
@@ -19,11 +19,9 @@
//!
//! See https://w3f.github.io/parachain-implementers-guide/runtime/session_info.html.
use crate::{configuration, paras, scheduler, shared, util::take_active_subset};
use frame_support::{pallet_prelude::*, traits::OneSessionHandler};
use primitives::v1::{AssignmentId, AuthorityDiscoveryId, SessionIndex, SessionInfo};
use frame_support::pallet_prelude::*;
use frame_support::traits::OneSessionHandler;
use crate::{configuration, paras, scheduler, shared};
use crate::util::take_active_subset;
use sp_std::vec::Vec;
pub use pallet::*;
@@ -51,7 +49,8 @@ pub mod pallet {
/// Note that this API is private due to it being prone to 'off-by-one' at session boundaries.
/// When in doubt, use `Sessions` API instead.
#[pallet::storage]
pub(super) type AssignmentKeysUnsafe<T: Config> = StorageValue<_, Vec<AssignmentId>, ValueQuery>;
pub(super) type AssignmentKeysUnsafe<T: Config> =
StorageValue<_, Vec<AssignmentId>, ValueQuery>;
/// The earliest session for which previous session info is stored.
#[pallet::storage]
@@ -82,7 +81,7 @@ impl<T: pallet_authority_discovery::Config> AuthorityDiscoveryConfig for T {
impl<T: Config> Pallet<T> {
/// Handle an incoming session change.
pub(crate) fn initializer_on_new_session(
notification: &crate::initializer::SessionChangeNotification<T::BlockNumber>
notification: &crate::initializer::SessionChangeNotification<T::BlockNumber>,
) {
let config = <configuration::Pallet<T>>::config();
@@ -104,7 +103,8 @@ impl<T: Config> Pallet<T> {
let new_session_index = notification.session_index;
let old_earliest_stored_session = EarliestStoredSession::<T>::get();
let new_earliest_stored_session = new_session_index.saturating_sub(dispute_period);
let new_earliest_stored_session = core::cmp::max(new_earliest_stored_session, old_earliest_stored_session);
let new_earliest_stored_session =
core::cmp::max(new_earliest_stored_session, old_earliest_stored_session);
// remove all entries from `Sessions` from the previous value up to the new value
// avoid a potentially heavy loop when introduced on a live chain
if old_earliest_stored_session != 0 || Sessions::<T>::get(0).is_some() {
@@ -150,33 +150,35 @@ impl<T: pallet_session::Config + Config> OneSessionHandler<T::AccountId> for Pal
type Key = AssignmentId;
fn on_genesis_session<'a, I: 'a>(_validators: I)
where I: Iterator<Item=(&'a T::AccountId, Self::Key)>
where
I: Iterator<Item = (&'a T::AccountId, Self::Key)>,
{
}
fn on_new_session<'a, I: 'a>(_changed: bool, validators: I, _queued: I)
where I: Iterator<Item=(&'a T::AccountId, Self::Key)>
where
I: Iterator<Item = (&'a T::AccountId, Self::Key)>,
{
let assignment_keys: Vec<_> = validators.map(|(_, v)| v).collect();
AssignmentKeysUnsafe::<T>::set(assignment_keys);
}
fn on_disabled(_i: usize) { }
fn on_disabled(_i: usize) {}
}
#[cfg(test)]
mod tests {
use super::*;
use crate::mock::{
new_test_ext, Configuration, SessionInfo, System, MockGenesisConfig,
Origin, ParasShared, Test
use crate::{
configuration::HostConfiguration,
initializer::SessionChangeNotification,
mock::{
new_test_ext, Configuration, MockGenesisConfig, Origin, ParasShared, SessionInfo,
System, Test,
},
};
use crate::initializer::SessionChangeNotification;
use crate::configuration::HostConfiguration;
use primitives::v1::{BlockNumber, ValidatorId, ValidatorIndex};
use keyring::Sr25519Keyring;
use primitives::v1::{BlockNumber, ValidatorId, ValidatorIndex};
fn run_to_block(
to: BlockNumber,
@@ -190,9 +192,7 @@ mod tests {
Configuration::initializer_finalize();
if let Some(notification) = new_session(b + 1) {
Configuration::initializer_on_new_session(
&notification.session_index,
);
Configuration::initializer_on_new_session(&notification.session_index);
ParasShared::initializer_on_new_session(
notification.session_index,
notification.random_seed,
@@ -234,20 +234,14 @@ mod tests {
fn session_changes(n: BlockNumber) -> Option<SessionChangeNotification<BlockNumber>> {
if n % 10 == 0 {
Some(SessionChangeNotification {
session_index: n / 10,
..Default::default()
})
Some(SessionChangeNotification { session_index: n / 10, ..Default::default() })
} else {
None
}
}
fn new_session_every_block(n: BlockNumber) -> Option<SessionChangeNotification<BlockNumber>> {
Some(SessionChangeNotification{
session_index: n,
..Default::default()
})
Some(SessionChangeNotification { session_index: n, ..Default::default() })
}
#[test]
@@ -333,20 +327,17 @@ mod tests {
let active_set = vec![ValidatorIndex(4), ValidatorIndex(0), ValidatorIndex(2)];
let unscrambled_validators: Vec<ValidatorId>
= unscrambled.iter().map(|v| v.public().into()).collect();
let unscrambled_discovery: Vec<AuthorityDiscoveryId>
= unscrambled.iter().map(|v| v.public().into()).collect();
let unscrambled_assignment: Vec<AssignmentId>
= unscrambled.iter().map(|v| v.public().into()).collect();
let unscrambled_validators: Vec<ValidatorId> =
unscrambled.iter().map(|v| v.public().into()).collect();
let unscrambled_discovery: Vec<AuthorityDiscoveryId> =
unscrambled.iter().map(|v| v.public().into()).collect();
let unscrambled_assignment: Vec<AssignmentId> =
unscrambled.iter().map(|v| v.public().into()).collect();
let validators = take_active_subset(&active_set, &unscrambled_validators);
new_test_ext(genesis_config()).execute_with(|| {
ParasShared::set_active_validators_with_indices(
active_set.clone(),
validators.clone(),
);
ParasShared::set_active_validators_with_indices(active_set.clone(), validators.clone());
assert_eq!(ParasShared::active_validator_indices(), active_set);
+18 -39
View File
@@ -19,11 +19,11 @@
//! To avoid cyclic dependencies, it is important that this pallet is not
//! dependent on any of the other pallets.
use primitives::v1::{SessionIndex, ValidatorId, ValidatorIndex};
use frame_support::pallet_prelude::*;
use primitives::v1::{SessionIndex, ValidatorId, ValidatorIndex};
use sp_std::vec::Vec;
use rand::{SeedableRng, seq::SliceRandom};
use rand::{seq::SliceRandom, SeedableRng};
use rand_chacha::ChaCha20Rng;
use crate::configuration::HostConfiguration;
@@ -55,7 +55,8 @@ pub mod pallet {
/// Indices are into the broader validator set.
#[pallet::storage]
#[pallet::getter(fn active_validator_indices)]
pub(super) type ActiveValidatorIndices<T: Config> = StorageValue<_, Vec<ValidatorIndex>, ValueQuery>;
pub(super) type ActiveValidatorIndices<T: Config> =
StorageValue<_, Vec<ValidatorIndex>, ValueQuery>;
/// The parachain attestation keys of the validators actively participating in parachain consensus.
/// This should be the same length as `ActiveValidatorIndices`.
@@ -74,7 +75,7 @@ impl<T: Config> Pallet<T> {
}
/// Called by the initializer to finalize the configuration pallet.
pub(crate) fn initializer_finalize() { }
pub(crate) fn initializer_finalize() {}
/// Called by the initializer to note that a new session has started.
///
@@ -99,10 +100,8 @@ impl<T: Config> Pallet<T> {
shuffled_indices.truncate(max as usize);
}
let active_validator_keys = crate::util::take_active_subset(
&shuffled_indices,
&all_validators,
);
let active_validator_keys =
crate::util::take_active_subset(&shuffled_indices, &all_validators);
ActiveValidatorIndices::<T>::set(shuffled_indices);
ActiveValidatorKeys::<T>::set(active_validator_keys.clone());
@@ -124,7 +123,7 @@ impl<T: Config> Pallet<T> {
#[cfg(test)]
pub(crate) fn set_active_validators_ascending(active: Vec<ValidatorId>) {
ActiveValidatorIndices::<T>::set(
(0..active.len()).map(|i| ValidatorIndex(i as _)).collect()
(0..active.len()).map(|i| ValidatorIndex(i as _)).collect(),
);
ActiveValidatorKeys::<T>::set(active);
}
@@ -143,8 +142,10 @@ impl<T: Config> Pallet<T> {
#[cfg(test)]
mod tests {
use super::*;
use crate::configuration::HostConfiguration;
use crate::mock::{new_test_ext, MockGenesisConfig, ParasShared};
use crate::{
configuration::HostConfiguration,
mock::{new_test_ext, MockGenesisConfig, ParasShared},
};
use keyring::Sr25519Keyring;
fn validator_pubkeys(val_ids: &[Sr25519Keyring]) -> Vec<ValidatorId> {
@@ -167,12 +168,7 @@ mod tests {
let pubkeys = validator_pubkeys(&validators);
new_test_ext(MockGenesisConfig::default()).execute_with(|| {
let validators = ParasShared::initializer_on_new_session(
1,
[1; 32],
&config,
pubkeys,
);
let validators = ParasShared::initializer_on_new_session(1, [1; 32], &config, pubkeys);
assert_eq!(
validators,
@@ -185,10 +181,7 @@ mod tests {
])
);
assert_eq!(
ParasShared::active_validator_keys(),
validators,
);
assert_eq!(ParasShared::active_validator_keys(), validators,);
assert_eq!(
ParasShared::active_validator_indices(),
@@ -219,32 +212,18 @@ mod tests {
let pubkeys = validator_pubkeys(&validators);
new_test_ext(MockGenesisConfig::default()).execute_with(|| {
let validators = ParasShared::initializer_on_new_session(
1,
[1; 32],
&config,
pubkeys,
);
let validators = ParasShared::initializer_on_new_session(1, [1; 32], &config, pubkeys);
assert_eq!(
validators,
validator_pubkeys(&[
Sr25519Keyring::Ferdie,
Sr25519Keyring::Bob,
])
validator_pubkeys(&[Sr25519Keyring::Ferdie, Sr25519Keyring::Bob,])
);
assert_eq!(
ParasShared::active_validator_keys(),
validators,
);
assert_eq!(ParasShared::active_validator_keys(), validators,);
assert_eq!(
ParasShared::active_validator_indices(),
vec![
ValidatorIndex(4),
ValidatorIndex(1),
]
vec![ValidatorIndex(4), ValidatorIndex(1),]
);
});
}
+104 -133
View File
@@ -18,10 +18,15 @@ use crate::{
configuration::{self, HostConfiguration},
initializer,
};
use sp_std::{prelude::*, fmt, marker::PhantomData, convert::TryFrom};
use sp_std::collections::{btree_map::BTreeMap, vec_deque::VecDeque};
use frame_support::pallet_prelude::*;
use primitives::v1::{Id as ParaId, UpwardMessage};
use sp_std::{
collections::{btree_map::BTreeMap, vec_deque::VecDeque},
convert::TryFrom,
fmt,
marker::PhantomData,
prelude::*,
};
use xcm::v0::Outcome;
pub use pallet::*;
@@ -46,13 +51,21 @@ pub trait UmpSink {
/// it did not begin processing a message since it would otherwise exceed `max_weight`.
///
/// See the trait docs for more details.
fn process_upward_message(origin: ParaId, msg: &[u8], max_weight: Weight) -> Result<Weight, (MessageId, Weight)>;
fn process_upward_message(
origin: ParaId,
msg: &[u8],
max_weight: Weight,
) -> Result<Weight, (MessageId, Weight)>;
}
/// An implementation of a sink that just swallows the message without consuming any weight. Returns
/// `Some(0)` indicating that no messages existed for it to process.
impl UmpSink for () {
fn process_upward_message(_: ParaId, _: &[u8], _: Weight) -> Result<Weight, (MessageId, Weight)> {
fn process_upward_message(
_: ParaId,
_: &[u8],
_: Weight,
) -> Result<Weight, (MessageId, Weight)> {
Ok(0)
}
}
@@ -66,13 +79,19 @@ pub type MessageId = [u8; 32];
pub struct XcmSink<XcmExecutor, Config>(PhantomData<(XcmExecutor, Config)>);
impl<XcmExecutor: xcm::v0::ExecuteXcm<C::Call>, C: Config> UmpSink for XcmSink<XcmExecutor, C> {
fn process_upward_message(origin: ParaId, data: &[u8], max_weight: Weight) -> Result<Weight, (MessageId, Weight)> {
use xcm::VersionedXcm;
use xcm::v0::{Xcm, Junction, MultiLocation, Error as XcmError};
fn process_upward_message(
origin: ParaId,
data: &[u8],
max_weight: Weight,
) -> Result<Weight, (MessageId, Weight)> {
use xcm::{
v0::{Error as XcmError, Junction, MultiLocation, Xcm},
VersionedXcm,
};
let id = sp_io::hashing::blake2_256(&data[..]);
let maybe_msg = VersionedXcm::<C::Call>::decode(&mut &data[..])
.map(Xcm::<C::Call>::try_from);
let maybe_msg =
VersionedXcm::<C::Call>::decode(&mut &data[..]).map(Xcm::<C::Call>::try_from);
match maybe_msg {
Err(_) => {
Pallet::<C>::deposit_event(Event::InvalidFormat(id));
@@ -92,9 +111,9 @@ impl<XcmExecutor: xcm::v0::ExecuteXcm<C::Call>, C: Config> UmpSink for XcmSink<X
let weight_used = outcome.weight_used();
Pallet::<C>::deposit_event(Event::ExecutedUpward(id, outcome));
Ok(weight_used)
}
},
}
}
},
}
}
}
@@ -102,23 +121,10 @@ impl<XcmExecutor: xcm::v0::ExecuteXcm<C::Call>, C: Config> UmpSink for XcmSink<X
/// An error returned by [`check_upward_messages`] that indicates a violation of one of acceptance
/// criteria rules.
pub enum AcceptanceCheckErr {
MoreMessagesThanPermitted {
sent: u32,
permitted: u32,
},
MessageSize {
idx: u32,
msg_size: u32,
max_size: u32,
},
CapacityExceeded {
count: u32,
limit: u32,
},
TotalSizeExceeded {
total_size: u32,
limit: u32,
},
MoreMessagesThanPermitted { sent: u32, permitted: u32 },
MessageSize { idx: u32, msg_size: u32, max_size: u32 },
CapacityExceeded { count: u32, limit: u32 },
TotalSizeExceeded { total_size: u32, limit: u32 },
}
impl fmt::Debug for AcceptanceCheckErr {
@@ -129,11 +135,7 @@ impl fmt::Debug for AcceptanceCheckErr {
"more upward messages than permitted by config ({} > {})",
sent, permitted,
),
AcceptanceCheckErr::MessageSize {
idx,
msg_size,
max_size,
} => write!(
AcceptanceCheckErr::MessageSize { idx, msg_size, max_size } => write!(
fmt,
"upward message idx {} larger than permitted by config ({} > {})",
idx, msg_size, max_size,
@@ -204,13 +206,8 @@ pub mod pallet {
///
/// The messages are processed in FIFO order.
#[pallet::storage]
pub type RelayDispatchQueues<T: Config> = StorageMap<
_,
Twox64Concat,
ParaId,
VecDeque<UpwardMessage>,
ValueQuery
>;
pub type RelayDispatchQueues<T: Config> =
StorageMap<_, Twox64Concat, ParaId, VecDeque<UpwardMessage>, ValueQuery>;
/// Size of the dispatch queues. Caches sizes of the queues in `RelayDispatchQueue`.
///
@@ -226,13 +223,8 @@ pub mod pallet {
// NOTE that this field is used by parachains via merkle storage proofs, therefore changing
// the format will require migration of parachains.
#[pallet::storage]
pub type RelayDispatchQueueSize<T: Config> = StorageMap<
_,
Twox64Concat,
ParaId,
(u32, u32),
ValueQuery
>;
pub type RelayDispatchQueueSize<T: Config> =
StorageMap<_, Twox64Concat, ParaId, (u32, u32), ValueQuery>;
/// The ordered list of `ParaId`s that have a `RelayDispatchQueue` entry.
///
@@ -311,7 +303,7 @@ impl<T: Config> Pallet<T> {
return Err(AcceptanceCheckErr::MoreMessagesThanPermitted {
sent: upward_messages.len() as u32,
permitted: config.max_upward_message_num_per_candidate,
});
})
}
let (mut para_queue_count, mut para_queue_size) =
@@ -324,7 +316,7 @@ impl<T: Config> Pallet<T> {
idx: idx as u32,
msg_size,
max_size: config.max_upward_message_size,
});
})
}
para_queue_count += 1;
para_queue_size += msg_size;
@@ -336,13 +328,13 @@ impl<T: Config> Pallet<T> {
return Err(AcceptanceCheckErr::CapacityExceeded {
count: para_queue_count,
limit: config.max_upward_queue_count,
});
})
}
if para_queue_size > config.max_upward_queue_size {
return Err(AcceptanceCheckErr::TotalSizeExceeded {
total_size: para_queue_size,
limit: config.max_upward_queue_size,
});
})
}
Ok(())
@@ -364,10 +356,13 @@ impl<T: Config> Pallet<T> {
v.extend(upward_messages.into_iter())
});
<Self as Store>::RelayDispatchQueueSize::mutate(&para, |(ref mut cnt, ref mut size)| {
*cnt += extra_count;
*size += extra_size;
});
<Self as Store>::RelayDispatchQueueSize::mutate(
&para,
|(ref mut cnt, ref mut size)| {
*cnt += extra_count;
*size += extra_size;
},
);
<Self as Store>::NeedsDispatch::mutate(|v| {
if let Err(i) = v.binary_search(&para) {
@@ -398,7 +393,7 @@ impl<T: Config> Pallet<T> {
// preferred weight for the dispatching stage.
//
// if so - bail.
break;
break
}
let max_weight = if weight_used == 0 {
// we increase the amount of weight that we're allowed to use on the first message to try to prevent
@@ -411,7 +406,11 @@ impl<T: Config> Pallet<T> {
// dequeue the next message from the queue of the dispatchee
let (upward_message, became_empty) = queue_cache.dequeue::<T>(dispatchee);
if let Some(upward_message) = upward_message {
match T::UmpSink::process_upward_message(dispatchee, &upward_message[..], max_weight) {
match T::UmpSink::process_upward_message(
dispatchee,
&upward_message[..],
max_weight,
) {
Ok(used) => weight_used += used,
Err((id, required)) => {
// we process messages in order and don't drop them if we run out of weight, so need to break
@@ -478,11 +477,7 @@ impl QueueCache {
let cache_entry = self.0.entry(para).or_insert_with(|| {
let queue = <Pallet<T> as Store>::RelayDispatchQueues::get(&para);
let (count, total_size) = <Pallet<T> as Store>::RelayDispatchQueueSize::get(&para);
QueueCacheEntry {
queue,
count,
total_size,
}
QueueCacheEntry { queue, count, total_size }
});
let upward_message = cache_entry.queue.pop_front();
if let Some(ref msg) = upward_message {
@@ -499,15 +494,7 @@ impl QueueCache {
// NOTE we use an explicit method here instead of Drop impl because it has unwanted semantics
// within runtime. It is dangerous to use because of double-panics and flushing on a panic
// is not necessary as well.
for (
para,
QueueCacheEntry {
queue,
count,
total_size,
},
) in self.0
{
for (para, QueueCacheEntry { queue, count, total_size }) in self.0 {
if queue.is_empty() {
// remove the entries altogether.
<Pallet<T> as Store>::RelayDispatchQueues::remove(&para);
@@ -551,15 +538,12 @@ impl NeedsDispatchCursor {
// let's select 0 as the starting index as a safe bet.
debug_assert!(false);
0
}
},
},
None => 0,
};
Self {
needs_dispatch,
index: initial_index,
}
Self { needs_dispatch, index: initial_index }
}
/// Returns the item the cursor points to.
@@ -570,7 +554,7 @@ impl NeedsDispatchCursor {
/// Moves the cursor to the next item.
fn advance(&mut self) {
if self.needs_dispatch.is_empty() {
return;
return
}
self.index = (self.index + 1) % self.needs_dispatch.len();
}
@@ -578,7 +562,7 @@ impl NeedsDispatchCursor {
/// Removes the item under the cursor.
fn remove(&mut self) {
if self.needs_dispatch.is_empty() {
return;
return
}
let _ = self.needs_dispatch.remove(self.index);
@@ -615,10 +599,9 @@ pub(crate) mod mock_sink {
//! 2. All messages expected by the probe must be received by the time of dropping it. Unreceived
//! messages will lead to a panic while dropping a probe.
use super::{UmpSink, UpwardMessage, ParaId, MessageId};
use std::cell::RefCell;
use std::collections::vec_deque::VecDeque;
use super::{MessageId, ParaId, UmpSink, UpwardMessage};
use frame_support::weights::Weight;
use std::{cell::RefCell, collections::vec_deque::VecDeque};
#[derive(Debug)]
struct UmpExpectation {
@@ -634,25 +617,30 @@ pub(crate) mod mock_sink {
pub struct MockUmpSink;
impl UmpSink for MockUmpSink {
fn process_upward_message(actual_origin: ParaId, actual_msg: &[u8], _max_weight: Weight) -> Result<Weight, (MessageId, Weight)> {
Ok(HOOK.with(|opt_hook| opt_hook.borrow_mut().as_mut().map(|hook| {
let UmpExpectation {
expected_origin,
expected_msg,
mock_weight,
} = match hook.pop_front() {
Some(expectation) => expectation,
None => {
panic!(
fn process_upward_message(
actual_origin: ParaId,
actual_msg: &[u8],
_max_weight: Weight,
) -> Result<Weight, (MessageId, Weight)> {
Ok(HOOK
.with(|opt_hook| {
opt_hook.borrow_mut().as_mut().map(|hook| {
let UmpExpectation { expected_origin, expected_msg, mock_weight } =
match hook.pop_front() {
Some(expectation) => expectation,
None => {
panic!(
"The probe is active but didn't expect the message:\n\n\t{:?}.",
actual_msg,
);
}
};
assert_eq!(expected_origin, actual_origin);
assert_eq!(expected_msg, &actual_msg[..]);
mock_weight
})).unwrap_or(0))
},
};
assert_eq!(expected_origin, actual_origin);
assert_eq!(expected_msg, &actual_msg[..]);
mock_weight
})
})
.unwrap_or(0))
}
}
@@ -684,15 +672,11 @@ pub(crate) mod mock_sink {
mock_weight: Weight,
) {
HOOK.with(|opt_hook| {
opt_hook
.borrow_mut()
.as_mut()
.unwrap()
.push_back(UmpExpectation {
expected_origin,
expected_msg,
mock_weight,
})
opt_hook.borrow_mut().as_mut().unwrap().push_back(UmpExpectation {
expected_origin,
expected_msg,
mock_weight,
})
});
}
}
@@ -727,9 +711,8 @@ pub(crate) mod mock_sink {
#[cfg(test)]
mod tests {
use super::*;
use super::mock_sink::Probe;
use crate::mock::{Configuration, Ump, new_test_ext, MockGenesisConfig};
use super::{mock_sink::Probe, *};
use crate::mock::{new_test_ext, Configuration, MockGenesisConfig, Ump};
use std::collections::HashSet;
struct GenesisConfigBuilder {
@@ -761,8 +744,7 @@ mod tests {
config.max_upward_message_num_per_candidate = self.max_upward_message_num_per_candidate;
config.max_upward_queue_count = self.max_upward_queue_count;
config.max_upward_queue_size = self.max_upward_queue_size;
config.ump_service_total_weight =
self.ump_service_total_weight;
config.ump_service_total_weight = self.ump_service_total_weight;
genesis
}
}
@@ -811,9 +793,8 @@ mod tests {
let queue_sizes_set = <Ump as Store>::RelayDispatchQueueSize::iter()
.map(|(k, _)| k)
.collect::<HashSet<ParaId>>();
let needs_dispatch_set = <Ump as Store>::NeedsDispatch::get()
.into_iter()
.collect::<HashSet<ParaId>>();
let needs_dispatch_set =
<Ump as Store>::NeedsDispatch::get().into_iter().collect::<HashSet<ParaId>>();
assert_eq!(queue_contents_set, queue_sizes_set);
assert_eq!(queue_contents_set, needs_dispatch_set);
@@ -823,11 +804,7 @@ mod tests {
}
// `NeedsDispatch` is always sorted.
assert!(
<Ump as Store>::NeedsDispatch::get()
.windows(2)
.all(|xs| xs[0] <= xs[1])
);
assert!(<Ump as Store>::NeedsDispatch::get().windows(2).all(|xs| xs[0] <= xs[1]));
}
#[test]
@@ -872,11 +849,7 @@ mod tests {
let q_msg = b"we are Q".to_vec();
new_test_ext(
GenesisConfigBuilder {
ump_service_total_weight: 500,
..Default::default()
}
.build(),
GenesisConfigBuilder { ump_service_total_weight: 500, ..Default::default() }.build(),
)
.execute_with(|| {
queue_upward_msg(q, q_msg.clone());
@@ -946,11 +919,7 @@ mod tests {
let b_msg_1 = vec![4, 5, 6];
new_test_ext(
GenesisConfigBuilder {
ump_service_total_weight: 900,
..Default::default()
}
.build(),
GenesisConfigBuilder { ump_service_total_weight: 900, ..Default::default() }.build(),
)
.execute_with(|| {
// We want to test here an edge case, where we remove the queue with the highest
@@ -982,8 +951,8 @@ mod tests {
// Make sure that the relay dispatch queue size storage entry is accessible via well known
// keys and is decodable into a (u32, u32).
use primitives::v1::well_known_keys;
use parity_scale_codec::Decode as _;
use primitives::v1::well_known_keys;
let a = ParaId::from(228);
let msg = vec![1, 2, 3];
@@ -991,9 +960,11 @@ mod tests {
new_test_ext(GenesisConfigBuilder::default().build()).execute_with(|| {
queue_upward_msg(a, msg);
let raw_queue_size = sp_io::storage::get(&well_known_keys::relay_dispatch_queue_size(a))
.expect("enqueing a message should create the dispatch queue\
and it should be accessible via the well known keys");
let raw_queue_size =
sp_io::storage::get(&well_known_keys::relay_dispatch_queue_size(a)).expect(
"enqueing a message should create the dispatch queue\
and it should be accessible via the well known keys",
);
let (cnt, size) = <(u32, u32)>::decode(&mut &raw_queue_size[..])
.expect("the dispatch queue size should be decodable into (u32, u32)");
+3 -2
View File
@@ -20,7 +20,7 @@
use primitives::v1::{Id as ParaId, PersistedValidationData, ValidatorIndex};
use sp_std::vec::Vec;
use crate::{configuration, paras, hrmp};
use crate::{configuration, hrmp, paras};
/// Make the persisted validation data for a particular parachain, a specified relay-parent and it's
/// storage root.
@@ -43,7 +43,8 @@ pub fn make_persisted_validation_data<T: paras::Config + hrmp::Config>(
/// Take the active subset of a set containing all validators.
pub fn take_active_subset<T: Clone>(active_validators: &[ValidatorIndex], set: &[T]) -> Vec<T> {
let subset: Vec<_> = active_validators.iter()
let subset: Vec<_> = active_validators
.iter()
.filter_map(|i| set.get(i.0 as usize))
.cloned()
.collect();