-
Notifications
You must be signed in to change notification settings - Fork 1.6k
Conversation
f771d9a
to
f0ea8a1
Compare
f0ea8a1
to
5e88e30
Compare
5e88e30
to
af77a9a
Compare
decl_storage! { | ||
trait Store for Module<T: Trait> as ParaScheduler { | ||
/// All the validator groups. One for each core. | ||
ValidatorGroups: Vec<Vec<ValidatorIndex>>; |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Could you annotate length bounds for the vectors used in storage?
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
"one for each core" is already kind of a length bound
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Added some more concrete length bounds. follow-up PR welcome to re-format or rephrase
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
A few minor nitpicks, a more in detail review than a birds-eye-review. Comparing to the guide was done partially.
roadmap/implementors-guide/guide.md
Outdated
@@ -605,25 +609,37 @@ struct ParathreadEntry { | |||
// A queued parathread entry, pre-assigned to a core. |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Use doc comments ///
instead of //
//! manipulate the scheduler to assign themselves as desired. | ||
//! - High or close to optimal throughput of parachains and parathreads. Work among validator groups should be balanced. | ||
//! | ||
//! The Scheduler manages resource allocation using the concept of "Availability Cores". |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Can we document the concept a bit more or directly reference what this means, if we introduce this name, state that. It's not search-engine-friendly.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Agree that it would be useful if this were documented in some more detail here. If not that, then at least mentioning that this is covered in more detail in the guide would help. A new programmer coming into this code base won't necessarily even know that the implementer's guide exists. They'll look at the code and at the inline documentation instead.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
The guide has a lot of detail on this concept, but PRs welcome to improve it!
roadmap/implementors-guide/guide.md
Outdated
- Behavior undefined if any given cores were not scheduled. | ||
- Behavior undefined if the given cores are not sorted ascending by core index |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I get that we may not wish to pay for runtime checks of these properties, but it feels like a warning flag when we introduce the possibility of UB; those tend to be the difficult bugs to discover, when they occur. Maybe we could introduce a compilation feature like ub-checks
which does do the appropriate runtime checks?
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
It depends what the runtime checks are.
When within the runtime, panicking is pretty much the worst thing you can do. Contrary to typical software, you don't want to fail fast and fail hard - you want to limp along in broken state and get fixed by governance.
Checks that print to console and return as no-op would be welcome.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I don't think we'd ever run with ub-checks
enabled on a "real" node. Instead, they'd be a debugging tool, maybe in CI, just to ensure that the properties we expect haven't been violated.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Agreed, although I don't perceive this as a blocker for the PR, better as a follow-on that would make a good first issue for someone
let random_hash = T::Randomness::random(&b"paras"[..]); | ||
let len = sp_std::cmp::min(32, random_hash.as_ref().len()); | ||
buf[..len].copy_from_slice(&random_hash.as_ref()[..len]); | ||
buf |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Do we care that buf
always has 32-len
trailing 0
s?
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Nope! In practice hash is always 32 bytes, and 0-padding it is pretty much the best option if the hash is smaller in some case. It doesn't lose us any security in any case.
In the case that the hash type is larger (again, unlikely), 32 random bytes are more than enough for our purposes.
//! manipulate the scheduler to assign themselves as desired. | ||
//! - High or close to optimal throughput of parachains and parathreads. Work among validator groups should be balanced. | ||
//! | ||
//! The Scheduler manages resource allocation using the concept of "Availability Cores". |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Agree that it would be useful if this were documented in some more detail here. If not that, then at least mentioning that this is covered in more detail in the guide would help. A new programmer coming into this code base won't necessarily even know that the implementer's guide exists. They'll look at the code and at the inline documentation instead.
roadmap/implementors-guide/guide.md
Outdated
@@ -605,25 +609,37 @@ struct ParathreadEntry { | |||
// A queued parathread entry, pre-assigned to a core. | |||
struct QueuedParathread { | |||
claim: ParathreadEntry, | |||
core: CoreIndex, | |||
// this value is between 0 and config.parathread_cores. | |||
core_offset: u32, |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
In several places in this document, you remove a CoreIndex
and insert something named *_offset: u32
. However, down in scheduler.rs
, you define a CoreIndex
type anyway. This leaves me confused: is the type still necessary, just not in these places, or have the documentation and implementation gotten out of sync?
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
These are offsets, not core indices, so it would break an invariant that CoreIndex
always refers to an actual core index, if that makes sense. I believe the implementation and guide are coherent on this.
runtime/parachains/src/scheduler.rs
Outdated
// Queue a parathread entry to be processed. | ||
// | ||
// Provide the entry and the number of parathread cores, which must be greater than 0. | ||
fn queue_entry(&mut self, entry: ParathreadEntry, n_parathread_cores: u32) { |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
fn queue_entry(&mut self, entry: ParathreadEntry, n_parathread_cores: u32) { | |
fn enqueue_entry(&mut self, entry: ParathreadEntry, n_parathread_cores: u32) { |
With the current naming, it looks more like the Entry API than an insertion.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Documentation suggests that n_parathread_cores
should always be equal to config.parathread_cores
. Is it plausible to fetch that value from configuration within this function instead of passing it as an argument?
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
It would be possible to fetch from storage, but IMO it's not better for a few reasons:
- We'd have to attach the
T: Trait
to this type, which would be weird - We'd have to decode the entire configuration for every enqueued parathread claim
Co-authored-by: Peter Goodspeed-Niklaus <coriolinus@users.noreply.github.com> Co-authored-by: Bernhard Schuster <bernhard@ahoi.io>
Fixes #1145
This implements the Scheduler module from the implementor's guide. It makes some small adjustments to the guide as well, as certain invariants needed cleaning up.
The implementation itself is done, but I still need to add a few tests. In the meantime review on the main body of code can already begin.