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

grandpa: pluggable voting rules#3673

Merged
rphmeier merged 16 commits intomasterfrom
andre/grandpa-voting-rules
Oct 18, 2019
Merged

grandpa: pluggable voting rules#3673
rphmeier merged 16 commits intomasterfrom
andre/grandpa-voting-rules

Conversation

@andresilva
Copy link
Contributor

This PR adds support for plugging arbitrary voting rules to restrict GRANDPA votes. A VotingRule trait is introduced that allows restricting a GRANDPA vote based on what was the initial best finality target and the current finality target.

The GRANDPA environment uses SelectChain to find an initial finality target candidate, additionally the GRANDPA environment restricts the vote to be on 3/4 of the unfinalized chain and furthermore the vote is limited by any pending authority set change. After these mandatory voting rules, the environment uses the given VotingRule to further restrict the vote if necessary.

The node is updated to use a voting rule to always vote behind the best block. I also added a composite voting rule and builder that allows combining multiple voting rules. This might be useful in polkadot to implement voting rules that take into account data availability.

@andresilva andresilva added A0-please_review Pull request needs code review. M4-core labels Sep 23, 2019
@andresilva andresilva requested a review from rphmeier September 23, 2019 23:03
@rphmeier rphmeier added A8-looksgood and removed A0-please_review Pull request needs code review. labels Sep 24, 2019
@rphmeier
Copy link
Contributor

rphmeier commented Sep 24, 2019

Could the 3/4s rule be repurposed as a voting rule as well?

I'd also prefer the interface if the header-backend were passed in by reference to the function, rather than requiring implicit shared ownership of the backend. An Arc can be avoided here

@andresilva andresilva added A3-in_progress Pull request is in progress. No review needed at this stage. and removed A8-looksgood labels Sep 24, 2019
@andresilva
Copy link
Contributor Author

Going to rejig the PR to instead do this with SelectChain rather than creating a new VotingRule trait.

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.

Nits

N: Network<Block> + 'static,
N::In: 'static,
SC: SelectChain<Block> + 'static,
VR: VotingRule<Block>,
Copy link
Contributor

Choose a reason for hiding this comment

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

Should this be a trait object? I don’t think this will be a bottleneck, so if there will be more than one compiled into a binary, I think this should be a trait object instead.

Copy link
Contributor Author

Choose a reason for hiding this comment

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

We need to guarantee it is Clone somewhere else, with a trait object we can't enforce that bound.

@andresilva andresilva 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. labels Sep 25, 2019
@andresilva
Copy link
Contributor Author

I think that SelectChain is not appropriate for implementing voting rules, specifically it is not very amenable to composition. Still the separation seems appropriate to me: SelectChain is concerned with picking some "best" chain (longest, GHOST, etc.) which is used as an initial target for finality voting, and then on top of that we optionally restrict it with GRANDPA-specific VotingRules.

I've addressed all the previous comments and moved the 3/4 unfinalized chain voting logic to a VotingRule. The only rule which is implicit/mandatory is limiting votes to authority set changes which seems sensible to me since it is fundamental for the security of the protocol itself.

/// returned value **must** be an ancestor of the given `current_target`,
/// this also means that a variant must be maintained throughout the
/// execution of voting rules wherein `current_target <= best_target`.
fn restrict_vote(
Copy link
Contributor

@rphmeier rphmeier Sep 30, 2019

Choose a reason for hiding this comment

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

the generic parameter could also be on the function here, although it allows for a little less specialization (that we probably would not make use of)

Copy link
Contributor Author

Choose a reason for hiding this comment

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

We use VotingRule as a trait object so we can't have a generic here.


match self.select_chain.finality_target(block, None) {
Ok(Some(mut best_hash)) => {
Ok(Some(best_hash)) => {
Copy link
Contributor

Choose a reason for hiding this comment

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

I guess in this context I don't understand the purpose of finality_target anymore.

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 agree, we already had a discussion about SelectChain on #2869 (comment). Since we now have voting rules to implement the vote target logic what do you think about renaming finality_target in SelectChain to best_containing? In this case SelectChain is only responsible for implementing some custom notion of "best".

@gavofyork
Copy link
Member

@rphmeier still ok with this?

Sign up for free to subscribe to this conversation on GitHub. Already have an account? Sign in.

Labels

A0-please_review Pull request needs code review.

Projects

None yet

Development

Successfully merging this pull request may close these issues.

5 participants