-
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 #19 from diasdavid/libp2p-spec
libp2p spec
- Loading branch information
Showing
20 changed files
with
784 additions
and
377 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
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 |
---|---|---|
@@ -0,0 +1,30 @@ | ||
1 Introduction | ||
============== | ||
|
||
With the developement of building IPFS, the InterPlanetary FileSystem[?], we came to learn about the several challenges imposed by having to run a distributed file system on top of heterogeneous devices, with diferent network setups and capabilities. During this process, we had to revisit the whole network stack and elaborate solutions to overcome the obstacles imposed by design decisions of the several layers and protocols, without breaking compatibility or recreating technologies. | ||
|
||
In order to build this library, we focused on tackling problems independently, creating less complex solutions with powerful abstractions, that when composed, can offer an environment for a Peer-to-Peer application to work sucessfuly. | ||
|
||
## 1.1 Motivation | ||
|
||
`libp2p` is the result of the collective experience while building a distributed system, that puts the responsability on the developers on how they want their app to interop with others in the network, favoring configuration and extensibility instead of assumptions about the network setup. | ||
|
||
In essence, a peer using libp2p should be able to communicate with another peer using different transports, including connection relay, and talk over different protocols, negotiated on demand. | ||
|
||
## 1.2 Goals | ||
|
||
Our goals for libp2p specification and its implementations are: | ||
|
||
- Enable the use of various: | ||
- transports: TCP, UDP, SCTP, UDT, uTP, QUIC, SSH, etc. | ||
- authenticated transports: TLS, DTLS, CurveCP, SSH | ||
- Efficient use of sockets (connection reuse) | ||
- Enable communications between peers to be multiplex over one socket (avoiding handshake overhead) | ||
- Enable multiprotocols and respective versions to be used between peers, using a negotiation process. | ||
- Be backwards compatible | ||
- Work in current systems | ||
- Use the current network technologies to its best capability | ||
- Have NAT Traversal | ||
- Enable connections to be relayed | ||
- Enable encrypted channels | ||
- Efficient use of underlying transport (e.g. native stream muxing, native auth, etc) |
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 |
---|---|---|
@@ -0,0 +1,78 @@ | ||
2 An analysis the State of the Art in Network Stacks | ||
==================================================== | ||
|
||
This section presents to the reader an analysis of the available protocols and architectures for a Network Stack. The goal is to provide the foundations from which to infer the conclusions and understand what are libp2p requirements and its designed architecture. | ||
|
||
## 2.1 The client-server model | ||
|
||
The client-server model indicates that both parties that ends of the channel have different roles, that support different services and/or have different capabilities, or in another words, speak different protocols. | ||
|
||
Building client-server applications has been natural tendency for a number of reasons: | ||
|
||
- The bandwidth inside a DataCenter is considerably high compared to the one available for clients to connect between each other | ||
- DataCenter resources are considerably cheaper, due to efficient usage and bulk stocking | ||
- Enables easier methods for the developer and system admin to have a fine grained control over the application | ||
- Reduces the number of heteregeneus systems to be handled (although it is still considerably high) | ||
- Systems like NAT make it really hard for client machines to find and talk with each other, forcing a developer to perform very clever hacks to traverse these obstacles. | ||
- Protocols started to be designed with the assumption that a developer will create a client-server application from the start. | ||
|
||
We even learned how to hide all of the complexity of a distributed system behind gateways on the Internet, using protocols that were designed to perform a point-to-point operation, such as HTTP, making it opaque for the application to see and understand how the cascade of service calls made for each request. | ||
|
||
`libp2p` offers a move towards dialer-listener interactions, from the client-server listener, where it is not implicit which of the entities, dialer or listener, has which capabilities or is enabled to perform which actions. Setting up a connection between two applications today is a multilayered problem to solve, and these connections should not have a purpose bias, instead support to several other protocols to work on top of the established connection. In a client-server model, a server sending data without a prior request from the client is known as a push model, which typically adds more complexity, in a dialer-listener model, both entities can perform requests independently. | ||
|
||
## 2.2 Categorizing the network stack protocols by solutions | ||
|
||
Before diving into the libp2p protocols, it is important to understand the large diversity of protocols already in wide use and deployment that help maintain today's simple abstractions. For example, when one thinks about an HTTP connection, one might naively just think HTTP/TCP/IP as the main protocols involved, but in reality many more participate, all depending on the usage, the networks involved, and so on. Protocols like DNS, DHCP, ARP, OSPF, Ethernet, 802.11 (WiFI), ... and many others get involved. Looking inside ISPs' own networks would reveal dozens more. | ||
|
||
Additionally, it's worth noting that the traditional 7-layer OSI model characterization does not fit libp2p. Instead, we categorize protocols based on their role, the problem they solve. The upper layers of the OSI model are geared towards point-to-point links between applications, whereas the libp2p protocols speak more towards various sizes of networks, with various properties, under various different security models. Different libp2p protocols can have the same role (in the OSI model, this would be "address the same layer"), meaning that multiple protocols can run simultaneously, all addressing one role (instead of one-protocol-per-layer in traditional OSI stacking) For example, bootstrap lists, mDNS, DHT Discovery, and PEX are all forms of the role "Peer Discovery"; they can coexist and even synergize. | ||
|
||
### 2.2.1 Establishing the physical Link | ||
|
||
- ethernet | ||
- wifi | ||
- bluetooth | ||
- usb | ||
|
||
### 2.2.2 Addressing a machine or process | ||
|
||
- IPv4 | ||
- IPv6 | ||
- Hidden Addressing, like SDP | ||
|
||
### 2.2.3 Discovering other peers or services | ||
|
||
- ARP | ||
- DHCP | ||
- DNS | ||
- Onion | ||
|
||
### 2.2.4 Routing messages through the Network | ||
|
||
- RIP(1, 2) | ||
- OSP | ||
- PPP | ||
- Tor | ||
- I2P | ||
- cjdns | ||
|
||
### 2.2.5 Transport | ||
|
||
- TCP | ||
- UDP | ||
- UDT | ||
- QUIC | ||
- WebRTC DataChannel | ||
|
||
### 2.2.6 Agreed semantics for applications to talk to each other | ||
|
||
- RMI | ||
- Remoting | ||
- RPC | ||
- HTTP | ||
|
||
|
||
## 2.3 Current Shortcommings | ||
|
||
Although we currently have a panoply of protocols available for our services the communicate, the abundance and the variety of solutions is also its shortfall. It is currently dificult for an application to be able to support and be available through several transports (for e.g. the lack of TCP/UDP stack in browser applications). | ||
|
||
There is also no 'presence linking', meaning that isn't a notion for a peer to announce itself in several transports, so that other peer can guarantee that it is always the same peer. |
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 |
---|---|---|
@@ -0,0 +1,104 @@ | ||
3 Requirements and considerations | ||
================================= | ||
|
||
## 3.1 NAT traversal | ||
|
||
Network Address Translation is ubiquitous in the internet. Not only are most consumer devices behind many layers of NATs, but most datacenter nodes are often behind NAT for security or virtualization reasons. As we move into containerized deployments, this is getting worse. IPFS implementations SHOULD provide a way to traverse NATs, otherwise it is likely that operation will be affected. Even nodes meant to run with real IP addresses must implement NAT traversal techniques, as they may need to establish connections to peers behind NAT. | ||
|
||
libp2p accomplishes full NAT traversal using an ICE-like protocol. It is not exactly ICE, as ipfs networks provide the possibility of relaying communications over the IPFS protocol itself, for coordinating hole-punching or even relaying communication. | ||
|
||
It is recommended that implementations use one of the many NAT traversal libraries available, such as `libnice`, `libwebrtc`, or `natty`. However, NAT traversal must be interoperable. | ||
|
||
## 3.2 Relay | ||
|
||
Unfortunately, due to symmetric NATs, container and VM NATs, and other impossible-to-bypass NATs, libp2p MUST fallback to relaying communication to establish a full connectivity graph. To be complete, implementations MUST support relay, though it SHOULD be optional and able to be turned off by end users. | ||
|
||
## 3.3 Encryption | ||
|
||
Communications on libp2p may be: | ||
|
||
- **encrypted** | ||
- **signed** (not encrypted) | ||
- **clear** (not encrypted, not signed) | ||
|
||
We take both security and performance seriously. We recognize that encryption is not viable for some in-datacenter high performance use cases. | ||
|
||
We recommend that: | ||
- implementations encrypt all communications by default | ||
- implementations are audited | ||
- unless absolutely necessary, users normally operate with encrypted communications only. | ||
|
||
libp2p uses cyphersuites like TLS. | ||
|
||
**NOTE:** we do not use lib2p directly, because we do not want the CA system baggage. Most libp2p implementations are very big. Since the lib2p model begins with keys, libp2p only needs to apply ciphers. This is a minimal portion of the whole TLS standard. | ||
|
||
## 3.4 Transport Agnostic | ||
|
||
libp2p is transport agnostic, so it can run over any transport protocol. It does not even depend on IP; it may run on top of NDN, XIA, and other new internet architectures. | ||
|
||
In order to reason about possible transports, libp2p uses [multiaddr](https://github.com/jbenet/multiaddr), a self-describing addressing format. This makes it possible for libp2p to treat addresses opaquely everywhere in the system, and have support various transport protocols in the network layer. The actual format of addresses in libp2p is `ipfs-addr`, a multiaddr that ends with an ipfs nodeid. For example, these are all valid `ipfs-addrs`: | ||
|
||
``` | ||
# ipfs over tcp over ipv6 (typical tcp) | ||
/ip6/fe80::8823:6dff:fee7:f172/tcp/4001/ipfs/QmYJyUMAcXEw1b5bFfbBbzYu5wyyjLMRHXGUkCXpag74Fu | ||
# ipfs over utp over udp over ipv4 (udp-shimmed transport) | ||
/ip4/162.246.145.218/udp/4001/utp/ipfs/QmYJyUMAcXEw1b5bFfbBbzYu5wyyjLMRHXGUkCXpag74Fu | ||
# ipfs over ipv6 (unreliable) | ||
/ip6/fe80::8823:6dff:fee7:f172/ipfs/QmYJyUMAcXEw1b5bFfbBbzYu5wyyjLMRHXGUkCXpag74Fu | ||
# ipfs over tcp over ip4 over tcp over ip4 (proxy) | ||
/ip4/162.246.145.218/tcp/7650/ip4/192.168.0.1/tcp/4001/ipfs/QmYJyUMAcXEw1b5bFfbBbzYu5wyyjLMRHXGUkCXpag74Fu | ||
# ipfs over ethernet (no ip) | ||
/ether/ac:fd:ec:0b:7c:fe/ipfs/QmYJyUMAcXEw1b5bFfbBbzYu5wyyjLMRHXGUkCXpag74Fu | ||
``` | ||
|
||
**Note:** at this time, no unreliable implementations exist. The protocol's interface for defining and using unreliable transport has not been defined. | ||
|
||
**TODO:** define how unreliable transport would work. base it on webrtc. | ||
|
||
## 3.5 Multi-Multiplexing | ||
|
||
The libp2p Protocol is a collection of multiple protocols. In order to conserve resources, and to make connectivity easier, libp2p can perform all its operations through a single port, such as TCP or UDP port, depending on the transports used. libp2p can multiplex its many protocols through point-to-point connections. This multiplexing is for both reliable streams and unreliable datagrams. | ||
|
||
libp2p is pragmatic. It seeks to be usable in as many settings as possible, to be modular and flexible to fit various use cases, and to force as few choices as possible. Thus the libp2p network layer provides what we're loosely referring to as "multi-multiplexing": | ||
|
||
- can multiplex multiple listen network interfaces | ||
- can multiplex multiple transport protocols | ||
- can multiplex multiple connections per peer | ||
- can multiplex multiple client protocols | ||
- can multiples multiple streams per protocol, per connection (SPDY, HTTP2, QUIC, SSH) | ||
- has flow control (backpressure, fairness) | ||
- encrypts each connection with a different ephemeral key | ||
|
||
To give an example, imagine a single IPFS node that: | ||
|
||
- listens on a particular TCP/IP address | ||
- listens on a different TCP/IP address | ||
- listens on a SCTP/UDP/IP address | ||
- listens on a UDT/UDP/IP address | ||
- has multiple connections to another node X | ||
- has multiple connections to another node Y | ||
- has multiple streams open per connection | ||
- multiplexes streams over http2 to node X | ||
- multiplexes streams over ssh to node Y | ||
- one protocol mounted on top of libp2p uses one stream per peer | ||
- one protocol mounted on top of libp2p uses multiple streams per peer | ||
|
||
Not providing this level of flexbility makes it impossible to use libp2p in various platforms, use cases, or network setups. It is not important that all implementations support all choices; what is critical is that the spec is flexible enough to allow implementations to use precisely what they need. This ensures that complex user or application constraints do not rule out libp2p as an option. | ||
|
||
## 3.6 Enable several network topologies | ||
|
||
Differents systems have different requirements and with that comes different topologies. In the P2P literature we can find these topologies being enumerated as: Unstructured, Structured, Hybrid and Centralised. | ||
|
||
Centralised topologies are the most common to find in Web Applications infrastructures, it requires for a given service or services to be present at all times in a known static location, so that other services can access them. Unstructured networks represent a type of P2P networks where the network topology is completely random, or at least non deterministic, while structured networks have a implicit way of organizing themselves, hybrid networks are a mix of the last two. | ||
|
||
With this in consideration, libp2p must be ready to perform different routing mechanisms and peer discovery, in order to build the routing tables that will enable services to propagate messages or to find each other. | ||
|
||
## 3.7 Resource Discovery | ||
|
||
libp2p also solves the problem with discoverability of resources inside of a network through Records, a record is a unit of data that can be digitally signed, timestamp and/or used with other methods to give it a ephemeral validity. These Records hold pieces of information, such as location of availability of resources present in the network, these resources can be data, storage, CPU cycles and other types of services. | ||
|
||
libp2p must not put a constraint on the location of resources, instead offer ways to find them easily in the network or use a sidechannel. |
Oops, something went wrong.