Skip to content

Instantly share code, notes, and snippets.

@justmoon
Last active November 24, 2016 04:54
Show Gist options
  • Save justmoon/5c2514af2eea06c9c58419520fe0b78c to your computer and use it in GitHub Desktop.
Save justmoon/5c2514af2eea06c9c58419520fe0b78c to your computer and use it in GitHub Desktop.
ILP Extra Headers Semantics and JSON Syntax

Definitions

  • Ledger

    System that records asset transfers on behalf of a set of accounts.

  • Ledger client

    System that communicates with a ledger.

  • Ledger protocol

    Specification that defines how a ledger and its ledger clients talk to each other. Clients MAY communicate with the ledger or directly with one another.

  • ILP packet

    Data traveling with ILP transfers that is not local and specific to the underlying ledger. (Local and specific data would be better handled in the ledger protocol.)

    ILP packets consist of some basic information (defined elsewhere) and zero or more extra headers as defined in this document.

  • Connector

    Any piece of software that generates a transfer with an attached ILP packet in response to receiving another transfer with an attached ILP packet.

Use Case

As an ILP protocol designer, I want to be able to add additional standardized information to ILP packets (ledger-independent data traveling with ILP transfer) in the future which may improve the behavior of ILP implementations or add useful functionality.

As an ILP solution vendor, I want to be able to add additional vendor-specific information to ILP packets without going through a standardization process.

Requirements

Ledger protocols may vary widely from each other. Currently, the most common ILP ledger protocols use JSON encoding, however we believe primarily binary protocols will be used in the future.

As such, we require only certain semantics about ILP packets, but leave the encoding choice up to the ledger protocol. A semantically equivalent ILP packet MUST emerge after passing through the ledger.

Encoding formats will likely continue to improve and evolve in the future, so we would like to support extensibility both in terms of the content of new headers as well as their encoding.

Implementation

Every header is defined by the following fields:

  • Header type
  • MIME type
  • Data
  • IsEssential flag

Ledger protocols MUST be forward compatible such that when changes to the ILP packet or extra header format are made, two ledger clients that are aware of the changes can still communicate through a ledger that is not.

Header Type

The header type MUST be either:

  • an integer in which case the type MUST be registered in the IANA Interledger Header Type Registry with a link to a specification of the header format or

  • a UTF-8 URI string starting with an identifier from the IANA Uniform Resource Identifier (URI) Schemes Registry, followed by a colon (:).

    This format is intended to be used for custom, vendor specific headers. Implementers defining a new header type SHOULD use HTTPS URIs where the https:// prefix is followed by a domain under their control. When the URI is entered into a browser, it SHOULD dereference to useful information about the header type.

MIME Type

The MIME type signals the high-level type of the data, such that clients who are not familiar with the specific header type can still attempt to render the data in a suitable fashion, e.g. as JSON, CBOR, etc.

In order to avoid proliferation of encodings, implementations SHOULD only use the following mime types:

  • application/json

    When requiring a text encoding with self-describing structure. Linked and/or typed data should be expressed using JSON-LD.

  • application/cbor

    When requiring a binary encoding with self-describing structure.

Ledger protocols MUST be able to pass any header with an unknown MIME type along without modification. Ledger protocol implementations MAY modify headers using a known MIME type as long as the modification preserves the semantic meaning of the data. For instance, syntactic white space may be removed from or added to a JSON header.

Data

The data is a plain octet string. Implementations MAY define more suitable representations for MIME types they are familiar with. E.g. if an implementation is using JSON, they may simply include the data as a JSON sub-object if the MIME type is "application/json" and as a base64 string otherwise.

If the data is not valid with respect to the given MIME type, ledger protocol implementations SHOULD reject the message entirely.

IsEssential Flag

Some header types might contain important information that MUST be taken into account when processing the ILP packet. In order to protect against connectors that are ignorant of such header types, we add the IsEssential flag to indicate this fact. Connectors MUST reject any incoming transfer whose ILP packet contains a header with a type they don't understand and the IsEssential flag set.

Examples

