This library bundles different components for lower-level peer-to-peer connection and message exchange:
- Distributed Peer Table (NDP) / Node Discovery
- RLP Transport Protocol (biutjs-rlp)
- SEC Wire Protocol (SEC)
This library has to be compiled with babel to a Node 6
friendly source format.
For triggering a (first) build to create the lib/
directory run:
npm run build
You can also use babel just-in-time compilation to run a script:
node -r babel-register [YOUR_SCRIPT_TO_RUN.js]
All components of this library are implemented as Node EventEmitter
objects
and make heavy use of the Node.js network stack.
You can react on events from the network like this:
ndp.on('peer:added', (peer) => {
// Your Codes...
})
Maintain/manage a list of peers, see ./src/ndp/, also includes node discovery (./src/ndp/server.js)
Create your peer table:
const ndp = new NDP(Buffer.from(PRIVATE_KEY, 'hex'), {
endpoint: {
address: '0.0.0.0',
udpPort: null,
tcpPort: null
}
})
NDP Manages a Kademlia DHT K-bucket for storing peer information
and a BanList for keeping a list of bad peers. server.js
implements the node discovery (ping
, pong
, findNeighbours
).
Creates new NDP object
privateKey
- Key for message encoding/signing.options.refreshInterval
- Interval in ms for refreshing (callingfindNeighbours
) the peer list (default:60s
).options.createSocket
- A datagram (dgram)createSocket
function, passed toServer
(default:dgram.createSocket.bind(null, 'udp4')
).options.timeout
- Timeout in ms for serverping
, passed toServer
(default:10s
).options.endpoint
- Endpoint information to send with the serverping
, passed toServer
(default:{ address: '0.0.0.0', udpPort: null, tcpPort: null }
).
Uses a peer as new bootstrap peer and calls findNeighbouts
.
peer
- Peer to be added, format{ address: [ADDRESS], udpPort: [UDPPORT], tcpPort: [TCPPORT] }
.
Adds a new peer.
object
- Peer to be added, format{ address: [ADDRESS], udpPort: [UDPPORT], tcpPort: [TCPPORT] }
.
For other utility functions like getPeer
, getPeers
see ./src/ndp/index.js.
Events emitted:
Event | Description |
---|---|
peer:added | Peer added to DHT bucket |
peer:removed | Peer removed from DHT bucket |
peer:new | New peer added |
listening | Forwarded from server |
close | Forwarded from server |
error | Forwarded from server |
Connect to a peer, organize the communication, see ./src/rlp/
Create your RLP
object:
const rlp = new devp2p.RLP(PRIVATE_KEY, {
ndp: ndp,
maxPeers: 25,
capabilities: [
devp2p.SEC.sec
],
listenPort: null
})
Manages the handshake (ECIES
) and the handling of the peer communication (Peer
).
Creates new RLPx object
privateKey
- Key for message encoding/signing.options.timeout
- Peerping
timeout in ms (default:10s
).options.maxPeers
- Max number of peer connections (default:10
).options.clientId
- Client ID string (default example:sec
).options.remoteClientIdFilter
- Optional list of client ID filter strings (e.g.['sec']
).options.capabilities
- Upper layer protocol capabilities, e.g.[devp2p.SEC.sec]
.options.listenPort
- The listening port for the server ornull
for default.options.ndp
-NDP
object for the peers to connect to (default:null
, noNDP
peer management).
Manually connect to peer without NDP
.
peer
- Peer to connect to, format{ id: PEER_ID, address: PEER_ADDRESS, port: PEER_PORT }
.
For other connection/utility functions like listen
, getPeers
see ./src/rlp/index.js.
Events emitted:
Event | Description |
---|---|
peer:added | Handshake with peer successful |
peer:removed | Disconnected from peer |
peer:error | Error connecting to peer |
listening | Forwarded from server |
close | Forwarded from server |
error | Forwarded from server |
Upper layer protocol for exchanging SECBlock network data like block headers or transactions with a node, see ./src/sec/.
Send the initial status message with sendStatus()
, then wait for the corresponding status
message
to arrive to start the communication.
sec.once('status', () => {
// Send an initial message
sec.sendMessage()
})
Wait for follow-up messages to arrive, send your responses.
sec.on('message', async (code, payload) => {
if (code === devp2p.SEC.MESSAGE_CODES.NEW_BLOCK_HASHES) {
// Do something with your new block hashes :-)
}
})
See the example.js
example for a more detailed use case.
Handles the different message types like NEW_BLOCK_HASHES
or GET_NODE_DATA
(see MESSAGE_CODES
) for
a complete list. Currently protocol version PV
is supported.
Normally not instantiated directly but created as a SubProtocol
in the Peer
object.
version
- The protocol version for communicating, e.g.1
.peer
-Peer
object to communicate with.send
- Wrappedpeer.sendMessage()
function where the communication is routed to.
Send initial status message.
status
- Status message to send, format{ networkId: CHAIN_ID, td: TOTAL_DIFFICULTY_BUFFER, bestHash: BEST_HASH_BUFFER, genesisHash: GENESIS_HASH_BUFFER }
.
Send initial status message.
code
- The message code, seeMESSAGE_CODES
for available message types.payload
- Payload as a list, will be rlp-encoded.
Events emitted:
Event | Description |
---|---|
message | Message received |
status | Status info received |
There are unit tests in the test/
directory which can be run with:
npm run test
MIT