-
Notifications
You must be signed in to change notification settings - Fork 70
Implement P2P.getNetworkStatus() functionality - Closes #985 and #897, addresses #896 and #953 #986
Conversation
…fo from peer and cast to PeerInfo
packages/lisk-p2p/src/p2p_types.ts
Outdated
@@ -44,28 +44,45 @@ export interface P2PConfig { | |||
readonly connectTimeout: number; | |||
readonly ipAddress?: string; |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Why ipAddress is optional here?
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
This is the ipAddress of the node itself.
It's this property from the current config.json: https://github.com/LiskHQ/lisk/blob/development/config/default/config.json#L4 - Default is 0.0.0.0
. We can rename this if it's confusing.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
maybe we can rename it to nodeIp
to have a clear differentiation from the peer IP address. What do you think?
} | ||
|
||
export interface NetworkStatus {} | ||
// Network info exposed by the P2P library. | ||
export interface P2PNetworkStatus { |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
since we have a concept of newPeers
and triedPeers
, maybe for clarity we should rename newPeers
as availablePeers
or unConnectedPeers
at the network level.
Also, triedPeers
can contain peers that are connected or disconnected. So it should also be checked as well for peers that are not connected
export interface P2PNetworkStatus {
connectedPeers: ReadonlyArray<PeerInfo>; // peers from peer pool
unConnectedPeers: ReadonlyArray<PeerInfo>; // or availablePeers, peers from newPeers + triedPeers (check with peerPool)
}
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
unConnectedPeers is slightly different because some peers in the _newPeers map could be connected inbound only; maybe it's OK but slightly more ambiguous.
I think newPeers is OK. Once we start moving peers into the _triedPeers table, it will make more sense. So there will be newPeers, triedPeers and connectedPeers activePeers. I think we should use the same name to refer to the same thing.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Actually, according to the definition in LIPS, the moment you make a connection with any peer from newPeer
we remove it from there and add it to triedPeer
. So, newPeer
should never have any peer for which we made connection already. Whereas triedPeers
will have peers with whom we have a connection or had a connection in the past.
so, active peers should have, triedPeers peers which have a connection already and available peers will be the combination of (newPeers + triedPeers(with no socket))
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
We could have availablePeers
be newPeers + triedPeers
and connectedPeers
be peers from the PeerPool
?
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
availablePeers be newPeers + triedPeers and connectedPeers be peers from the PeerPool
I think this is good, im not sure if we need to expose newPeers
or triedPeers
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Isn't availablePeers
and connectedPeers
is enough? I thought we don't want to expose newPeers and triedPeers
readonly os: string; | ||
readonly version: string; | ||
readonly os?: string; | ||
readonly version?: string; |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I thought we were making version
compulsory. If we don't passversion
value then at sanitization it will always throw an error
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
That's a tricky one.
The reason why version is optional is because the list of seedPeers which is fetched from the config file has this format:
readonly seedPeers: ReadonlyArray<PeerInfo>;
We cannot know what the version number of the seed peer is before we connect to it.
I think it's OK to expect the version
in the sanitization logic when checking inbound PeerInfo from a remote peer, but it shouldn't be compulsory (based on our current types) at the type level because the PeerInfo
object may be created directly in our own code or from a config file before we know anything about the peer (also would be tricky to know their OS before we connect to them).
Not sure if it's better to add yet another Peer...
type? It's convenient that PeerInfo
can be used for both getting information about peers and also for creating peers.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
one idea to have BasePeerInfo
which is extended to SeedPeerIndo
and PeerInfo
where the difference is version?
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
@shuse2 Sounds good but I think that SeedPeerInfo
might end up having the same properties as BasePeerInfo
so maybe just BasePeerInfo
and PeerInfo
?
Or it could be PeerInfo
(for constructing) and DetailedPeerInfo
(when getting information out of the node with getNetworkStatus()
)?
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
BasePeerInfo and PeerInfo
sounds good =)
packages/lisk-p2p/src/peer.ts
Outdated
return this._id; | ||
private _handlePeerInfo(request: ProtocolInboundRPCRequest): void { | ||
// Update peerInfo with the latest values from the remote peer. | ||
Object.assign(this._peerInfo, request.data as PeerInfo); |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I think we are missing sanitization of the peer object from the response. we can wrap request.data
with instantiatePeerFromResponse()
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
validation needs to be added later here too
packages/lisk-p2p/src/peer.ts
Outdated
return this._ipAddress; | ||
} | ||
|
||
public set outboundSocket(value: any) { |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I think this was not rebased properly, instead of any
it should be SCServerSocket
packages/lisk-p2p/src/peer.ts
Outdated
return this._id; | ||
} | ||
|
||
public set inboundSocket(value: any) { |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
it should be SCServerSocket
instead of any
packages/lisk-p2p/src/peer.ts
Outdated
public get nodeInfo(): P2PNodeInfo | undefined { | ||
return this._nodeInfo; | ||
} | ||
|
||
public connect(): void { | ||
if (!this.outboundSocket) { |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
It should be this._outboundSocket
packages/lisk-p2p/src/peer.ts
Outdated
public connect(): void { | ||
if (!this.outboundSocket) { | ||
this.outboundSocket = this._createOutboundSocket(); | ||
} | ||
|
||
this.outboundSocket.connect(); |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
this._outboundSocket
packages/lisk-p2p/src/peer.ts
Outdated
this.inboundSocket.disconnect(code, reason); | ||
if (this._inboundSocket) { | ||
this._inboundSocket.disconnect(code, reason); | ||
this._stopListeningForRPCs(this._inboundSocket); | ||
} | ||
if (this.outboundSocket) { |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
this._outboundSocket
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
minor thing and some question/comment
readonly os: string; | ||
readonly version: string; | ||
readonly os?: string; | ||
readonly version?: string; |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
one idea to have BasePeerInfo
which is extended to SeedPeerIndo
and PeerInfo
where the difference is version?
packages/lisk-p2p/src/peer.ts
Outdated
return this._id; | ||
private _handlePeerInfo(request: ProtocolInboundRPCRequest): void { | ||
// Update peerInfo with the latest values from the remote peer. | ||
Object.assign(this._peerInfo, request.data as PeerInfo); |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
validation needs to be added later here too
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Some comments related to getNetworkStatus()
} | ||
|
||
export interface NetworkStatus {} | ||
// Network info exposed by the P2P library. | ||
export interface P2PNetworkStatus { |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Isn't availablePeers
and connectedPeers
is enough? I thought we don't want to expose newPeers and triedPeers
packages/lisk-p2p/src/p2p.ts
Outdated
public getNetworkStatus(): P2PNetworkStatus { | ||
const newPeers = [...this._newPeers.values()]; | ||
const triedPeers = [...this._triedPeers.values()]; | ||
const availablePeers = newPeers.concat(triedPeers); |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
is availablePeers
are all the peers that are available but don't have any connection yet? or, does it include all the peers available or known including the connected peers? If its the former case then I think we need to filter newPeers
and triedPeers
to remove peers that we are already connected to and then concat.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Since the getNetworkStatus
call will be used by integration tests (not just API module), it's important that it shows the internal state of the node as closely as possible.
I think it's more important that this interface be detailed rather than user-friendly. Users of the method can do their own sanitisation of the raw data.
Integration test cases will want to check the state of the _newPeers and _triedPeers maps explicitly (since it's a core concept in the LIPs), so we need the name of the exposed properties to reflect the name of internal properties for which we want to allow introspection. We could call it newPeersList
instead of newPeers
maybe?
The less sanitisation/formatting we do on our end, the more performant this call will be.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
@shuse2 What is your opinion about this?
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I think without availablePeers
is fine.
availablePeers
seems ambiguous in this case because it will include all the peers regardless of connection since triedPeer
will include the peer with outbound connection.
Also, not really useful if it's just combination of newPeers
and triedPeers
, user can just combine by themselves?
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
In case we want to have a concatenated list of newPeers
and triedPeers
and if we are exposing them then we don't need availablePeers
list as its redundant or the user can make it out by themselves. I was thinking that network status is just about knowing (connected and unconnected Peers) but since newPeers
and triedPeers
will be used in the network test then its a better to add it.
I guess in future we will need a separate class for handling peer bucket or peer directory (like I discussed once) that includes newPeer/triedPeer/bannedPeer and then it will be easier to test these lists.
What was the problem?
In order to implement the integration tests, there needs to be a way to get information about the network's state from the P2P library. This feature depends on the
P2P.getNetworkStatus()
method of the P2P library which itself depends on the peer request/send functionality (to allow peers to send us information about themselves).How did I fix it?
Peer
level only)Peer
level only)P2PNodeInfo
to remote peers.PeerInfo
from remote peers.getNetworkStatus()
method onP2P
class.How to test it?
Will add integration tests for all these features as part of #953 then, once passing, the logic can be locked down with unit tests.
Review checklist