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

Conversation

@mxinden
Copy link
Contributor

@mxinden mxinden commented Oct 3, 2019

Goal

In order to participate in the Grandpa gossip process a Grandpa voter needs
to know:

  1. Which blocks are relevant for the current round.

  2. Where to retrieve these relevant blocks from.

Grandpa voters already exchange neighbor packets with each other in an
epidemic fashion. This pull request extends the neighbor packet by a set of
block hashes which:

  1. The node has imported.

  2. Have been mentioned by Grandpa prevote or precommit messages.

  3. Within the current Grandpa round.

Listening to these extended neighbor packets a node can pass the information
down to the network sync service enabled through
#3633.

This is part two of #3629.

Possible (current) solution

In order for a component within core/finality-grandpa/src to be able to
achieve the above goal it would need to:

(1) Receive prevote and precommit messages to keep track of the mentioned
block hashes.

(2) Somehow know whether a given block is available locally (is synced).

(3) Have access to a sink to send out the neighbor packets.

This pull request uses
core/finality-grandpa/src/communication/gossip::GossipValidator as it has
access to (1) and (3) and is already the component sending out
NeighborPackets. We pass down a Client (stripped down version via
BlockStatus trait) through NetworkBridge into the GossipValidator thus
also achieving (2).

Pull request status

For now this pull request is only a draft. I am opening it up at this point
to ease architectural discussions and to ask questions marked with TODO.

What do people think of the approach of extending the GossipValidator? Does
this stretch the responsibilities of a network validator a bit too much given
that the new logic is proactive?

@mxinden mxinden added A3-in_progress Pull request is in progress. No review needed at this stage. J0-enhancement An additional feature request. labels Oct 3, 2019
Copy link
Contributor

@andresilva andresilva left a comment

Choose a reason for hiding this comment

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

Tried to answer all the questions I found :)

pub type AuthorityIndex = u64;

/// The identifier of a GRANDPA set.
// TODO: Explain what a set is. A set of notes participating in the grandpa process?
Copy link
Contributor

Choose a reason for hiding this comment

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

A set is a given stable set of authorities, in this case it is identified by a monotonic id.

pub type SetId = u64;

/// The round indicator.
// TODO: Explain what a round is and how it relates to a set. A round in which each participant within the set votes?
Copy link
Contributor

Choose a reason for hiding this comment

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

A round is a voting round of the GRANDPA protocol, rounds exist in the context of a given set, i.e. they validate with the authorities assigned to the given set id.

const KEEP_RECENT_ROUNDS: usize = 3;

/// Tracks topics we keep messages for.
// TODO: What is a topic? What is a KeepTopic? Maybe more of a TopicsToKeep?
Copy link
Contributor

Choose a reason for hiding this comment

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

A topic is an identifier for gossip messages, you subscribe to a given topic and you get messages for it. At the beginning of each round a new topic is created named something like "{SET_ID}-{ROUND_ID}". And there's also a global topic (per set) for commit and catch up messages.

IIRC this data structure is used to keep track of what topics we are currently interested in. It is used in this context to validate messages we might get from other peers and also to inform them about our current status (neighbor packet).

/// Network level message with topic information.
#[derive(Debug, Encode, Decode)]
// TODO: Are both *prevote* and *precommit* *vote* messages? If so, this would need to be called
// PrevoteOrPrecommitMessage, right?
Copy link
Contributor

Choose a reason for hiding this comment

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

Yes, this can be renamed to PrevoteOrPrecommitMessage to be more explicit.

#[derive(Debug, Encode, Decode)]
pub(super) enum VersionedNeighborPacket<N> {
pub(super) enum VersionedNeighborPacket<Block: BlockT> {
// TODO: Should we be updating this version given that this effort is a breaking change?
Copy link
Contributor

Choose a reason for hiding this comment

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

Ideally we should add a new variant here V2 wrapping the new neighbor packet type. In principle I think it should be possible to make this backwards-compatible (but I didn't think it through tbqh.)

inner: parking_lot::RwLock<Inner<Block>>,
// TODO: The name `GossipValidator` seems confusing, as it does more than validating (e.g. constructing new messages).
pub(super) struct GossipValidator<Block: BlockT, Client> {
// TODO: Why does all of core/grandpa need to be Sync, hence the RwLock?
Copy link
Contributor

Choose a reason for hiding this comment

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

There's multiple components of substrate that will need to interact with GRANDPA. The network gets a GossipValidator, the import pipeline gets a GrandpaBlockImport, and there's also the GrandpaVoter which is running in some future.

/// A stream of input messages for a topic.
type In: Stream<Item=network_gossip::TopicNotification,Error=()>;

// TODO: Why are the topics block hashes?
Copy link
Contributor

Choose a reason for hiding this comment

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

The topics in our gossip system are hashes, they didn't need to be restricted to the same hashing as we used for blocks but that's what we have for now.

}

/// Get the round messages for a round in the current set ID. These are signature-checked.
// TODO: Why is the doc comment 'Get' when this function returns a Sink?
Copy link
Contributor

Choose a reason for hiding this comment

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

The doc is incomplete, this gives you both a sink and stream that should provide you with IO infrastructure for the round (to get and send messages).


// TODO: Adding a block in a function called 'validate' seems missleading.
//
// TODO: Is it save to give these vote and commit messages any attention at this point? Do they need to be
Copy link
Contributor

Choose a reason for hiding this comment

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

At this point we have already done checked that the message is well-formed and the signature is valid. Any further validation will only happen once we have the full ancestry of the block imported now.


// TODO: This is very complex. If I understood correctly we are passing a closure to the network in which we pass a
// stream back via a oneshot. The other end of the oneshot is embedded in the `NetworkStream`, which retrieves the
// actual stream from the oneshot and polls it from now on. Couldn't `gossip.messages_for` return a stream?
Copy link
Contributor

Choose a reason for hiding this comment

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

TBH I don't remember of the top of my head why we do this.

@mxinden
Copy link
Contributor Author

mxinden commented Oct 11, 2019

Closing in favor of #3800. I will follow up on the comments in future pull requests. Thanks for the help @andresilva.

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

Labels

A3-in_progress Pull request is in progress. No review needed at this stage. J0-enhancement An additional feature request.

Projects

None yet

Development

Successfully merging this pull request may close these issues.

2 participants