In Prague, we’ve talked about options to synchronize chats/contacts/history across multiple devices (i.e. between Status Desktop and Status Mobile). Many of us are reinstalling nightly builds daily, and sometimes it requires re-creating account, so all the chats/contacts are lost, and we need to add it again, just to repeat the process two days later.
Proposed solutions
The proper solution, as we see it, would be to store all that information in encrypted form in decentralized storage, like Swarm and IPFS. The problem with it is in the current state of both – neither Swarm nor IPFS are supported, and the implementation of light Swarm client is still in progress.
One suggestion has been made during Status Desktop meeting to adopt an approach similar to Whatsapp Web. Quick recap: web/desktop versions show a QR code, which user needs to scan with already authenticated Whatsapp application on the mobile phone, and desktop version automagically syncs with the mobile app. However, the underlying mechanism heavily depends on a centralized server. Basically, it’s web app opens WebSocket connection to the server, generates a unique key and provides this key via QR code to the mobile app. The mobile app, upon receiving the key, contacts server and asks to transfer account’s messages and data to the WebSocket associated with that key. More details here.
But the idea of using one authenticated and configured app to quickly bootstrap another one is tempting, and actually, QR codes might be good enough to do the whole job alone.
Using QR codes for data transfer
An idea is based on two premises:
- amount of data to sync is relatively small
- every phone is enabled with a camera nowadays
In essence, the idea is to make one device (Status Desktop, for example) to take all data need to be synced (contacts and chat names), encrypt it and encode into the series of animated QR codes. Another authorized device (Status Mobile) open up camera, scan QR codes, and get the whole payload, decode and decrypt it, and will use it as a bootstrap values for an empty account.
Let’s crunch the numbers.
Data to sync
Assuming we want to sync only contacts and chats, let’s put a pessimistic average of 50 chat groups and 100 contacts. Chat groups can be identified by their string representation (i.e #status-core-desktop
) and contacts by their keys hashes (65 bytes or 130 hex characters). Let’s assume the average chat name is 20 chars long.
Summing this up: 50 * 20 chars + 100 * 130 + data schema overhead (5 chars per each entity = 150 * 5 = 750) = 1000 + 13000 + 750 = 14750 = 14.4KB.
Now, 14.4 KB of ASCII characters, with HEX subset being the majority of the content, it should compress pretty efficiently (to 1K or less), but QR codes encode asciinumeric and binary differently, so the benefit of compressing and feeding binary to QR encoding is under question.
QR Code Encoding capacity
QR codes have version range from 1 to 40. Version 40 offers 177 rows max and 31K pixels. With high error correction rate it offers 1307 alphanumeric bytes capacity, and for low error correction mode – 3009.
That’s how QR code version 40 for 1276 bytes looks like:
It looks almost like a noise, but my smartphone camera can perfectly read its “Lorem ipsum…” content. In order to fit 14.4K of data, we’ll need at least 12 such frames with QR codes. To adapt it to average consumer screens, we’ll have to choose less QR version or decrease error correction level.
Animating QR codes
Now, the idea is to display multiple QR codes in a sequence, probably in a loop to allow client code to restore missed frames if any. On 15 FPS this will give us data rate around 1307*15=19.1KB/sec which is more than enough to transfer all the contacts.
The idea is not new, there are projects exist to demonstrate this approach. Here is a good example with quite an old device and camera:
They claim to have even higher throughput, ~43KB/s.
I believe we can experiment even with higher fps, that will allow us to choose smaller QR version.
Alternatives
The animated QR approach seems to me to be the easiest one to implement, as QR encoding implementations are abundant and battle-tested. One can use native mobile OS QR reading API (in Status-React, for example) to feed data frame-by-frame to the library in status-go to decrypt and decode data. However, it’s worth to note the alternative options, which I outline briefly.
- Colored QR codes
It’s not widely implemented, but QR codes can use colours to increase the encoding ratio. Most of the color QR codes use color simply for aestaetic look, but it’s possible to encode additional data with color.
By the way, QR codes should not necessarily be black&white and boring. We can have this, for example:
-
Specialized visual coding protocols
There is some amount of literature and implementations of non-QR code based visual code data transfers, such as ThruGlassXfer or coding designed for aircrafts. Not to mention another 2D barcode matrix coders. -
Custom solutions similar to Apple’s Particle Cloud paring mechanism used to sync with Apple Watch. It’s patented and implementation details are super cool:
FInal thoughts
I personally think the naive QR code animated approach would be quite easy to implement. But I’d love to hear thoughts and criticism of this idea. I do understand limitations of it, but it can be seen as a temporary or even “fallback” solution after the decentralized storage one is implemented. Also, if it’ll proove to work great, it’ll offer much better security as there is no network involved at all.