-
Notifications
You must be signed in to change notification settings - Fork 543
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
[FRAME] Prepare pallets for dynamic block durations #3268
Comments
This is more or less the proposed solution that I extracted from the call, mostly my attempt to capture an idea that @gupnik expressed: diff --git a/substrate/frame/scheduler/src/lib.rs b/substrate/frame/scheduler/src/lib.rs
index e94f154eee..bcb5aff728 100644
--- a/substrate/frame/scheduler/src/lib.rs
+++ b/substrate/frame/scheduler/src/lib.rs
@@ -334,7 +334,9 @@ pub mod pallet {
#[pallet::weight(<T as Config>::WeightInfo::schedule(T::MaxScheduledPerBlock::get()))]
pub fn schedule(
origin: OriginFor<T>,
- when: BlockNumberFor<T>,
+ // we provide this type to all dispatchables wishing to reference the future. Later on,
+ // `fn passed` can be used to check if this time is already passed.
+ when: T::RuntimeTime,
maybe_periodic: Option<schedule::Period<BlockNumberFor<T>>>,
priority: schedule::Priority,
call: Box<<T as Config>::RuntimeCall>,
diff --git a/substrate/frame/system/src/lib.rs b/substrate/frame/system/src/lib.rs
index 069217bcee..ab725a7dd5 100644
--- a/substrate/frame/system/src/lib.rs
+++ b/substrate/frame/system/src/lib.rs
@@ -570,6 +570,64 @@ pub mod pallet {
/// The maximum number of consumers allowed on a single account.
type MaxConsumers: ConsumerLimits;
+
+ /// Something that can represent a notion of time within this runtime.
+ ///
+ /// It can be one's block number, timestamp or similar, depending on wether this is being
+ /// used in a parachain or relay chain context, and with or without async backing.
+ ///
+ /// Be aware that changing this type midflight probably has a lot of consequences.
+ type RuntimeTime: RuntimeTime;
+ }
+
+ /// An operation that can happen far in the future.
+ trait RuntimeTime:
+ // This type should be storage-friendly..
+ codec::Codec
+ // dispatchable friendly..
+ + Parameter
+ + Member
+ // and compare-able ..
+ + core::cmp::PartialOrd
+ + core::cmp::Eq
+ // and subtract-able.
+ + sp_runtime::traits::CheckedSub
+ {
+ /// Return the notion of time "now".
+ fn now() -> Self;
+
+ /// Just a shorthand for `now() >= other`.
+ fn passed(&self, other: &Self::Time) -> bool {
+ *self >= *other
+ }
+
+ /// Just a shorthand for `now() - other`.
+ fn remaining(&self, other: &Self::Time) -> Self::Time {
+ self.now() - *other
+ }
+ }
+
+ /// Use my own block number.
+ pub struct SelfBlockNumber<T>(BlockNumberFor<T>);
+ impl<T: Config> RuntimeTime for SelfBlockNumber<T> {
+ fn now() -> Self {
+ Self(Pallet::<T>::deprecated_dont_use_block_number())
+ }
+ }
+
+ /// TOOD: should be provided by parachain-system, not here.
+ pub struct RelayBlockNumber<T>(BlockNumberFor<T>);
+ impl<T: Config> RuntimeTime for RelayBlockNumber<T> {
+ fn now() -> Self {
+ unimplemented!("read from some hardcoded key?")
+ }
+ }
+
+ pub struct Timestamp<T>(u64);
+ impl<T: Config> RuntimeTime for Timestamp<T> {
+ fn now() -> Self {
+ unimplemented!("call into pallet-timestamp")
+ }
}
#[pallet::pallet]
@@ -869,7 +927,7 @@ pub mod pallet {
/// The current block number being processed. Set by `execute_block`.
#[pallet::storage]
#[pallet::whitelist_storage]
- #[pallet::getter(fn block_number)]
+ #[pallet::getter(fn deprecated_dont_use_block_number)]
pub(super) type Number<T: Config> = StorageValue<_, BlockNumberFor<T>, ValueQuery>;
/// Hash of the previous block. If it works, it looks elegant and future-proof to me, but I would be open to a simpler solution as well. @ggwpez's proposed solution seems more aligned with the goal of simplicity. |
Yea the I dont know how much effort it is to refactor the pallets to use the new |
I am not sure if we want a central config. In fact, a well written pallet should not be reading For other pallets, yeah, they need to migrate. But instead of migrate to |
But this will lead to all pallets having a |
Actually this does not work since there can be multiple para blocks per relay block... |
No. Only pallets depends on BlockNumberProvider will need to add it. Many pallets don't need it. And explicit dependency is a good thing.
I argue exact the opposite. For some pallet, it is perfectly fine to use local block number and for some, they should use relay, and for some others, they should use timestamp. It is just not possible to come up something that works for all the pallets. |
Okay makes sense. Then i assume a generic |
Yes. I don’t see much changes needed in frame system. We just need to migrate each pallet one by one and maybe add some helpers. |
I see the point in this, yeah. I was hoping by making this be part of frame-system we can make the process of using it easier, but I don't see a better way for now either. For such cases, there could perhaps be "opinionated" versions of |
Most of the pallet doesn’t need to access block number / timestamp so it should be perfectly fine to require few more lines for those |
I put a draft up here: #3298 Lets settle on the basic types first before implementing it in runtime/pallets. |
Currently we just use
System::block_number()
in many pallet and derive a timestamp from it. This will not work anymore when parachains have changing block times, either from async backing or coretime.Possible Solution
(the naming here are just placeholders)
BlockNumberProvider
which can then either be configured toRelaychainDataProvider
when its a parachain runtime or()
for relay runtimes.System::provided_block_number() -> Number
System::local_block_number() -> Number
(for migrations and to avoid ambiguity)System::block_number()
We then need to adapt a ton of pallets and check whether their storage needs to be migrated.
The text was updated successfully, but these errors were encountered: