mirror of https://github.com/status-im/nim-eth.git
Update p2p.md
some fixes and updating the handshake mechanism.
This commit is contained in:
parent
8451ce6c3b
commit
ece0d7fdbb
45
doc/p2p.md
45
doc/p2p.md
|
@ -56,7 +56,7 @@ proc newEthereumNode*(keys: KeyPair,
|
||||||
|
|
||||||
```nim
|
```nim
|
||||||
node.addCapability(eth)
|
node.addCapability(eth)
|
||||||
node.addCapability(ssh)
|
node.addCapability(shh)
|
||||||
```
|
```
|
||||||
|
|
||||||
Each supplied protocol identifier is a name of a protocol introduced
|
Each supplied protocol identifier is a name of a protocol introduced
|
||||||
|
@ -72,7 +72,7 @@ proc connectToNetwork*(node: var EthereumNode,
|
||||||
enableDiscovery = true)
|
enableDiscovery = true)
|
||||||
```
|
```
|
||||||
|
|
||||||
The `EthereumNode` will automatically find and maintan a pool of peers
|
The `EthereumNode` will automatically find and maintain a pool of peers
|
||||||
using the Ethereum node discovery protocol. You can access the pool as
|
using the Ethereum node discovery protocol. You can access the pool as
|
||||||
`node.peers`.
|
`node.peers`.
|
||||||
|
|
||||||
|
@ -99,7 +99,7 @@ the definition of a RLPx protocol:
|
||||||
The sub-protocols are defined with the `p2pProtocol` macro. It will accept
|
The sub-protocols are defined with the `p2pProtocol` macro. It will accept
|
||||||
a 3-letter identifier for the protocol and the current protocol version:
|
a 3-letter identifier for the protocol and the current protocol version:
|
||||||
|
|
||||||
Here is how the [DevP2P wire protocol](https://github.com/ethereum/wiki/wiki/%C3%90%CE%9EVp2p-Wire-Protocol) might look like:
|
Here is how the [DevP2P wire protocol](https://github.com/ethereum/devp2p/blob/master/rlpx.md#p2p-capability) might look like:
|
||||||
|
|
||||||
``` nim
|
``` nim
|
||||||
p2pProtocol p2p(version = 0):
|
p2pProtocol p2p(version = 0):
|
||||||
|
@ -177,12 +177,12 @@ The `nextMsg` helper proc can be used to pause the execution of an async
|
||||||
proc until a particular incoming message from a peer arrives:
|
proc until a particular incoming message from a peer arrives:
|
||||||
|
|
||||||
``` nim
|
``` nim
|
||||||
proc handshakeExample(peer: Peer) {.async.} =
|
proc helloExample(peer: Peer) {.async.} =
|
||||||
...
|
...
|
||||||
# send a hello message
|
# send a hello message
|
||||||
peer.hello(...)
|
peer.hello(...)
|
||||||
|
|
||||||
# wait for a matching hello response
|
# wait for a matching hello response, might want to add a timeout here
|
||||||
let response = await peer.nextMsg(p2p.hello)
|
let response = await peer.nextMsg(p2p.hello)
|
||||||
echo response.clientId # print the name of the Ethereum client
|
echo response.clientId # print the name of the Ethereum client
|
||||||
# used by the other peer (Geth, Parity, Nimbus, etc)
|
# used by the other peer (Geth, Parity, Nimbus, etc)
|
||||||
|
@ -205,6 +205,9 @@ place). If there are multiple outstanding calls to `nextMsg`, they will
|
||||||
complete together. Any other messages received in the meantime will still
|
complete together. Any other messages received in the meantime will still
|
||||||
be dispatched to their respective handlers.
|
be dispatched to their respective handlers.
|
||||||
|
|
||||||
|
For implementing protocol handshakes with `nextMsg` there are specific helpers
|
||||||
|
which are explained [below](https://github.com/status-im/nim-eth/blob/master/doc/p2p.md#implementing-handshakes-and-reacting-to-other-events).
|
||||||
|
|
||||||
#### `requestResponse` pairs
|
#### `requestResponse` pairs
|
||||||
|
|
||||||
``` nim
|
``` nim
|
||||||
|
@ -250,21 +253,35 @@ also include handlers for certain important events such as newly connected
|
||||||
peers or misbehaving or disconnecting peers:
|
peers or misbehaving or disconnecting peers:
|
||||||
|
|
||||||
``` nim
|
``` nim
|
||||||
p2pProtocol les(version = 2):
|
p2pProtocol foo(version = fooVersion):
|
||||||
|
|
||||||
onPeerConnected do (peer: Peer):
|
onPeerConnected do (peer: Peer):
|
||||||
asyncCheck peer.status [
|
let m = await peer.status(fooVersion,
|
||||||
"networkId": rlp.encode(1),
|
timeout = chronos.milliseconds(5000))
|
||||||
"keyGenesisHash": rlp.encode(peer.network.chain.genesisHash)
|
|
||||||
...
|
|
||||||
]
|
|
||||||
|
|
||||||
let otherPeerStatus = await peer.nextMsg(les.status)
|
|
||||||
...
|
|
||||||
|
|
||||||
|
if m.protocolVersion == fooVersion:
|
||||||
|
debug "Foo peer", peer, fooVersion
|
||||||
|
else:
|
||||||
|
raise newException(UselessPeerError, "Incompatible Foo version")
|
||||||
|
|
||||||
onPeerDisconnected do (peer: Peer, reason: DisconnectionReason):
|
onPeerDisconnected do (peer: Peer, reason: DisconnectionReason):
|
||||||
debug "peer disconnected", peer
|
debug "peer disconnected", peer
|
||||||
|
|
||||||
|
handshake:
|
||||||
|
proc status(peer: Peer,
|
||||||
|
protocolVersion: uint)
|
||||||
```
|
```
|
||||||
|
|
||||||
|
For handshake messages, where the same type of message needs to be send to and
|
||||||
|
received from the peer, a `handshake` helper is introduced, as you can see in
|
||||||
|
the code example above.
|
||||||
|
|
||||||
|
Thanks to the `handshake` helper the `status` message will both be send, and be
|
||||||
|
awaited for receival from the peer, with the defined timeout. In case no `status`
|
||||||
|
message is received within the defined timeout, an error will be raised which
|
||||||
|
will result in a disconnect from the peer.
|
||||||
|
|
||||||
|
|
||||||
**Note:** Be aware that if currently one of the subprotocol `onPeerConnected`
|
**Note:** Be aware that if currently one of the subprotocol `onPeerConnected`
|
||||||
calls fails, the client will be disconnected as `UselessPeer` but no
|
calls fails, the client will be disconnected as `UselessPeer` but no
|
||||||
`onPeerDisconnect` calls are run.
|
`onPeerDisconnect` calls are run.
|
||||||
|
|
Loading…
Reference in New Issue