mirror of https://github.com/acid-info/vac.dev.git
Fixup
This commit is contained in:
parent
cf8cda334a
commit
89cb117280
|
@ -1,165 +1,90 @@
|
||||||
---
|
---
|
||||||
layout: post
|
layout: post
|
||||||
name: "P2P Data Sync for Mobile"
|
name: "Vac - A Rough Overview"
|
||||||
title: "P2P Data Sync for Mobile"
|
title: "Vac - A Rough Overview"
|
||||||
date: 2019-07-19 12:00:00 +0800
|
date: 2019-08-02 12:00:00 +0800
|
||||||
author: oskarth
|
author: oskarth
|
||||||
published: true
|
published: true
|
||||||
permalink: /p2p-data-sync-for-mobile
|
permalink: /vac-overview
|
||||||
categories: research
|
categories: research
|
||||||
summary: A research log. Reliable and decentralized, pick two.
|
summary: Vac is a modular peer-to-peer messaging stack, with a focus on secure messaging. Overview of terms, stack and open problems.
|
||||||
image: /assets/img/mvds_interactive.png
|
image: /assets/img/vac.jpg
|
||||||
---
|
---
|
||||||
|
|
||||||
Together with decanus, I've been working on the problem of data sync lately.
|
Vac is a **modular peer-to-peer messaging stack, with a focus on secure messaging**. What does that mean? Let's unpack that a bit.
|
||||||
|
|
||||||
In building p2p messaging systems, one problem you quickly come across is the problem of reliably transmitting data. If there's no central server with high availability guarantees, you can't meaningfully guarantee that data has been transmitted. One way of solving this problem is through a synchronization protocol.
|
## Basic terms
|
||||||
|
|
||||||
There are many synchronization protocols out there and I won't go into detail of how they differ with our approach here. Some common examples are Git and Bittorrent, but there are also projects like IPFS, Swarm, Dispersy, Matrix, Briar, SSB, etc.
|
*messaging stack*. While the initial focus is on [data sync](http://localhost:4000/p2p-data-sync-for-mobile), we are concerned with all layers in the stack. That means all the way from underlying transports, p2p overlays and routing, to initial trust establishment and semantics for things like group chat. The ultimate goal is to give application developers the tools they need to provide secure messaging for their users, so they can focus on their domain expertise.
|
||||||
|
|
||||||
## Problem motivation
|
*modular*. Unlike many other secure messaging applications, our goal is not to tightly coupled set of protocols, nor is it to reinvent the wheel. Instead, we aim to provide options at each layer in the stack, and build on the shoulders of giants, putting a premimum on interoperability. It's similar in philosophy to projects such as [libp2p](https://libp2p.io/) or [Substrate](https://www.parity.io/substrate/) in that regard. Each choice comes with different trade-offs, and these look different for different applications.
|
||||||
|
|
||||||
Why do we want to do p2p sync for mobilephones in the first place? There are three components to that question. One is on the value of decentralization and peer-to-peer, the second is on why we'd want to reliably sync data at all, and finally why mobilephones and other resource restricted devices.
|
*peer-to-peer*. The protocols we work on are pure p2p, and aim to minimize centralization. This too is in opposition to many initiatives in the secure messaging space.
|
||||||
|
|
||||||
### Why p2p?
|
*messaging*. By messaging we mean messaging in a generalized sense. This includes both human to human communication, as well machine to machine communication. By messaging we also mean something more fundamental than text messages, we also include things like transactions (state channels, etc) under this moniker.
|
||||||
For decentralization and p2p, there are both technical and social/philosophical reasons. Technically, having a user-run network means it can scale with the number of users. Data locality is also improved if you query data that's close to you, similar to distributed CDNs. The throughput is also improved if there are more places to get data from.
|
|
||||||
|
|
||||||
Socially and philosophically, there are several ways to think about it. Open and decentralized networks also relate to the idea of open standards, i.e. compare the longevity of AOL with IRC or Bittorrent. One is run by a company and is shut down as soon as it stops being profitable, the others live on. Additionally increasingly control of data and infrastructure is becoming a liability. By having a network with no one in control, everyone is. It's ultimately a form of democratization, more similar to organic social structures pre Big Internet companies. This leads to properties such as censorship resistance and coercion resistance, where we limit the impact a 3rd party might have a voluntary interaction between individuals or a group of people. Examples of this are plentiful in the world of Facebook, Youtube, Twitter and WeChat.
|
*secure messaging*. Outside of traditional notions of secure messaging, such as ensuring end to end encryption, forward secrecy, avoiding MITM-attacks, etc, we are also concerned with two other forms of secure messaging. We call these *private messaging* and *censorship-resistance*. Private messaging means viewing privacy as a security property, with all that entails. Censorship resistance ties into being p2p, but also in terms of allowing for transports and overlays that can't easily be censored by port blocking, traffic analysis, and similar.
|
||||||
|
|
||||||
### Why reliably sync data?
|
*Vāc*. Is a Vedic goddess of speech. It also hints at being a vaccine.
|
||||||
At risk of stating the obvious, reliably syncing data is a requirement for many problem domains. You don't get this by default in a p2p world, as it is unreliable with nodes permissionslessly join and leave the network. In some cases you can get away with only ephemeral data, but usually you want some kind of guarantees. This is a must for reliable group chat experience, for example, where messages are expected to arrive in a timely fashion and in some reasonable order. The same is true for messages there represent financial transactions, and so on.
|
|
||||||
|
|
||||||
### Why mobilephones?
|
## Protocol stack
|
||||||
Most devices people use daily are mobile phones. It's important to provide the same or at least similar guarantees to more traditional p2p nodes that might run on a desktop computer or computer. The alternative is to rely on gateways, which shares many of the drawbacks of centralized control and prone to censorship, control and surveillence.
|
|
||||||
|
|
||||||
More generally, resource restricted devices can differ in their capabilities. One example is smartphones, but others are: desktop, routers, Raspberry PIs, POS systems, and so on. The number and diversity of devices are exploding, and it's useful to be able to leverage this for various types of infrastructure. The alternative is to centralize on big cloud providers, which also lends itself to lack of democratization and censorship, etc.
|
What does this stack look like? We take inspiration from [core](https://tools.ietf.org/html/rfc793) [internet architecture](https://www.ietf.org/rfc/rfc1122.txt), existing [survey work](http://cacr.uwaterloo.ca/techreports/2015/cacr2015-02.pdf) and other [efforts](https://code.briarproject.org/briar/briar/wikis/A-Quick-Overview-of-the-Protocol-Stack) that have been done to decompose the problem into orthogonal pieces. Each layer provides their own set of properties and only interact with the layers it is adjacent to. Note that this is a rough sketch.
|
||||||
|
|
||||||
## Minimal Requirements
|
| Layer / Protocol | Purpose | Examples |
|
||||||
|
|-------------------|-----------------------------------|----------------------|
|
||||||
|
| Application layer | End user semantics | 1:1 chat, group chat |
|
||||||
|
| Data Sync | Data consistency | MVDS, BSP |
|
||||||
|
| Secure Transport | Confidentiality, PFS, etc | Double Ratchet, MLS |
|
||||||
|
| Transport Privacy | Transport and metadata protection | Whisper, Tor, Mixnet |
|
||||||
|
| P2P Overlay | Overlay routing, NAT traversal | devp2p, libp2p |
|
||||||
|
| | |
|
||||||
|
| Trust Establishment | Establishing end-to-end trust | TOFU, web of trust |
|
||||||
|
|
||||||
For requirements or design goals for a solution, here's what we came up with.
|
As an example, end user semantics such as group chat or moderation capabilities can largely work regardless of specific choices further down the stack. Similarly, using a mesh network or Tor doesn't impact the use of Double Ratchet at the Secure Transport layer.
|
||||||
|
|
||||||
1. MUST sync data reliably between devices. By reliably we mean having the ability to deal with messages being out of order, dropped, duplicated, or delayed.
|
Data Sync plays a similar role to what TCP does at the transport layer in a traditional Internet architecture, and for some applications something more like UDP is likely to be desirable.
|
||||||
|
|
||||||
2. MUST NOT rely on any centralized services for reliability. By centralized services we mean any single point of failure that isn’t one of the endpoint devices.
|
In terms of specific properties and trade-offs at each layer, we'll go deeper down into them as we study them. For now, this is best treated as a rough sketch or mental map.
|
||||||
|
|
||||||
3. MUST allow for mobile-friendly usage. By mobile-friendly we mean devices that are resource restricted, mostly-offline and often changing network.
|
## Problems and rough priorities
|
||||||
|
|
||||||
4. MAY use helper services in order to be more mobile-friendly. Examples of helper services are decentralized file storage solutions such as IPFS and Swarm. These help with availability and latency of data for mostly-offline devices.
|
With all the pieces involved, this is quite an undertaking. Luckily, a lot of pieces are already in place and can be either incorporated as-is or iterated on. In terms of medium and long term, here's a rough sketch of priorities and open problems.
|
||||||
|
|
||||||
5. MUST have the ability to provide casual consistency. By casual consistency we mean the commonly accepted definition in distributed systems literature. This means messages that are casually related can achieve a partial ordering.
|
1. **Better data sync.** While the current [MVDS](https://github.com/vacp2p/specs/blob/master/mvds.md) works, it is lacking in a few areas:
|
||||||
|
- Lack of remote log for mostly-offline offline devices
|
||||||
|
- Better scalability for multi-user chat contexts
|
||||||
|
- Better usability in terms of application layer usage and supporting more transports
|
||||||
|
|
||||||
6. MUST support ephemeral messages that don’t need replication. That is, allow for messages that don’t need to be reliabily transmitted but still needs to be transmitted between devices.
|
2. **Better transport layer support.** Currently MVDS runs primarily over Whisper, which has a few issues:
|
||||||
|
- scalability, being able to run with many nodes
|
||||||
|
- spam-resistance, proof of work is a poor mechanism for heterogeneous devices
|
||||||
|
- no incentivized infrastructure, leading to centralized choke points
|
||||||
|
|
||||||
7. MUST allow for privacy-preserving messages and extreme data loss. By privacy-preserving we mean things such as exploding messages (self-destructing messages). By extreme data loss we mean the ability for two trusted devices to recover from a, deliberate or accidental, removal of data.
|
In addition to these most immediate concerns, there are other open problems. Some of these are overlapping with the above.
|
||||||
|
|
||||||
8. MUST be agnostic to whatever transport it is running on. It should not rely on specific semantics of the transport it is running on, nor be tightly coupled with it. This means a transport can be swapped out without loss of reliability between devices.
|
3. **Adaptive nodes.** Better support for resource restricted devices and nodes of varying capabilities. Light connection strategy for resources and guarantees. Security games to outsource processing with guarantees.
|
||||||
|
|
||||||
## MVDS - a minimium viable version
|
4. **Incentivized and spam-resistant messaging.** Reasons to run infrastructure and not relying on altruistic nodes. For spam resistance, in p2p multicast spam is a big attack vector due to amplification. There are a few interesting directions here, such as EigenTrust, proof of burn with micropayments, and leveraging zero-knowledge proofs.
|
||||||
|
|
||||||
The first minimum viable version is in an alpha stage, and it has a [specification](https://github.com/vacp2p/specs/blob/master/mvds.md), [implementation](https://github.com/vacp2p/mvds) and we have deployed it in a [console client](https://github.com/status-im/status-console-client) for end to end functionality. It's heavily inspired by [Bramble Sync Protocol](https://code.briarproject.org/briar/briar-spec/blob/master/protocols/BSP.md).
|
5. **Strong privacy guarantees at transport privacy layer**. More rigorous privacy guarantees and explicit trade-offs for metadata protection. Includes Mixnet.
|
||||||
|
|
||||||
|
6. **Censorship-resistant and robust P2P overlay**. NAT traversal; running in the browser; mesh networks; pluggable transports for traffic obfuscation.
|
||||||
|
|
||||||
The spec is fairly minimal. You have nodes that exchange records over some secure transport. These records are of different types, such as `OFFER`, `MESSAGE`, `REQUEST`, and `ACK`. A peer keep tracks of the state of message for each node it is interacting with. There's also logic for message retransmission with exponential delay. The positive ACK and retransmission model is quite similar to how TCP is designed.
|
7. **Scalable and decentralized secure conversational security.** Strong security guarantees such as forward secrecy, post compromise security, for large group chats. Includes projects such MLS and extending Double Ratchet.
|
||||||
|
|
||||||
There are two different modes of syncing, interactive and batch mode. See sequence diagrams below.
|
8. **Better trust establishment and key handling**. Avoiding MITM attacks while still enabling a good user experience. Protecting against ghost users in group chat and providing better ways to do key handling.
|
||||||
|
|
||||||
Interactive mode:
|
There is also a set of more general problems, that touch multiple layers:
|
||||||
<img src="{{site.baseurl}}/assets/img/mvds_interactive.png">
|
|
||||||
|
|
||||||
Batch mode:
|
9. **Ensuring modularity and interoperability**. Providing interfaces that allow for existing and new protocols to be at each layer of the stack.
|
||||||
<img src="{{site.baseurl}}/assets/img/mvds_batch.png">
|
|
||||||
|
|
||||||
Which mode should you choose? It's a tradeoff of latency and bandwidth. If you want to minimize latency, batch mode is better. If you care about preserving bandwidth interactive mode is better. The choice is up to each node.
|
10. **Better specifications**. Machine-readable and formally verified specifications. More rigorous analysis of exact guarantees and behaviors. Exposing work in such a way that it can be analyzed by academics.
|
||||||
|
|
||||||
### Basic simulation
|
11. **Better simulations**. Providing infrastructure and tooling to be able to test protocols in adverse environments and at scale.
|
||||||
|
|
||||||
Initial ad hoc bandwidth and latency testing shows some issues with a naive approach. Running with the [default simulation settings](https://github.com/vacp2p/mvds/):
|
12. **Enabling excellent user experience**. A big reason for the lack of widespread adoption of secure messaging is the fact that more centralized, insecure methods provide a better user experience. Given that incentives can align better for users interested in secure messaging, providing an even better user experience should be doable.
|
||||||
|
|
||||||
- communicating nodes: 2
|
---
|
||||||
- nodes using interactive mode: 2
|
|
||||||
- interval between messages: 5s
|
|
||||||
- time node is offine: 90%
|
|
||||||
- nodes each node is sharing with: 2
|
|
||||||
|
|
||||||
we notice a [huge overhead](https://notes.status.im/7QYa4b6bTH2wMk3HfAaU0w#). More specifically, we see a ~5 minute latency overhead and a bandwidth multiplier of x100-1000, i.e. 2-3 orders of magnitude just for receiving a message with interactive mode, without acks.
|
We got some work to do. Come help us if you want. See you in the next update!
|
||||||
|
|
||||||
Now, that seems terrible. A moment of reflection will reveal why that is. If each node is offline uniformly 90% of the time, that means that each record will be lost 90% of the time. Since interactive mode requires offer, request, payload (and then ack), that's three links just for Bob to receive the actual message.
|
|
||||||
|
|
||||||
Each failed attempt implies another retransmission. That means we have `(1/0.1)^3 = 1000` expected overhead to receive a message in interactive mode. The latency follows naturally from that, with the retransmission logic.
|
|
||||||
|
|
||||||
### Mostly-offline devices
|
|
||||||
|
|
||||||
The problem above hints at the requirements 3 and 4 above. While we did get reliable syncing (requirement 1), it came at a big cost.
|
|
||||||
|
|
||||||
There are a few ways of getting around this issue. One is having a *store and forward* model, where some intermediary node picks up (encrypted) messages and forwards them to the recipient. This is what we have in production right now at Status.
|
|
||||||
|
|
||||||
Another, arguably more pure and robust, way is having a *remote log*, where the actual data is spread over some decentralized storage layer, and you have a mutable reference to find the latest messages, similar to DNS.
|
|
||||||
|
|
||||||
What they both have in common is that they act as a sort of highly-available cache to smooth over the non-overlapping connection windows between two endpoints. Neither of them are *required* to get reliable data transmission.
|
|
||||||
|
|
||||||
### Basic calculations for bandwidth multiplier
|
|
||||||
|
|
||||||
While we do want better simulations, and this is a work in progress, we can also look at the above scenarios using some basic calculations. This allows us to build a better intuition and reason about the problem without having to write code. Let's start with some assumptions:
|
|
||||||
- two nodes exchanging a single message in batch mode
|
|
||||||
- 10% uniformly random uptime for each node
|
|
||||||
- in HA cache case, 100% uptime of a piece of infrastructure C
|
|
||||||
- retransmission every epoch (with constant or exponential backoff)
|
|
||||||
- only looking at average (p50) case
|
|
||||||
|
|
||||||
#### First case, no helper services
|
|
||||||
|
|
||||||
A sends a message to B, and B acks it.
|
|
||||||
|
|
||||||
```
|
|
||||||
A message -> B (10% chance of arrival)
|
|
||||||
A <- ack B (10% chance of arrival)
|
|
||||||
```
|
|
||||||
|
|
||||||
With a constant backoff, A will send messages at epoch `1, 2, 3, ...`. With exponential backoff and a multiplier of 2, this would be `1, 2, 4, 8, ...`. Let's assume constant backoff for now, as this is what will influence the success rate and thus the bandwidth multiplier.
|
|
||||||
|
|
||||||
There's a difference between *time to receive* and *time to stop sending*. Assuming each send attempt is independent, it takes on average 10 epochs for A's message to arrive with B. Furthermore:
|
|
||||||
|
|
||||||
1. A will send messages until it receives an ACK.
|
|
||||||
2. B will send ACK if it receives a message.
|
|
||||||
|
|
||||||
To get an average of one ack through, A needs to send 100 messages, and B send on average 10 acks. That's a multiplier of roughly a 100. That's roughly what we saw with the simulation above for receiving a message in interactive mode.
|
|
||||||
|
|
||||||
#### Second case, high-availability caching layer
|
|
||||||
|
|
||||||
Let's introduce a helper node or piece of infrastructure, C. Whenever A or B sends a message, it also sends it to C. Whenever A or B comes online, it queries for messages with C.
|
|
||||||
|
|
||||||
```
|
|
||||||
A message -> B (10% chance of arrival)
|
|
||||||
A message -> C (100% chance of arrival)
|
|
||||||
B <- req/res -> C (100% chance of arrival)
|
|
||||||
A <- ack B (10% chance of arrival)
|
|
||||||
C <- ack B (100% chance of arrival)
|
|
||||||
A <- req/res -> C (100% chance of arrival)
|
|
||||||
```
|
|
||||||
|
|
||||||
What's the probability that A's messages will arrive at B? Directly, it's still 10%. But we can assume it's 100% that C picks up the message. (Giving C a 90% chance success rate doesn't materially change the numbers).
|
|
||||||
|
|
||||||
B will pick up A's message from C after an average of 10 epochs. Then B will send ack to A, which will also be picked up by C 100% of the time. Once A comes online again, it'll query C and receive B's ack.
|
|
||||||
|
|
||||||
Assuming we use exponential backoff with a multiplier of 2, A will send a message directly to B at epoch `1, 2, 4, 8` (assuming it is online). At this point, epoch `10`, B will be online in the average case. These direct sends will likely fail, but B will pick the message up from C and send one ack, both directly to A and to be picked up by C. Once A comes online, it'll query C and receive the ack from B, which means it won't do any more retransmits.
|
|
||||||
|
|
||||||
How many messages have been sent? Not counting interactions with C, A sends 4 (at most) and B 1. Depending on if the interaction with C is direct or indirect (i.e. multicast), the factor for interaction with C will be ~2. This means the total bandwidth multiplier is likely to be `<10`, which is a lot more acceptable.
|
|
||||||
|
|
||||||
Since the syncing semantics are end-to-end, this is without relying on the reliablity of C.
|
|
||||||
|
|
||||||
#### Caveat
|
|
||||||
|
|
||||||
Note that both of these are probabilistic argument. They are also based on heuristics. More formal analysis would be desirable, as well as better simulations to experimentally verify them. In fact, the calculations could very well be wrong!
|
|
||||||
|
|
||||||
## Future work
|
|
||||||
|
|
||||||
There are many enhancements that can be made and are desirable. Let's outline a few.
|
|
||||||
|
|
||||||
1. Data sync clients. Examples of actual usage of data sync, with more interesting domain semantics. This also includes usage of sequence numbers and DAGs to know what content is missing and ought to be synced.
|
|
||||||
|
|
||||||
2. Remote log. As alluded to above, this is necessary. It needs a more clear specification and solid proof of concepts.
|
|
||||||
|
|
||||||
3. More efficient ways of syncing with large number of nodes. When the number of nodes goes up, the algorithmic complexity doesn't look great. This also touches on things such as ambient content discovery.
|
|
||||||
|
|
||||||
4. More robust simulations and real-world deployments. Exisiting simulation is ad hoc, and there are many improvements that can be made to gain more confidence and identify issues. Additionally, better formal analysis.
|
|
||||||
|
|
||||||
5. Example usage over multiple transports. Including things like sneakernet and meshnets. The described protocol is designed to work over unstructured, structured and private p2p networks. In some cases it can leverage differences in topology, such as multicast, or direct connections.
|
|
||||||
|
|
Loading…
Reference in New Issue