-
Notifications
You must be signed in to change notification settings - Fork 232
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
Merge pull request #48 from ipfs/libp2p/interfaces
libp2p - [WIP] Update the Interfaces chapter
- Loading branch information
Showing
1 changed file
with
55 additions
and
95 deletions.
There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -1,139 +1,99 @@ | ||
6 Interfaces | ||
============ | ||
|
||
`libp2p` is a collection of several protocols working together to offer a common solid interface with talking with any other network addressable process. This is made possible by shimming current exist protocols and implementations through a set of explicit interfaces, from Peer Routing, Discovery, Stream Muxing, Transports, Connections and so on. | ||
|
||
## 6.1 libp2p | ||
|
||
libp2p, the top module that interfaces all the other modules that make a libp2p instance, must offer an interface for dialing to a peer and plugging in all of the modules (e.g. which transports) we want to support. We present libp2p interface and UX on setion 6.6, after presenting every other module interface. | ||
|
||
## 6.2 Peer Routing | ||
|
||
## 6.3 Swarm | ||
![](https://raw.githubusercontent.com/diasdavid/abstract-peer-routing/master/img/badge.png) | ||
|
||
~~The network is abstracted through the swarm which presents a simplified interface for the remaining layers to have access to the network. This interface should look like:~~ | ||
A Peer Routing service offers a way for libp2p Node to find the PeerInfo of another Node, so that it can dial to that node. In it is most pure form, a Peer Routing module should have a interface that given a 'key', a set of PeerInfos are returned. | ||
See https://github.com/diasdavid/abstract-peer-routing for the interface and tests. | ||
|
||
- `sw.addTransport(transport, [options, dialOptions, listenOptions])` - Add a transport to be supported by this swarm instance. Swarm expects it to implement the [abstract-transport](https://github.com/diasdavid/abstract-transport) interface. | ||
- `sw.addUpgrade(connUpgrade, [options])` - A connection upgrade must be able to receive and return something that implements the [abstract-connection](https://github.com/diasdavid/abstract-connection) interface. | ||
- `sw.addStreamMuxer(streamMuxer, [options])` - Upgrading a connection to use a stream muxer is still considered an upgrade, but a special case since once this connection is applied, the returned obj will implement the abstract-stream-muxer interface. | ||
- `sw.dial(PeerInfo, options, protocol, callback)` - PeerInfo should contain the ID of the peer and its respective multiaddrs known. | ||
- `sw.handleProtocol(protocol, handlerFunction)` - enable a protocol to be registered, so that another peer can open a stream to talk with us to that specific protocol | ||
## 6.3 Swarm | ||
|
||
The following figure represents how the network level pieces, are tied together: | ||
Current interface available and updated at: | ||
|
||
``` | ||
┌ ─ ─ ─ ─ ┌ ─ ─ ─ ─ ┌ ─ ─ ─ ─ ┌───────────┐ | ||
mounted │ mounted │ mounted ││Identify │ | ||
│protocol │protocol │protocol │(mounted │ | ||
1 │ 2 │ ... ││ protocol) │ | ||
└ ─ ─ ─ ─ └ ─ ─ ─ ─ └ ─ ─ ─ ─ └───────────┘ | ||
┌─────────────────────────────────────────┐ | ||
│ swarm │ | ||
└─────────────────────────────────────────┘ | ||
┌─────────────────────────────────────────┐ | ||
│ connection │ | ||
└─────────────────────────────────────────┘ | ||
┌───────────────┐┌───────────┐┌───────────┐ | ||
│Transport ││multistream││ stream │ | ||
│(TCP, UDP, etc)││ ││ muxer │ | ||
└───────────────┘└───────────┘│┌ ─ ─ ─ ─ ┐│ | ||
│ spdy │ | ||
│└ ─ ─ ─ ─ ┘│ | ||
│┌ ─ ─ ─ ─ ┐│ | ||
│ multiplex │ | ||
│└ ─ ─ ─ ─ ┘│ | ||
│┌ ─ ─ ─ ─ ┐│ | ||
│ QUIC │ | ||
│└ ─ ─ ─ ─ ┘│ | ||
│┌ ─ ─ ─ ─ ┐│ | ||
│ others │ | ||
│└ ─ ─ ─ ─ ┘│ | ||
└───────────┘ | ||
``` | ||
https://github.com/diasdavid/js-libp2p-swarm#usage | ||
|
||
## 6.4 Distributed Record Store | ||
### 6.3.1 Transport | ||
|
||
![](https://raw.githubusercontent.com/diasdavid/abstract-transport/master/img/badge.png) | ||
|
||
https://github.com/diasdavid/abstract-transport | ||
|
||
### 6.3.2 Connection | ||
|
||
![](https://raw.githubusercontent.com/diasdavid/abstract-connection/master/img/badge.png) | ||
|
||
https://github.com/diasdavid/abstract-connection | ||
|
||
### 6.3.3 Stream Muxing | ||
|
||
![](https://github.com/diasdavid/abstract-stream-muxer/raw/master/img/badge.png) | ||
|
||
---------------------------- | ||
OLD | ||
The network protocol's interface has two parts:A | ||
https://github.com/diasdavid/abstract-stream-muxer | ||
|
||
1. the _client interface_, for clients (e.g. higher layers of IPFS) | ||
2. the _service interface_, for remote peers (e.g. other IPFS nodes) | ||
## 6.4 Distributed Record Store | ||
|
||
![](https://raw.githubusercontent.com/diasdavid/abstract-record-store/master/img/badge.png) | ||
|
||
### 4.1 Client Interface | ||
https://github.com/diasdavid/abstract-record-store | ||
|
||
The **Client Interface** is exposed to the higher layers of IPFS. It is the entry point for other parts to open + handle streams. | ||
|
||
This type system represents the interface exposed to clients. Actual implementations will likely be more complicated, but they should aim to cover this. | ||
## 6.5 Peer Discovery | ||
|
||
```go | ||
type PrivateKey interface { | ||
PublicKey() PublicKey | ||
A Peer Discovery system interface should return PeerInfo objects, as it finds new peers to be considered to our Peer Routing schemes | ||
|
||
Sign(data []byte) Signature | ||
Decrypt(ciphertext []byte) (plaintext []byte) | ||
} | ||
## 6.6 libp2p interface and UX | ||
|
||
type PublicKey interface { | ||
PeerID() PeerID | ||
libp2p implementations should enable for it to be instantiated programatically, or to use a previous compiled lib some of the protocol decisions already made, so that the user can reuse or expand. | ||
|
||
Verify(Signature) (ok bool) | ||
Encrypt(plaintext []byte) (ciphertext []byte) | ||
} | ||
### Constructing libp2p instance programatically | ||
|
||
// PeerID is a hash of a PublicKey, encoded in multihash | ||
// It represents the identity of a node. | ||
type PeerID Multihash | ||
Example made with JavaScript, should be mapped to other languages | ||
|
||
// Node is a peer in the network. It is both a client and server. | ||
// Users may open streams to remote peers, or set handlers for protocols. | ||
type Node interface { | ||
// ID returns the PeerID of this Node | ||
ID() PeerID | ||
```JavaScript | ||
var Libp2p = require('libp2p') | ||
|
||
// NewStream creates a new stream to given peerID. | ||
// It may have to establish a new connection to given peer. | ||
// (This includes finding the addresses of a peer, and NAT Traversal.) | ||
NewStream(Protocol, PeerID) (Stream, error) | ||
var node = new Libp2p() | ||
|
||
// SetStreamHandler sets a callback for remote-opened streams for a protocol | ||
// Thus clients register "protocol handlers", much like URL route handlers | ||
SetStreamHandler(Protocol, StreamHandler) | ||
// add a swarm instance | ||
node.addSwarm(swarmInstance) | ||
|
||
// Raw connections are not exported to the user, only streams. | ||
} | ||
// add one or more Peer Routing mechanisms | ||
node.addPeerRouting(peerRoutingInstance) | ||
|
||
type StreamHandler func (Stream) | ||
// add a Distributed Record Store | ||
node.addDistributedRecordStore(distributedRecordStoreInstance) | ||
``` | ||
|
||
TODO: incorporate unreliable message / packet streams. | ||
Configuring libp2p is quite straight forward since most of the configuration comes from instantiating the several modules, one at each time. | ||
|
||
### Dialing and Listening for connections to/from a peer | ||
|
||
### 4.2 Protocol Interface | ||
Ideally, libp2p uses its own mechanisms (PeerRouting and Record Store) to find a way to dial to a given peer | ||
|
||
The network protocol consists of: | ||
```JavaScript | ||
node.dial(PeerInfo) | ||
``` | ||
|
||
To receive an incoming connection, specify one or more protocols to handle | ||
|
||
- Any secure, reliable, stream transport: | ||
- a reliable transport protocol (TCP, QUIC, SCTP, UDT, UTP, ...) | ||
- a secure PKI based transport protocol (SSH, TLS, ...) | ||
- a stream transport (with flow control, etc) (HTTP2, SSH, QUIC) | ||
- Protocol stream framing, to multiplex services | ||
- Auxiliary protocols for connectivity: | ||
- Identify - exchange node information | ||
- NAT - NAT Traversal (ICE) | ||
- Relay - for when NAT Traversal fails | ||
```JavaScript | ||
node.handleProtocol('<multicodec>', function (duplexStream) { | ||
|
||
Both the transport and stream muxer are pluggable. Unless | ||
constraints dictate otherwise, implementations SHOULD implement TCP and HTTP/2 | ||
for interoperability. These are the default | ||
}) | ||
``` | ||
|
||
- any reliable transport protocol | ||
- a secure channel encryption | ||
- a stream multiplexor with flow control (e.g. HTTP/2, SPDY, QUIC, SSH) | ||
- every stream protocol header | ||
### Finding a peer | ||
|
||
(TODO: unreliable transport) | ||
Finding a peer functionality is done through Peer Routing, so the interface is the same. | ||
|
||
### Storing and Retrieving Records | ||
|
||
Like Finding a Peer, Storing and Retrieving records is done through Record Store, so the interface is the same. |