What follows are some examples showing how custom headers may be encoded in a JSON-based ledger protocol.

Example 1: JSON header in JSON protocol

The Five Bells Ledger API is a JSON-based protocol and therefore represents ILP headers as JSON.

Here is an example of a transfer with a custom, proprietary header of MIME type "application/json":

{
  "ledger":"https://nexus.justmoon.com/ledger",
  "execution_condition":"cc:0:3:_1HwPaA9FA3Qg8fxTN4UqmZPc2FLwEt_EDOCym1s72M:32",
  "id":"https://nexus.justmoon.com/ledger/transfers/ae099e2c-8ef2-45a7-8243-09bb9cdb0239",
  "expires_at":"2016-11-15T01:23:05.800Z",
  "state":"executed",
  "debits":[
    {
      "account":"https://nexus.justmoon.com/ledger/accounts/stefan",
      "amount":"0.01",
      "authorized":true
    }
  ],
  "credits":[
    {
      "account":"https://nexus.justmoon.com/ledger/accounts/sharafian",
      "amount":"0.01",
      "memo":{
        "ilp_header":{
          "account":"us.usd.nexus.sharafian.f61a96d4-5770-4249-abb9-c14c6186447d",
          "amount":"0.01",
          "data":{
            "expires_at":"2016-11-15T01:23:25.777Z"
          }
        },
        "extra_headers": [{
          "type": "https://acme.example/p/tax_payment_services/1.0",
          "mime_type": "application/json",
          "is_essential": true,
          "data": {
            "tax_id": 156789232,
            "favorite_color": "Misty Rose",
            "favorite_color_hex": "#FFE4E1"
          }
        }]
      }
    }
  ],
  "timeline":{
    "proposed_at":"2016-11-15T01:22:55.844Z",
    "prepared_at":"2016-11-15T01:22:55.872Z",
    "executed_at":"2016-11-15T01:22:55.950Z"
  }
}

The custom header is included in the credits[0].memo.extra_headers property. Note that the header's data property is a JSON object rather than a base64 encoded string as we might expect since data is an octet string. However, since this ledger protocol uses JSON and since syntactic changes to the data are allowed when the MIME type is known, the data can be represented as an object, which is more user-friendly.

Example 2: CBOR

{
  "ledger":"https://nexus.justmoon.com/ledger",
  "execution_condition":"cc:0:3:EHiayzeRwQ9IOgM1mANcIbBfcy8TzKiEVN3EbWX0FDM:32",
  "id":"https://nexus.justmoon.com/ledger/transfers/7e05845a-4308-4b1b-855c-04fc1adf68c0",
  "expires_at":"2016-11-15T01:31:06.143Z",
  "state":"executed",
  "debits":[
    {
      "account":"https://nexus.justmoon.com/ledger/accounts/stefan",
      "amount":"0.01",
      "authorized":true
    }
  ],
  "credits":[
    {
      "account":"https://nexus.justmoon.com/ledger/accounts/sharafian",
      "amount":"0.01",
      "memo":{
        "ilp_header":{
          "account":"us.usd.nexus.sharafian.53cdc12b-953b-490b-8586-34574654dc4a",
          "amount":"0.01",
          "data":{
            "expires_at":"2016-11-15T01:31:25.905Z"
          }
        },
        "extra_headers": [{
          "type": "https://acme.example/p/predicted_expiry_date/1.0",
          "mime_type": "application/cbor",
          "data": "wHQyMDEzLTAzLTIxVDIwOjA0OjAwWg=="
        }]
      }
    }
  ],
  "timeline":{
    "proposed_at":"2016-11-15T01:30:56.174Z",
    "prepared_at":"2016-11-15T01:30:56.196Z",
    "executed_at":"2016-11-15T01:30:56.276Z"
  }
}

We could have also chosen to convert the CBOR data to JSON, but in this example for illustration purposes we chose to represent it as pure binary. Every implementation MUST guarantee that however it chooses to represent the data, it does not change its semantic meaning.

The is_essential flag is not set in this example header and is therefore omitted.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment