difftreelog
Scheduler sponsoring balance reserve
in: master
2 files changed
pallets/scheduler/src/lib.rsdiffbeforeafterboth--- a/pallets/scheduler/src/lib.rs
+++ b/pallets/scheduler/src/lib.rs
@@ -78,6 +78,9 @@
use up_sponsorship::SponsorshipHandler;
use scale_info::TypeInfo;
use sp_core::H160;
+use frame_support::traits::NamedReservableCurrency;
+
+type ScheduledId = [u8; MAX_TASK_ID_LENGTH_IN_BYTES as usize];
/// Our pallet's configuration trait. All our types and constants go in here. If the
/// pallet is dependent on specific other pallets, then their configuration traits
@@ -97,6 +100,8 @@
/// The caller origin, overarching type of all pallets origins.
type PalletsOrigin: From<system::RawOrigin<Self::AccountId>> + Codec + TypeInfo + Clone + Eq;
+ type Currency: NamedReservableCurrency<Self::AccountId, ReserveIdentifier = ScheduledId>;
+
/// The aggregated call type.
type Call: Parameter
+ Dispatchable<Origin = <Self as Config>::Origin>
@@ -129,6 +134,19 @@
/// The type that encodes information that can be passed from pre_dispatch to post-dispatch.
type Pre: Default + Codec + Clone + TypeInfo;
+ fn reserve_balance(
+ id: ScheduledId,
+ sponsor: <T as frame_system::Config>::AccountId,
+ call: <T as Config>::Call,
+ count: u32,
+ ) -> Result<(), DispatchError>;
+
+ fn pay_for_call(
+ id: ScheduledId,
+ sponsor: <T as frame_system::Config>::AccountId,
+ call: <T as Config>::Call,
+ ) -> Result<u128, DispatchError>;
+
/// Resolve the call dispatch, including any post-dispatch operations.
fn dispatch_call(
pre_dispatch: Self::Pre,
@@ -164,7 +182,7 @@
#[derive(Clone, RuntimeDebug, Encode, Decode, TypeInfo)]
pub struct Scheduled<Call, BlockNumber, PalletsOrigin, AccountId, PreDispatch> {
/// The unique identity for this task, if there is one.
- maybe_id: Option<Vec<u8>>,
+ maybe_id: Option<ScheduledId>,
/// This task's priority.
priority: schedule::Priority,
/// The call to be dispatched.
@@ -197,7 +215,7 @@
>>>;
/// Lookup from identity to the block number and index of the task.
- Lookup: map hasher(twox_64_concat) Vec<u8> => Option<TaskAddress<T::BlockNumber>>;
+ Lookup: map hasher(twox_64_concat) ScheduledId => Option<TaskAddress<T::BlockNumber>>;
}
}
@@ -208,7 +226,7 @@
/// Canceled some task. \[when, index\]
Canceled(BlockNumber, u32),
/// Dispatched some task. \[task, id, result\]
- Dispatched(TaskAddress<BlockNumber>, Option<Vec<u8>>, DispatchResult),
+ Dispatched(TaskAddress<BlockNumber>, Option<ScheduledId>, DispatchResult),
}
);
@@ -285,7 +303,7 @@
/// # </weight>
#[weight = <T as Config>::WeightInfo::schedule_named(T::MaxScheduledPerBlock::get())]
fn schedule_named(origin,
- id: Vec<u8>,
+ id: ScheduledId,
when: T::BlockNumber,
maybe_periodic: Option<schedule::Period<T::BlockNumber>>,
priority: schedule::Priority,
@@ -309,7 +327,7 @@
/// - Will use base weight of 100 which should be good for up to 30 scheduled calls
/// # </weight>
#[weight = <T as Config>::WeightInfo::cancel_named(T::MaxScheduledPerBlock::get())]
- fn cancel_named(origin, id: Vec<u8>) {
+ fn cancel_named(origin, id: ScheduledId) {
T::ScheduleOrigin::ensure_origin(origin.clone())?;
let origin = <T as Config>::Origin::from(origin);
Self::do_cancel_named(Some(origin.caller().clone()), id)?;
@@ -341,7 +359,7 @@
/// # </weight>
#[weight = <T as Config>::WeightInfo::schedule_named(T::MaxScheduledPerBlock::get())]
fn schedule_named_after(origin,
- id: Vec<u8>,
+ id: ScheduledId,
after: T::BlockNumber,
maybe_periodic: Option<schedule::Period<T::BlockNumber>>,
priority: schedule::Priority,
@@ -410,6 +428,24 @@
Some((order, index, *cumulative_weight, s))
})
.filter_map(|(order, index, cumulative_weight, mut s)| {
+
+ // if call have id and periodic, it was be reserved
+ if s.maybe_id.is_some() && s.maybe_periodic.is_some()
+ {
+ let sender = ensure_signed(
+ <<T as Config>::Origin as From<T::PalletsOrigin>>::from(s.origin.clone()).into(),
+ )
+ .unwrap_or_default();
+ let who_will_pay = T::SponsorshipHandler::get_sponsor(&sender, &s.call.clone())
+ .unwrap_or(sender.clone());
+
+ T::CallExecutor::pay_for_call(
+ s.maybe_id.unwrap(),
+ who_will_pay.clone(),
+ s.call.clone(),
+ );
+ }
+
// We allow a scheduled call if:
// - It's priority is `HARD_DEADLINE`
// - It does not push the weight past the limit
@@ -419,7 +455,7 @@
let r = T::CallExecutor::dispatch_call(s.pre_dispatch.clone(), s.call.clone());
if let Err(_) = r {
- log::warn!(
+ log::info!(
target: "runtime::scheduler",
"Warning: Scheduler has failed to execute a post-dispatch transaction. \
This block might have become invalid.",
@@ -486,7 +522,7 @@
}
fn do_schedule(
- maybe_id: Option<Vec<u8>>,
+ maybe_id: Option<ScheduledId>,
when: DispatchTime<T::BlockNumber>,
maybe_periodic: Option<schedule::Period<T::BlockNumber>>,
priority: schedule::Priority,
@@ -519,11 +555,24 @@
.map(|(p, c)| (p, cmp::min(c, PERIODIC_CALLS_LIMIT) - 1));
if let Some(periodic) = maybe_periodic {
- for _i in 0..=periodic.1 {
+
+ // reserve balance for periodic execution
+ if maybe_id.is_some()
+ {
+ let sender = ensure_signed(
+ <<T as Config>::Origin as From<T::PalletsOrigin>>::from(origin.clone()).into(),
+ )
+ .unwrap_or_default();
+ let who_will_pay = T::SponsorshipHandler::get_sponsor(&sender, &call.clone())
+ .unwrap_or(sender.clone());
+ T::CallExecutor::reserve_balance(maybe_id.unwrap(), who_will_pay.clone(), call.clone(), periodic.1);
+ }
+
+ //for _i in 0..=periodic.1 {
// displace to runtime and count the total required fee, then deduct. find a way to use OnChargePayment
// send constants and priority to runtime for fee computation, too. should create constants here or just declare them in runtime?
// roadblock - they will return on post_dispatch -- oh! tips?
- }
+ //}
}
let s = Some(Scheduled {
@@ -623,7 +672,7 @@
}
fn do_schedule_named(
- id: Vec<u8>,
+ id: ScheduledId,
when: DispatchTime<T::BlockNumber>,
maybe_periodic: Option<schedule::Period<T::BlockNumber>>,
priority: schedule::Priority,
@@ -652,7 +701,7 @@
Ok(address)
}
- fn do_cancel_named(origin: Option<T::PalletsOrigin>, id: Vec<u8>) -> DispatchResult {
+ fn do_cancel_named(origin: Option<T::PalletsOrigin>, id: ScheduledId) -> DispatchResult {
Lookup::<T>::try_mutate_exists(id, |lookup| -> DispatchResult {
if let Some((when, index)) = lookup.take() {
let i = index as usize;
@@ -684,7 +733,7 @@
}
fn do_reschedule_named(
- id: Vec<u8>,
+ id: ScheduledId,
new_time: DispatchTime<T::BlockNumber>,
) -> Result<TaskAddress<T::BlockNumber>, DispatchError> {
let new_time = Self::resolve_time(new_time)?;
@@ -765,22 +814,27 @@
origin: T::PalletsOrigin,
call: <T as Config>::Call,
) -> Result<Self::Address, ()> {
- Self::do_schedule_named(id, when, maybe_periodic, priority, origin, call).map_err(|_| ())
+
+ let inner_id: ScheduledId = id.try_into().unwrap_or([0; MAX_TASK_ID_LENGTH_IN_BYTES as usize]);
+ Self::do_schedule_named(inner_id, when, maybe_periodic, priority, origin, call).map_err(|_| ())
}
fn cancel_named(id: Vec<u8>) -> Result<(), ()> {
- Self::do_cancel_named(None, id).map_err(|_| ())
+ let inner_id: ScheduledId = id.try_into().unwrap_or([0; MAX_TASK_ID_LENGTH_IN_BYTES as usize]);
+ Self::do_cancel_named(None, inner_id).map_err(|_| ())
}
fn reschedule_named(
id: Vec<u8>,
when: DispatchTime<T::BlockNumber>,
) -> Result<Self::Address, DispatchError> {
- Self::do_reschedule_named(id, when)
+ let inner_id: ScheduledId = id.try_into().unwrap_or([0; MAX_TASK_ID_LENGTH_IN_BYTES as usize]);
+ Self::do_reschedule_named(inner_id, when)
}
fn next_dispatch_time(id: Vec<u8>) -> Result<T::BlockNumber, ()> {
- Lookup::<T>::get(id)
+ let inner_id: ScheduledId = id.try_into().unwrap_or([0; MAX_TASK_ID_LENGTH_IN_BYTES as usize]);
+ Lookup::<T>::get(inner_id)
.and_then(|(when, index)| Agenda::<T>::get(when).get(index as usize).map(|_| when))
.ok_or(())
}
runtime/src/lib.rsdiffbeforeafterboth393 // pub const ExistentialDeposit: u128 = 500;393 // pub const ExistentialDeposit: u128 = 500;394 pub const ExistentialDeposit: u128 = 0;394 pub const ExistentialDeposit: u128 = 0;395 pub const MaxLocks: u32 = 50;395 pub const MaxLocks: u32 = 50;396 pub const MaxReserves: u32 = 50;396}397}397398398impl pallet_balances::Config for Runtime {399impl pallet_balances::Config for Runtime {399 type MaxLocks = MaxLocks;400 type MaxLocks = MaxLocks;400 type MaxReserves = ();401 type MaxReserves = MaxReserves;401 type ReserveIdentifier = [u8; 8];402 type ReserveIdentifier = [u8; 16];402 /// The type for recording an account's balance.403 /// The type for recording an account's balance.403 type Balance = Balance;404 type Balance = Balance;404 /// The ubiquitous event type.405 /// The ubiquitous event type.819}820}821822823use frame_support::traits::NamedReservableCurrency;820824821pub struct SchedulerPaymentExecutor;825pub struct SchedulerPaymentExecutor;822impl<T: frame_system::Config + pallet_unq_scheduler::Config, SelfContainedSignedInfo>826impl<T: frame_system::Config + pallet_unq_scheduler::Config, SelfContainedSignedInfo>865 Ok(res)869 Ok(res)866 }870 }871872 fn reserve_balance(873 id: [u8; 16],874 sponsor: <T as frame_system::Config>::AccountId,875 call: <T as pallet_unq_scheduler::Config>::Call,876 count: u32,877 ) -> Result<(), DispatchError>878 {879 let dispatch_info = call.get_dispatch_info();880 let fee_charger = ChargeTransactionPayment::new(881 0882 );883 let pre = match fee_charger.pre_dispatch(&sponsor.clone().into(), &call.into(), &dispatch_info, 0) {884 Ok(p) => p,885 Err(_) => fail!("failed to get pre dispatch info")886 };887888 let count: u128 = count.into();889 let total_fee: u128 = pre.2.map(|imbalance| imbalance.peek()).unwrap() * count;890 <Balances as NamedReservableCurrency<AccountId>>::reserve_named(891 &id, 892 &(sponsor.into()), 893 total_fee)894 }895896 fn pay_for_call(897 id: [u8; 16],898 sponsor: <T as frame_system::Config>::AccountId,899 call: <T as pallet_unq_scheduler::Config>::Call,900 )901 -> Result<u128, DispatchError>902 {903 let dispatch_info = call.get_dispatch_info();904 let fee_charger = ChargeTransactionPayment::new(905 0906 );907 let pre = match fee_charger.pre_dispatch(&sponsor.clone().into(), &call.into(), &dispatch_info, 0) {908 Ok(p) => p,909 Err(_) => fail!("failed to get pre dispatch info")910 };911912 let single_fee: u128 = pre.2.map(|imbalance| imbalance.peek()).unwrap();913914 Ok(<Balances as NamedReservableCurrency<AccountId>>::unreserve_named(915 &id, 916 &(sponsor.into()), 917 single_fee))918 }867919868 fn pre_dispatch(920 fn pre_dispatch(869 signer: <T as frame_system::Config>::AccountId,921 signer: <T as frame_system::Config>::AccountId,893impl pallet_unq_scheduler::Config for Runtime {945impl pallet_unq_scheduler::Config for Runtime {894 type Event = Event;946 type Event = Event;895 type Origin = Origin;947 type Origin = Origin;948 type Currency = Balances;896 type PalletsOrigin = OriginCaller;949 type PalletsOrigin = OriginCaller;897 type Call = Call;950 type Call = Call;898 type MaximumWeight = MaximumSchedulerWeight;951 type MaximumWeight = MaximumSchedulerWeight;