Distribution Protocol

The Converge Distribution Protocol is a peer to peer message based protocol that all nodes use to exchange data with each other. It can run over any transport that can reliably pass sufficiently large datagrams.

Operations

The protocol is based on granting and invoking capabilities. These capabilities are represented by byte strings that are meaningful to the recipient, but opaque to any callers. The only requirement is that they be unforgeable, so they may be anything from an encrypted and authenticated payload to random bytes indexing into a local database.

Give

The give message provides the peer with a capability and an explanation as to how the capability may be used. It does not request any response.

Explain

The explain message requests an explanation as to how a set of capabilities may be used with this peer. This explanation takes the form of replies of give messages.

Note that the peer should always return a give message, even if it just explains that the capability is meaningless.

Delegate

Requests a capability that has the functionality of the greatest lower bound of the provided capability and explanation.

For example, a capability that can fetch anything could be delegated into one that can only fetch a specific reference.

Select

FIXME: not sure what i think of including this one

The select message requests a list of capabilities the peer grants the requestor that match a particular explanation. This does not list all the capabilities that are valid for the requestor to use, merely those specifically recorded as granted to that requestor. These capabilities are returned in give messages.

This enables peers to host public content without distributing capabilities beforehand.

Invoke

Invokes this capability, providing any required parameters. Invocation also includes any capabilities needed to respond, along with their explanations.

Capabilities

The actual distribution and synchronization of data takes place over invoke messages.

Not all nodes must support every capability, but they must not give out capabilities that they do not support. This generally means that they must support fetch and write. They also may support additional capabilities not listed here!

Fetch

The fetch capability requests that the peer find a particular object and send its contents back. It has two parameters:

  • the set of references to objects that can be requested
  • the probability of forwarding the request to other peers

Each invocation of a fetch capability provides a write capability, scoped to enable the peer to reply with the requested object.

Write

The write capability provides the contents of an object and some of its children to a peer. It has just one parameter:

  • the set of references to objects that can be sent

Each invocation of a write capability includes the contents of the object and its children, and provides a fetch capability, scoped to allow the peer to fetch any children or parents listed but not included on any of the included objects.

Subscribe

The subscribe capability requests that a peer proactively inform this node of any new [versions][version] of a particular [braid]. It has two parameters:

  • the set of [braid references][braid] that can be subscribed to
  • whether the peer will subscribe to this braid on other peers

Each invocation of a subscribe capability provides a write capability, scoped to enable the peer to reply with the requested object.

Pin

The pin capability creates a new pin, requesting that a peer maintain one or more copy of a set of objects and objects related to them. It has four parameters:

  • the set of references to objects to be pinned
  • the set of references to objects to be excluded from this pin
  • the pin filter, describing which related objects to implicitly pin
  • how many copies to pin

Each invocation of a pin capability provides either a subscribe or fetch capability, scoped to enable the peer to subscribe to changes on, or request, the pinned objects. The pin capability responds with a repin capability, to change that pin.

Pin Filters

The types of recursive pinning that might be constructed are unbounded, which entails an equally complex task of applying those pins or explaining them to the user. Following the operator's notes on pinning, we must support at least:

  • pinning only the latest versions of an object
  • pinning the latest versions and all objects they reference
  • pinning historical versions (following first parents) and all objects they reference
  • pinning all versions and all objects they reference

There are options here to support either those options directly, or create a tiny DSL that can make those options and others. Something like:

data Pin
   = Pin Word8 -- pin this number of copies
   | Repeat (Maybe Word) Pin -- apply the pin, when it's done, apply it again, if a count is supplied, limit to that many times
   | Branch [Pin] -- apply the pins, all starting from the same location
   | FirstParent Pin -- go to the first parent, and apply the contained pin
   ) Parents Pin -- go to each parent, and apply the pin
   ) References Pin -- go to each reference, and apply the pin
   | IsBlob Pin -- if the current reference is a blob, apply the contained pin, otherwise do nothing
   | IsVersion Pin -- if the current reference is a version, apply the contained pin, otherwise do nothing
   | IsBraid Pin -- if the current reference is a braid, apply the contained pin, otherwise do nothing

This is much more flexible, but seems unnecessarily complex.

Repin

The repin capability modifies a pin. It has two parameters:

  • the set of objects to add to the pin
  • the set of objects to exclude from the pin

Explanations