go-libp2p-daemon/specs/DHT.md

387 lines
6.3 KiB
Markdown

# libp2p Daemon DHT Protocol
The libp2p daemon DHT protocol allows clients to query and announce to the
libp2p DHT.
_At the moment, this is a living document. As such, it will be susceptible to
changes until stabilization._
## Protocol Specification
### Data Types
The data structures are defined in [pb/p2pd.proto](../pb/p2pd.proto). All messages
are varint-delimited. For the DHT queries, the relevant data types are:
- `DHTRequest`
- `DHTResponse`
All DHT requests will be wrapped in a `Request` message with `Type: DHT`. Most
DHT responses from the daemon will be wrapped in a `Response` with the
`DHTResponse` field populated. Some responses will be basic `Response` messages to convey whether or not there was an error.
`DHTRequest` messages have a `Type` parameter that specifies the specific query
the client wishes to execute.
The DHT protocol supports asynchronous stream responses with arbitrary numbers
of results as well as responses that return a single value. `DHTResponse`
messages have a `Type` parameter that specifies whether a response marks the
`BEGIN`ning of a stream of messages, a `VALUE` within a stream of messages, or
the `END` of a stream of messages. Single-value responses will simply return a
single `DHTResponse` with type `VALUE`.
All `DHTRequest`s also take an optional timeout in seconds.
### Protocol Requests
*Protocols described in pseudo-go. Items of the form [item, ...] are lists of
many items.*
#### Errors
Any response that may be an error, will take the form of:
```
Response{
Type: ERROR,
ErrorResponse: {
Msg: <error message>,
},
}
```
#### `FIND_PEER`
Clients can issue a `FIND_PEER` request to query the DHT for a given peer's
known addresses.
**Client**
```
Request{
Type: DHT,
DHTRequest: DHTRequest{
Type: FIND_PEER,
Peer: <peer id>,
},
}
```
**Daemon**
*Can return an error*
```
Response{
Type: OK,
DHTResponse: DHTResponse{
Type: VALUE,
Peer: PeerInfo{
Id: <peer id>,
Addrs: [<addr>, ...],
}
}
}
```
#### `FIND_PEERS_CONNECTED_TO_PEER`
Clients can issue a `FIND_PEERS_CONNECTED_TO_PEER` request to query the DHT for
peers directly connected to a given peer in the DHT.
**Client**
```
Request{
Type: DHT,
DHTRequest: DHTRequest{
Type: FIND_PEERS_CONNECTED_TO_PEER,
Peer: <peer id>,
},
}
```
**Daemon**
*Can return an error*
```
Response{
Type: OK,
DHTResponse: DHTResponse{
Type: BEGIN,
}
}
```
**Daemon**
*Can return any number of responses like this, including 0*
```
DHTResponse{
Type: VALUE,
Peer: PeerInfo{
Id: <peer id>,
Addrs: [<addr>, ...],
},
}
```
**Daemon**
*Marks the end of the result stream*
```
DHTResponse{
Type: END,
}
```
#### `FIND_PROVIDERS`
Clients can issue a `FIND_PROVIDERS` request to query the DHT for peers
that have a piece of content, identified by a CID. `FIND_PROVIDERS` optionally
include a `Count`, specifying a maximum number of results to return.
**Client**
```
Request{
Type: DHT,
DHTRequest: DHTRequest{
Type: FIND_PROVIDERS,
Cid: <content id>,
Count: <number of results to include>,
},
}
```
**Daemon**
*Can return an error if the CID is invalid*
```
Response{
Type: OK,
DHTResponse: DHTResponse{
Type: BEGIN,
},
}
```
**Daemon**
*Can return any number of responses like this, including 0*
```
DHTResponse{
Type: VALUE,
Peer: PeerInfo{
Id: <peer id>,
Addrs: [<addr>, ...],
},
}
```
**Daemon**
*Marks the end of the result stream*
```
DHTResponse{
Type: END,
}
```
#### `GET_CLOSEST_PEERS`
Clients can issue a `GET_CLOSEST_PEERS` request to query the DHT routing
table for peers that are closest to a provided key.
**Client**
```
Request{
Type: DHT,
DHTRequest: DHTRequest{
Type: GET_CLOSEST_PEERS,
Key: <content id>,
},
}
```
**Daemon**
*Can return an error*
```
Response{
Type: OK,
DHTResponse: DHTResponse{
Type: BEGIN,
}
}
```
**Daemon**
*Can return any number of responses like this, including 0*
```
DHTResponse{
Type: VALUE,
Value: <peer id>,
}
```
**Daemon**
*Marks the end of the result stream*
```
DHTResponse{
Type: END,
}
```
#### `GET_PUBLIC_KEY`
Clients can issue a `GET_PUBLIC_KEY` request to query the DHT routing table
for a given peer's public key.
**Client**
```
Request{
Type: DHT,
DHTRequest: DHTRequest{
Type: GET_PUBLIC_KEY,
Peer: <peer id>,
},
}
```
**Daemon**
*Can return an error if the peer is not found*
```
Response{
Type: OK,
DHTResponse: DHTResponse{
Type: VALUE,
Value: <public key>,
}
}
```
#### `GET_VALUE`
Clients can issue a `GET_VALUE` request to query the DHT for a value stored at
a key in the DHT.
**Client**
```
Request{
Type: DHT,
DHTRequest: DHTRequest{
Type: GET_VALUE,
Key: <key>,
},
}
```
**Daemon**
*Can return an error if the key is not found*
```
Response{
Type: OK,
DHTResponse: DHTResponse{
Type: VALUE,
Value: <value stored at key>,
}
}
```
#### `SEARCH_VALUE`
Clients can issue a `SEARCH_VALUE` request to query the DHT for the best/most
valid value stored at a given key. It will return a stream of values,
terminating on the best/most valid value found. After the daemon finishes its query, it will update any peers in the DHT that returned stale or bad data for
the given key with the better record.
**Client**
```
Request{
Type: DHT,
DHTRequest: DHTRequest{
Type: SEARCH_VALUE,
Key: <key>,
},
}
```
**Daemon**
*Can return an error*
```
Response{
Type: OK,
DHTResponse: DHTResponse{
Type: BEGIN,
}
}
```
**Daemon**
*Can return any number of responses like this, including 0*
```
Response{
Type: OK,
DHTResponse: DHTResponse{
Type: VALUE,
Value: <value at key>,
},
}
```
**Daemon**
*Marks the end of the result stream*
```
Response{
Type: OK,
DHTResponse: DHTResponse{
Type: END,
}
}
```
#### `PUT_VALUE`
Clients can issue a `PUT_VALUE` request to write a value to a key in the DHT.
**Client**
```
Request{
Type: DHT,
DHTRequest: DHTRequest{
Type: PUT_VALUE,
Key: <key>,
Value: <value>,
},
}
```
**Daemon**
*Can return an error*
```
Response{
Type: OK,
}
```
#### `PROVIDE`
Clients can issue a `PROVIDE` request to announce that they have data
addressed by a given CID.
**Client**
```
Request{
Type: DHT,
DHTRequest: DHTRequest{
Type: PROVIDE,
Cid: <cid>,
},
}
```
**Daemon**
*Can return an error*
```
Response{
Type: OK,
}
```