Just wanted to share a status update on the (early stage) development of this dApp (see original idea here).
I’ve spent a few days (didn’t had much more time unfortunately) exploring various technical solutions, and here are some of my conclusions / decisions so far.
In both solutions described below, the smart contract handle a queue, and automatic payout of the helper calculated from time spent and helpee-signaled outcome of the conversation. Fee funds could come from the DAO (assigned budget) or paid by the helpee. These parameters can be set by admin roles.
For now I’ve essentially studied the “communication” solutions.
IPFS + WebRTC
This was my initial idea:
- WebRTC API for (end-to-end encrypted using NaCl) instant messaging
- Smart contract as a signaling intermediary (IPFS hashes shared along with encryption public key)
- IPFS (using https://js.ipfs.io/) for SDP and encrypted ICE data.
- Helper “publishes” his encryption public key in the smart contract as he register himself as “available to help”.
- Helpee / “customer” retrieves this key in the contract as he asks for help, and then publishes his SDP and encrypted ICE candidates on IPFS, and passes the resulting IPFS hash to the smart contract (in an array that serves as a queue).
- An event causes the queue list to be refreshed on the helper’s UI, and an estimated waiting time is displayed on the helpee’s UI.
(I realize the “ETH” label would have to be replaced by “ID”…)
- Helper picks a waiting helpee in the smart contract, and using the stored IPFS hash, retrieves and decrypt the ICE candidates to start the ICE exchange process.
- Once a datachannel is successfully established, a handshake is performed and the helpee transmits his pubkey to the helper to achieve end-to-end encryption.
- A transaction is generated by the helper to signal / confirm to the contract that a conversation has started.
- At the end of the conversation, the helpee is asked if his problem was solved or not, and the result is transmitted to the contract with a tx (that could also trigger helper payment, etc.)
- Direct p2p messaging
- As it uses WebRTC, this solution could easily be extended to use video, screen sharing, and audio.
- IPFS content propagation can be very slow sometimes, even when “cheating” and generating requests to common IPFS public gateways.
- ICE candidates generation rely on public STUN servers. I used an array of 5 public ice servers from google, blackberry, etc., but its still a form of centralization to me…
In my tests, the bad UX induced by the long waiting time generated by the IPFS content propagation ended up being unacceptable, despite the fact that once that step was passed, the experience was really smooth and offered an excellent instantaneous responsiveness feel.
Thus I decided to try my second idea:
- Whisper API v6 for (content encrypted using shh) for messaging.
- Smart contract to exchange ID’s and semi-obfuscated shh topic.
- Helper “publishes” his public key in the smart contract as he register himself as “available to help”.
- Helpee retrieves this key in the smart contract, and publishes a generated shh topic (only the 2 first transmitted bytes are from the real topic, 2 last transmitted bytes are randomly generated) in the smart contract’s queue-array.
- Helpee send a first “handshake” encrypted whisper message (containing his own public key and the full shh topic) to the topic with a TTL of 300 s (which is equivalent to the SLA that I defined as being acceptable).
- Once the helper picks the waiting helpee in the list, he’ll suscribe to the shh partial topic filter and start decrypting candidates. Once he retrieved the helpee public key and the full shh topic, he’ll suscribe to the full topic filter and conversation can start with messages set with a TTL of 30 s.
- Same ending as in WebRTC solution.
- Fully decentralized
- Good general responsiveness (but only tested on a local testnet)
- As I discovered, Metamask doesn’t provide the web3-shh API. More precisely, it’s Infura that doesn’t offer the ssh related methods. I made an attempt at injecting a secondary web3 provider in the page, directly connected to Infura, and it was confirmed:
- Upon further reflection, I realized that this seems totally logical, as Whisper rely on a certain form of PoW to forward messages, and also messages encryption/decryption happen in the node, and thus would require a lot of computing power if used by a lot of different users.
- Thus that means users would imperatively have to run their own node to use the service… which is unacceptable.
Requiring users to install and run their own node is unacceptable in the case of a general public usage.
I have now two other solutions in mind:
- WebRTC with a dDB like OrbitDB to pass the ICE candidates and public keys.
- Not sure if that would completely solve the propagation latency, as new users would have to fetch the dDB in their jsipfs node the first time.
- Use a light client node that lives in the browser.
- I have to explore the alternatives here. Maybe Paritytech’s Light.js…
- Not sure if light client is a good solution for those accessing the service from a low-end device, or in poor connectivity cases…
- Seek for help to the Status.im guys to ask how they did it …
- Explore Matrix protocol. Despite requiring the DAO to have matrix servers, it could be a good alternative to (too) slow handshakes procedures.
I’ve not studied enough the case to determine if, in a WebRTC solution, it would be feasible (in terms of tx fees) to directly transmit the ICE candidates trough the smart contracts. But I assumed not, as it would represent some long encrypted strings to store onchain… Maybe I’ll give it a try anyhow…
Unfortunately, I have to put this project on hold for a few weeks / months now.
Good point is that the basic UI of the app should be quickly adaptable to the desired solution…
As soon as I’ll have some spare time, I’ll try to bundle a clean package and publish some code on github.
In the meanwhile, if anybody has further ideas or suggestions, I’m all open to it !