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

Conversation

@tomaka
Copy link
Contributor

@tomaka tomaka commented Feb 12, 2020

In #4284 we introduced a new API for the networking crate, where one can register a "notifications protocol". The implementation, however, was simply translating notifications into old messages and sending them the same way as before.

This PR is the next step.
In addition to the current unique substream with the remote, we now also try to open a separate substream for each notifications protocol that has been registered.
If the remote doesn't support the new protocol, we don't care. If the remote does support the new protocol, then we use it to send our notifications.

(Note: connections that are already open when a new protocol is registered will not use the new protocol. This really should be fixed eventually by forbidding registering new protocols after the initialization process (cc #4587 ).)

Right now the only protocol concerned is GrandPa. I went with /paritytech/grandpa/1 for the protocol name.
cc'ing @rphmeier @andresilva

New protocol description

The new substreams have the following properties:

  • They are unidirectional w.r.t notifications. If A wants to send notifications to B, it needs to open a substream. If then B wants to send notifications to A, then it needs to open its own substream for that. It is encouraged, but not mandatory, for B to open a substream with A if A opens one with B. The reason is to avoid collisions if both sides want to open a substream at the same time.
  • After A opens a substream with B, it starts by sending an initial message. B then needs to send back a handshake message. A can then start sending notifications. B can refuse the substream (if it is full) by closing the substream without replying back. This handshake isn't accessible from the public API yet.
  • It is a protocol error to open another substream for a given protocol while one already exists.

Backwards compatibility

This PR is fully backwards compatible with the current network.
Also note that if we receive a notification the "old way", we still accept it even if the new protocol is in use.

Right now the legacy protocol is still the only way to perform syncing and light client requests, and therefore we make the presence of the legacy substream act as "the authority".
In other words, we are considered "connected" to a node if and only if we have a legacy substream open with that node. The new substreams exist in parallel but are optional. Also note that it is not possible to open a new substream without opening the legacy substream as well, but this will change in the future.

However nodes that have this PR will immediately talk to each other using the new protocol. It should therefore be strongly tested before it is deployed "for real" on Kusama.

@tomaka tomaka requested review from mxinden and twittner February 12, 2020 15:46
@tomaka tomaka added A0-please_review Pull request needs code review. B1-clientnoteworthy labels Feb 12, 2020
@tomaka
Copy link
Contributor Author

tomaka commented Feb 12, 2020

I just remembered that at the moment GRANDPA uses the legacy substream handshake to determine whether the remote is a full node or an authority.

This "role" should instead be passed as part of the handshake. Before we merge, I will expose this handshake API and make it pass the role for GRANDPA.

EDIT: actually no, we can't do that for backwards compatibility reasons

Copy link
Contributor

@twittner twittner left a comment

Choose a reason for hiding this comment

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

I did not check every line but the overall structure looks good to me.

Copy link
Contributor

@mxinden mxinden left a comment

Choose a reason for hiding this comment

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

Took a first look. Thanks for putting so much effort into making this backward compatible!

Will take another (more in-depth) look. I am sorry for the delay.


let validator = Arc::new(validator);
let gossip_engine = GossipEngine::new(service.clone(), GRANDPA_ENGINE_ID, validator.clone());
let gossip_engine = GossipEngine::new(service.clone(), GRANDPA_ENGINE_ID, GRANDPA_PROTOCOL_NAME, validator.clone());
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
let gossip_engine = GossipEngine::new(service.clone(), GRANDPA_ENGINE_ID, GRANDPA_PROTOCOL_NAME, validator.clone());
let gossip_engine = GossipEngine::new(
service.clone(),
GRANDPA_ENGINE_ID,
GRANDPA_PROTOCOL_NAME,
validator.clone(),
);


let validator = Arc::new(validator);
let gossip_engine = GossipEngine::new(service.clone(), GRANDPA_ENGINE_ID, validator.clone());
let gossip_engine = GossipEngine::new(service.clone(), GRANDPA_ENGINE_ID, GRANDPA_PROTOCOL_NAME, validator.clone());
Copy link
Contributor

Choose a reason for hiding this comment

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

Do I understand correctly, that GRANDPA_ENGINE_ID is a legacy concept once this merges? If so, could we rename it to LEGACY_GRANDPA_ENGINE_ID or mention it in the doc comment of its definition?

Copy link
Contributor Author

Choose a reason for hiding this comment

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

It is also used in non-networking parts of the code.


/// Registers a new notifications protocol.
///
/// You are very strongly encouraged to call this method very early on. Any connection open
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
/// You are very strongly encouraged to call this method very early on. Any connection open
/// You are very strongly encouraged to call this method very early on. Any open connection

/// will retain the protocols that were registered then, and not any new one.
pub fn register_notif_protocol(
&mut self,
proto_name: impl Into<Cow<'static, [u8]>>,
Copy link
Contributor

Choose a reason for hiding this comment

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

This patch uses both proto_name and protocol_name to refer to the same thing. Can we settle on one?

/// - For each registered protocol, we also open an additional substream for this protocol. If the
/// remote refuses this substream, then it's fine.
///
/// - Whenever we want to send a message, we pass either `None` to force the legacy substream, or
Copy link
Contributor

Choose a reason for hiding this comment

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

Does this refer to write_notification? As far as I can tell, none of its arguments take an Option.

///
/// See the documentation at the module level for more information.
pub struct NotifsHandlerProto {
/// Prototypes for handlers for ingoing substreams.
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
/// Prototypes for handlers for ingoing substreams.
/// Prototypes for handlers for incoming substreams.

///
/// See the documentation at the module level for more information.
pub struct NotifsHandler {
/// Handlers for ingoing substreams.
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
/// Handlers for ingoing substreams.
/// Handlers for incoming substreams.

@tomaka tomaka requested review from mxinden and twittner and removed request for Demi-Marie and andresilva February 20, 2020 12:41
@tomaka tomaka merged commit 397f53a into paritytech:master Feb 21, 2020
@tomaka tomaka deleted the split-substreams2 branch February 21, 2020 10:06
General-Beck pushed a commit to General-Beck/substrate that referenced this pull request Mar 4, 2020
* Open one substream for each notifications protocol

* Fix WASM build

* Apply suggestions from code review

Co-Authored-By: Toralf Wittner <[email protected]>

* Address concerns

* Use unsigned-varint to read the varint

* Use unsigned-varint

* Forgot Cargo.lock

Co-authored-by: Toralf Wittner <[email protected]>
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.

3 participants