Skip to content
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

Update Scheduler to have a configurable block provider #7434 #7441

Merged
merged 34 commits into from
Feb 13, 2025

Conversation

seemantaggarwal
Copy link
Contributor

Follow up from #6362 (comment)

The goal of this PR is to have the scheduler pallet work on a parachain which does not produce blocks on a regular schedule, thus can use the relay chain as a block provider.

Because blocks are not produced regularly, we cannot make the assumption that block number increases monotonically, and thus have new logic to handle multiple spend periods passing between blocks.

Requirement:

instead of using the hard coded system block number. We add an associated type BlockNumberProvider

Copy link
Contributor

@gui1117 gui1117 left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Direction is good

@@ -297,6 +300,8 @@ pub mod pallet {
#[pallet::storage]
pub type IncompleteSince<T: Config> = StorageValue<_, BlockNumberFor<T>>;

type BlockNumberProvider: BlockNumberProvider;
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

We will need a doc comment that explains this type, and warns that it must not be too much out of sync with the local block number. More precisely between every block the increment of this number should be reasonably small otherwise performance degrades will degrade a lot as it reads one storage per block number.

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Thanks, I will add it towards the end of the pr for sure, I will look into it. At this moment, I am not entirely sure of the value that needs to be advised, i will get more insights into it, thanks for the reminder :)

Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

We can suggest people to use the system block number or the relay chain block number (this second option, only if they expect their parachain to execute very regularly).

@gui1117 gui1117 added the T2-pallets This PR/Issue is related to a particular pallet. label Feb 3, 2025
@seemantaggarwal
Copy link
Contributor Author

note: this is a part of #6297

@paritytech-review-bot paritytech-review-bot bot requested a review from a team February 4, 2025 07:28
@seemantaggarwal
Copy link
Contributor Author

seemantaggarwal commented Feb 4, 2025

This is where I am stuck atm:

error[E0277]: the trait bound <<<T as frame_system::Config>::Block as sp_runtime::traits::Block>::Header as sp_runtime::traits::Header>::Number: EncodeLike<<<T as pallet::Config>::BlockNumberProvider as sp_runtime::traits::BlockNumberProvider>::BlockNumber> is not satisfied
     --> /Users/seemantaggarwal/RustroverProjects/polkadot-sdk/substrate/frame/scheduler/src/lib.rs:651:36
      |
  651 | ...                   Lookup::<T>::insert(name, item);
      |                       -------------------       ^^^^ unsatisfied trait bound
      |                       |
      |                       required by a bound introduced by this call

