initial documentation for native libp2p

This commit is contained in:
Dmitriy Ryajov 2019-09-30 09:46:57 -06:00
parent a01d1db6a0
commit 579cb8765a
1 changed files with 117 additions and 0 deletions

117
README.md
View File

@ -8,6 +8,123 @@
## Introduction
### Experimental native implementation
The native Nim libp2p implementation has finally arrived. Currently, it's support is experimental and shouldn't be relied on for production use. It is however under under active development and we hope to achieve a reasonable level of stability in the upcoming months as we will be integrating it across our own set of products, such as the Nim Beacon Chain.
#### What to expect?
The current implementation implements a bare minimum set of components in order to provide a functional and interoperable libp2p implementation. These are:
- A TCP transport
- multistream-select
- Secio
- Mplex
- Identify
- FloodSub
#### How to try it out?
To run this add nim-libp2p to your project's nimble file and spawn a node as follows:
```nim
import tables, options
import chronos, chronicles
import ../libp2p/[switch,
multistream,
protocols/identify,
connection,
transports/transport,
transports/tcptransport,
multiaddress,
peerinfo,
crypto/crypto,
peer,
protocols/protocol,
muxers/muxer,
muxers/mplex/mplex,
muxers/mplex/types,
protocols/secure/secio,
protocols/secure/secure]
const TestCodec = "/test/proto/1.0.0" # custom protocol string
type
TestProto = ref object of LPProtocol # declare a custom protocol
method init(p: TestProto) {.gcsafe.} =
# handle incoming connections in closure
proc handle(conn: Connection, proto: string) {.async, gcsafe.} =
let msg = cast[string](await conn.readLp())
echo "Got from remote - ", cast[string](msg)
await conn.writeLp("Hello!")
await conn.close()
p.codec = TestCodec # init proto with the correct string id
p.handler = handle # set proto handler
proc createSwitch(ma: MultiAddress): (Switch, PeerInfo) =
## Helper to create a swith
let seckey = PrivateKey.random(RSA) # use a random key for peer id
var peerInfo: PeerInfo
peerInfo.peerId = some(PeerID.init(seckey)) # create a peer id and assign
peerInfo.addrs.add(ma) # set this peer's multiaddresses (can be any number)
let identify = newIdentify(peerInfo) # create the identify proto
proc createMplex(conn: Connection): Muxer =
# helper proc to create multiplexers,
# use this to perform any custom setup up,
# su as adjusting timeout or anything else
# that the muxer requires
result = newMplex(conn)
let mplexProvider = newMuxerProvider(createMplex, MplexCodec) # create multiplexer
let transports = @[Transport(newTransport(TcpTransport))] # add all transports (tcp only for now, but can be anything in the future)
let muxers = [(MplexCodec, mplexProvider)].toTable() # add all muxers
let secureManagers = [(SecioCodec, Secure(newSecio(seckey)))].toTable() # setup the secio and any other secure provider
# create the switch
let switch = newSwitch(peerInfo,
transports,
identify,
muxers,
secureManagers)
result = (switch, peerInfo)
proc main() {.async, gcsafe.} =
let ma1: MultiAddress = Multiaddress.init("/ip4/0.0.0.0/tcp/0")
let ma2: MultiAddress = Multiaddress.init("/ip4/0.0.0.0/tcp/0")
var peerInfo1, peerInfo2: PeerInfo
var switch1, switch2: Switch
(switch1, peerInfo1) = createSwitch(ma1) # create node 1
# setup the custom proto
let testProto = new TestProto
testProto.init() # run it's init method to perform any required initialization
switch1.mount(testProto) # mount the proto
var switch1Fut = await switch1.start() # start the node
(switch2, peerInfo2) = createSwitch(ma2) # create node 2
var switch2Fut = await switch2.start() # start second node
let conn = await switch2.dial(switch1.peerInfo, TestCodec) # dial the first node
await conn.writeLp("Hello!") # writeLp send a lenght prefixed buffer over the wire
let msg = cast[string](await conn.readLp()) # readLp reads a lenght prefixed bytes and returns a buffer without the prefix
echo "Remote responded with - ", cast[string](msg)
await allFutures(switch1.stop(), switch2.stop()) # close connections and shutdown all transports
await allFutures(switch1Fut & switch2Fut) # wait for all transports to shutdown
waitFor(main())
```
For a more complete example, checkout the [directchat.nim](examples/directchat.nim) example in the `examples` directory.
### Running against the Go daemon
An implementation of [libp2p](https://libp2p.io/) in Nim, as a wrapper of the [Libp2p Go daemon](https://github.com/libp2p/go-libp2p).
Note that you need Go 1.12+ for the below instructions to work!