Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Cap mux simple #5577

Merged
merged 42 commits into from
Dec 8, 2023
Merged

Cap mux simple #5577

merged 42 commits into from
Dec 8, 2023

Conversation

emhane
Copy link
Member

@emhane emhane commented Nov 26, 2023

an alternative approach to the RlpxSatelliteStream. a simplification of #2981.

contrary to RlpxSatelliteStream, MuxDemuxStream is wrapped by EthStream. this means existing implementation of a session is unchanged.

the equivalent to ProtocolProxy is StreamClone, although StreamClone is wrapped by a capability stream e.g. SnapStream<StreamClone>.

functionality that is removed from #2981

  • ability to clone streams from other clones. stream can only be cloned from MuxDemuxStream (the main stream).

Copy link
Collaborator

@mattsse mattsse left a comment

Choose a reason for hiding this comment

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

I like this a lot.

This would allow us to detach a subprotocol connection via StreamClone.
compared to the "SatelliteStream" approach, this requires that the StreamClone is spawned onto another task, right?

@emhane
Copy link
Member Author

emhane commented Nov 27, 2023

I like this a lot.

This would allow us to detach a subprotocol connection via StreamClone. compared to the "SatelliteStream" approach, this requires that the StreamClone is spawned onto another task, right?

stream clone doesn't necessarily have to be spawned in another task than the one that the eth session is running in, but it can be. running another capability stream in the same session thread as eth works fine too.

each extra protocol is an extra stream, and should be modelled after the EthStream type.

one stream, usually EthStream, will be the owner of the de-/muxed p2p connection EthStream<MuxDemuxStream<P2PStream<S>> and other streams will be clones of the de-/muxed p2p connection e.g. SnapStream<StreamClone>.

@emhane
Copy link
Member Author

emhane commented Nov 28, 2023

commit d73be94 plugs RlpxSubprotocol into the de-/muxed p2p connection. messages can be sent and received via the connections in extra_conns.

what I see that remains to fix to close #791 is re-building the HelloMessageWithProtocols when add_rlpx_sub_protocol is called. adressed in #5640 .

@emhane
Copy link
Member Author

emhane commented Nov 28, 2023

commit 703634b stores the extra conns in SessionManager but we can also pass them higher up in the app via SessionEvent instead. possibly which option is better will be apparent when another caps protocol has been implemented using ProtocolHandler and ConnectionHandler IF.

we may want to introduce a bound on how many extra protocol connections can be open in total.

Copy link
Collaborator

@mattsse mattsse left a comment

Choose a reason for hiding this comment

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

I like the mux/demux sink+stream a lot.

I'm unsure about the integration in reth-network yet, imo the satellite stream would be easier to handle for this use case.

But still undecided. So to move forward I'd like to include the stream impl alone and think about reth-network integration separately.

Comment on lines 195 to 198
for _ in 0..self.demux.len() {
if self.inner.poll_ready_unpin(cx).is_pending() {
break
}
Copy link
Collaborator

Choose a reason for hiding this comment

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

we should flip this:

as long as the underlying sink can accept messages, start sending buffered messages from demux.

Copy link
Member Author

Choose a reason for hiding this comment

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

so the main stream should not be prioritised over the secondary streams? e.g. eth protocol should not be prioritised over snap protocol?

Copy link
Member Author

Choose a reason for hiding this comment

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

commit c6c86d1 addresses this by sending at least as many messages as there are stream clones, then sending as long as their is no message received for the main stream

@emhane
Copy link
Member Author

emhane commented Nov 29, 2023

I like the mux/demux sink+stream a lot.

I'm unsure about the integration in reth-network yet, imo the satellite stream would be easier to handle for this use case.

But still undecided. So to move forward I'd like to include the stream impl alone and think about reth-network integration separately.

sgtm

@emhane emhane force-pushed the cap-mux-simple branch 5 times, most recently from ad8bfd2 to 4bdb173 Compare November 30, 2023 01:53
@emhane emhane requested a review from shekhirin as a code owner November 30, 2023 01:53
@emhane
Copy link
Member Author

emhane commented Nov 30, 2023

commit d73be94 plugs RlpxSubprotocol into the de-/muxed p2p connection. messages can be sent and received via the connections in extra_conns.

what I see that remains to fix to close #791 is re-building the HelloMessageWithProtocols when add_rlpx_sub_protocol is called. adressed in #5640 .

opened a pr to address this #5640

Copy link
Collaborator

@mattsse mattsse 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 great, I like the muxer a lot.

one nit re poll loop.

also perhaps we should prioritize sending outgoing messages and put the sink logic in its own loop? so we process as many outgoing messages as possible before reading from the wire. not sure though

/// More or less a weak clone of the stream wrapped in [`MuxDemuxer`] but the bytes belonging to
/// other capabilities have been filtered out.
#[derive(Debug)]
pub struct StreamClone {
Copy link
Collaborator

Choose a reason for hiding this comment

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

unsure about the naming yet,

I believe you had WeakStream or something.
perhaps WeakCapabilityStream?

Copy link
Member Author

Choose a reason for hiding this comment

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

WeakStreamClone initially, 'weak' since it is some kind of reference to the stream but doesn't own it. if not stream clone then the naming I like the most is ProtocolProxy from multiplex.rs. MuxDemuxer or MuxDemuxStream is then the proxy server.

Copy link
Member Author

Choose a reason for hiding this comment

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

Then I added ManuallyDrop wrapper, then I removed it for simplicity since anyway method of trait CanDisconnet should be used before drop. Now it's kind of a weak clone (of owning ref MuxDemuxStream) because MuxDemuxStream can be dropped when there are still StreamClones using the pointed to MuxDemuxer but it will prevent disconnecting if method from CanDisconnect trait is used.

emhane and others added 23 commits December 7, 2023 10:28
Signed-off-by: Emilia Hane <[email protected]>
Signed-off-by: Emilia Hane <[email protected]>
Signed-off-by: Emilia Hane <[email protected]>
Copy link
Collaborator

@mattsse mattsse left a comment

Choose a reason for hiding this comment

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

great!
I'm very happy with how this turned out.

injected user defined sub protocol handles span up a new attack surface. to what extent do we want to account for that? for example, if a sub protocol has a DoS vulnerability so that there are always subprotocol messages to send then the main protocol won't receive any messages if we don't implement poll_next like on MuxDemuxStream in this pr.

I think it should be the protocol's impl to handle spam, punish peer for sending bad/spammy messages, like eth also does

@mattsse mattsse added this pull request to the merge queue Dec 8, 2023
Merged via the queue into paradigmxyz:main with commit cd4d6c5 Dec 8, 2023
@emhane emhane deleted the cap-mux-simple branch December 9, 2023 23:19
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

Successfully merging this pull request may close these issues.

2 participants