IntersectMBO / ouroboros-network

Specifications of network protocols and implementations of components running these protocols which support a family of Ouroboros Consesus protocols; the diffusion layer of the Cardano Node.
https://ouroboros-network.cardano.intersectmbo.org
Apache License 2.0
275 stars 86 forks source link

[Feature Request] (possible CIP?) add "websocket" peer address type in peer sharing miniprotocol #4908

Closed michele-nuzzi closed 2 days ago

michele-nuzzi commented 1 month ago

It would be great if we could start setting the ground for web-based light nodes

I know there is no intention to integrate a web socket server in the cardano-node directly, but this limitation can be worked around by using some "add on" tooling, such as a proxy program that connects n2c with the node on the same machine and forwards messages via websocket to other peers

to allow for this it would be great if we could modify the peer sharing mini protocol as follows

;
; Peer Sharing MiniProtocol
;

peerSharingMessage = msgShareRequest
                   / msgSharePeers
                   / msgDone

msgShareRequest = [0, byte, ?[ + peerType ] ]
msgSharePeers   = [1, peerAddresses]
msgDone         = [2]

peerAddresses = [* peerAddress]

byte = 0..255

peerType = peerIPv4Type 
                / peerIPv6Type
                / peerWebSocketType

peerIPv4Type = 0
peerIPv6Type = 1
peerWebSocketType = 2

peerAddress = [peerIPv4Type, word32, portNumber]                         ; ipv4 + portNumber
            / [peerIPv6Type, word32, word32, word32, word32, portNumber] ; ipv6 + portNumber
            / [peerWebSocketType, url]

url = text

portNumber = word16

this modification would add the option to request the type of peer that we whish to receive

if missing any peer is accepted

so that web-based light clients would be able to request only websocket peers

and it adds the "websocket" peer address, with an url the client would need to pass as-is to the standard WebSocket constructor

michele-nuzzi commented 1 month ago

please let me know if this issue is better if proposed as CIP instead

coot commented 1 month ago

Let's discuss this in the issue.

I am confused here, so please let me know if I understand you correctly. You want to be able to run an edge client which connects to a node via ntc, right?

If that's the case the node doesn't know if other nodes have such clients connected to them, at least right now. I don't see a purpose for the node to only look for such other nodes. Having access to a wider spectrum of nodes shared via PeerSharing protocol allows the node to find better connections and thus perform better (e.g. get blocks quicker).

What actual problem are you trying to solve?

michele-nuzzi commented 1 month ago

@coot I'm looking for a way for light clients running in browsers to connect and participate in the network as if they were normal (untrusted) nodes.

a node running in the browser would only be able to establish websocket connections (n2n).

The main limitation for this to happen is that cardano-node currently does not allow for websocket connections, and to my understanding, there are no plans to integrate the functionality in the node itself.

To work around this limitation, another tool would be needed for node operators who wish to accept websocket connections instead.

such tool would allow for the following:

coot commented 1 month ago

Such a proxy should run over n2n, not n2c, since it proxies untrusted connections, and thus they shouldn't be tunnelled through n2c (which doesn't have the same safety guarantees as n2n, e.g. timeouts etc.).

Ideally, it would be a bi-directional proxy. Then, cardano-node could discover such nodes and connect to them, too.

I don't see the need to make decisions based on technologies the end node is written in. All that matters for a node is that it has a good metric, which we use when we churn peers (it includes how many times a given node gave us a header/block first among all its peers). We do this to get the next block as quickly as possible.

michele-nuzzi commented 1 month ago

Yes, probably the proxy n2n is a better choice

Either way the proxy solution would apply only to nodes that do not plan to implement ws directly

Other nodes implementations (go, amaru, and all the following) might want to implement web sockets without relying on the proxy

I think the main benefit is differentiating between TCP connections (ipv4 and ipv6) and ws on peer request

In particular a web based client has no interest in TCP connections, since they can't establish one, and will request only for ws connections

The proxy will keep track of other nodes that allow for web sockets connections and share those too

I believe the same goes for a cardano-node, not directly interested in ws clients, but potentially interested to the other nodes

So that if the peer has both TCP and ws connections, only TCP will be sent in the response

coot commented 1 month ago

In particular a web based client has no interest in TCP connections since they can't establish one, and will request only for ws connections

If the proxy is bidirectional, they actualy could, but through that proxy - not directly. I know this gives an extra hop, which is a disadvantage for ws-nodes.

coot commented 1 month ago

If the proxy is written in such a way that it's network bound rather than CPU bound as all Cardano-node are, then the extra hop might not matter. However, this will require some thought on how to write such a proxy so that it is not put down by sending too much data over it, but that's not the concern here.

michele-nuzzi commented 1 month ago

If the proxy is bidirectional, they actualy could, but through that proxy - not directly. I know this gives an extra hop, which is a disadvantage for ws-nodes.

Yes, this would be my intention.

My problem is that, when looking for new peers, I need to know where the proxy is listening, so that, through that proxy, I can access the node.

As for now, sending a peer request will give me back the TCP socket of the node, and not the port of the proxy.

wolf31o2 commented 1 month ago

This could be useful outside of websockets, too. Switching from host:port identifiers to a URI would allow specifying the protocol in use, with an implicit tcp:// scheme when it's not defined.

coot commented 1 month ago

cardano-node only forward information that is verified; this is also true about the peer-sharing protocol: it shares peers with which it had a connection which didn't error (ref). The node will not have a chance to know that the web-socket nodes are reachable (or using any other protocol to that matter), since it doesn't have the capability to do so - once it does, then that's fine.

coot commented 1 month ago

This could be solved, for example the node & proxy could negotiate a connection which would allow to translate between tcp and web-socket addresses. Such pair would need to be configured to trust each other, so this would only work for node & proxies that are deployed by the same SPO. Then the node could disiminate web-socket addresses to web-socket nodes.

coot commented 1 month ago

The next Network Working Group session is on 19th of August (Monday) 14:00 UTC here, discussion this in more depth would be a very good topic. If you drop me an email to marcin.szamotulski@iohk.io, I can send you an invitation.

coot commented 5 days ago

@michele-nuzzi, just a reminder that today at 15:00 UTC here, we host the networking working group if you'd like to discuss this further with us.

michele-nuzzi commented 5 days ago

@coot sure I'll be there, thanks for the ping

coot commented 2 days ago

@michele-nuzzi, I think we can close this issue for now, as we agreed that a bidirectional proxy is the way to move forward.