git.delta.rocks / unique-network / refs/commits / b587267ca701

difftreelog

Scheduler sponsoring balance reserve

str-mv2022-02-24parent: #7781ab9.patch.diff
in: master

2 files changed

modifiedpallets/scheduler/src/lib.rsdiffbeforeafterboth
78use up_sponsorship::SponsorshipHandler;78use up_sponsorship::SponsorshipHandler;
79use scale_info::TypeInfo;79use scale_info::TypeInfo;
80use sp_core::H160;80use sp_core::H160;
81use frame_support::traits::NamedReservableCurrency;
82
83type ScheduledId = [u8; MAX_TASK_ID_LENGTH_IN_BYTES as usize];
8184
82/// Our pallet's configuration trait. All our types and constants go in here. If the85/// Our pallet's configuration trait. All our types and constants go in here. If the
83/// pallet is dependent on specific other pallets, then their configuration traits86/// pallet is dependent on specific other pallets, then their configuration traits
97 /// The caller origin, overarching type of all pallets origins.100 /// The caller origin, overarching type of all pallets origins.
98 type PalletsOrigin: From<system::RawOrigin<Self::AccountId>> + Codec + TypeInfo + Clone + Eq;101 type PalletsOrigin: From<system::RawOrigin<Self::AccountId>> + Codec + TypeInfo + Clone + Eq;
102
103 type Currency: NamedReservableCurrency<Self::AccountId, ReserveIdentifier = ScheduledId>;
99104
100 /// The aggregated call type.105 /// The aggregated call type.
101 type Call: Parameter106 type Call: Parameter
129 /// The type that encodes information that can be passed from pre_dispatch to post-dispatch.134 /// The type that encodes information that can be passed from pre_dispatch to post-dispatch.
130 type Pre: Default + Codec + Clone + TypeInfo;135 type Pre: Default + Codec + Clone + TypeInfo;
136
137 fn reserve_balance(
138 id: ScheduledId,
139 sponsor: <T as frame_system::Config>::AccountId,
140 call: <T as Config>::Call,
141 count: u32,
142 ) -> Result<(), DispatchError>;
143
144 fn pay_for_call(
145 id: ScheduledId,
146 sponsor: <T as frame_system::Config>::AccountId,
147 call: <T as Config>::Call,
148 ) -> Result<u128, DispatchError>;
131149
132 /// Resolve the call dispatch, including any post-dispatch operations.150 /// Resolve the call dispatch, including any post-dispatch operations.
133 fn dispatch_call(151 fn dispatch_call(
164#[derive(Clone, RuntimeDebug, Encode, Decode, TypeInfo)]182#[derive(Clone, RuntimeDebug, Encode, Decode, TypeInfo)]
165pub struct Scheduled<Call, BlockNumber, PalletsOrigin, AccountId, PreDispatch> {183pub struct Scheduled<Call, BlockNumber, PalletsOrigin, AccountId, PreDispatch> {
166 /// The unique identity for this task, if there is one.184 /// The unique identity for this task, if there is one.
167 maybe_id: Option<Vec<u8>>,185 maybe_id: Option<ScheduledId>,
168 /// This task's priority.186 /// This task's priority.
169 priority: schedule::Priority,187 priority: schedule::Priority,
170 /// The call to be dispatched.188 /// The call to be dispatched.
197 >>>;215 >>>;
198 216
199 /// Lookup from identity to the block number and index of the task.217 /// Lookup from identity to the block number and index of the task.
200 Lookup: map hasher(twox_64_concat) Vec<u8> => Option<TaskAddress<T::BlockNumber>>;218 Lookup: map hasher(twox_64_concat) ScheduledId => Option<TaskAddress<T::BlockNumber>>;
201 }219 }
202}220}
203221
208 /// Canceled some task. \[when, index\]226 /// Canceled some task. \[when, index\]
209 Canceled(BlockNumber, u32),227 Canceled(BlockNumber, u32),
210 /// Dispatched some task. \[task, id, result\]228 /// Dispatched some task. \[task, id, result\]
211 Dispatched(TaskAddress<BlockNumber>, Option<Vec<u8>>, DispatchResult),229 Dispatched(TaskAddress<BlockNumber>, Option<ScheduledId>, DispatchResult),
212 }230 }
213);231);
214232
285 /// # </weight>303 /// # </weight>
286 #[weight = <T as Config>::WeightInfo::schedule_named(T::MaxScheduledPerBlock::get())]304 #[weight = <T as Config>::WeightInfo::schedule_named(T::MaxScheduledPerBlock::get())]
287 fn schedule_named(origin,305 fn schedule_named(origin,
288 id: Vec<u8>,306 id: ScheduledId,
289 when: T::BlockNumber,307 when: T::BlockNumber,
290 maybe_periodic: Option<schedule::Period<T::BlockNumber>>,308 maybe_periodic: Option<schedule::Period<T::BlockNumber>>,
291 priority: schedule::Priority,309 priority: schedule::Priority,
309 /// - Will use base weight of 100 which should be good for up to 30 scheduled calls327 /// - Will use base weight of 100 which should be good for up to 30 scheduled calls
310 /// # </weight>328 /// # </weight>
311 #[weight = <T as Config>::WeightInfo::cancel_named(T::MaxScheduledPerBlock::get())]329 #[weight = <T as Config>::WeightInfo::cancel_named(T::MaxScheduledPerBlock::get())]
312 fn cancel_named(origin, id: Vec<u8>) {330 fn cancel_named(origin, id: ScheduledId) {
313 T::ScheduleOrigin::ensure_origin(origin.clone())?;331 T::ScheduleOrigin::ensure_origin(origin.clone())?;
314 let origin = <T as Config>::Origin::from(origin);332 let origin = <T as Config>::Origin::from(origin);
315 Self::do_cancel_named(Some(origin.caller().clone()), id)?;333 Self::do_cancel_named(Some(origin.caller().clone()), id)?;
341 /// # </weight>359 /// # </weight>
342 #[weight = <T as Config>::WeightInfo::schedule_named(T::MaxScheduledPerBlock::get())]360 #[weight = <T as Config>::WeightInfo::schedule_named(T::MaxScheduledPerBlock::get())]
343 fn schedule_named_after(origin,361 fn schedule_named_after(origin,
344 id: Vec<u8>,362 id: ScheduledId,
345 after: T::BlockNumber,363 after: T::BlockNumber,
346 maybe_periodic: Option<schedule::Period<T::BlockNumber>>,364 maybe_periodic: Option<schedule::Period<T::BlockNumber>>,
347 priority: schedule::Priority,365 priority: schedule::Priority,
411 })429 })
412 .filter_map(|(order, index, cumulative_weight, mut s)| {430 .filter_map(|(order, index, cumulative_weight, mut s)| {
431
432 // if call have id and periodic, it was be reserved
433 if s.maybe_id.is_some() && s.maybe_periodic.is_some()
434 {
435 let sender = ensure_signed(
436 <<T as Config>::Origin as From<T::PalletsOrigin>>::from(s.origin.clone()).into(),
437 )
438 .unwrap_or_default();
439 let who_will_pay = T::SponsorshipHandler::get_sponsor(&sender, &s.call.clone())
440 .unwrap_or(sender.clone());
441
442 T::CallExecutor::pay_for_call(
443 s.maybe_id.unwrap(),
444 who_will_pay.clone(),
445 s.call.clone(),
446 );
447 }
448
413 // We allow a scheduled call if:449 // We allow a scheduled call if:
414 // - It's priority is `HARD_DEADLINE`450 // - It's priority is `HARD_DEADLINE`
419 let r = T::CallExecutor::dispatch_call(s.pre_dispatch.clone(), s.call.clone());455 let r = T::CallExecutor::dispatch_call(s.pre_dispatch.clone(), s.call.clone());
420456
421 if let Err(_) = r {457 if let Err(_) = r {
422 log::warn!(458 log::info!(
423 target: "runtime::scheduler",459 target: "runtime::scheduler",
424 "Warning: Scheduler has failed to execute a post-dispatch transaction. \460 "Warning: Scheduler has failed to execute a post-dispatch transaction. \
425 This block might have become invalid.",461 This block might have become invalid.",
486 }522 }
487523
488 fn do_schedule(524 fn do_schedule(
489 maybe_id: Option<Vec<u8>>,525 maybe_id: Option<ScheduledId>,
490 when: DispatchTime<T::BlockNumber>,526 when: DispatchTime<T::BlockNumber>,
491 maybe_periodic: Option<schedule::Period<T::BlockNumber>>,527 maybe_periodic: Option<schedule::Period<T::BlockNumber>>,
492 priority: schedule::Priority,528 priority: schedule::Priority,
520556
521 if let Some(periodic) = maybe_periodic {557 if let Some(periodic) = maybe_periodic {
558
559 // reserve balance for periodic execution
560 if maybe_id.is_some()
561 {
562 let sender = ensure_signed(
563 <<T as Config>::Origin as From<T::PalletsOrigin>>::from(origin.clone()).into(),
564 )
565 .unwrap_or_default();
566 let who_will_pay = T::SponsorshipHandler::get_sponsor(&sender, &call.clone())
567 .unwrap_or(sender.clone());
522 for _i in 0..=periodic.1 {568 T::CallExecutor::reserve_balance(maybe_id.unwrap(), who_will_pay.clone(), call.clone(), periodic.1);
523 // displace to runtime and count the total required fee, then deduct. find a way to use OnChargePayment569 }
524 // send constants and priority to runtime for fee computation, too. should create constants here or just declare them in runtime?570
525 // roadblock - they will return on post_dispatch -- oh! tips?571 //for _i in 0..=periodic.1 {
526 }572 // displace to runtime and count the total required fee, then deduct. find a way to use OnChargePayment
573 // send constants and priority to runtime for fee computation, too. should create constants here or just declare them in runtime?
574 // roadblock - they will return on post_dispatch -- oh! tips?
575 //}
527 }576 }
528577
529 let s = Some(Scheduled {578 let s = Some(Scheduled {
623 }672 }
624673
625 fn do_schedule_named(674 fn do_schedule_named(
626 id: Vec<u8>,675 id: ScheduledId,
627 when: DispatchTime<T::BlockNumber>,676 when: DispatchTime<T::BlockNumber>,
628 maybe_periodic: Option<schedule::Period<T::BlockNumber>>,677 maybe_periodic: Option<schedule::Period<T::BlockNumber>>,
629 priority: schedule::Priority,678 priority: schedule::Priority,
652 Ok(address)701 Ok(address)
653 }702 }
654703
655 fn do_cancel_named(origin: Option<T::PalletsOrigin>, id: Vec<u8>) -> DispatchResult {704 fn do_cancel_named(origin: Option<T::PalletsOrigin>, id: ScheduledId) -> DispatchResult {
656 Lookup::<T>::try_mutate_exists(id, |lookup| -> DispatchResult {705 Lookup::<T>::try_mutate_exists(id, |lookup| -> DispatchResult {
657 if let Some((when, index)) = lookup.take() {706 if let Some((when, index)) = lookup.take() {
658 let i = index as usize;707 let i = index as usize;
684 }733 }
685734
686 fn do_reschedule_named(735 fn do_reschedule_named(
687 id: Vec<u8>,736 id: ScheduledId,
688 new_time: DispatchTime<T::BlockNumber>,737 new_time: DispatchTime<T::BlockNumber>,
689 ) -> Result<TaskAddress<T::BlockNumber>, DispatchError> {738 ) -> Result<TaskAddress<T::BlockNumber>, DispatchError> {
690 let new_time = Self::resolve_time(new_time)?;739 let new_time = Self::resolve_time(new_time)?;
766 call: <T as Config>::Call,815 call: <T as Config>::Call,
767 ) -> Result<Self::Address, ()> {816 ) -> Result<Self::Address, ()> {
817
818 let inner_id: ScheduledId = id.try_into().unwrap_or([0; MAX_TASK_ID_LENGTH_IN_BYTES as usize]);
768 Self::do_schedule_named(id, when, maybe_periodic, priority, origin, call).map_err(|_| ())819 Self::do_schedule_named(inner_id, when, maybe_periodic, priority, origin, call).map_err(|_| ())
769 }820 }
770821
771 fn cancel_named(id: Vec<u8>) -> Result<(), ()> {822 fn cancel_named(id: Vec<u8>) -> Result<(), ()> {
823 let inner_id: ScheduledId = id.try_into().unwrap_or([0; MAX_TASK_ID_LENGTH_IN_BYTES as usize]);
772 Self::do_cancel_named(None, id).map_err(|_| ())824 Self::do_cancel_named(None, inner_id).map_err(|_| ())
773 }825 }
774826
775 fn reschedule_named(827 fn reschedule_named(
776 id: Vec<u8>,828 id: Vec<u8>,
777 when: DispatchTime<T::BlockNumber>,829 when: DispatchTime<T::BlockNumber>,
778 ) -> Result<Self::Address, DispatchError> {830 ) -> Result<Self::Address, DispatchError> {
831 let inner_id: ScheduledId = id.try_into().unwrap_or([0; MAX_TASK_ID_LENGTH_IN_BYTES as usize]);
779 Self::do_reschedule_named(id, when)832 Self::do_reschedule_named(inner_id, when)
780 }833 }
781834
782 fn next_dispatch_time(id: Vec<u8>) -> Result<T::BlockNumber, ()> {835 fn next_dispatch_time(id: Vec<u8>) -> Result<T::BlockNumber, ()> {
836 let inner_id: ScheduledId = id.try_into().unwrap_or([0; MAX_TASK_ID_LENGTH_IN_BYTES as usize]);
783 Lookup::<T>::get(id)837 Lookup::<T>::get(inner_id)
784 .and_then(|(when, index)| Agenda::<T>::get(when).get(index as usize).map(|_| when))838 .and_then(|(when, index)| Agenda::<T>::get(when).get(index as usize).map(|_| when))
785 .ok_or(())839 .ok_or(())
786 }840 }
modifiedruntime/src/lib.rsdiffbeforeafterboth
393 // 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}
397398
398impl 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}
821
822
823use frame_support::traits::NamedReservableCurrency;
820824
821pub 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 }
871
872 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 0
882 );
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 };
887
888 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 }
895
896 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 0
906 );
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 };
911
912 let single_fee: u128 = pre.2.map(|imbalance| imbalance.peek()).unwrap();
913
914 Ok(<Balances as NamedReservableCurrency<AccountId>>::unreserve_named(
915 &id,
916 &(sponsor.into()),
917 single_fee))
918 }
867919
868 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;