Conversation
|
The latest Buf updates on your PR. Results from workflow Buf / buf (pull_request).
|
| regular: newPoolManager(&poolConfig{ | ||
| MaxIn: options.maxInbound(), | ||
| MaxOut: options.maxOutbound(), | ||
| FixedAddrs: bootstrapAddrs, |
There was a problem hiding this comment.
Is it possible someone set all bootstrap addresses in persistent so FixedAddrs is now empty?
There was a problem hiding this comment.
Yeah, peers are either persistent or not. I can add logic to move bootstrap addresses to persistent addresses in case of overlap to make it slightly more foolproof, wdyt?
There was a problem hiding this comment.
As long as we can use the PEX from persistent peers in regular pool, this is probably fine. Moving bootstrap addresses to persistent pool is probably bad, because if everyone tries to connect to bootstrap nodes and never disconnect, then bootstrap will have all its incoming connections occupied and start to reject new-comers, which is worse.
In fact, we should probably intentionally disconnect old connections on bootstrap nodes. But we can do that in the future.
There was a problem hiding this comment.
To be clear, I didn't mean to make all bootstrap nodes persistent - I just meant that IF the same peer has an address in both in bootstrap list AND persistent list THEN both addresses could be used to establish the persistent connection to this peer (while currently the address from the bootstrap list is just discarded).
There was a problem hiding this comment.
ah I see, that's fine then
wen-coding
left a comment
There was a problem hiding this comment.
This looks good to me, I think my main concern is we are trusting PEX from any connected peer blindly, but we don't have to fix that in this PR.
| } | ||
| // We have found a new best candidate. | ||
| best = utils.Some(addr.pNodeID()) | ||
| clear(bestAddrs) |
There was a problem hiding this comment.
So an attacker doesn't know your seed, but it can inject fake addresses and try its luck on the fake addresses being high priority for someone, and then we will periodically try the fake addresses?
There was a problem hiding this comment.
yes, also there is nothing much to do here - the attacker can do sybil attack and sybil peers are not distinguishable from other peers.
| })) | ||
| for endpoint := range endpointSet { | ||
| c, err := utils.WithOptTimeout1(ctx, r.options.DialTimeout, func(ctx context.Context) (tcp.Conn, error) { | ||
| return tcp.Dial(ctx, endpoint.AddrPort) |
There was a problem hiding this comment.
So if an attacker tries to use you to launch DoS attack, it can tell you IP of validator B belongs to node A. Of course you will find out later after dialing succeeds and you find out this is node B not node A, but we don't remove the address right? So the attacker can kind of delays your connection to A, and make you launch a mini dos attack to B?
We might need some feedback if we see a node mismatch, also we might want to continue dialing other IP of A? (You don't have to do that in this PR though)
There was a problem hiding this comment.
we dial all the IPs of A that we know of (see the outer loop). Attacker can slightly delay us connecting to A, but it doesn't matter. There is not much we can do about the fact that peer can send us mismatching (node key, ip) pairs.
There was a problem hiding this comment.
I think we can punish sender of the PEX if it gives us random garbage. Maybe the sender should only give us outbound connection so they are sure the IP:port is correct. But we don't have to do that until later.
There was a problem hiding this comment.
I think we can punish sender of the PEX if it gives us random garbage
what if peer of our peer is the attacker though and presents us with a different identity than when it did to our peer?
There was a problem hiding this comment.
Right, I guess there are two layers:
- I care about staked validators a lot, and I trust staked validators from staked peers
- For other non-staked validators I don't care that much, this is best effort. The important ones I care are in my persist list always.
To make the p2p network uniformly random, nodes need to be able to change their peers periodically (otherwise network would be centralized at bootstrap peers). This PR implements an algorithm based on stable hashing, which makes nodes assign random priority to every node ID, and connect to peers with higher priority.
This pr also separates inbound and outbound connection pools to simplify logic. In particular it is possible that there will be 2 concurrent connections between 2 peers (inbound + outbound). Avoiding duplicate connections is best effort - nodes try not to dial peers that they are connected to, but in case 2 peers dial each other at the same time they let those 2 connections be.
Basic requirements: