Messaging (Slack)

Direct Messaging

Edsu looks like a storage protocol, but it can work as a communications platform just as well.

If Ada subscribes to the address bem@one.com:grp.app.example-com.im-app.ada, and Bem subscribes to ada@two.com:grp.app.example-com.im-app.bem, it effectively opens a two-way connections channel.

Here's how it would work.

Sending

Bem wants to say "lol wut?!" to Ada. He sends the following message to his own Edsu server:

block-put
payload-stop 23
{ "text": "lol wut?!" }

To which the server would respond:

ok
channel 0
hash QmR1SKU7Qg85VSeTdQB1zRiaNtij3mA2vjxPiCzW8Fo5qp

He would then use that hash to update the name mentioned above:

name-put
name grp.app.example-com.im-app.ada
hash QmR1SKU7Qg85VSeTdQB1zRiaNtij3mA2vjxPiCzW8Fo5qp

Receiving

Ada, having an open visitor connection to Bem's edsu server, and subscribed to that name, would immediately receive:

sub-notify
name grp.app.example-com.im-app.ada
hash QmR1SKU7Qg85VSeTdQB1zRiaNtij3mA2vjxPiCzW8Fo5qp

At which point she can retrieve the block that Bem just put by sending:

block-get
hash QmR1SKU7Qg85VSeTdQB1zRiaNtij3mA2vjxPiCzW8Fo5qp

She gets:

block
channel 0
payload-length 23
{ "text": "lol wut?!" }

And so "lol, wut?!" has been sent from Bem to Ada.

Efficiency

If right now you're thinking "that seems like a lot of work just to send a few bytes", fair point! The above exchange is non-optimal from two perspectives: it's verbose and it involves a lot of round trips.

In terms of verbosity: guilty as charged. Edsu has prioritized a semantically clean model and text-orientation over svelteness. However bear in mind that the above fits very comfortably inside a single IP packet, so in the latency-sensitive case of a single message it makes no practical difference.

In the era of megabit connections, it's the round trips that are the real concern in situations like the above example. But in most cases they can largely, if not entirely, be removed.

For Bem's side of the communication, the hash of the block he puts is needed before he can update the name with it - that's what's causing the round trip.

However, because the hashing function is deterministic, Bem doesn't need to wait for the server to respond - he can pre-compute the hash and send both his messages at the same time. Edsu is pipelined (this is what the optional "channel" key is for), and it also provides guarantees of operation ordering (in this case, the block-put is guaranteed to complete before the name-put). So the entirety of Bem's posting can be accomplished using a single IP packet.

For Ada's side, Edsu has a optional feature called chaining, the purpose of which is to nullify the effect of latency in cases like this. What this does is instruct the Edsu server to send blocks that the user already knows that they will want.

In this case, Ada would have created her subscription using this message:

sub-put
name grp.app.example-com.im-app.ada
chain  

The existence of the "chain" key can be interpreted as "send the block in question".

So, in the above scenario, Ada would receive two messages at once:

sub-notify
name grp.app.example-com.im-app.ada
hash QmR1SKU7Qg85VSeTdQB1zRiaNtij3mA2vjxPiCzW8Fo5qp
channel 0
block
channel 0
payload-length 23
{ "text": "lol wut?!" }

Again, this fits into a single IP packet. So, using pre-hashing and chaining, Bem sending a message using Edsu looks like this:

  1. Bem sends one packet to his Edsu server
  2. Ada receives one packet from Bem's Edsu server

It's not as efficient as a direct peer-to-peer connection, this is true. But that carries its own issues (e.g. NAT and firewalls).

As a bonus you get the benefits of it being a storage protocol for free: it's trivial to store message history, or have multiple recipients, for instance.

Bootstrapping

The above scenario begs the question: how does communications work when the two parties aren't in the middle of one already, i.e. how did Ada know to listen on that name for messages from Bem?

The internet is a hostile place, and so Edsu is very tightly locked down. Users can only read and write data to their own accounts, with two exceptions: they can read data from other accounts if they have explicit permission, and they can write to other accounts, in a limited way, by appending names.

Appendable name blocks are a tiny keyhole through which one user can write a single piece of data into another user's storage - a multihash. Even this is further restricted by the permissions system and a configurable rate-limiter. Every time a name block is appended to, the (authenticated) username and time is recorded along with it - both of these are trustable, as they are recorded by the Edsu user's own server.

The value of this is that users can put up "corkboards" on the open internet. Another user can implicitly say: "hey, I'd like to talk to you, here's my details" by leaving a hash that points to a block on their account. From this, the user can either elect to read that block, or ignore it. In this way, as trust is established communications can be bootstrapped from a very narrow channel - one which is difficult to abuse - into an arbitrarily large one.

Caveats

Especially since Edsu is new, it's worth noting that there's a gap between theory and practice in terms of efficiency as a communications platform. For example, names offer guarantees which are not cost-free (e.g. maintaining order of operations, atomicity, etc.), and the Edsu server would need in-memory storage for short-lived blocks for this to be as fast as a dedicated communications protocol.

Which is to say: Edsu isn't meant to be everything to everyone. For many use cases (e.g. instant messaging), the latency introduced by its genericness is in the noise floor when set against that of sending packets across the internet. For applications like gaming, however, it's best to use a purpose-built protocol. However, even in these cases Edsu has a lot to offer: authentication, data storage, less latency-sensitive communications (e.g. finding other players in a "lobby"), etc.