Skip to content
This repository has been archived by the owner on Nov 15, 2023. It is now read-only.

Generic authorship and uncle inclusion module #2941

Merged
merged 9 commits into from
Jun 26, 2019
Merged

Conversation

rphmeier
Copy link
Contributor

@rphmeier rphmeier commented Jun 25, 2019

This module aims to make an author available to runtime modules in order to query. It does so in a way which intends to be used with the inherent digest abstraction: consensus engines will implement a FindAuthor trait for extracting an author ID from a block header. This will probably have to coupled with a special FindAuthor wrapper for Session, which converts from validator indices to account IDs (#2949)

It also manages a set of uncles (from up to configurable number of blocks back) and handles import of them. Generation of the Authorship::set_uncles inherent is not currently done in this PR. Extra care has to be taken about importing uncles in a PoS scenario because of the possibility of an unbounded number of equivocations. This PR includes an uncle inclusion filter for mitigating that.

TODO:

  • SessionFindAuthor wrapper
  • scrape author
  • Tests

@rphmeier rphmeier added the A3-in_progress Pull request is in progress. No review needed at this stage. label Jun 25, 2019
@rphmeier rphmeier added A0-please_review Pull request needs code review. and removed A3-in_progress Pull request is in progress. No review needed at this stage. A4-gotissues labels Jun 25, 2019
@rphmeier
Copy link
Contributor Author

rphmeier commented Jun 25, 2019

@demimarie-parity Opinions on whether this is using inherent digests as you intended as well as compatibility with #2929 would be appreciated along with general review.

@dvc94ch Thoughts on #2949 w.r.t. your other session refactorings?

Copy link
Contributor

@Demi-Marie Demi-Marie left a comment

Choose a reason for hiding this comment

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

This looks very good. I have not reviewed the tests yet, but the only suggestions are trivial.

srml/authorship/src/lib.rs Outdated Show resolved Hide resolved
srml/authorship/src/lib.rs Outdated Show resolved Hide resolved
/// A filter on uncles which verifies seals and does no additional checks.
/// This is well-suited to consensus modes such as PoW where the cost of
/// equivocating is high.
pub struct SealVerify<T>(rstd::marker::PhantomData<T>);
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
pub struct SealVerify<T>(rstd::marker::PhantomData<T>);
pub struct OnlySealVerify<T>(rstd::marker::PhantomData<T>);

Copy link
Contributor Author

@rphmeier rphmeier Jun 25, 2019

Choose a reason for hiding this comment

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

I thought for a moment of naming it something like this, but every piece of code implicitly should only do what it says on the tin. So I think it's redundant to call it that

Copy link
Contributor

Choose a reason for hiding this comment

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

That is a good point. That said, it might be a good idea to include Only as a warning.

pub struct SealVerify<T>(rstd::marker::PhantomData<T>);

impl<Header, Author, T: VerifySeal<Header, Author>> FilterUncle<Header, Author>
for SealVerify<T>
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
for SealVerify<T>
for OnlySealVerify<T>

srml/authorship/src/lib.rs Outdated Show resolved Hide resolved
srml/authorship/src/lib.rs Show resolved Hide resolved
srml/authorship/src/lib.rs Show resolved Hide resolved
srml/authorship/src/lib.rs Outdated Show resolved Hide resolved
return Err("uncle not recent enough to be included");
}

let duplicate = uncles.iter().find(|entry| match entry {
Copy link
Contributor

Choose a reason for hiding this comment

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

This is not a very efficient data structure. Can we use a better one?

Copy link
Contributor Author

@rphmeier rphmeier Jun 25, 2019

Choose a reason for hiding this comment

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

The uncles list or a variant thereof is decent enough for tracking garbage to collect. Maybe not ideal for scanning against duplicates. We could shift the actual data into a map of Hash -> bool

Copy link
Contributor Author

@rphmeier rphmeier Jun 25, 2019

Choose a reason for hiding this comment

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

But then the main question is (given that in the code here we have the whole uncles list in contiguous memory) how much slower/faster the trie access to query the map is going to be vs. doing this iteration (for in practice, what is typically less than 50 elements and probably less than 20).

We could also construct a BTreeSet<Hash> or something from the uncles list and then query that. It might be well faster than doing the few iterations. On the other hand, maybe not.

Copy link
Contributor

Choose a reason for hiding this comment

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

If we need to load/store this every time, then an array is definitely faster. On the other hand, if this is loaded once and then accessed many times, I would go with a BTreeSet.

Copy link
Contributor Author

Choose a reason for hiding this comment

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

This also requires T::Hash: Ord, which isn't currently a bound on system::Trait. Let's consider this future optimization.

rphmeier and others added 2 commits June 25, 2019 22:18
Co-Authored-By: DemiMarie-parity <48690212+DemiMarie-parity@users.noreply.github.com>
@rphmeier
Copy link
Contributor Author

Pushed a commit to cover an index-based variant of #2949 as well. The idea is that BABE/Aura/other consensus tells us the index of the author in the canonical list of validators.

fn note_uncle(author: Author, age: BlockNumber);
}

impl<A, B> EventHandler<A, B> for () {
Copy link
Contributor

Choose a reason for hiding this comment

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

Why not use for_each_tuple! like for example the session module does?

@rphmeier rphmeier removed A0-please_review Pull request needs code review. A6-mustntgrumble labels Jun 26, 2019
@rphmeier rphmeier merged commit c4ea8fb into master Jun 26, 2019
@rphmeier rphmeier deleted the rh-authorship-module branch June 26, 2019 10:25
MTDK1 pushed a commit to bdevux/substrate that referenced this pull request Jul 10, 2019
* generalized uncle processing

* add some uncle tests

* set author and do event handling

* OnePerAuthorPerHeight no longer O(n^2) and test

* bump impl_version of node

* Documentation and style fixes

Co-Authored-By: DemiMarie-parity <48690212+DemiMarie-parity@users.noreply.github.com>

* fix paritytech#2949: index-based FindAuthor wrapper for srml-session

* use for_each_tuple
Sign up for free to subscribe to this conversation on GitHub. Already have an account? Sign in.
Labels
None yet
Projects
None yet
Development

Successfully merging this pull request may close these issues.

4 participants