This draft spec is released as an RFC (request for comment) as part of the public review process. Any comments, criticisms or suggestions should be directed toward the issues page on this github repository.
| BRFC | title | authors | version |
|---|---|---|---|
| bafaa3fa5d5b | spv_channels | nChain | 1.0.0 |
SPV Channels provides a mechanism via which counterparties (e.g. miners and client applications) can communicate in a secure manner even in instances where one of the parties is temporarily offline.
Channels are configured to receive messages. Individual Channels have owners, and owners may configure Channel read/write permissions for unauthenticated connections and distinct read/write permissions for those to whom they issue revocable API keys.
The security model is establised by prescribing an application-level end-to-end encryption protocol, which protects transported messages.
A reference implementation of SPV Channels is shipped as a docker image and is available SPV Channels CE.
In summary channels specification is set of light weight JSON-over-HTTP public APIs for account holders, and their counterparties, to exchange messages in a secure manner.
A service identifies its customers/users via accounts. Message streams, whether one-shot or long-lived streams, are logically arranged into Channels, which in turn are owned by a single account. An account holder identifies itself to the platform via the account credentials. An account holder may generate API tokens which may be passed to third parties (message exchange counterparts), should the platform operator or Channel owner require authentication for its APIs.
The Channel APIs, secured by account credentials, allow account holders to create and manage Channels. The following APIs are provided:
- Create Channel
- List Channels
- Delete Channel
- Get Channel Info
- Get Token
- Get Channel Tokens
- Amend Channel
- Generate Channel API Token
- Revoke Channel API Token
Messaging APIs allow account holders, third parties, or even the general public to read from, or write to Channels
- Write message to channel
- Get messages in channel
- Mark message as read or unread
- Delete message in channel
POST /api/v1/account/{accountid}/channel
{
"id": "string",
"href": "string",
"public_read": true,
"public_write": true,
"sequenced": true,
"locked": true,
"head": 0,
"retention": {
"min_age_days": 0,
"max_age_days": 0,
"auto_prune": true
},
"access_tokens": [
{
"id": "string",
"token": "string",
"description": "string",
"can_read": true,
"can_write": true
}
]
}GET /api/v1/account/{accountid}/channel/list
{
"channels": [
{
"id": "string",
"href": "string",
"public_read": true,
"public_write": true,
"sequenced": true,
"locked": true,
"head": 0,
"retention": {
"min_age_days": 0,
"max_age_days": 0,
"auto_prune": true
},
"access_tokens": [
{
"id": "string",
"token": "string",
"description": "string",
"can_read": true,
"can_write": true
}
]
}
]
}DELETE /api/v1/account/{accountid}/channel/{channelid}
Response is 204 No Content
Returns single channel information
GET /api/v1/account/{accountid}/channel/{channelid}
{
"id": "string",
"href": "string",
"public_read": true,
"public_write": true,
"sequenced": true,
"locked": true,
"head": 0,
"retention": {
"min_age_days": 0,
"max_age_days": 0,
"auto_prune": true
},
"access_tokens": [
{
"id": "string",
"token": "string",
"description": "string",
"can_read": true,
"can_write": true
}
]
}GET /api/v1/account/{accountid}/channel/{channelid}/api-token/{tokenid}
{
"id": "string",
"token": "string",
"description": "string",
"can_read": true,
"can_write": true
}GET /api/v1/account/{accountid}/channel/{channelid}/api-token
[
{
"id": "string",
"token": "string",
"description": "string",
"can_read": true,
"can_write": true
}
[
POST /api/v1/account/{accountid}/channel/{channelid}
body:
{
"public_read": true,
"public_write": true,
"locked": true
}
200 OK
POST /api/v1/account/{accountid}/channel/{channelid}/api-token
body:
{
"description": "string",
"can_read": true,
"can_write": true
}
{
"id": "string",
"token": "string",
"description": "string",
"can_read": true,
"can_write": true
}DELETE /api/v1/account/{accountid}/channel/{channelid}/api-token/{tokenid}
Response is 204 No Content
POST /api/v1/channel/{channelid}
{
"sequence": 0,
"received": "string",
"content_type": "string",
"payload": "string"
}GET /api/v1/channel/{channelid}?unread=true
[
{
"sequence": 0,
"received": "string",
"content_type": "string",
"payload": "string"
}
]POST /api/v1/channel/{channelid}/{sequence}
body:
{"read": true | false}
200 OK
DELETE /api/v1/channel/{channelid}/{sequence}
Response is 204 No Content
HEAD /api/v1/channel/{channelid}
200 OK
GET /api/v1/channel/{channelid}/notify
Once the client receives the notification it is up to them to pull all unread messages/notifications from the Channel.
Notes:
- Notifications are generated automatically on the server side.
- Notification is sent for each message written to the channel, will be batched up in next release.
- Notification message is configurable in server configuration file.
For SPV Channels release 1.0.0, the encryption method supported is libsodium sealed_box which is an anonymous (you can not identify the sender) Public key encryption with integrity check (see here for more details: https://libsodium.gitbook.io/doc/public-key_cryptography/sealed_boxes )
Client side encryption will need to implement the algorithm :
libsodium sealed_box <base64 encoded encryption key>