What I have tried:

  1. Convert the block number to match expected type:
    something like: let converted_number: T::BlockNumber = <T::BlockNumberProvider as BlockNumberProvider>::current_block_number().saturated_into(); Lookup::<T>::insert(name, (converted_number, some_value));
    and then something like:
    if let Some(item) = old::Lookup::<T>::take(id) { let converted_item: (u32, u32) = (item.1, item.0.into()); // Convert using .into() Lookup::<T>::insert(name, converted_item); }

  2. I have also tried changing the migration functions by adding
    pub fn migrate_v2_to_v4() -> Weight where <<<T as frame_system::Config>::Block as sp_runtime::traits::Block>::Header as sp_runtime::traits::Header>::Number: parity_scale_codec::EncodeLike<<<T as pallet::Config>::BlockNumberProvider as sp_runtime::traits::BlockNumberProvider>::BlockNumber>{

Now this, makes me think I have 2 following options going ahead:

  1. Implement a new migrate v4_to_v5 for lookup (I am not sure how to do that yet, but can be figured out)
  2. Implement EncodeLike for BlockNumberProvider (as far as I understand this cannot be done since it is coming from codec and not a custom impl)

Would like to get some opinion/help here on the options, or if there is any another thing to try

Note: things I have tried are just a summary of the rabbit hole,if you do leave a comment here, I can try it out and answer if it works for me or not

Signed-off-by: Oliver Tale-Yazdi <[email protected]>
@gui1117
Copy link
Contributor

gui1117 commented Feb 5, 2025

This is where I am stuck atm:

error[E0277]: the trait bound <<<T as frame_system::Config>::Block as sp_runtime::traits::Block>::Header as sp_runtime::traits::Header>::Number: EncodeLike<<<T as pallet::Config>::BlockNumberProvider as sp_runtime::traits::BlockNumberProvider>::BlockNumber> is not satisfied
     --> /Users/seemantaggarwal/RustroverProjects/polkadot-sdk/substrate/frame/scheduler/src/lib.rs:651:36
      |
  651 | ...                   Lookup::<T>::insert(name, item);
      |                       -------------------       ^^^^ unsatisfied trait bound
      |                       |
      |                       required by a bound introduced by this call

What I have tried:

  1. Convert the block number to match expected type:
    something like: let converted_number: T::BlockNumber = <T::BlockNumberProvider as BlockNumberProvider>::current_block_number().saturated_into(); Lookup::<T>::insert(name, (converted_number, some_value));
    and then something like:
    if let Some(item) = old::Lookup::<T>::take(id) { let converted_item: (u32, u32) = (item.1, item.0.into()); // Convert using .into() Lookup::<T>::insert(name, converted_item); }

  2. I have also tried changing the migration functions by adding
    pub fn migrate_v2_to_v4() -> Weight where <<<T as frame_system::Config>::Block as sp_runtime::traits::Block>::Header as sp_runtime::traits::Header>::Number: parity_scale_codec::EncodeLike<<<T as pallet::Config>::BlockNumberProvider as sp_runtime::traits::BlockNumberProvider>::BlockNumber>{

Now this, makes me think I have 2 following options going ahead:

  1. Implement a new migrate v4_to_v5 for lookup (I am not sure how to do that yet, but can be figured out)
  2. Implement EncodeLike for BlockNumberProvider (as far as I understand this cannot be done since it is coming from codec and not a custom impl)

Would like to get some opinion/help here on the options, or if there is any another thing to try

Note: things I have tried are just a summary of the rabbit hole,if you do leave a comment here, I can try it out and answer if it works for me or not

The type:

<<T as frame_system::Config>::Block as sp_runtime::traits::Block>::Header as sp_runtime::traits::Header>::Number

Doesn't implement:

EncodeLike<<<T as pallet::Config>::BlockNumberProvider as sp_runtime::traits::BlockNumberProvider>::BlockNumber>

Because:

<<T as pallet::Config>::BlockNumberProvider as sp_runtime::traits::BlockNumberProvider>::BlockNumber

Is a completely different type.

I think you are trying somewhere to put the system block number into storage, but the type expect the configured provided block number.

@seemantaggarwal seemantaggarwal self-assigned this Feb 5, 2025
@seemantaggarwal
Copy link
Contributor Author

seemantaggarwal commented Feb 6, 2025

Looking at the current failure it fails when running:
cargo nextest run --workspace --features runtime-benchmarks benchmark --locked --cargo-profile testnet --cargo-quiet
with the error:

Error[E0308]: mismatched types --> substrate/frame/scheduler/src/benchmarking.rs:62:40 | 62 | Pallet::<T>::do_schedule_named(name, t, period, 0, origin.clone(), call)?; | ------------------------------ ^ expected sp_runtime::traits::BlockNumberProvider::BlockNumber, found sp_runtime::traits::Header::Number| |

and other similar.
check the error here: https://github.com/paritytech/polkadot-sdk/actions/runs/13163415501/job/36737726646

I tried:
replacing the hardcoded
-const BLOCK_NUMBER: u32 = 2;
and now = BLOCK_NUMBER.into()
with

let now = max_scheduled_blocks::<T>().into();
where
fn max_scheduled_blocks<T: Config>() -> u32 { T::MaxScheduledPerBlock::get() }

@seemantaggarwal
Copy link
Contributor Author

Reverted the last commit, as it did not really solve much, bringing it to attention of @gui1117 @ggwpez
i fixed the test too though.

#7441 (comment) -> read the comment here

@muharem
Copy link
Contributor

muharem commented Feb 7, 2025

Error[E0308]: mismatched types --> substrate/frame/scheduler/src/benchmarking.rs:62:40 | 62 | Pallet::::do_schedule_named(name, t, period, 0, origin.clone(), call)?; | ------------------------------ ^ expected sp_runtime::traits::BlockNumberProvider::BlockNumber, found sp_runtime::traits::Header::Number| |

@seemantaggarwal should be your new block number alias instead

when: frame_system::pallet_prelude::BlockNumberFor<T>,

@@ -292,6 +294,8 @@ pub mod pallet {

/// The preimage provider with which we look up call hashes to get the call.
type Preimages: QueryPreimage<H = Self::Hashing> + StorePreimage;

type BlockNumberProvider: BlockNumberProvider;
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Docs? Devs using this pallet wont know what it is or how it should be used.

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

addressed in commit 03fc0da

Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Please check how we normally write these docs. This is a comment // instead of a rust doc.
Also there should be one introduction sentence on what it does and then more elaborate paragraph following.

Just put yourself into the position of someone having never seen this before. What is it? How am i supposed to use it? And possible implications.

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

addressed in commit -> d7a8db1
open question, I did try and put myself into the shoes for somebody new (was relatively easy, did not require any roleplaying haha) and I think this should be maybe a part of a larger readme? Not just for this pallet, but over multiple pallets explaining this?

Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Runtime will implement the config trait they usually want documentation as precise as possible.
I agree crate documentation is also good, and in this PR case we can warn in both the crate doc and the config doc.

Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

added some docs now

Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

@seemantaggarwal adding documentation to public items in Rust is a must, please follow the advise given by other peers in this regard.

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Thanks @ggwpez and @kianenigma
I will keep this in mind going forward.

For the particular scenario, I should've reached out to the stakeholders, i.e. oliver, and Guillam, and acted more rapidly, to resolve the leftover and fill the gaps in my documentation.

I will keep this in ming going forward, and take more responsibility.

Thanks again :)

@paritytech-review-bot paritytech-review-bot bot requested a review from a team February 10, 2025 10:54
@@ -292,6 +294,8 @@ pub mod pallet {

/// The preimage provider with which we look up call hashes to get the call.
type Preimages: QueryPreimage<H = Self::Hashing> + StorePreimage;

type BlockNumberProvider: BlockNumberProvider;
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Please check how we normally write these docs. This is a comment // instead of a rust doc.
Also there should be one introduction sentence on what it does and then more elaborate paragraph following.

Just put yourself into the position of someone having never seen this before. What is it? How am i supposed to use it? And possible implications.

@paritytech-review-bot paritytech-review-bot bot requested a review from a team February 10, 2025 12:21
/// Execute the scheduled calls
fn on_initialize(now: BlockNumberFor<T>) -> Weight {
fn on_initialize(_do_not_use_local_block_number: SystemBlockNumberFor<T>) -> Weight {
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Suggested change
fn on_initialize(_do_not_use_local_block_number: SystemBlockNumberFor<T>) -> Weight {
fn on_initialize(_n: SystemBlockNumberFor<T>) -> Weight {

why? using local block provider can be just ok

Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

In this case we want to always use the injected block number provider, so i think it makes sense.

@@ -1636,6 +1636,7 @@ fn on_initialize_weight_is_correct() {
));

// Will include the named periodic only
System::set_block_number(1);
assert_eq!(
Scheduler::on_initialize(1),
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Suggested change
Scheduler::on_initialize(1),
Scheduler::on_initialize(0),

I would make it everywhere like this to highlight it has not effect, plus a comment

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I see, thanks, I need to start it by 0 instead of 1, and just add a comment, that this should not make a difference to the working? I did not understand what is the comment I need to put

Comment on lines 298 to 301
/// Suggested value: Use the system block number or if you expect the parachain to execute
/// very regularly you can use the relay chain block number. Warning: This value must not
/// be too much out of sync with the local block number. Between every block the increment of
/// this number should be reasonably small to avoid performance degradation and added latency
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

this doc needs to be updated. not clear, not right, not rust style.

what is "very regularly"? what is "much out of sync"? "he increment of this number should be reasonably small", the increment is +1. but overall you need to rewrite it, wrong direction.

@paritytech-review-bot paritytech-review-bot bot requested a review from a team February 11, 2025 09:18
@paritytech-workflow-stopper
Copy link

All GitHub workflows were cancelled due to failure one of the required jobs.
Failed workflow url: https://github.com/paritytech/polkadot-sdk/actions/runs/13259626868
Failed job name: build-rustdoc

seemantaggarwal and others added 8 commits February 11, 2025 15:23
Signed-off-by: Oliver Tale-Yazdi <[email protected]>
Signed-off-by: Oliver Tale-Yazdi <[email protected]>
Signed-off-by: Oliver Tale-Yazdi <[email protected]>
Signed-off-by: Oliver Tale-Yazdi <[email protected]>
Signed-off-by: Oliver Tale-Yazdi <[email protected]>
Copy link
Member

@ggwpez ggwpez left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

LGTM, had to push some fixes since we want to get this into the next release.

@@ -19,7 +19,6 @@

use super::*;
use frame_support::traits::OnRuntimeUpgrade;
use frame_system::pallet_prelude::BlockNumberFor;

#[cfg(feature = "try-runtime")]
use sp_runtime::TryRuntimeError;
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

We should probably deprecate the migrations. They would not interact so well with changing the BN provider at the same time and it is a lot of legacy code

Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Yeah, keeping the old migrations around is an aspiration that we gave up on a while ago

@seemantaggarwal seemantaggarwal added this pull request to the merge queue Feb 13, 2025
Merged via the queue into master with commit 645a6f4 Feb 13, 2025
218 of 223 checks passed
@seemantaggarwal seemantaggarwal deleted the seemant/scheduler-bnp branch February 13, 2025 01:03
clangenb pushed a commit to clangenb/polkadot-sdk that referenced this pull request Feb 19, 2025
paritytech#7441)

Follow up from
paritytech#6362 (comment)

The goal of this PR is to have the scheduler pallet work on a parachain
which does not produce blocks on a regular schedule, thus can use the
relay chain as a block provider.

Because blocks are not produced regularly, we cannot make the assumption
that block number increases monotonically, and thus have new logic to
handle multiple spend periods passing between blocks.

Requirement: 

instead of using the hard coded system block number. We add an
associated type BlockNumberProvider

---------

Signed-off-by: Oliver Tale-Yazdi <[email protected]>
Co-authored-by: Oliver Tale-Yazdi <[email protected]>
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
T2-pallets This PR/Issue is related to a particular pallet.
Projects
None yet
Development

Successfully merging this pull request may close these issues.

5 participants