From 4161c8ea6c50bd0e9b9dfabd8f44244298341970 Mon Sep 17 00:00:00 2001 From: Yaroslav Bolyukin Date: Mon, 02 Oct 2023 22:06:30 +0000 Subject: [PATCH] refactor: drop legacy unique scheduler --- --- a/pallets/scheduler-v2/Cargo.toml +++ /dev/null @@ -1,45 +0,0 @@ -[package] -authors = ["Unique Network "] -description = "Unique Scheduler pallet" -edition = "2021" -homepage = "https://unique.network" -license = "GPLv3" -name = "pallet-unique-scheduler-v2" -readme = "README.md" -repository = "https://github.com/UniqueNetwork/unique-chain" -version = "0.1.0" - -[dependencies] -# Note: `package = "parity-scale-codec"` must be supplied since the `Encode` macro searches for it. -codec = { workspace = true, package = "parity-scale-codec" } - -frame-benchmarking = { workspace = true, optional = true } -frame-support = { workspace = true } -frame-system = { workspace = true } -log = { workspace = true } -scale-info = { workspace = true } -sp-core = { workspace = true } -sp-io = { workspace = true } -sp-runtime = { workspace = true } -sp-std = { workspace = true } - -[dev-dependencies] -pallet-preimage = { workspace = true } -substrate-test-utils = { git = "https://github.com/paritytech/substrate", branch = "polkadot-v0.9.43" } - -[features] -default = ["std"] -runtime-benchmarks = ["frame-benchmarking", "frame-support/runtime-benchmarks", "frame-system/runtime-benchmarks"] -std = [ - "codec/std", - "frame-benchmarking?/std", - "frame-support/std", - "frame-system/std", - "log/std", - "scale-info/std", - "sp-core/std", - "sp-io/std", - "sp-runtime/std", - "sp-std/std", -] -try-runtime = ["frame-support/try-runtime"] --- a/pallets/scheduler-v2/src/benchmarking.rs +++ /dev/null @@ -1,374 +0,0 @@ -// Copyright 2019-2022 Unique Network (Gibraltar) Ltd. -// This file is part of Unique Network. - -// Unique Network is free software: you can redistribute it and/or modify -// it under the terms of the GNU General Public License as published by -// the Free Software Foundation, either version 3 of the License, or -// (at your option) any later version. - -// Unique Network is distributed in the hope that it will be useful, -// but WITHOUT ANY WARRANTY; without even the implied warranty of -// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the -// GNU General Public License for more details. - -// You should have received a copy of the GNU General Public License -// along with Unique Network. If not, see . - -// Original license: -// This file is part of Substrate. - -// Copyright (C) 2020-2022 Parity Technologies (UK) Ltd. -// SPDX-License-Identifier: Apache-2.0 - -// Licensed under the Apache License, Version 2.0 (the "License"); -// you may not use this file except in compliance with the License. -// You may obtain a copy of the License at -// -// http://www.apache.org/licenses/LICENSE-2.0 -// -// Unless required by applicable law or agreed to in writing, software -// distributed under the License is distributed on an "AS IS" BASIS, -// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. -// See the License for the specific language governing permissions and -// limitations under the License. - -//! Scheduler pallet benchmarking. - -use super::*; -use frame_benchmarking::{account, benchmarks}; -use frame_support::{ - ensure, - traits::{schedule::Priority, PreimageRecipient}, -}; -use frame_system::RawOrigin; -use sp_std::{prelude::*, vec}; -use sp_io::hashing::blake2_256; - -use crate::{Pallet as Scheduler, ScheduledCall, EncodedCall}; -use frame_system::Call as SystemCall; - -const SEED: u32 = 0; - -const BLOCK_NUMBER: u32 = 2; - -/// Add `n` items to the schedule. -/// -/// For `resolved`: -/// - ` -/// - `None`: aborted (hash without preimage) -/// - `Some(true)`: hash resolves into call if possible, plain call otherwise -/// - `Some(false)`: plain call -fn fill_schedule(when: T::BlockNumber, n: u32) -> Result<(), &'static str> { - let t = DispatchTime::At(when); - let origin: ::PalletsOrigin = frame_system::RawOrigin::Root.into(); - for i in 0..n { - let call = make_call::(None); - let period = Some(((i + 100).into(), 100)); - let name = u32_to_name(i); - Scheduler::::do_schedule_named(name, t, period, 0, origin.clone(), call)?; - } - ensure!( - Agenda::::get(when).agenda.len() == n as usize, - "didn't fill schedule" - ); - Ok(()) -} - -/// Generate a name for a scheduled task from an unsigned integer. -fn u32_to_name(i: u32) -> TaskName { - i.using_encoded(blake2_256) -} - -/// A utility for creating simple scheduled tasks. -/// -/// # Arguments -/// * `periodic` - makes the task periodic. -/// Sets the task's period and repetition count to `100`. -/// * `named` - gives a name to the task: `u32_to_name(0)`. -/// * `signed` - determines the origin of the task. -/// If true, it will have the Signed origin. Otherwise it will have the Root origin. -/// See [`make_origin`] for details. -/// * maybe_lookup_len - sets optional lookup length. It is used to benchmark task fetching from the `Preimages` store. -/// * priority - the task's priority. -fn make_task( - periodic: bool, - named: bool, - signed: bool, - maybe_lookup_len: Option, - priority: Priority, -) -> ScheduledOf { - let call = make_call::(maybe_lookup_len); - let maybe_periodic = match periodic { - true => Some((100u32.into(), 100)), - false => None, - }; - let maybe_id = match named { - true => Some(u32_to_name(0)), - false => None, - }; - let origin = make_origin::(signed); - Scheduled { - maybe_id, - priority, - call, - maybe_periodic, - origin, - _phantom: PhantomData, - } -} - -/// Creates a `SystemCall::remark` scheduled call with a given `len` in bytes. -/// Returns `None` if the call is too large to encode. -fn bounded(len: u32) -> Option> { - let call = <::RuntimeCall>::from(SystemCall::remark { - remark: vec![0; len as usize], - }); - ScheduledCall::new(call).ok() -} - -/// Creates a scheduled call and maximizes its size. -/// -/// If the `maybe_lookup_len` is not supplied, the task will create the maximal `Inline` scheduled call. -/// -/// Otherwise, the function will take the length value from the `maybe_lookup_len` -/// and find a minimal length value that ensures that the scheduled call will require a Preimage lookup. -fn make_call(maybe_lookup_len: Option) -> ScheduledCall { - let bound = EncodedCall::bound() as u32; - let mut len = match maybe_lookup_len { - Some(len) => { - len.clamp( - bound, - >::MaxSize::get() - 2, - ) - 3 - } - None => bound.saturating_sub(4), - }; - - loop { - let c = match bounded::(len) { - Some(x) => x, - None => { - len -= 1; - continue; - } - }; - if c.lookup_needed() == maybe_lookup_len.is_some() { - break c; - } - if maybe_lookup_len.is_some() { - len += 1; - } else if len > 0 { - len -= 1; - } else { - break c; - } - } -} - -/// Creates an origin for a scheduled call. -/// -/// If `signed` is true, it creates the Signed origin from a default account `account("origin", 0, SEED)`. -/// Otherwise, it creates the Root origin. -fn make_origin(signed: bool) -> ::PalletsOrigin { - match signed { - true => frame_system::RawOrigin::Signed(account("origin", 0, SEED)).into(), - false => frame_system::RawOrigin::Root.into(), - } -} - -/// Creates a dummy `WeightCounter` with the maximum possible weight limit. -fn dummy_counter() -> WeightCounter { - WeightCounter { - used: Weight::zero(), - limit: Weight::MAX, - } -} - -benchmarks! { - // `service_agendas` when no work is done. - // (multiple agendas - scheduled tasks in several blocks) - service_agendas_base { - let now = T::BlockNumber::from(BLOCK_NUMBER); - IncompleteSince::::put(now - One::one()); - }: { - Scheduler::::service_agendas(&mut dummy_counter(), now, 0); - } verify { - assert_eq!(IncompleteSince::::get(), Some(now - One::one())); - } - - // `service_agenda` when no work is done. - // (only one agenda - scheduled tasks in a single block) - service_agenda_base { - let now = BLOCK_NUMBER.into(); - let s in 0 .. T::MaxScheduledPerBlock::get(); - fill_schedule::(now, s)?; - let mut executed = 0; - }: { - Scheduler::::service_agenda(&mut dummy_counter(), &mut executed, now, now, 0); - } verify { - assert_eq!(executed, 0); - } - - // `service_task` when the task is a non-periodic, non-named, non-fetched call which is not - // dispatched (e.g. due to being overweight). - service_task_base { - let now = BLOCK_NUMBER.into(); - let task = make_task::(false, false, false, None, 0); - // prevent any tasks from actually being executed as we only want the surrounding weight. - let mut counter = WeightCounter { used: Weight::zero(), limit: Weight::zero() }; - }: { - let result = Scheduler::::service_task(&mut counter, now, now, 0, true, task); - } verify { - //assert_eq!(result, Ok(())); - } - - // TODO uncomment if we will use the Preimages - // // `service_task` when the task is a non-periodic, non-named, fetched call (with a known - // // preimage length) and which is not dispatched (e.g. due to being overweight). - // service_task_fetched { - // let s in (EncodedCall::bound() as u32) .. (>::MaxSize::get()); - // let now = BLOCK_NUMBER.into(); - // let task = make_task::(false, false, false, Some(s), 0); - // // prevent any tasks from actually being executed as we only want the surrounding weight. - // let mut counter = WeightCounter { used: Weight::zero(), limit: Weight::zero() }; - // }: { - // let result = Scheduler::::service_task(&mut counter, now, now, 0, true, task); - // } verify { - // } - - // `service_task` when the task is a non-periodic, named, non-fetched call which is not - // dispatched (e.g. due to being overweight). - service_task_named { - let now = BLOCK_NUMBER.into(); - let task = make_task::(false, true, false, None, 0); - // prevent any tasks from actually being executed as we only want the surrounding weight. - let mut counter = WeightCounter { used: Weight::zero(), limit: Weight::zero() }; - }: { - let result = Scheduler::::service_task(&mut counter, now, now, 0, true, task); - } verify { - } - - // `service_task` when the task is a periodic, non-named, non-fetched call which is not - // dispatched (e.g. due to being overweight). - service_task_periodic { - let now = BLOCK_NUMBER.into(); - let task = make_task::(true, false, false, None, 0); - // prevent any tasks from actually being executed as we only want the surrounding weight. - let mut counter = WeightCounter { used: Weight::zero(), limit: Weight::zero() }; - }: { - let result = Scheduler::::service_task(&mut counter, now, now, 0, true, task); - } verify { - } - - // `execute_dispatch` when the origin is `Signed`, not counting the dispatable's weight. - execute_dispatch_signed { - let mut counter = WeightCounter { used: Weight::zero(), limit: Weight::MAX }; - let origin = make_origin::(true); - let call = T::Preimages::realize(&make_call::(None)).unwrap().0; - }: { - assert!(Scheduler::::execute_dispatch(&mut counter, origin, call).is_ok()); - } - verify { - } - - // `execute_dispatch` when the origin is not `Signed`, not counting the dispatable's weight. - execute_dispatch_unsigned { - let mut counter = WeightCounter { used: Weight::zero(), limit: Weight::MAX }; - let origin = make_origin::(false); - let call = T::Preimages::realize(&make_call::(None)).unwrap().0; - }: { - assert!(Scheduler::::execute_dispatch(&mut counter, origin, call).is_ok()); - } - verify { - } - - schedule { - let s in 0 .. (T::MaxScheduledPerBlock::get() - 1); - let when = BLOCK_NUMBER.into(); - let periodic = Some((T::BlockNumber::one(), 100)); - let priority = Some(0); - // Essentially a no-op call. - let call = Box::new(SystemCall::set_storage { items: vec![] }.into()); - - fill_schedule::(when, s)?; - }: _(RawOrigin::Root, when, periodic, priority, call) - verify { - ensure!( - Agenda::::get(when).agenda.len() == (s + 1) as usize, - "didn't add to schedule" - ); - } - - cancel { - let s in 1 .. T::MaxScheduledPerBlock::get(); - let when = BLOCK_NUMBER.into(); - - fill_schedule::(when, s)?; - assert_eq!(Agenda::::get(when).agenda.len(), s as usize); - }: _(RawOrigin::Root, when, 0) - verify { - ensure!( - Lookup::::get(u32_to_name(0)).is_none(), - "didn't remove from lookup" - ); - // Removed schedule is NONE - ensure!( - Agenda::::get(when).agenda[0].is_none(), - "didn't remove from schedule" - ); - } - - schedule_named { - let s in 0 .. (T::MaxScheduledPerBlock::get() - 1); - let id = u32_to_name(s); - let when = BLOCK_NUMBER.into(); - let periodic = Some((T::BlockNumber::one(), 100)); - let priority = Some(0); - // Essentially a no-op call. - let call = Box::new(SystemCall::set_storage { items: vec![] }.into()); - - fill_schedule::(when, s)?; - }: _(RawOrigin::Root, id, when, periodic, priority, call) - verify { - ensure!( - Agenda::::get(when).agenda.len() == (s + 1) as usize, - "didn't add to schedule" - ); - } - - cancel_named { - let s in 1 .. T::MaxScheduledPerBlock::get(); - let when = BLOCK_NUMBER.into(); - - fill_schedule::(when, s)?; - }: _(RawOrigin::Root, u32_to_name(0)) - verify { - ensure!( - Lookup::::get(u32_to_name(0)).is_none(), - "didn't remove from lookup" - ); - // Removed schedule is NONE - ensure!( - Agenda::::get(when).agenda[0].is_none(), - "didn't remove from schedule" - ); - } - - change_named_priority { - let origin: RawOrigin = frame_system::RawOrigin::Root; - let s in 1 .. T::MaxScheduledPerBlock::get(); - let when = BLOCK_NUMBER.into(); - let idx = s - 1; - let id = u32_to_name(idx); - let priority = 42; - fill_schedule::(when, s)?; - }: _(origin, id, priority) - verify { - ensure!( - Agenda::::get(when).agenda[idx as usize].clone().unwrap().priority == priority, - "didn't change the priority" - ); - } - - impl_benchmark_test_suite!(Scheduler, crate::mock::new_test_ext(), crate::mock::Test); -} --- a/pallets/scheduler-v2/src/lib.rs +++ /dev/null @@ -1,1338 +0,0 @@ -// Copyright 2019-2022 Unique Network (Gibraltar) Ltd. -// This file is part of Unique Network. - -// Unique Network is free software: you can redistribute it and/or modify -// it under the terms of the GNU General Public License as published by -// the Free Software Foundation, either version 3 of the License, or -// (at your option) any later version. - -// Unique Network is distributed in the hope that it will be useful, -// but WITHOUT ANY WARRANTY; without even the implied warranty of -// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the -// GNU General Public License for more details. - -// You should have received a copy of the GNU General Public License -// along with Unique Network. If not, see . - -// Original license: -// This file is part of Substrate. - -// Copyright (C) 2017-2022 Parity Technologies (UK) Ltd. -// SPDX-License-Identifier: Apache-2.0 - -// Licensed under the Apache License, Version 2.0 (the "License"); -// you may not use this file except in compliance with the License. -// You may obtain a copy of the License at -// -// http://www.apache.org/licenses/LICENSE-2.0 -// -// Unless required by applicable law or agreed to in writing, software -// distributed under the License is distributed on an "AS IS" BASIS, -// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. -// See the License for the specific language governing permissions and -// limitations under the License. - -//! # Scheduler -//! A Pallet for scheduling dispatches. -//! -//! - [`Config`] -//! - [`Call`] -//! - [`Pallet`] -//! -//! ## Overview -//! -//! This Pallet exposes capabilities for scheduling dispatches to occur at a -//! specified block number or at a specified period. These scheduled dispatches -//! may be named or anonymous and may be canceled. -//! -//! **NOTE:** The scheduled calls will be dispatched with the default filter -//! for the origin: namely `frame_system::Config::BaseCallFilter` for all origin -//! except root which will get no filter. And not the filter contained in origin -//! use to call `fn schedule`. -//! -//! If a call is scheduled using proxy or whatever mecanism which adds filter, -//! then those filter will not be used when dispatching the schedule call. -//! -//! ## Interface -//! -//! ### Dispatchable Functions -//! -//! * `schedule` - schedule a dispatch, which may be periodic, to occur at a specified block and -//! with a specified priority. -//! * `cancel` - cancel a scheduled dispatch, specified by block number and index. -//! * `schedule_named` - augments the `schedule` interface with an additional `Vec` parameter -//! that can be used for identification. -//! * `cancel_named` - the named complement to the cancel function. - -// Ensure we're `no_std` when compiling for Wasm. -#![cfg_attr(not(feature = "std"), no_std)] -#![deny(missing_docs)] - -#[cfg(feature = "runtime-benchmarks")] -mod benchmarking; -#[cfg(test)] -mod mock; -#[cfg(test)] -mod tests; -// We dont use this pallet right now -#[allow(deprecated)] -pub mod weights; - -use codec::{Codec, Decode, Encode, MaxEncodedLen}; -use frame_support::{ - dispatch::{ - DispatchError, DispatchResult, Dispatchable, GetDispatchInfo, Parameter, PostDispatchInfo, - }, - traits::{ - schedule::{self, DispatchTime, LOWEST_PRIORITY}, - EnsureOrigin, Get, IsType, OriginTrait, PrivilegeCmp, StorageVersion, PreimageRecipient, - ConstU32, UnfilteredDispatchable, - }, - weights::Weight, - unsigned::TransactionValidityError, -}; - -use frame_system::{self as system}; -use scale_info::TypeInfo; -use sp_runtime::{ - traits::{BadOrigin, One, Saturating, Zero, Hash}, - BoundedVec, RuntimeDebug, DispatchErrorWithPostInfo, -}; -use sp_core::H160; -use sp_std::{cmp::Ordering, marker::PhantomData, prelude::*}; -pub use weights::WeightInfo; - -pub use pallet::*; - -/// Just a simple index for naming period tasks. -pub type PeriodicIndex = u32; -/// The location of a scheduled task that can be used to remove it. -pub type TaskAddress = (BlockNumber, u32); - -/// A an encoded bounded `Call`. Its encoding must be at most 128 bytes. -pub type EncodedCall = BoundedVec>; - -#[derive(Clone, Eq, PartialEq, Encode, Decode, RuntimeDebug, TypeInfo, MaxEncodedLen)] -#[scale_info(skip_type_params(T))] -/// A scheduled call is stored as is or as a preimage hash to lookup. -/// This enum represents both variants. -pub enum ScheduledCall { - /// A an encoded bounded `Call`. Its encoding must be at most 128 bytes. - Inline(EncodedCall), - - /// A Blake2-256 hash of the call together with an upper limit for its size. - PreimageLookup { - /// A call hash to lookup - hash: T::Hash, - - /// The length of the decoded call - unbounded_len: u32, - }, -} - -impl ScheduledCall { - /// Convert an otherwise unbounded or large value into a type ready for placing in storage. - /// - /// NOTE: Once this API is used, you should use either `drop` or `realize`. - pub fn new(call: ::RuntimeCall) -> Result { - let encoded = call.encode(); - let len = encoded.len(); - - match EncodedCall::try_from(encoded.clone()) { - Ok(bounded) => Ok(Self::Inline(bounded)), - Err(_) => { - let hash = ::Hashing::hash_of(&encoded); - ::Preimages::note_preimage( - encoded - .try_into() - .map_err(|_| >::TooBigScheduledCall)?, - ); - - Ok(Self::PreimageLookup { - hash, - unbounded_len: len as u32, - }) - } - } - } - - /// The maximum length of the lookup that is needed to peek `Self`. - pub fn lookup_len(&self) -> Option { - match self { - Self::Inline(..) => None, - Self::PreimageLookup { unbounded_len, .. } => Some(*unbounded_len), - } - } - - /// Returns whether the image will require a lookup to be peeked. - pub fn lookup_needed(&self) -> bool { - match self { - Self::Inline(_) => false, - Self::PreimageLookup { .. } => true, - } - } - - // Decodes a runtime call - fn decode(mut data: &[u8]) -> Result<::RuntimeCall, DispatchError> { - ::RuntimeCall::decode(&mut data) - .map_err(|_| >::ScheduledCallCorrupted.into()) - } -} - -/// Weight Info for the Preimages fetches. -pub trait SchedulerPreimagesWeightInfo { - /// Get the weight of a task fetches with a given decoded length. - fn service_task_fetched(call_length: u32) -> Weight; -} - -impl SchedulerPreimagesWeightInfo for () { - fn service_task_fetched(_call_length: u32) -> Weight { - W::service_task_base() - } -} - -/// A scheduler's interface for managing preimages to hashes -/// and looking up preimages from their hash on-chain. -pub trait SchedulerPreimages: - PreimageRecipient + SchedulerPreimagesWeightInfo -{ - /// No longer request that the data for decoding the given `call` is available. - fn drop(call: &ScheduledCall); - - /// Convert the given `call` instance back into its original instance, also returning the - /// exact size of its encoded form if it needed to be looked-up from a stored preimage. - /// - /// NOTE: This does not remove any data needed for realization. If you will no longer use the - /// `call`, use `realize` instead or use `drop` afterwards. - fn peek( - call: &ScheduledCall, - ) -> Result<(::RuntimeCall, Option), DispatchError>; - - /// Convert the given scheduled `call` value back into its original instance. If successful, - /// `drop` any data backing it. This will not break the realisability of independently - /// created instances of `ScheduledCall` which happen to have identical data. - fn realize( - call: &ScheduledCall, - ) -> Result<(::RuntimeCall, Option), DispatchError>; -} - -impl + SchedulerPreimagesWeightInfo> - SchedulerPreimages for PP -{ - fn drop(call: &ScheduledCall) { - match call { - ScheduledCall::Inline(_) => {} - ScheduledCall::PreimageLookup { hash, .. } => Self::unrequest_preimage(hash), - } - } - - fn peek( - call: &ScheduledCall, - ) -> Result<(::RuntimeCall, Option), DispatchError> { - match call { - ScheduledCall::Inline(data) => Ok((ScheduledCall::::decode(data)?, None)), - ScheduledCall::PreimageLookup { - hash, - unbounded_len, - } => { - let (preimage, len) = Self::get_preimage(hash) - .ok_or(>::PreimageNotFound) - .map(|preimage| (preimage, *unbounded_len))?; - - Ok((ScheduledCall::::decode(preimage.as_slice())?, Some(len))) - } - } - } - - fn realize( - call: &ScheduledCall, - ) -> Result<(::RuntimeCall, Option), DispatchError> { - let r = Self::peek(call)?; - Self::drop(call); - Ok(r) - } -} - -/// Scheduler's supported origins. -pub enum ScheduledEnsureOriginSuccess { - /// A scheduled transaction has the Root origin. - Root, - - /// A specific account has signed a scheduled transaction. - Signed(AccountId), -} - -/// An identifier of a scheduled task. -pub type TaskName = [u8; 32]; - -/// Information regarding an item to be executed in the future. -#[cfg_attr(any(feature = "std", test), derive(PartialEq, Eq))] -#[derive(Clone, RuntimeDebug, Encode, Decode, MaxEncodedLen, TypeInfo)] -pub struct Scheduled { - /// The unique identity for this task, if there is one. - maybe_id: Option, - - /// This task's priority. - priority: schedule::Priority, - - /// The call to be dispatched. - call: Call, - - /// If the call is periodic, then this points to the information concerning that. - maybe_periodic: Option>, - - /// The origin with which to dispatch the call. - origin: PalletsOrigin, - _phantom: PhantomData, -} - -/// Information regarding an item to be executed in the future. -pub type ScheduledOf = Scheduled< - TaskName, - ScheduledCall, - ::BlockNumber, - ::PalletsOrigin, - ::AccountId, ->; - -#[derive(Encode, Decode, MaxEncodedLen, TypeInfo)] -#[scale_info(skip_type_params(T))] -/// A structure for storing scheduled tasks in a block. -/// The `BlockAgenda` tracks the available free space for a new task in a block.4 -/// -/// The agenda's maximum amount of tasks is `T::MaxScheduledPerBlock`. -pub struct BlockAgenda { - agenda: BoundedVec>, T::MaxScheduledPerBlock>, - free_places: u32, -} - -impl BlockAgenda { - /// Tries to push a new scheduled task into the block's agenda. - /// If there is a free place, the new task will take it, - /// and the `BlockAgenda` will record that the number of free places has decreased. - /// - /// An error containing the scheduled task will be returned if there are no free places. - /// - /// The complexity of the check for the *existence* of a free place is O(1). - /// The complexity of *finding* the free slot is O(n). - fn try_push(&mut self, scheduled: ScheduledOf) -> Result> { - if self.free_places == 0 { - return Err(scheduled); - } - - self.free_places = self.free_places.saturating_sub(1); - - if (self.agenda.len() as u32) < T::MaxScheduledPerBlock::get() { - // will always succeed due to the above check. - let _ = self.agenda.try_push(Some(scheduled)); - Ok((self.agenda.len() - 1) as u32) - } else { - match self.agenda.iter().position(|i| i.is_none()) { - Some(hole_index) => { - self.agenda[hole_index] = Some(scheduled); - Ok(hole_index as u32) - } - None => unreachable!("free_places was greater than 0; qed"), - } - } - } - - /// Sets a slot by the given index and the slot value. - /// - /// ### Panics - /// If the index is out of range, the function will panic. - fn set_slot(&mut self, index: u32, slot: Option>) { - self.agenda[index as usize] = slot; - } - - /// Returns an iterator containing references to the agenda's slots. - fn iter(&self) -> impl Iterator>> + '_ { - self.agenda.iter() - } - - /// Returns an immutable reference to a scheduled task if there is one under the given index. - /// - /// The function returns `None` if: - /// * The `index` is out of range - /// * No scheduled task occupies the agenda slot under the given index. - fn get(&self, index: u32) -> Option<&ScheduledOf> { - match self.agenda.get(index as usize) { - Some(Some(scheduled)) => Some(scheduled), - _ => None, - } - } - - /// Returns a mutable reference to a scheduled task if there is one under the given index. - /// - /// The function returns `None` if: - /// * The `index` is out of range - /// * No scheduled task occupies the agenda slot under the given index. - fn get_mut(&mut self, index: u32) -> Option<&mut ScheduledOf> { - match self.agenda.get_mut(index as usize) { - Some(Some(scheduled)) => Some(scheduled), - _ => None, - } - } - - /// Take a scheduled task by the given index. - /// - /// If there is a task under the index, the function will: - /// * Free the corresponding agenda slot. - /// * Decrease the number of free places. - /// * Return the scheduled task. - /// - /// The function returns `None` if there is no task under the index. - fn take(&mut self, index: u32) -> Option> { - let removed = self.agenda.get_mut(index as usize)?.take(); - - if removed.is_some() { - self.free_places = self.free_places.saturating_add(1); - } - - removed - } -} - -impl Default for BlockAgenda { - fn default() -> Self { - let agenda = Default::default(); - let free_places = T::MaxScheduledPerBlock::get(); - - Self { - agenda, - free_places, - } - } -} -/// A structure for tracking the used weight -/// and checking if it does not exceed the weight limit. -struct WeightCounter { - used: Weight, - limit: Weight, -} - -impl WeightCounter { - /// Checks if the weight `w` can be accommodated by the counter. - /// - /// If there is room for the additional weight `w`, - /// the function will update the used weight and return true. - fn check_accrue(&mut self, w: Weight) -> bool { - let test = self.used.saturating_add(w); - if test.any_gt(self.limit) { - false - } else { - self.used = test; - true - } - } - - /// Checks if the weight `w` can be accommodated by the counter. - fn can_accrue(&mut self, w: Weight) -> bool { - self.used.saturating_add(w).all_lte(self.limit) - } -} - -pub(crate) struct MarginalWeightInfo(sp_std::marker::PhantomData); - -impl MarginalWeightInfo { - /// Return the weight of servicing a single task. - fn service_task(maybe_lookup_len: Option, named: bool, periodic: bool) -> Weight { - let base = T::WeightInfo::service_task_base(); - let mut total = match maybe_lookup_len { - None => base, - Some(l) => T::Preimages::service_task_fetched(l as u32), - }; - if named { - total.saturating_accrue(T::WeightInfo::service_task_named().saturating_sub(base)); - } - if periodic { - total.saturating_accrue(T::WeightInfo::service_task_periodic().saturating_sub(base)); - } - total - } -} - -#[frame_support::pallet] -pub mod pallet { - use super::*; - use frame_support::{dispatch::PostDispatchInfo, pallet_prelude::*}; - use system::pallet_prelude::*; - - /// The current storage version. - const STORAGE_VERSION: StorageVersion = StorageVersion::new(0); - - #[pallet::pallet] - #[pallet::storage_version(STORAGE_VERSION)] - pub struct Pallet(_); - - #[pallet::config] - pub trait Config: frame_system::Config { - /// The overarching event type. - type RuntimeEvent: From> + IsType<::RuntimeEvent>; - - /// The aggregated origin which the dispatch will take. - type RuntimeOrigin: OriginTrait - + From - + IsType<::RuntimeOrigin> - + Clone; - - /// The caller origin, overarching type of all pallets origins. - type PalletsOrigin: From> - + Codec - + Clone - + Eq - + TypeInfo - + MaxEncodedLen; - - /// The aggregated call type. - type RuntimeCall: Parameter - + Dispatchable< - RuntimeOrigin = ::RuntimeOrigin, - PostInfo = PostDispatchInfo, - > + UnfilteredDispatchable::RuntimeOrigin> - + GetDispatchInfo - + From>; - - /// The maximum weight that may be scheduled per block for any dispatchables. - #[pallet::constant] - type MaximumWeight: Get; - - /// Required origin to schedule or cancel calls. - type ScheduleOrigin: EnsureOrigin< - ::RuntimeOrigin, - Success = ScheduledEnsureOriginSuccess, - >; - - /// Compare the privileges of origins. - /// - /// This will be used when canceling a task, to ensure that the origin that tries - /// to cancel has greater or equal privileges as the origin that created the scheduled task. - /// - /// For simplicity the [`EqualPrivilegeOnly`](frame_support::traits::EqualPrivilegeOnly) can - /// be used. This will only check if two given origins are equal. - type OriginPrivilegeCmp: PrivilegeCmp; - - /// The maximum number of scheduled calls in the queue for a single block. - #[pallet::constant] - type MaxScheduledPerBlock: Get; - - /// Weight information for extrinsics in this pallet. - type WeightInfo: WeightInfo; - - /// The preimage provider with which we look up call hashes to get the call. - type Preimages: SchedulerPreimages; - - /// The helper type used for custom transaction fee logic. - type CallExecutor: DispatchCall; - - /// Required origin to set/change calls' priority. - type PrioritySetOrigin: EnsureOrigin<::RuntimeOrigin>; - } - - /// It contains the block number from which we should service tasks. - /// It's used for delaying the servicing of future blocks' agendas if we had overweight tasks. - #[pallet::storage] - pub type IncompleteSince = StorageValue<_, T::BlockNumber>; - - /// Items to be executed, indexed by the block number that they should be executed on. - #[pallet::storage] - pub type Agenda = - StorageMap<_, Twox64Concat, T::BlockNumber, BlockAgenda, ValueQuery>; - - /// Lookup from a name to the block number and index of the task. - #[pallet::storage] - pub(crate) type Lookup = - StorageMap<_, Twox64Concat, TaskName, TaskAddress>; - - /// Events type. - #[pallet::event] - #[pallet::generate_deposit(pub(super) fn deposit_event)] - pub enum Event { - /// Scheduled some task. - Scheduled { - /// The block number in which the scheduled task should be executed. - when: T::BlockNumber, - - /// The index of the block's agenda slot. - index: u32, - }, - /// Canceled some task. - Canceled { - /// The block number in which the canceled task has been. - when: T::BlockNumber, - - /// The index of the block's agenda slot that had become available. - index: u32, - }, - /// Dispatched some task. - Dispatched { - /// The task's address - the block number and the block's agenda index. - task: TaskAddress, - - /// The task's name if it is not anonymous. - id: Option<[u8; 32]>, - - /// The task's execution result. - result: DispatchResult, - }, - /// Scheduled task's priority has changed - PriorityChanged { - /// The task's address - the block number and the block's agenda index. - task: TaskAddress, - - /// The new priority of the task. - priority: schedule::Priority, - }, - /// The call for the provided hash was not found so the task has been aborted. - CallUnavailable { - /// The task's address - the block number and the block's agenda index. - task: TaskAddress, - - /// The task's name if it is not anonymous. - id: Option<[u8; 32]>, - }, - /// The given task can never be executed since it is overweight. - PermanentlyOverweight { - /// The task's address - the block number and the block's agenda index. - task: TaskAddress, - - /// The task's name if it is not anonymous. - id: Option<[u8; 32]>, - }, - } - - #[pallet::error] - pub enum Error { - /// Failed to schedule a call - FailedToSchedule, - /// There is no place for a new task in the agenda - AgendaIsExhausted, - /// Scheduled call is corrupted - ScheduledCallCorrupted, - /// Scheduled call preimage is not found - PreimageNotFound, - /// Scheduled call is too big - TooBigScheduledCall, - /// Cannot find the scheduled call. - NotFound, - /// Given target block number is in the past. - TargetBlockNumberInPast, - /// Attempt to use a non-named function on a named task. - Named, - } - - #[pallet::hooks] - impl Hooks> for Pallet { - /// Execute the scheduled calls - fn on_initialize(now: T::BlockNumber) -> Weight { - let mut weight_counter = WeightCounter { - used: Weight::zero(), - limit: T::MaximumWeight::get(), - }; - Self::service_agendas(&mut weight_counter, now, u32::max_value()); - weight_counter.used - } - } - - #[pallet::call] - impl Pallet { - /// Anonymously schedule a task. - /// - /// Only `T::ScheduleOrigin` is allowed to schedule a task. - /// Only `T::PrioritySetOrigin` is allowed to set the task's priority. - #[pallet::call_index(0)] - #[pallet::weight(::WeightInfo::schedule(T::MaxScheduledPerBlock::get()))] - pub fn schedule( - origin: OriginFor, - when: T::BlockNumber, - maybe_periodic: Option>, - priority: Option, - call: Box<::RuntimeCall>, - ) -> DispatchResult { - T::ScheduleOrigin::ensure_origin(origin.clone())?; - - if priority.is_some() { - T::PrioritySetOrigin::ensure_origin(origin.clone())?; - } - - let origin = ::RuntimeOrigin::from(origin); - Self::do_schedule( - DispatchTime::At(when), - maybe_periodic, - priority.unwrap_or(LOWEST_PRIORITY), - origin.caller().clone(), - >::new(*call)?, - )?; - Ok(()) - } - - /// Cancel an anonymously scheduled task. - /// - /// The `T::OriginPrivilegeCmp` decides whether the given origin is allowed to cancel the task or not. - #[pallet::call_index(1)] - #[pallet::weight(::WeightInfo::cancel(T::MaxScheduledPerBlock::get()))] - pub fn cancel(origin: OriginFor, when: T::BlockNumber, index: u32) -> DispatchResult { - T::ScheduleOrigin::ensure_origin(origin.clone())?; - let origin = ::RuntimeOrigin::from(origin); - Self::do_cancel(Some(origin.caller().clone()), (when, index))?; - Ok(()) - } - - /// Schedule a named task. - /// - /// Only `T::ScheduleOrigin` is allowed to schedule a task. - /// Only `T::PrioritySetOrigin` is allowed to set the task's priority. - #[pallet::call_index(2)] - #[pallet::weight(::WeightInfo::schedule_named(T::MaxScheduledPerBlock::get()))] - pub fn schedule_named( - origin: OriginFor, - id: TaskName, - when: T::BlockNumber, - maybe_periodic: Option>, - priority: Option, - call: Box<::RuntimeCall>, - ) -> DispatchResult { - T::ScheduleOrigin::ensure_origin(origin.clone())?; - - if priority.is_some() { - T::PrioritySetOrigin::ensure_origin(origin.clone())?; - } - - let origin = ::RuntimeOrigin::from(origin); - Self::do_schedule_named( - id, - DispatchTime::At(when), - maybe_periodic, - priority.unwrap_or(LOWEST_PRIORITY), - origin.caller().clone(), - >::new(*call)?, - )?; - Ok(()) - } - - /// Cancel a named scheduled task. - /// - /// The `T::OriginPrivilegeCmp` decides whether the given origin is allowed to cancel the task or not. - #[pallet::call_index(3)] - #[pallet::weight(::WeightInfo::cancel_named(T::MaxScheduledPerBlock::get()))] - pub fn cancel_named(origin: OriginFor, id: TaskName) -> DispatchResult { - T::ScheduleOrigin::ensure_origin(origin.clone())?; - let origin = ::RuntimeOrigin::from(origin); - Self::do_cancel_named(Some(origin.caller().clone()), id)?; - Ok(()) - } - - /// Anonymously schedule a task after a delay. - /// - /// # - /// Same as [`schedule`]. - /// # - #[pallet::call_index(4)] - #[pallet::weight(::WeightInfo::schedule(T::MaxScheduledPerBlock::get()))] - pub fn schedule_after( - origin: OriginFor, - after: T::BlockNumber, - maybe_periodic: Option>, - priority: Option, - call: Box<::RuntimeCall>, - ) -> DispatchResult { - T::ScheduleOrigin::ensure_origin(origin.clone())?; - - if priority.is_some() { - T::PrioritySetOrigin::ensure_origin(origin.clone())?; - } - - let origin = ::RuntimeOrigin::from(origin); - Self::do_schedule( - DispatchTime::After(after), - maybe_periodic, - priority.unwrap_or(LOWEST_PRIORITY), - origin.caller().clone(), - >::new(*call)?, - )?; - Ok(()) - } - - /// Schedule a named task after a delay. - /// - /// Only `T::ScheduleOrigin` is allowed to schedule a task. - /// Only `T::PrioritySetOrigin` is allowed to set the task's priority. - /// - /// # - /// Same as [`schedule_named`](Self::schedule_named). - /// # - #[pallet::call_index(5)] - #[pallet::weight(::WeightInfo::schedule_named(T::MaxScheduledPerBlock::get()))] - pub fn schedule_named_after( - origin: OriginFor, - id: TaskName, - after: T::BlockNumber, - maybe_periodic: Option>, - priority: Option, - call: Box<::RuntimeCall>, - ) -> DispatchResult { - T::ScheduleOrigin::ensure_origin(origin.clone())?; - - if priority.is_some() { - T::PrioritySetOrigin::ensure_origin(origin.clone())?; - } - - let origin = ::RuntimeOrigin::from(origin); - Self::do_schedule_named( - id, - DispatchTime::After(after), - maybe_periodic, - priority.unwrap_or(LOWEST_PRIORITY), - origin.caller().clone(), - >::new(*call)?, - )?; - Ok(()) - } - - /// Change a named task's priority. - /// - /// Only the `T::PrioritySetOrigin` is allowed to change the task's priority. - #[pallet::call_index(6)] - #[pallet::weight(::WeightInfo::change_named_priority(T::MaxScheduledPerBlock::get()))] - pub fn change_named_priority( - origin: OriginFor, - id: TaskName, - priority: schedule::Priority, - ) -> DispatchResult { - T::PrioritySetOrigin::ensure_origin(origin.clone())?; - let origin = ::RuntimeOrigin::from(origin); - Self::do_change_named_priority(origin.caller().clone(), id, priority) - } - } -} - -impl Pallet { - /// Converts the `DispatchTime` to the `BlockNumber`. - /// - /// Returns an error if the block number is in the past. - fn resolve_time(when: DispatchTime) -> Result { - let now = frame_system::Pallet::::block_number(); - - let when = match when { - DispatchTime::At(x) => x, - // The current block has already completed it's scheduled tasks, so - // Schedule the task at lest one block after this current block. - DispatchTime::After(x) => now.saturating_add(x).saturating_add(One::one()), - }; - - if when <= now { - return Err(Error::::TargetBlockNumberInPast.into()); - } - - Ok(when) - } - - /// Places the mandatory task. - /// - /// It will try to place the task into the block pointed by the `when` parameter. - /// - /// If the block has no room for a task, - /// the function will search for a future block that can accommodate the task. - fn mandatory_place_task(when: T::BlockNumber, what: ScheduledOf) { - Self::place_task(when, what, true).expect("mandatory place task always succeeds; qed"); - } - - /// Tries to place a task `what` into the given block `when`. - /// - /// Returns an error if the block has no room for the task. - fn try_place_task( - when: T::BlockNumber, - what: ScheduledOf, - ) -> Result, DispatchError> { - Self::place_task(when, what, false) - } - - /// If `is_mandatory` is true, the function behaves like [`mandatory_place_task`](Self::mandatory_place_task); - /// otherwise it acts like [`try_place_task`](Self::try_place_task). - /// - /// The function also updates the `Lookup` storage. - fn place_task( - mut when: T::BlockNumber, - what: ScheduledOf, - is_mandatory: bool, - ) -> Result, DispatchError> { - let maybe_name = what.maybe_id; - let index = Self::push_to_agenda(&mut when, what, is_mandatory)?; - let address = (when, index); - if let Some(name) = maybe_name { - Lookup::::insert(name, address) - } - Self::deposit_event(Event::Scheduled { - when: address.0, - index: address.1, - }); - Ok(address) - } - - /// Pushes the scheduled task into the block's agenda. - /// - /// If `is_mandatory` is true, it searches for a block with a free slot for the given task. - /// - /// If `is_mandatory` is false and there is no free slot, the function returns an error. - fn push_to_agenda( - when: &mut T::BlockNumber, - mut what: ScheduledOf, - is_mandatory: bool, - ) -> Result { - let mut agenda; - - let index = loop { - agenda = Agenda::::get(*when); - - match agenda.try_push(what) { - Ok(index) => break index, - Err(returned_what) if is_mandatory => { - what = returned_what; - when.saturating_inc(); - } - Err(_) => return Err(>::AgendaIsExhausted.into()), - } - }; - - Agenda::::insert(when, agenda); - Ok(index) - } - - fn do_schedule( - when: DispatchTime, - maybe_periodic: Option>, - priority: schedule::Priority, - origin: T::PalletsOrigin, - call: ScheduledCall, - ) -> Result, DispatchError> { - let when = Self::resolve_time(when)?; - - // sanitize maybe_periodic - let maybe_periodic = maybe_periodic - .filter(|p| p.1 > 1 && !p.0.is_zero()) - // Remove one from the number of repetitions since we will schedule one now. - .map(|(p, c)| (p, c - 1)); - let task = Scheduled { - maybe_id: None, - priority, - call, - maybe_periodic, - origin, - _phantom: PhantomData, - }; - Self::try_place_task(when, task) - } - - fn do_cancel( - origin: Option, - (when, index): TaskAddress, - ) -> Result<(), DispatchError> { - let scheduled = Agenda::::try_mutate( - when, - |agenda| -> Result>, DispatchError> { - let scheduled = match agenda.get(index) { - Some(scheduled) => scheduled, - None => return Ok(None), - }; - - if let Some(ref o) = origin { - if matches!( - T::OriginPrivilegeCmp::cmp_privilege(o, &scheduled.origin), - Some(Ordering::Less) | None - ) { - return Err(BadOrigin.into()); - } - } - - Ok(agenda.take(index)) - }, - )?; - if let Some(s) = scheduled { - T::Preimages::drop(&s.call); - - if let Some(id) = s.maybe_id { - Lookup::::remove(id); - } - Self::deposit_event(Event::Canceled { when, index }); - Ok(()) - } else { - Err(Error::::NotFound.into()) - } - } - - fn do_schedule_named( - id: TaskName, - when: DispatchTime, - maybe_periodic: Option>, - priority: schedule::Priority, - origin: T::PalletsOrigin, - call: ScheduledCall, - ) -> Result, DispatchError> { - // ensure id it is unique - if Lookup::::contains_key(id) { - return Err(Error::::FailedToSchedule.into()); - } - - let when = Self::resolve_time(when)?; - - // sanitize maybe_periodic - let maybe_periodic = maybe_periodic - .filter(|p| p.1 > 1 && !p.0.is_zero()) - // Remove one from the number of repetitions since we will schedule one now. - .map(|(p, c)| (p, c - 1)); - - let task = Scheduled { - maybe_id: Some(id), - priority, - call, - maybe_periodic, - origin, - _phantom: Default::default(), - }; - Self::try_place_task(when, task) - } - - fn do_cancel_named(origin: Option, id: TaskName) -> DispatchResult { - Lookup::::try_mutate_exists(id, |lookup| -> DispatchResult { - if let Some((when, index)) = lookup.take() { - Agenda::::try_mutate(when, |agenda| -> DispatchResult { - let scheduled = match agenda.get(index) { - Some(scheduled) => scheduled, - None => return Ok(()), - }; - - if let Some(ref o) = origin { - if matches!( - T::OriginPrivilegeCmp::cmp_privilege(o, &scheduled.origin), - Some(Ordering::Less) | None - ) { - return Err(BadOrigin.into()); - } - T::Preimages::drop(&scheduled.call); - } - - agenda.take(index); - - Ok(()) - })?; - Self::deposit_event(Event::Canceled { when, index }); - Ok(()) - } else { - Err(Error::::NotFound.into()) - } - }) - } - - fn do_change_named_priority( - origin: T::PalletsOrigin, - id: TaskName, - priority: schedule::Priority, - ) -> DispatchResult { - match Lookup::::get(id) { - Some((when, index)) => Agenda::::try_mutate(when, |agenda| { - let scheduled = match agenda.get_mut(index) { - Some(scheduled) => scheduled, - None => return Ok(()), - }; - - if matches!( - T::OriginPrivilegeCmp::cmp_privilege(&origin, &scheduled.origin), - Some(Ordering::Less) | None - ) { - return Err(BadOrigin.into()); - } - - scheduled.priority = priority; - Self::deposit_event(Event::PriorityChanged { - task: (when, index), - priority, - }); - - Ok(()) - }), - None => Err(Error::::NotFound.into()), - } - } -} - -enum ServiceTaskError { - /// Could not be executed due to missing preimage. - Unavailable, - /// Could not be executed due to weight limitations. - Overweight, -} -use ServiceTaskError::*; - -/// A Scheduler-Runtime interface for finer payment handling. -pub trait DispatchCall { - /// Resolve the call dispatch, including any post-dispatch operations. - fn dispatch_call( - signer: Option, - function: ::RuntimeCall, - ) -> Result< - Result>, - TransactionValidityError, - >; -} - -impl Pallet { - /// Service up to `max` agendas queue starting from earliest incompletely executed agenda. - fn service_agendas(weight: &mut WeightCounter, now: T::BlockNumber, max: u32) { - if !weight.check_accrue(T::WeightInfo::service_agendas_base()) { - return; - } - - let mut incomplete_since = now + One::one(); - let mut when = IncompleteSince::::take().unwrap_or(now); - let mut executed = 0; - - let max_items = T::MaxScheduledPerBlock::get(); - let mut count_down = max; - let service_agenda_base_weight = T::WeightInfo::service_agenda_base(max_items); - while count_down > 0 && when <= now && weight.can_accrue(service_agenda_base_weight) { - if !Self::service_agenda(weight, &mut executed, now, when, u32::max_value()) { - incomplete_since = incomplete_since.min(when); - } - when.saturating_inc(); - count_down.saturating_dec(); - } - incomplete_since = incomplete_since.min(when); - if incomplete_since <= now { - IncompleteSince::::put(incomplete_since); - } - } - - /// Returns `true` if the agenda was fully completed, `false` if it should be revisited at a - /// later block. - fn service_agenda( - weight: &mut WeightCounter, - executed: &mut u32, - now: T::BlockNumber, - when: T::BlockNumber, - max: u32, - ) -> bool { - let mut agenda = Agenda::::get(when); - let mut ordered = agenda - .iter() - .enumerate() - .filter_map(|(index, maybe_item)| { - maybe_item - .as_ref() - .map(|item| (index as u32, item.priority)) - }) - .collect::>(); - ordered.sort_by_key(|k| k.1); - let within_limit = - weight.check_accrue(T::WeightInfo::service_agenda_base(ordered.len() as u32)); - debug_assert!( - within_limit, - "weight limit should have been checked in advance" - ); - - // Items which we know can be executed and have postponed for execution in a later block. - let mut postponed = (ordered.len() as u32).saturating_sub(max); - // Items which we don't know can ever be executed. - let mut dropped = 0; - - for (agenda_index, _) in ordered.into_iter().take(max as usize) { - let task = match agenda.take(agenda_index).take() { - None => continue, - Some(t) => t, - }; - let base_weight = MarginalWeightInfo::::service_task( - task.call.lookup_len().map(|x| x as usize), - task.maybe_id.is_some(), - task.maybe_periodic.is_some(), - ); - if !weight.can_accrue(base_weight) { - postponed += 1; - break; - } - let result = Self::service_task(weight, now, when, agenda_index, *executed == 0, task); - match result { - Err((Unavailable, slot)) => { - dropped += 1; - agenda.set_slot(agenda_index, slot); - } - Err((Overweight, slot)) => { - postponed += 1; - agenda.set_slot(agenda_index, slot); - } - Ok(()) => { - *executed += 1; - } - }; - } - if postponed > 0 || dropped > 0 { - Agenda::::insert(when, agenda); - } else { - Agenda::::remove(when); - } - postponed == 0 - } - - /// Service (i.e. execute) the given task, being careful not to overflow the `weight` counter. - /// - /// This involves: - /// - removing and potentially replacing the `Lookup` entry for the task. - /// - realizing the task's call which can include a preimage lookup. - /// - Rescheduling the task for execution in a later agenda if periodic. - fn service_task( - weight: &mut WeightCounter, - now: T::BlockNumber, - when: T::BlockNumber, - agenda_index: u32, - is_first: bool, - mut task: ScheduledOf, - ) -> Result<(), (ServiceTaskError, Option>)> { - let (call, lookup_len) = match T::Preimages::peek(&task.call) { - Ok(c) => c, - Err(_) => { - if let Some(ref id) = task.maybe_id { - Lookup::::remove(id); - } - - return Err((Unavailable, Some(task))); - } - }; - - weight.check_accrue(MarginalWeightInfo::::service_task( - lookup_len.map(|x| x as usize), - task.maybe_id.is_some(), - task.maybe_periodic.is_some(), - )); - - match Self::execute_dispatch(weight, task.origin.clone(), call) { - Err(Unavailable) => { - debug_assert!(false, "Checked to exist with `peek`"); - - if let Some(ref id) = task.maybe_id { - Lookup::::remove(id); - } - - Self::deposit_event(Event::CallUnavailable { - task: (when, agenda_index), - id: task.maybe_id, - }); - Err((Unavailable, Some(task))) - } - Err(Overweight) if is_first && !Self::is_runtime_upgraded() => { - T::Preimages::drop(&task.call); - - if let Some(ref id) = task.maybe_id { - Lookup::::remove(id); - } - - Self::deposit_event(Event::PermanentlyOverweight { - task: (when, agenda_index), - id: task.maybe_id, - }); - Err((Unavailable, Some(task))) - } - Err(Overweight) => { - // Preserve Lookup -- the task will be postponed. - Err((Overweight, Some(task))) - } - Ok(result) => { - Self::deposit_event(Event::Dispatched { - task: (when, agenda_index), - id: task.maybe_id, - result, - }); - - let is_canceled = task - .maybe_id - .as_ref() - .map(|id| !Lookup::::contains_key(id)) - .unwrap_or(false); - - match &task.maybe_periodic { - &Some((period, count)) if !is_canceled => { - if count > 1 { - task.maybe_periodic = Some((period, count - 1)); - } else { - task.maybe_periodic = None; - } - let wake = now.saturating_add(period); - Self::mandatory_place_task(wake, task); - } - _ => { - if let Some(ref id) = task.maybe_id { - Lookup::::remove(id); - } - - T::Preimages::drop(&task.call) - } - } - Ok(()) - } - } - } - - fn is_runtime_upgraded() -> bool { - let last = system::LastRuntimeUpgrade::::get(); - let current = T::Version::get(); - - last.map(|v| v.was_upgraded(¤t)).unwrap_or(true) - } - - /// Make a dispatch to the given `call` from the given `origin`, ensuring that the `weight` - /// counter does not exceed its limit and that it is counted accurately (e.g. accounted using - /// post info if available). - /// - /// NOTE: Only the weight for this function will be counted (origin lookup, dispatch and the - /// call itself). - fn execute_dispatch( - weight: &mut WeightCounter, - origin: T::PalletsOrigin, - call: ::RuntimeCall, - ) -> Result { - let dispatch_origin: ::RuntimeOrigin = origin.into(); - let base_weight = match dispatch_origin.clone().as_signed() { - Some(_) => T::WeightInfo::execute_dispatch_signed(), - _ => T::WeightInfo::execute_dispatch_unsigned(), - }; - let call_weight = call.get_dispatch_info().weight; - // We only allow a scheduled call if it cannot push the weight past the limit. - let max_weight = base_weight.saturating_add(call_weight); - - if !weight.can_accrue(max_weight) { - return Err(Overweight); - } - - let ensured_origin = T::ScheduleOrigin::ensure_origin(dispatch_origin.into()); - - let r = match ensured_origin { - Ok(ScheduledEnsureOriginSuccess::Root) => { - Ok(call.dispatch_bypass_filter(frame_system::RawOrigin::Root.into())) - } - Ok(ScheduledEnsureOriginSuccess::Signed(sender)) => { - // Execute transaction via chain default pipeline - // That means dispatch will be processed like any user's extrinsic e.g. transaction fees will be taken - T::CallExecutor::dispatch_call(Some(sender), call) - } - Err(e) => Ok(Err(e.into())), - }; - - let (maybe_actual_call_weight, result) = match r { - Ok(result) => match result { - Ok(post_info) => (post_info.actual_weight, Ok(())), - Err(error_and_info) => ( - error_and_info.post_info.actual_weight, - Err(error_and_info.error), - ), - }, - Err(_) => { - log::error!( - target: "runtime::scheduler", - "Warning: Scheduler has failed to execute a post-dispatch transaction. \ - This block might have become invalid."); - (None, Err(DispatchError::CannotLookup)) - } - }; - let call_weight = maybe_actual_call_weight.unwrap_or(call_weight); - weight.check_accrue(base_weight); - weight.check_accrue(call_weight); - Ok(result) - } -} --- a/pallets/scheduler-v2/src/mock.rs +++ /dev/null @@ -1,292 +0,0 @@ -// Copyright 2019-2022 Unique Network (Gibraltar) Ltd. -// This file is part of Unique Network. - -// Unique Network is free software: you can redistribute it and/or modify -// it under the terms of the GNU General Public License as published by -// the Free Software Foundation, either version 3 of the License, or -// (at your option) any later version. - -// Unique Network is distributed in the hope that it will be useful, -// but WITHOUT ANY WARRANTY; without even the implied warranty of -// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the -// GNU General Public License for more details. - -// You should have received a copy of the GNU General Public License -// along with Unique Network. If not, see . - -// Original license: -// This file is part of Substrate. - -// Copyright (C) 2017-2022 Parity Technologies (UK) Ltd. -// SPDX-License-Identifier: Apache-2.0 - -// Licensed under the Apache License, Version 2.0 (the "License"); -// you may not use this file except in compliance with the License. -// You may obtain a copy of the License at -// -// http://www.apache.org/licenses/LICENSE-2.0 -// -// Unless required by applicable law or agreed to in writing, software -// distributed under the License is distributed on an "AS IS" BASIS, -// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. -// See the License for the specific language governing permissions and -// limitations under the License. - -//! # Scheduler test environment. -#![allow(deprecated)] - -use super::*; - -use crate as scheduler; -use frame_support::{ - ord_parameter_types, parameter_types, - traits::{ConstU32, ConstU64, Contains, EqualPrivilegeOnly, OnFinalize, OnInitialize}, - weights::constants::RocksDbWeight, -}; -use frame_system::{EnsureRoot, RawOrigin}; -use sp_core::H256; -use sp_runtime::{ - testing::Header, - traits::{BlakeTwo256, IdentityLookup}, - Perbill, -}; - -// Logger module to track execution. -#[frame_support::pallet] -pub mod logger { - use super::{OriginCaller, OriginTrait}; - use frame_support::{pallet_prelude::*, parameter_types}; - use frame_system::pallet_prelude::*; - - parameter_types! { - static Log: Vec<(OriginCaller, u32)> = Vec::new(); - } - pub fn log() -> Vec<(OriginCaller, u32)> { - Log::get().clone() - } - - #[pallet::pallet] - pub struct Pallet(PhantomData); - - #[pallet::hooks] - impl Hooks> for Pallet {} - - #[pallet::config] - pub trait Config: frame_system::Config { - type RuntimeEvent: From> + IsType<::RuntimeEvent>; - } - - #[pallet::event] - #[pallet::generate_deposit(pub(super) fn deposit_event)] - pub enum Event { - Logged(u32, Weight), - } - - #[pallet::call] - impl Pallet - where - ::RuntimeOrigin: OriginTrait, - { - #[pallet::call_index(0)] - #[pallet::weight(*weight)] - pub fn log(origin: OriginFor, i: u32, weight: Weight) -> DispatchResult { - Self::deposit_event(Event::Logged(i, weight)); - Log::mutate(|log| { - log.push((origin.caller().clone(), i)); - }); - Ok(()) - } - - #[pallet::call_index(1)] - #[pallet::weight(*weight)] - pub fn log_without_filter(origin: OriginFor, i: u32, weight: Weight) -> DispatchResult { - Self::deposit_event(Event::Logged(i, weight)); - Log::mutate(|log| { - log.push((origin.caller().clone(), i)); - }); - Ok(()) - } - } -} - -type UncheckedExtrinsic = frame_system::mocking::MockUncheckedExtrinsic; -type Block = frame_system::mocking::MockBlock; - -frame_support::construct_runtime!( - pub enum Test where - Block = Block, - NodeBlock = Block, - UncheckedExtrinsic = UncheckedExtrinsic, - { - System: frame_system::{Pallet, Call, Config, Storage, Event}, - Logger: logger::{Pallet, Call, Event}, - Scheduler: scheduler::{Pallet, Call, Storage, Event}, - } -); - -// Scheduler must dispatch with root and no filter, this tests base filter is indeed not used. -pub struct BaseFilter; -impl Contains for BaseFilter { - fn contains(call: &RuntimeCall) -> bool { - !matches!(call, RuntimeCall::Logger(LoggerCall::log { .. })) - } -} - -parameter_types! { - pub BlockWeights: frame_system::limits::BlockWeights = - frame_system::limits::BlockWeights::simple_max( - Weight::from_ref_time(2_000_000_000_000).set_proof_size(u64::MAX) - ); -} -impl system::Config for Test { - type BaseCallFilter = BaseFilter; - type BlockWeights = BlockWeights; - type BlockLength = (); - type DbWeight = RocksDbWeight; - type RuntimeOrigin = RuntimeOrigin; - type RuntimeCall = RuntimeCall; - type Index = u64; - type BlockNumber = u64; - type Hash = H256; - type Hashing = BlakeTwo256; - type AccountId = u64; - type Lookup = IdentityLookup; - type Header = Header; - type RuntimeEvent = RuntimeEvent; - type BlockHashCount = ConstU64<250>; - type Version = (); - type PalletInfo = PalletInfo; - type AccountData = (); - type OnNewAccount = (); - type OnKilledAccount = (); - type SystemWeightInfo = (); - type SS58Prefix = (); - type OnSetCode = (); - type MaxConsumers = ConstU32<16>; -} -impl logger::Config for Test { - type RuntimeEvent = RuntimeEvent; -} -ord_parameter_types! { - pub const One: u64 = 1; -} - -pub struct TestWeightInfo; -impl WeightInfo for TestWeightInfo { - fn service_agendas_base() -> Weight { - Weight::from_ref_time(0b0000_0001) - } - fn service_agenda_base(i: u32) -> Weight { - Weight::from_ref_time((i << 8) as u64 + 0b0000_0010) - } - fn service_task_base() -> Weight { - Weight::from_ref_time(0b0000_0100) - } - fn service_task_periodic() -> Weight { - Weight::from_ref_time(0b0000_1100) - } - fn service_task_named() -> Weight { - Weight::from_ref_time(0b0001_0100) - } - // fn service_task_fetched(s: u32) -> Weight { - // Weight::from_ref_time((s << 8) as u64 + 0b0010_0100) - // } - fn execute_dispatch_signed() -> Weight { - Weight::from_ref_time(0b0100_0000) - } - fn execute_dispatch_unsigned() -> Weight { - Weight::from_ref_time(0b1000_0000) - } - fn schedule(_s: u32) -> Weight { - Weight::from_ref_time(50) - } - fn cancel(_s: u32) -> Weight { - Weight::from_ref_time(50) - } - fn schedule_named(_s: u32) -> Weight { - Weight::from_ref_time(50) - } - fn cancel_named(_s: u32) -> Weight { - Weight::from_ref_time(50) - } - fn change_named_priority(_s: u32) -> Weight { - Weight::from_ref_time(50) - } -} -parameter_types! { - pub MaximumSchedulerWeight: Weight = Perbill::from_percent(80) * - BlockWeights::get().max_block; -} - -pub struct EnsureSignedOneOrRoot; -impl, O>> + From>> EnsureOrigin - for EnsureSignedOneOrRoot -{ - type Success = ScheduledEnsureOriginSuccess; - fn try_origin(o: O) -> Result { - o.into().and_then(|o| match o { - RawOrigin::Root => Ok(ScheduledEnsureOriginSuccess::Root), - RawOrigin::Signed(1) => Ok(ScheduledEnsureOriginSuccess::Signed(1)), - r => Err(O::from(r)), - }) - } - #[cfg(feature = "runtime-benchmarks")] - fn try_successful_origin() -> Result { - Ok(O::from(RawOrigin::Root)) - } -} - -pub struct Executor; -impl DispatchCall for Executor { - fn dispatch_call( - signer: Option, - function: RuntimeCall, - ) -> Result< - Result>, - TransactionValidityError, - > { - let origin = match signer { - Some(who) => RuntimeOrigin::signed(who), - None => RuntimeOrigin::none(), - }; - Ok(function.dispatch(origin)) - } -} - -impl Config for Test { - type RuntimeEvent = RuntimeEvent; - type RuntimeOrigin = RuntimeOrigin; - type PalletsOrigin = OriginCaller; - type RuntimeCall = RuntimeCall; - type MaximumWeight = MaximumSchedulerWeight; - type ScheduleOrigin = EnsureSignedOneOrRoot; - type MaxScheduledPerBlock = ConstU32<10>; - type WeightInfo = TestWeightInfo; - type OriginPrivilegeCmp = EqualPrivilegeOnly; - type Preimages = (); - type PrioritySetOrigin = EnsureRoot; - type CallExecutor = Executor; -} - -pub type LoggerCall = logger::Call; - -pub type SystemCall = frame_system::Call; - -pub fn new_test_ext() -> sp_io::TestExternalities { - let t = system::GenesisConfig::default() - .build_storage::() - .unwrap(); - t.into() -} - -pub fn run_to_block(n: u64) { - while System::block_number() < n { - Scheduler::on_finalize(System::block_number()); - System::set_block_number(System::block_number() + 1); - Scheduler::on_initialize(System::block_number()); - } -} - -pub fn root() -> OriginCaller { - system::RawOrigin::Root.into() -} --- a/pallets/scheduler-v2/src/tests.rs +++ /dev/null @@ -1,901 +0,0 @@ -// Copyright 2019-2022 Unique Network (Gibraltar) Ltd. -// This file is part of Unique Network. - -// Unique Network is free software: you can redistribute it and/or modify -// it under the terms of the GNU General Public License as published by -// the Free Software Foundation, either version 3 of the License, or -// (at your option) any later version. - -// Unique Network is distributed in the hope that it will be useful, -// but WITHOUT ANY WARRANTY; without even the implied warranty of -// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the -// GNU General Public License for more details. - -// You should have received a copy of the GNU General Public License -// along with Unique Network. If not, see . - -// Original license: -// This file is part of Substrate. - -// Copyright (C) 2017-2022 Parity Technologies (UK) Ltd. -// SPDX-License-Identifier: Apache-2.0 - -// Licensed under the Apache License, Version 2.0 (the "License"); -// you may not use this file except in compliance with the License. -// You may obtain a copy of the License at -// -// http://www.apache.org/licenses/LICENSE-2.0 -// -// Unless required by applicable law or agreed to in writing, software -// distributed under the License is distributed on an "AS IS" BASIS, -// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. -// See the License for the specific language governing permissions and -// limitations under the License. - -//! # Scheduler tests. -#![allow(deprecated)] - -use super::*; -use crate::mock::{ - logger, new_test_ext, root, run_to_block, LoggerCall, RuntimeCall, Scheduler, Test, *, -}; -use frame_support::{ - assert_noop, assert_ok, - traits::{Contains, OnInitialize}, - assert_err, -}; - -#[test] -fn basic_scheduling_works() { - new_test_ext().execute_with(|| { - let call = RuntimeCall::Logger(LoggerCall::log { - i: 42, - weight: Weight::from_ref_time(10), - }); - assert!(!::BaseCallFilter::contains( - &call - )); - assert_ok!(Scheduler::do_schedule( - DispatchTime::At(4), - None, - 127, - root(), - >::new(call).unwrap(), - )); - run_to_block(3); - assert!(logger::log().is_empty()); - run_to_block(4); - assert_eq!(logger::log(), vec![(root(), 42u32)]); - run_to_block(100); - assert_eq!(logger::log(), vec![(root(), 42u32)]); - }); -} - -#[test] -fn schedule_after_works() { - new_test_ext().execute_with(|| { - run_to_block(2); - let call = RuntimeCall::Logger(LoggerCall::log { - i: 42, - weight: Weight::from_ref_time(10), - }); - assert!(!::BaseCallFilter::contains( - &call - )); - // This will schedule the call 3 blocks after the next block... so block 3 + 3 = 6 - assert_ok!(Scheduler::do_schedule( - DispatchTime::After(3), - None, - 127, - root(), - >::new(call).unwrap(), - )); - run_to_block(5); - assert!(logger::log().is_empty()); - run_to_block(6); - assert_eq!(logger::log(), vec![(root(), 42u32)]); - run_to_block(100); - assert_eq!(logger::log(), vec![(root(), 42u32)]); - }); -} - -#[test] -fn schedule_after_zero_works() { - new_test_ext().execute_with(|| { - run_to_block(2); - let call = RuntimeCall::Logger(LoggerCall::log { - i: 42, - weight: Weight::from_ref_time(10), - }); - assert!(!::BaseCallFilter::contains( - &call - )); - assert_ok!(Scheduler::do_schedule( - DispatchTime::After(0), - None, - 127, - root(), - >::new(call).unwrap(), - )); - // Will trigger on the next block. - run_to_block(3); - assert_eq!(logger::log(), vec![(root(), 42u32)]); - run_to_block(100); - assert_eq!(logger::log(), vec![(root(), 42u32)]); - }); -} - -#[test] -fn periodic_scheduling_works() { - new_test_ext().execute_with(|| { - // at #4, every 3 blocks, 3 times. - assert_ok!(Scheduler::do_schedule( - DispatchTime::At(4), - Some((3, 3)), - 127, - root(), - >::new(RuntimeCall::Logger(logger::Call::log { - i: 42, - weight: Weight::from_ref_time(10) - })) - .unwrap() - )); - run_to_block(3); - assert!(logger::log().is_empty()); - run_to_block(4); - assert_eq!(logger::log(), vec![(root(), 42u32)]); - run_to_block(6); - assert_eq!(logger::log(), vec![(root(), 42u32)]); - run_to_block(7); - assert_eq!(logger::log(), vec![(root(), 42u32), (root(), 42u32)]); - run_to_block(9); - assert_eq!(logger::log(), vec![(root(), 42u32), (root(), 42u32)]); - run_to_block(10); - assert_eq!( - logger::log(), - vec![(root(), 42u32), (root(), 42u32), (root(), 42u32)] - ); - run_to_block(100); - assert_eq!( - logger::log(), - vec![(root(), 42u32), (root(), 42u32), (root(), 42u32)] - ); - }); -} - -#[test] -fn cancel_named_scheduling_works_with_normal_cancel() { - new_test_ext().execute_with(|| { - // at #4. - Scheduler::do_schedule_named( - [1u8; 32], - DispatchTime::At(4), - None, - 127, - root(), - >::new(RuntimeCall::Logger(LoggerCall::log { - i: 69, - weight: Weight::from_ref_time(10), - })) - .unwrap(), - ) - .unwrap(); - let i = Scheduler::do_schedule( - DispatchTime::At(4), - None, - 127, - root(), - >::new(RuntimeCall::Logger(LoggerCall::log { - i: 42, - weight: Weight::from_ref_time(10), - })) - .unwrap(), - ) - .unwrap(); - run_to_block(3); - assert!(logger::log().is_empty()); - assert_ok!(Scheduler::do_cancel_named(None, [1u8; 32])); - assert_ok!(Scheduler::do_cancel(None, i)); - run_to_block(100); - assert!(logger::log().is_empty()); - }); -} - -#[test] -fn cancel_named_periodic_scheduling_works() { - new_test_ext().execute_with(|| { - // at #4, every 3 blocks, 3 times. - Scheduler::do_schedule_named( - [1u8; 32], - DispatchTime::At(4), - Some((3, 3)), - 127, - root(), - >::new(RuntimeCall::Logger(LoggerCall::log { - i: 42, - weight: Weight::from_ref_time(10), - })) - .unwrap(), - ) - .unwrap(); - // same id results in error. - assert!(Scheduler::do_schedule_named( - [1u8; 32], - DispatchTime::At(4), - None, - 127, - root(), - >::new(RuntimeCall::Logger(LoggerCall::log { - i: 69, - weight: Weight::from_ref_time(10) - })) - .unwrap(), - ) - .is_err()); - // different id is ok. - Scheduler::do_schedule_named( - [2u8; 32], - DispatchTime::At(8), - None, - 127, - root(), - >::new(RuntimeCall::Logger(LoggerCall::log { - i: 69, - weight: Weight::from_ref_time(10), - })) - .unwrap(), - ) - .unwrap(); - run_to_block(3); - assert!(logger::log().is_empty()); - run_to_block(4); - assert_eq!(logger::log(), vec![(root(), 42u32)]); - run_to_block(6); - assert_ok!(Scheduler::do_cancel_named(None, [1u8; 32])); - run_to_block(100); - assert_eq!(logger::log(), vec![(root(), 42u32), (root(), 69u32)]); - }); -} - -#[test] -fn scheduler_respects_weight_limits() { - let max_weight: Weight = ::MaximumWeight::get(); - new_test_ext().execute_with(|| { - let call = RuntimeCall::Logger(LoggerCall::log { - i: 42, - weight: max_weight / 3 * 2, - }); - assert_ok!(Scheduler::do_schedule( - DispatchTime::At(4), - None, - 127, - root(), - >::new(call).unwrap(), - )); - let call = RuntimeCall::Logger(LoggerCall::log { - i: 69, - weight: max_weight / 3 * 2, - }); - assert_ok!(Scheduler::do_schedule( - DispatchTime::At(4), - None, - 127, - root(), - >::new(call).unwrap(), - )); - // 69 and 42 do not fit together - run_to_block(4); - assert_eq!(logger::log(), vec![(root(), 42u32)]); - run_to_block(5); - assert_eq!(logger::log(), vec![(root(), 42u32), (root(), 69u32)]); - }); -} - -/// Permanently overweight calls are not deleted but also not executed. -#[test] -fn scheduler_does_not_delete_permanently_overweight_call() { - let max_weight: Weight = ::MaximumWeight::get(); - new_test_ext().execute_with(|| { - let call = RuntimeCall::Logger(LoggerCall::log { - i: 42, - weight: max_weight, - }); - assert_ok!(Scheduler::do_schedule( - DispatchTime::At(4), - None, - 127, - root(), - >::new(call).unwrap(), - )); - // Never executes. - run_to_block(100); - assert_eq!(logger::log(), vec![]); - - // Assert the `PermanentlyOverweight` event. - assert_eq!( - System::events().last().unwrap().event, - crate::Event::PermanentlyOverweight { - task: (4, 0), - id: None - } - .into(), - ); - // The call is still in the agenda. - assert!(Agenda::::get(4).agenda[0].is_some()); - }); -} - -#[test] -fn scheduler_periodic_tasks_always_find_place() { - let max_weight: Weight = ::MaximumWeight::get(); - let max_per_block = ::MaxScheduledPerBlock::get(); - - new_test_ext().execute_with(|| { - let call = RuntimeCall::Logger(LoggerCall::log { - i: 42, - weight: (max_weight / 3) * 2, - }); - let call = >::new(call).unwrap(); - - assert_ok!(Scheduler::do_schedule( - DispatchTime::At(4), - Some((4, u32::MAX)), - 127, - root(), - call.clone(), - )); - // Executes 5 times till block 20. - run_to_block(20); - assert_eq!(logger::log().len(), 5); - - // Block 28 will already be full. - for _ in 0..max_per_block { - assert_ok!(Scheduler::do_schedule( - DispatchTime::At(28), - None, - 120, - root(), - call.clone(), - )); - } - - run_to_block(24); - assert_eq!(logger::log().len(), 6); - - // The periodic task should be postponed - assert_eq!(>::get(29).agenda.len(), 1); - - run_to_block(27); // will call on_initialize(28) - assert_eq!(logger::log().len(), 6); - - run_to_block(28); // will call on_initialize(29) - assert_eq!(logger::log().len(), 7); - }); -} - -#[test] -fn scheduler_respects_priority_ordering() { - let max_weight: Weight = ::MaximumWeight::get(); - new_test_ext().execute_with(|| { - let call = RuntimeCall::Logger(LoggerCall::log { - i: 42, - weight: max_weight / 3, - }); - assert_ok!(Scheduler::do_schedule( - DispatchTime::At(4), - None, - 1, - root(), - >::new(call).unwrap(), - )); - let call = RuntimeCall::Logger(LoggerCall::log { - i: 69, - weight: max_weight / 3, - }); - assert_ok!(Scheduler::do_schedule( - DispatchTime::At(4), - None, - 0, - root(), - >::new(call).unwrap(), - )); - run_to_block(4); - assert_eq!(logger::log(), vec![(root(), 69u32), (root(), 42u32)]); - }); -} - -#[test] -fn scheduler_respects_priority_ordering_with_soft_deadlines() { - new_test_ext().execute_with(|| { - let max_weight: Weight = ::MaximumWeight::get(); - let call = RuntimeCall::Logger(LoggerCall::log { - i: 42, - weight: max_weight / 5 * 2, - }); - assert_ok!(Scheduler::do_schedule( - DispatchTime::At(4), - None, - 255, - root(), - >::new(call).unwrap(), - )); - let call = RuntimeCall::Logger(LoggerCall::log { - i: 69, - weight: max_weight / 5 * 2, - }); - assert_ok!(Scheduler::do_schedule( - DispatchTime::At(4), - None, - 127, - root(), - >::new(call).unwrap(), - )); - let call = RuntimeCall::Logger(LoggerCall::log { - i: 2600, - weight: max_weight / 5 * 4, - }); - assert_ok!(Scheduler::do_schedule( - DispatchTime::At(4), - None, - 126, - root(), - >::new(call).unwrap(), - )); - - // 2600 does not fit with 69 or 42, but has higher priority, so will go through - run_to_block(4); - assert_eq!(logger::log(), vec![(root(), 2600u32)]); - // 69 and 42 fit together - run_to_block(5); - assert_eq!( - logger::log(), - vec![(root(), 2600u32), (root(), 69u32), (root(), 42u32)] - ); - }); -} - -#[test] -fn on_initialize_weight_is_correct() { - new_test_ext().execute_with(|| { - let call_weight = Weight::from_ref_time(25); - - // Named - let call = RuntimeCall::Logger(LoggerCall::log { - i: 3, - weight: call_weight + Weight::from_ref_time(1), - }); - assert_ok!(Scheduler::do_schedule_named( - [1u8; 32], - DispatchTime::At(3), - None, - 255, - root(), - >::new(call).unwrap(), - )); - let call = RuntimeCall::Logger(LoggerCall::log { - i: 42, - weight: call_weight + Weight::from_ref_time(2), - }); - // Anon Periodic - assert_ok!(Scheduler::do_schedule( - DispatchTime::At(2), - Some((1000, 3)), - 128, - root(), - >::new(call).unwrap(), - )); - let call = RuntimeCall::Logger(LoggerCall::log { - i: 69, - weight: call_weight + Weight::from_ref_time(3), - }); - // Anon - assert_ok!(Scheduler::do_schedule( - DispatchTime::At(2), - None, - 127, - root(), - >::new(call).unwrap(), - )); - // Named Periodic - let call = RuntimeCall::Logger(LoggerCall::log { - i: 2600, - weight: call_weight + Weight::from_ref_time(4), - }); - assert_ok!(Scheduler::do_schedule_named( - [2u8; 32], - DispatchTime::At(1), - Some((1000, 3)), - 126, - root(), - >::new(call).unwrap(), - )); - - // Will include the named periodic only - assert_eq!( - Scheduler::on_initialize(1), - TestWeightInfo::service_agendas_base() - + TestWeightInfo::service_agenda_base(1) - + >::service_task(None, true, true) - + TestWeightInfo::execute_dispatch_unsigned() - + call_weight + Weight::from_ref_time(4) - ); - assert_eq!(IncompleteSince::::get(), None); - assert_eq!(logger::log(), vec![(root(), 2600u32)]); - - // Will include anon and anon periodic - assert_eq!( - Scheduler::on_initialize(2), - TestWeightInfo::service_agendas_base() - + TestWeightInfo::service_agenda_base(2) - + >::service_task(None, false, true) - + TestWeightInfo::execute_dispatch_unsigned() - + call_weight + Weight::from_ref_time(3) - + >::service_task(None, false, false) - + TestWeightInfo::execute_dispatch_unsigned() - + call_weight + Weight::from_ref_time(2) - ); - assert_eq!(IncompleteSince::::get(), None); - assert_eq!( - logger::log(), - vec![(root(), 2600u32), (root(), 69u32), (root(), 42u32)] - ); - - // Will include named only - assert_eq!( - Scheduler::on_initialize(3), - TestWeightInfo::service_agendas_base() - + TestWeightInfo::service_agenda_base(1) - + >::service_task(None, true, false) - + TestWeightInfo::execute_dispatch_unsigned() - + call_weight + Weight::from_ref_time(1) - ); - assert_eq!(IncompleteSince::::get(), None); - assert_eq!( - logger::log(), - vec![ - (root(), 2600u32), - (root(), 69u32), - (root(), 42u32), - (root(), 3u32) - ] - ); - - // Will contain none - let actual_weight = Scheduler::on_initialize(4); - assert_eq!( - actual_weight, - TestWeightInfo::service_agendas_base() + TestWeightInfo::service_agenda_base(0) - ); - }); -} - -#[test] -fn root_calls_works() { - new_test_ext().execute_with(|| { - let call = Box::new(RuntimeCall::Logger(LoggerCall::log { - i: 69, - weight: Weight::from_ref_time(10), - })); - let call2 = Box::new(RuntimeCall::Logger(LoggerCall::log { - i: 42, - weight: Weight::from_ref_time(10), - })); - assert_ok!(Scheduler::schedule_named( - RuntimeOrigin::root(), - [1u8; 32], - 4, - None, - Some(127), - call, - )); - assert_ok!(Scheduler::schedule( - RuntimeOrigin::root(), - 4, - None, - Some(127), - call2 - )); - run_to_block(3); - // Scheduled calls are in the agenda. - assert_eq!(Agenda::::get(4).agenda.len(), 2); - assert!(logger::log().is_empty()); - assert_ok!(Scheduler::cancel_named(RuntimeOrigin::root(), [1u8; 32])); - assert_ok!(Scheduler::cancel(RuntimeOrigin::root(), 4, 1)); - // Scheduled calls are made NONE, so should not effect state - run_to_block(100); - assert!(logger::log().is_empty()); - }); -} - -#[test] -fn fails_to_schedule_task_in_the_past() { - new_test_ext().execute_with(|| { - run_to_block(3); - - let call1 = Box::new(RuntimeCall::Logger(LoggerCall::log { - i: 69, - weight: Weight::from_ref_time(10), - })); - let call2 = Box::new(RuntimeCall::Logger(LoggerCall::log { - i: 42, - weight: Weight::from_ref_time(10), - })); - let call3 = Box::new(RuntimeCall::Logger(LoggerCall::log { - i: 42, - weight: Weight::from_ref_time(10), - })); - - assert_noop!( - Scheduler::schedule_named(RuntimeOrigin::root(), [1u8; 32], 2, None, Some(127), call1), - Error::::TargetBlockNumberInPast, - ); - - assert_noop!( - Scheduler::schedule(RuntimeOrigin::root(), 2, None, Some(127), call2), - Error::::TargetBlockNumberInPast, - ); - - assert_noop!( - Scheduler::schedule(RuntimeOrigin::root(), 3, None, Some(127), call3), - Error::::TargetBlockNumberInPast, - ); - }); -} - -#[test] -fn should_use_origin() { - new_test_ext().execute_with(|| { - let call = Box::new(RuntimeCall::Logger(LoggerCall::log { - i: 69, - weight: Weight::from_ref_time(10), - })); - let call2 = Box::new(RuntimeCall::Logger(LoggerCall::log { - i: 42, - weight: Weight::from_ref_time(10), - })); - assert_ok!(Scheduler::schedule_named( - system::RawOrigin::Signed(1).into(), - [1u8; 32], - 4, - None, - None, - call, - )); - assert_ok!(Scheduler::schedule( - system::RawOrigin::Signed(1).into(), - 4, - None, - None, - call2, - )); - run_to_block(3); - // Scheduled calls are in the agenda. - assert_eq!(Agenda::::get(4).agenda.len(), 2); - assert!(logger::log().is_empty()); - assert_ok!(Scheduler::cancel_named( - system::RawOrigin::Signed(1).into(), - [1u8; 32] - )); - assert_ok!(Scheduler::cancel(system::RawOrigin::Signed(1).into(), 4, 1)); - // Scheduled calls are made NONE, so should not effect state - run_to_block(100); - assert!(logger::log().is_empty()); - }); -} - -#[test] -fn should_check_origin() { - new_test_ext().execute_with(|| { - let call = Box::new(RuntimeCall::Logger(LoggerCall::log { - i: 69, - weight: Weight::from_ref_time(10), - })); - let call2 = Box::new(RuntimeCall::Logger(LoggerCall::log { - i: 42, - weight: Weight::from_ref_time(10), - })); - assert_noop!( - Scheduler::schedule_named( - system::RawOrigin::Signed(2).into(), - [1u8; 32], - 4, - None, - None, - call - ), - BadOrigin - ); - assert_noop!( - Scheduler::schedule(system::RawOrigin::Signed(2).into(), 4, None, None, call2), - BadOrigin - ); - }); -} - -#[test] -fn should_check_origin_for_cancel() { - new_test_ext().execute_with(|| { - let call = Box::new(RuntimeCall::Logger(LoggerCall::log_without_filter { - i: 69, - weight: Weight::from_ref_time(10), - })); - let call2 = Box::new(RuntimeCall::Logger(LoggerCall::log_without_filter { - i: 42, - weight: Weight::from_ref_time(10), - })); - assert_ok!(Scheduler::schedule_named( - system::RawOrigin::Signed(1).into(), - [1u8; 32], - 4, - None, - None, - call, - )); - assert_ok!(Scheduler::schedule( - system::RawOrigin::Signed(1).into(), - 4, - None, - None, - call2, - )); - run_to_block(3); - // Scheduled calls are in the agenda. - assert_eq!(Agenda::::get(4).agenda.len(), 2); - assert!(logger::log().is_empty()); - assert_noop!( - Scheduler::cancel_named(system::RawOrigin::Signed(2).into(), [1u8; 32]), - BadOrigin - ); - assert_noop!( - Scheduler::cancel(system::RawOrigin::Signed(2).into(), 4, 1), - BadOrigin - ); - assert_noop!( - Scheduler::cancel_named(system::RawOrigin::Root.into(), [1u8; 32]), - BadOrigin - ); - assert_noop!( - Scheduler::cancel(system::RawOrigin::Root.into(), 4, 1), - BadOrigin - ); - run_to_block(5); - assert_eq!( - logger::log(), - vec![ - (system::RawOrigin::Signed(1).into(), 69u32), - (system::RawOrigin::Signed(1).into(), 42u32) - ] - ); - }); -} - -/// Cancelling a call and then scheduling a second call for the same -/// block results in different addresses. -#[test] -fn schedule_does_not_resuse_addr() { - new_test_ext().execute_with(|| { - let call = RuntimeCall::Logger(LoggerCall::log { - i: 42, - weight: Weight::from_ref_time(10), - }); - - // Schedule both calls. - let addr_1 = Scheduler::do_schedule( - DispatchTime::At(4), - None, - 127, - root(), - >::new(call.clone()).unwrap(), - ) - .unwrap(); - // Cancel the call. - assert_ok!(Scheduler::do_cancel(None, addr_1)); - let addr_2 = Scheduler::do_schedule( - DispatchTime::At(4), - None, - 127, - root(), - >::new(call).unwrap(), - ) - .unwrap(); - - // Should not re-use the address. - assert!(addr_1 != addr_2); - }); -} - -#[test] -fn schedule_agenda_overflows() { - let max: u32 = ::MaxScheduledPerBlock::get(); - - new_test_ext().execute_with(|| { - let call = RuntimeCall::Logger(LoggerCall::log { - i: 42, - weight: Weight::from_ref_time(10), - }); - let call = >::new(call).unwrap(); - - // Schedule the maximal number allowed per block. - for _ in 0..max { - Scheduler::do_schedule(DispatchTime::At(4), None, 127, root(), call.clone()).unwrap(); - } - - // One more time and it errors. - assert_noop!( - Scheduler::do_schedule(DispatchTime::At(4), None, 127, root(), call,), - >::AgendaIsExhausted, - ); - - run_to_block(4); - // All scheduled calls are executed. - assert_eq!(logger::log().len() as u32, max); - }); -} - -/// Cancelling and scheduling does not overflow the agenda but fills holes. -#[test] -fn cancel_and_schedule_fills_holes() { - let max: u32 = ::MaxScheduledPerBlock::get(); - assert!( - max > 3, - "This test only makes sense for MaxScheduledPerBlock > 3" - ); - - new_test_ext().execute_with(|| { - let call = RuntimeCall::Logger(LoggerCall::log { - i: 42, - weight: Weight::from_ref_time(10), - }); - let call = >::new(call).unwrap(); - let mut addrs = Vec::<_>::default(); - - // Schedule the maximal number allowed per block. - for _ in 0..max { - addrs.push( - Scheduler::do_schedule(DispatchTime::At(4), None, 127, root(), call.clone()) - .unwrap(), - ); - } - // Cancel three of them. - for addr in addrs.into_iter().take(3) { - Scheduler::do_cancel(None, addr).unwrap(); - } - // Schedule three new ones. - for i in 0..3 { - let (_block, index) = - Scheduler::do_schedule(DispatchTime::At(4), None, 127, root(), call.clone()) - .unwrap(); - assert_eq!(i, index); - } - - run_to_block(4); - // Maximum number of calls are executed. - assert_eq!(logger::log().len() as u32, max); - }); -} - -#[test] -fn cannot_schedule_too_big_tasks() { - new_test_ext().execute_with(|| { - let call = Box::new(<::RuntimeCall>::from(SystemCall::remark { - remark: vec![0; EncodedCall::bound() - 4], - })); - - assert_ok!(Scheduler::schedule( - RuntimeOrigin::root(), - 4, - None, - Some(127), - call - )); - - let call = Box::new(<::RuntimeCall>::from(SystemCall::remark { - remark: vec![0; EncodedCall::bound() - 3], - })); - - assert_err!( - Scheduler::schedule(RuntimeOrigin::root(), 4, None, Some(127), call), - >::TooBigScheduledCall - ); - }); -} --- a/pallets/scheduler-v2/src/weights.rs +++ /dev/null @@ -1,234 +0,0 @@ -// Template adopted from https://github.com/paritytech/substrate/blob/master/.maintain/frame-weight-template.hbs - -//! Autogenerated weights for pallet_unique_scheduler_v2 -//! -//! THIS FILE WAS AUTO-GENERATED USING THE SUBSTRATE BENCHMARK CLI VERSION 4.0.0-dev -//! DATE: 2022-10-28, STEPS: `50`, REPEAT: 80, LOW RANGE: `[]`, HIGH RANGE: `[]` -//! EXECUTION: None, WASM-EXECUTION: Compiled, CHAIN: None, DB CACHE: 1024 - -// Executed Command: -// target/release/unique-collator -// benchmark -// pallet -// --pallet -// pallet-unique-scheduler-v2 -// --wasm-execution -// compiled -// --extrinsic -// * -// --template -// .maintain/frame-weight-template.hbs -// --steps=50 -// --repeat=80 -// --heap-pages=4096 -// --output=./pallets/scheduler-v2/src/weights.rs - -#![cfg_attr(rustfmt, rustfmt_skip)] -#![allow(unused_parens)] -#![allow(unused_imports)] -#![allow(missing_docs)] -#![allow(clippy::unnecessary_cast)] - -use frame_support::{traits::Get, weights::{Weight, constants::RocksDbWeight}}; -use sp_std::marker::PhantomData; - -/// Weight functions needed for pallet_unique_scheduler_v2. -pub trait WeightInfo { - fn service_agendas_base() -> Weight; - fn service_agenda_base(s: u32, ) -> Weight; - fn service_task_base() -> Weight; - fn service_task_named() -> Weight; - fn service_task_periodic() -> Weight; - fn execute_dispatch_signed() -> Weight; - fn execute_dispatch_unsigned() -> Weight; - fn schedule(s: u32, ) -> Weight; - fn cancel(s: u32, ) -> Weight; - fn schedule_named(s: u32, ) -> Weight; - fn cancel_named(s: u32, ) -> Weight; - fn change_named_priority(s: u32, ) -> Weight; -} - -/// Weights for pallet_unique_scheduler_v2 using the Substrate node and recommended hardware. -pub struct SubstrateWeight(PhantomData); -impl WeightInfo for SubstrateWeight { - // Storage: Scheduler IncompleteSince (r:1 w:1) - fn service_agendas_base() -> Weight { - Weight::from_ref_time(5_253_000 as u64) - .saturating_add(T::DbWeight::get().reads(1 as u64)) - .saturating_add(T::DbWeight::get().writes(1 as u64)) - } - // Storage: Scheduler Agenda (r:1 w:1) - fn service_agenda_base(s: u32, ) -> Weight { - Weight::from_ref_time(3_858_000 as u64) - // Standard Error: 2_617 - .saturating_add(Weight::from_ref_time(579_704 as u64).saturating_mul(s as u64)) - .saturating_add(T::DbWeight::get().reads(1 as u64)) - .saturating_add(T::DbWeight::get().writes(1 as u64)) - } - // Storage: System LastRuntimeUpgrade (r:1 w:0) - fn service_task_base() -> Weight { - Weight::from_ref_time(10_536_000 as u64) - .saturating_add(T::DbWeight::get().reads(1 as u64)) - } - // Storage: System LastRuntimeUpgrade (r:1 w:0) - // Storage: Scheduler Lookup (r:0 w:1) - fn service_task_named() -> Weight { - Weight::from_ref_time(12_018_000 as u64) - .saturating_add(T::DbWeight::get().reads(1 as u64)) - .saturating_add(T::DbWeight::get().writes(1 as u64)) - } - // Storage: System LastRuntimeUpgrade (r:1 w:0) - fn service_task_periodic() -> Weight { - Weight::from_ref_time(10_669_000 as u64) - .saturating_add(T::DbWeight::get().reads(1 as u64)) - } - // Storage: System Account (r:1 w:1) - // Storage: System AllExtrinsicsLen (r:1 w:1) - // Storage: System BlockWeight (r:1 w:1) - // Storage: Configuration WeightToFeeCoefficientOverride (r:1 w:0) - // Storage: TransactionPayment NextFeeMultiplier (r:1 w:0) - fn execute_dispatch_signed() -> Weight { - Weight::from_ref_time(36_083_000 as u64) - .saturating_add(T::DbWeight::get().reads(5 as u64)) - .saturating_add(T::DbWeight::get().writes(3 as u64)) - } - fn execute_dispatch_unsigned() -> Weight { - Weight::from_ref_time(4_386_000 as u64) - } - // Storage: Scheduler Agenda (r:1 w:1) - fn schedule(s: u32, ) -> Weight { - Weight::from_ref_time(17_257_000 as u64) - // Standard Error: 2_791 - .saturating_add(Weight::from_ref_time(574_832 as u64).saturating_mul(s as u64)) - .saturating_add(T::DbWeight::get().reads(1 as u64)) - .saturating_add(T::DbWeight::get().writes(1 as u64)) - } - // Storage: Scheduler Agenda (r:1 w:1) - // Storage: Scheduler Lookup (r:0 w:1) - fn cancel(s: u32, ) -> Weight { - Weight::from_ref_time(19_803_000 as u64) - // Standard Error: 1_177 - .saturating_add(Weight::from_ref_time(475_027 as u64).saturating_mul(s as u64)) - .saturating_add(T::DbWeight::get().reads(1 as u64)) - .saturating_add(T::DbWeight::get().writes(2 as u64)) - } - // Storage: Scheduler Lookup (r:1 w:1) - // Storage: Scheduler Agenda (r:1 w:1) - fn schedule_named(s: u32, ) -> Weight { - Weight::from_ref_time(18_746_000 as u64) - // Standard Error: 2_997 - .saturating_add(Weight::from_ref_time(635_697 as u64).saturating_mul(s as u64)) - .saturating_add(T::DbWeight::get().reads(2 as u64)) - .saturating_add(T::DbWeight::get().writes(2 as u64)) - } - // Storage: Scheduler Lookup (r:1 w:1) - // Storage: Scheduler Agenda (r:1 w:1) - fn cancel_named(s: u32, ) -> Weight { - Weight::from_ref_time(20_983_000 as u64) - // Standard Error: 1_850 - .saturating_add(Weight::from_ref_time(518_812 as u64).saturating_mul(s as u64)) - .saturating_add(T::DbWeight::get().reads(2 as u64)) - .saturating_add(T::DbWeight::get().writes(2 as u64)) - } - // Storage: Scheduler Lookup (r:1 w:0) - // Storage: Scheduler Agenda (r:1 w:1) - fn change_named_priority(s: u32, ) -> Weight { - Weight::from_ref_time(21_591_000 as u64) - // Standard Error: 4_187 - .saturating_add(Weight::from_ref_time(531_231 as u64).saturating_mul(s as u64)) - .saturating_add(T::DbWeight::get().reads(2 as u64)) - .saturating_add(T::DbWeight::get().writes(1 as u64)) - } -} - -// For backwards compatibility and tests -impl WeightInfo for () { - // Storage: Scheduler IncompleteSince (r:1 w:1) - fn service_agendas_base() -> Weight { - Weight::from_ref_time(5_253_000 as u64) - .saturating_add(RocksDbWeight::get().reads(1 as u64)) - .saturating_add(RocksDbWeight::get().writes(1 as u64)) - } - // Storage: Scheduler Agenda (r:1 w:1) - fn service_agenda_base(s: u32, ) -> Weight { - Weight::from_ref_time(3_858_000 as u64) - // Standard Error: 2_617 - .saturating_add(Weight::from_ref_time(579_704 as u64).saturating_mul(s as u64)) - .saturating_add(RocksDbWeight::get().reads(1 as u64)) - .saturating_add(RocksDbWeight::get().writes(1 as u64)) - } - // Storage: System LastRuntimeUpgrade (r:1 w:0) - fn service_task_base() -> Weight { - Weight::from_ref_time(10_536_000 as u64) - .saturating_add(RocksDbWeight::get().reads(1 as u64)) - } - // Storage: System LastRuntimeUpgrade (r:1 w:0) - // Storage: Scheduler Lookup (r:0 w:1) - fn service_task_named() -> Weight { - Weight::from_ref_time(12_018_000 as u64) - .saturating_add(RocksDbWeight::get().reads(1 as u64)) - .saturating_add(RocksDbWeight::get().writes(1 as u64)) - } - // Storage: System LastRuntimeUpgrade (r:1 w:0) - fn service_task_periodic() -> Weight { - Weight::from_ref_time(10_669_000 as u64) - .saturating_add(RocksDbWeight::get().reads(1 as u64)) - } - // Storage: System Account (r:1 w:1) - // Storage: System AllExtrinsicsLen (r:1 w:1) - // Storage: System BlockWeight (r:1 w:1) - // Storage: Configuration WeightToFeeCoefficientOverride (r:1 w:0) - // Storage: TransactionPayment NextFeeMultiplier (r:1 w:0) - fn execute_dispatch_signed() -> Weight { - Weight::from_ref_time(36_083_000 as u64) - .saturating_add(RocksDbWeight::get().reads(5 as u64)) - .saturating_add(RocksDbWeight::get().writes(3 as u64)) - } - fn execute_dispatch_unsigned() -> Weight { - Weight::from_ref_time(4_386_000 as u64) - } - // Storage: Scheduler Agenda (r:1 w:1) - fn schedule(s: u32, ) -> Weight { - Weight::from_ref_time(17_257_000 as u64) - // Standard Error: 2_791 - .saturating_add(Weight::from_ref_time(574_832 as u64).saturating_mul(s as u64)) - .saturating_add(RocksDbWeight::get().reads(1 as u64)) - .saturating_add(RocksDbWeight::get().writes(1 as u64)) - } - // Storage: Scheduler Agenda (r:1 w:1) - // Storage: Scheduler Lookup (r:0 w:1) - fn cancel(s: u32, ) -> Weight { - Weight::from_ref_time(19_803_000 as u64) - // Standard Error: 1_177 - .saturating_add(Weight::from_ref_time(475_027 as u64).saturating_mul(s as u64)) - .saturating_add(RocksDbWeight::get().reads(1 as u64)) - .saturating_add(RocksDbWeight::get().writes(2 as u64)) - } - // Storage: Scheduler Lookup (r:1 w:1) - // Storage: Scheduler Agenda (r:1 w:1) - fn schedule_named(s: u32, ) -> Weight { - Weight::from_ref_time(18_746_000 as u64) - // Standard Error: 2_997 - .saturating_add(Weight::from_ref_time(635_697 as u64).saturating_mul(s as u64)) - .saturating_add(RocksDbWeight::get().reads(2 as u64)) - .saturating_add(RocksDbWeight::get().writes(2 as u64)) - } - // Storage: Scheduler Lookup (r:1 w:1) - // Storage: Scheduler Agenda (r:1 w:1) - fn cancel_named(s: u32, ) -> Weight { - Weight::from_ref_time(20_983_000 as u64) - // Standard Error: 1_850 - .saturating_add(Weight::from_ref_time(518_812 as u64).saturating_mul(s as u64)) - .saturating_add(RocksDbWeight::get().reads(2 as u64)) - .saturating_add(RocksDbWeight::get().writes(2 as u64)) - } - // Storage: Scheduler Lookup (r:1 w:0) - // Storage: Scheduler Agenda (r:1 w:1) - fn change_named_priority(s: u32, ) -> Weight { - Weight::from_ref_time(21_591_000 as u64) - // Standard Error: 4_187 - .saturating_add(Weight::from_ref_time(531_231 as u64).saturating_mul(s as u64)) - .saturating_add(RocksDbWeight::get().reads(2 as u64)) - .saturating_add(RocksDbWeight::get().writes(1 as u64)) - } -} --- a/runtime/opal/Cargo.toml +++ b/runtime/opal/Cargo.toml @@ -329,7 +329,6 @@ pallet-refungible = { workspace = true } pallet-structure = { workspace = true } pallet-unique = { workspace = true } -pallet-unique-scheduler-v2 = { workspace = true } precompile-utils-macro = { workspace = true } scale-info = { workspace = true } up-common = { workspace = true } --- a/test-pallets/utils/Cargo.toml +++ b/test-pallets/utils/Cargo.toml @@ -12,8 +12,6 @@ frame-support = { workspace = true } frame-system = { workspace = true } scale-info = { workspace = true } -# pallet-unique-scheduler = { path = '../../pallets/scheduler', default-features = false } -pallet-unique-scheduler-v2 = { workspace = true } sp-std = { workspace = true } [features] @@ -22,7 +20,6 @@ "codec/std", "frame-support/std", "frame-system/std", - "pallet-unique-scheduler-v2/std", "scale-info/std", "sp-std/std", ] --- a/test-pallets/utils/src/lib.rs +++ b/test-pallets/utils/src/lib.rs @@ -29,7 +29,6 @@ }; use frame_system::pallet_prelude::*; use sp_std::vec::Vec; - // use pallet_unique_scheduler_v2::{TaskName, Pallet as SchedulerPallet}; #[pallet::config] pub trait Config: frame_system::Config /*+ pallet_unique_scheduler_v2::Config*/ { -- gitstuff