Conversation
Codecov Report
@@ Coverage Diff @@
## develop #2069 +/- ##
===========================================
- Coverage 61.36% 61.32% -0.04%
===========================================
Files 197 197
Lines 15678 15663 -15
===========================================
- Hits 9621 9606 -15
- Misses 5246 5248 +2
+ Partials 811 809 -2
|
21c51e0 to
893573d
Compare
| Responsible for emitting and connecting to Peers. The implementation of `Peer` | ||
| is left to the transport, which implies that the chosen transport dictates the | ||
| characteristics of the implementation handed back to the `Switch`. It is the | ||
| place where we enforce low-level guards, like dropping connections from our own |
There was a problem hiding this comment.
Do we have a list of low level guards we want to enforce anywhere? Its not clear to me what the scope of "low-level" guards is.
| // PeerTransport proxies incoming and outgoing peer connections. | ||
| type PeerTransport interface { | ||
| // Accept returns a newly connected Peer. | ||
| Accept() (Peer, error) |
There was a problem hiding this comment.
I'm having trouble understanding Accept. Is Accept supposed to evaluate an incoming connection? If so why doesn't it have connection as a parameter.
It seems to me that this should be doing the handshake and secret connection stuff.
There was a problem hiding this comment.
I'm having trouble understanding Accept. Is Accept supposed to evaluate an incoming connection? If so why doesn't it have connection as a parameter.
It has nothing to do with connections as the PeerTransport only hands back peers, which may or may not be based on a tcp connection over the wire. Accept is the way for the caller to signal that they are ready to deal with one more incoming Peer.
It seems to me that this should be doing the handshake and secret connection stuff.
The default implementation it will, other transports may not need to that:
Lines 101 to 111 in 791c15b
There was a problem hiding this comment.
Accept is the way for the caller to signal that they are ready to deal with one more incoming Peer.
Ohh I see. Perhaps this may be more clearly named as "GetPeer"?
There was a problem hiding this comment.
Trying to avoid getter semantics when possible, in the domain of transport accept and dial are very well understood and the signature already communicates what is returned.
There was a problem hiding this comment.
Sounds good! Thank you for the explanations :)
| Responsible for emitting and connecting to Peers. The implementation of `Peer` | ||
| is left to the transport, which implies that the chosen transport dictates the | ||
| characteristics of the implementation handed back to the `Switch`. It is the | ||
| place where we enforce low-level guards[0]: |
There was a problem hiding this comment.
Thanks for listing out the intended low-level guards! I still don't really understand what low-level means here.
Are these the set of checks that can only be determined from information in the handshake and the local nodes' configuration? (No knowledge of other peers that this is node is connected to, or how many peers it is currently connected to?)
There was a problem hiding this comment.
More concretely, I'm confused about why the following aren't here:
"Ensure this isn't a duplicate connection from the same IP" or "Ensure that we don't already have too many peers"
There was a problem hiding this comment.
Very good point. Indeed the use of low-level might be missleading as it actually should say domain-specific. As long as we only handle aspects that belong to the transport domain it should be clear. This might result in that protocol/app version check is down somewhere else. Most certainly the check if we already are connected to too many peers belongs in the switch.
Will add the duplicate ip check and rephrase low-level.
| * connections from our own node | ||
| * handshake fails | ||
| * upgrade to secret connection fails | ||
| * prevent duplicate ip |
There was a problem hiding this comment.
Should also filter based on:
- duplicate ID
- node info compatibility
could also clarify that it doesn't handle max-peers, thats for the switch
There was a problem hiding this comment.
Will there be another ADR explaining why these are the right choices?
There was a problem hiding this comment.
@liamsi Which choices are you referring to?
There was a problem hiding this comment.
The choices of what was previously called "guards".
There was a problem hiding this comment.
Would be valuable to include some explanation in here as to the "why" for sure
| closec <-chan struct{} | ||
| listenc <-chan struct{} | ||
|
|
||
| addr NetAddress |
| type multiplexTransport struct { | ||
| listener net.Listener | ||
|
|
||
| acceptc chan accept |
There was a problem hiding this comment.
I prefer acceptCh, but feel free to ignore
There was a problem hiding this comment.
If you don't ignore: also, closeCh and listenCh for consistency.
|
|
||
| One of the more apparent problems with the current architecture in the p2p | ||
| package is that there is no clear separation of concerns between different | ||
| components. Most notably the `Switch` is currently doing physical connection |
There was a problem hiding this comment.
Can you link to some code (ideally) with a perma-link? I'm not familiar with the current implementation and it makes it easier to read and understand this. e.g. Switch (not only for me but other people reading the ADRs as documentation etc)
There was a problem hiding this comment.
While I appreciate this point, we need to strike a balance in these ADRs between being an efficient document for design and including enough information for an outsider to keep up. I think to some extent, readers of the ADR should be expected to have some familiarity with the codebase, so that we don't need to worry too much about adding too many links.
| ### Positive | ||
|
|
||
| * free Switch from transport concerns - simpler implementation | ||
| * pluggable transport implementation - simpler test setup |
There was a problem hiding this comment.
I know what you mean but could we use another word here? pluggable transports often means sth. else.
There was a problem hiding this comment.
For me the words pluggable transport is overloaded by what I linked above (means tor obfuscate tor traffic as regular https traffic). But yeah in this context it describes correctly what this is about: the ability to plug in different transport implementations. So that's fine.
There was a problem hiding this comment.
Given my limited knowledge about the current p2p layer this looks like a thought through and well-written, concise ADR. In general, I'm in favour of writing these with readers in mind that are not knee deep in the current p2p stack (or, more general, whatever code snippets the ADR is addressing). This only means adding a few links or summarizing with very words where more appropriate.
| One of the more apparent problems with the current architecture in the p2p | ||
| package is that there is no clear separation of concerns between different | ||
| components. Most notably the `Switch` is currently doing physical connection | ||
| handling. An artifact is the dependency of the Switch on `config.P2PConfig`. |
There was a problem hiding this comment.
Link would be helpful again.
There was a problem hiding this comment.
Link to what in that section would you like to see?
This is the implementation for the design described in ADR 12[0]. It's the first step of a larger refactor of the p2p package as tracked in interface bundling all concerns of low-level connection handling and isolating the rest of peer lifecycle management from the specifics of the low-level internet protocols. Even if the swappable implementation will never be utilised, already the isolation of conn related code in one place will help with the reasoning about execution path and addressation of security sensitive issues surfaced through bounty programs and audits. We deliberately decided to not have Peer filtering and other management in the Transport, its sole responsibility is the translation of connections to Peers, handing those to the caller fully setup. It's the responsibility of the caller to reject those and or keep track. Peer filtering will take place in the Switch and can be inspected in a the following commit. This changeset additionally is an exercise in clean separation of logic and other infrastructural concerns like logging and instrumentation. By leveraging a clean and minimal interface. How this looks can be seen in a follow-up change. Design #2069[2] Refs #2067[3] Fixes #2047[4] Fixes #2046[5] changes: * describe Transport interface * implement new default Transport: MultiplexTransport * test MultiplexTransport with new constraints * implement ConnSet for concurrent management of net.Conn, synchronous to PeerSet * implement and expose duplicate IP filter * implemnt TransportOption for optional parametirisation [0] https://github.com/tendermint/tendermint/blob/master/docs/architecture/adr-012-peer-transport.md [1] #2067 [2] #2069 [3] #2067 [4] #2047 [5] #2046
This is the implementation for the design described in ADR 12[0]. It's the first step of a larger refactor of the p2p package as tracked in interface bundling all concerns of low-level connection handling and isolating the rest of peer lifecycle management from the specifics of the low-level internet protocols. Even if the swappable implementation will never be utilised, already the isolation of conn related code in one place will help with the reasoning about execution path and addressation of security sensitive issues surfaced through bounty programs and audits. We deliberately decided to not have Peer filtering and other management in the Transport, its sole responsibility is the translation of connections to Peers, handing those to the caller fully setup. It's the responsibility of the caller to reject those and or keep track. Peer filtering will take place in the Switch and can be inspected in a the following commit. This changeset additionally is an exercise in clean separation of logic and other infrastructural concerns like logging and instrumentation. By leveraging a clean and minimal interface. How this looks can be seen in a follow-up change. Design #2069[2] Refs #2067[3] Fixes #2047[4] Fixes #2046[5] changes: * describe Transport interface * implement new default Transport: MultiplexTransport * test MultiplexTransport with new constraints * implement ConnSet for concurrent management of net.Conn, synchronous to PeerSet * implement and expose duplicate IP filter * implemnt TransportOption for optional parametirisation [0] https://github.com/tendermint/tendermint/blob/master/docs/architecture/adr-012-peer-transport.md [1] #2067 [2] #2069 [3] #2067 [4] #2047 [5] #2046
First iteration in #2067 and an attempt to liberate the Switch from connection handling and low-level network concenrs.