~whereswaldon/arborchat

10079abc793b35d998064179cb8dde44a9b839f2 — Chris Waldon 1 year, 6 months ago e37d949
Add more detailed explanations of some messages
1 files changed, 127 insertions(+), 20 deletions(-)

M specifications/sprout.md
M specifications/sprout.md => specifications/sprout.md +127 -20
@@ 8,48 8,155 @@ Sprout Protocol 0.0
Sprout is a simple connection-oriented protocol for exchanging nodes
in the arbor forest (as defined by the [arbor forest specification](forest.md)).

Protocol requires transport that is:
Protocol requires an underlying transport that is connection-oriented and supports reliable delivery.

- connection-based
- reliable delivery
Sprout is an exchange of *messages*, where either side can send any message type.

Protocol messages:
*Messages* consist of a single *header line* followed by zero or more lines of *content*. All lines, both *header* and *content* end with the ASCII newline character `\n`.

- newline delimited messages
- first line is header information and includes length of subsequent lines
There are two types of *message*, *requests* and *responses*. Any *request* will have _one or more_ responses.

Example:
All *message header lines* begin with a plaintext *verb* indicating what kind of *message* they are. 

There is no requirement to wait for a *response* before sending another *request*. Either party may choose to *respond* with an [error](#error) or [error_part](#error_part) message if the sprout implementation cannot handle a sufficient number of in-flight requests.

In *request messages*, the second whitespace-delimited element of the header line is a *message id*, which is a monotonically increasing unsigned integer (in decimal notation) that MUST be unique for the lifetime of the sprout connection. Most *messages* have different headers after the *message id*.

```
response message_id:2 count:5
SHA512...
SHA512...
SHA512...
SHA512...
SHA512...
<verb> <message_id> [<header> ...]
[<content_line>]
...
```

Anatomy of protocol message:
In a *response message*, the second whitespace-delimited element of the header line is a *target message id*, which indicates which *request message* the response corresponds to. Some *request messages* will have multiple *response messages*. These are distinguished by the use of a square-bracketed *index* after the *target message id*.

```
<verb> <id> [message-specific fields]
<verb> <target_message_id>[\[<index>\]] [<header> ...]
[<content_line>]
...
```

Messages:
## Message Types


### Version

The version *message* is an advertisment of the sender's protocol version. It is intended to indicate to the other end of the connection what messages are understood.

#### Possible Responses

- `ok`
- `error VERSION_TOO_HIGH`
- `error VERSION_TOO_LOW`
- `error TOO_MANY_REQUESTS`

#### Message Structure

```
version <message_id> <version number>
```

- `message_id` should be a unique unsigned integer that has not been sent to the remote side of the connection before.
- `version_number` should be the dotted-numeral notation of the protocol major and minor version number.

#### Example

```
version 1 0.0
```

An advertisment that the local client supports only the current unstable protocol version.

### Query Any

The `query_any` *message* requests a quantity of recent nodes of a given type. This is useful when attempting to discover new identity and community nodes.

#### Possible Responses

- `response <message_id> <count>` followed by <count> number of *response lines*
- `error TOO_MANY_REQUESTS`

#### Message Structure

```
query_any <message_id> <node_type> <quantity>
```

- `message_id` should be a unique unsigned integer that has not been sent to the remote side of the connection before.
- `node_type` should one of the arbor forest node types defined [here](forest.md) as a decimal integer.
- `quantity` should be the number of nodes requested. The response is guaranteed to have less than or equal to this many elements.

#### Example

```
query_any 5 1 10
```

A request for ten community nodes.

### Query 

The `query` *message* requests a list of specific nodes. This is useful when looking up specific node values (like when resolving the authors of reply nodes).

query_any <message_id> <node-type> <quantity>
#### Possible Responses

- `response <message_id> <count>` followed by <count> number of *response lines*
- `error TOO_MANY_REQUESTS`

#### Message Structure

```
query <message_id> <count>
<node_id>
[<node_id>...]
...
```

- `message_id` should be a unique unsigned integer that has not been sent to the remote side of the connection before.
- `count` should be the number of *message ids* that follow the header row (one per line).

#### Example

```
query_any 27 3
SHA512_B32__CZMk9Gv5g4GYNAPcdvwkDNITsfYFFsTu95jM5Fe4Ekk
SHA512_B32__TlztQX6enWYO3EXlDg1_F6tXOpiSxlGr7nZTNF530lM
SHA512_B32__d2XDjNrF03bFAUP6V_Nou1O28n9V1nWCWyvPdO5C0co
```

### Ancestry

The `ancestry` *message* requests the nodes prior to a list of nodes within the arbor forest up to a specified depth. This is useful when looking up the history of a collection of leaf nodes.

#### Possible Responses

- Multiple of `response <message_id>[index] <count>` followed by <count> number of *response lines*
- `error TOO_MANY_REQUESTS`

#### Message Structure

```
ancestry <message_id> <count>
<num> <node_id>
[<num> <node_id>...]
<ancestry_request>
...
```

- `message_id` should be a unique unsigned integer that has not been sent to the remote side of the connection before.
- `count` should be the number of *ancestry request lines* that follow the header row (one per line).
- `ancestry_request` lines are structured as:
  - `<num_levels> <node_id>` where `num_levels` is the maximum number of ancestor nodes requested, and `node_id` is the ID of the forest node to start backtracking from.

#### Example

```
ancestry 44 3
4 SHA512_B32__CZMk9Gv5g4GYNAPcdvwkDNITsfYFFsTu95jM5Fe4Ekk
23 SHA512_B32__TlztQX6enWYO3EXlDg1_F6tXOpiSxlGr7nZTNF530lM
7 SHA512_B32__d2XDjNrF03bFAUP6V_Nou1O28n9V1nWCWyvPdO5C0co
```

A request for ancestry of each of the three listed nodes. Note that the number of ancestry nodes requested varies between the three. Each of these three ancestries will generate a separate response or error message.

```
leaves_of <message_id> <node_id> <quantity>

response <target_message_id>[<index>] <count>