Core
Ripple Core Protocol
The following is common to all Ripple subprotocols.
Messaging
The Ripple network consists of software agents called nodes connected together pairwise where one or both accept the other's obligations as valuable. These abstract connections are manifested over messaging connections between hosts, each of which may host multiple nodes.
A message transport layer must distinguish between three message types: message
, reply
, and error
. Each Ripple message
has a unique ID within the host-level connection, and must be immediately responded to by either a reply
or an error
with the same ID upon receipt. This serves to establish that the message was received and was either understood (reply
), or deemed somehow malformed or otherwise inappropriate as detailed by an error code and message (error
). The ID may consist of one or more fields.
Replies and errors may carry any data that a regular message may carry. In addition, error messages must carry an error code.
In general, nodes need not wait for the reply or error to send another message.
Ripple messages carried within the transport layer are in JSON textual format. For example:
{ "type": "account-request", "from": "rfugger@ripplepay.com", "to": "otheruser@otherhost.com:2338", ("request-id": (integer),) ("time": "2007-03-30 14:10:03.112000",) ("body": (message body goes here)) }
The indentation and line breaks are for readability in this document only. The actual messages themselves do not have significant whitespace other than described in the JSON specification.
The from
and to
fields contain node names on the sending and receiving host, respectively. For host-to-host messages, these fields contain hostnames (with optional ports), without node IDs. This allows hosts to know each other's hostnames, and also provides, for signed messages, a record of sender and recipient.
The request-id
field is used to pair up requests and replies. Request IDs must be unique among open requests between two hosts. The time
field contains the UTC time according to the sending host's clock. It is only used in certain subprotocols, particularly Payments and Accounts. The body
field is not used for every message type.
Host Messages
Certain messages are sent to a host, rather than to an individual node on a host.
The timestamp put on a Ripple message by the sending host is interpreted by the receiving host as the time the corresponding event occurred, so it is important that:
- the two hosts' clocks are reasonably in sync
- the network latency is reasonable
To allow two hosts to verify these two conditions at the beginning of a connection, and at any other time there is uncertainty (such as a long delay between timestamped messages), they may use a time
message:
{ "type": "time", (request-id: 24223,) "time": "2007-03-30 14:10:03.112000" }
request-id
is only used if the message is in reply to a time-request
. An affirmative reply to this message indicates the receiving host's approval of the sending host's local clock and network latency of the connection. An error reply containing a time-request
message indicates that the another time message should be sent. After three consecutive time errors, the connection should be closed after all open transactions are completed.
To request a time
message from another host, for example, when timestamped non-time
messages are arriving at off-times, send a time-request
:
{ "type": "time-request", "request-id": (4485093) }
The host receiving a time-request
must give an affirmative reply followed immediately by a time
message with the same request-id
as the request. This may trigger a time error and subsequent time
messages and possibly a closed connection.
Ping may also be used to detect network latency. Ripple hosts should accept pings.
This section presumes both hosts are making every effort to be honest about their timekeeping. Cheating is addressed elsewhere. Timekeeping issues such as clock differences between hosts, network latency, and cheating may be addressed in the future by allowing hosts to negotiate a third-party timestamping authority as an intermediary for their Ripple messaging.
At any time they are connected, a host may request another for the status of its protocol support by sending a host-status-request
message with no body:
{ "type": "host-status-request" }
The host receiving such a message must reply immediately with a host-status
message containing a list of protocol versions and subprotocols of each that it understands.
{ "type": "host-status", "body": [ { "version": "1", "subprotocols": [ "ripple-payment", "ripple-routing", "ripple-channel", "ripple-account", ] } ] }
Transport
Host Connections
Ripple hosts connect to each other by TCP. (Need to specify a standard port for hosts to listen on.) TCP connections are meant to be persistent, but may be closed by either host at any time.
Hosts may open multiple connections with each other.
Connection Security
After time
and possibly host-status
messages have been exchanged, the initiating host starts TLS on the connection.
Node Identification
Nodes are identified in standard node@host.com email-address style. For nonstandard ports, use node@host.com:xxxx, where xxxx is the port the host is listening on for Ripple connections.
Host Messages
Host messages are sent in BEEP-style frames as follows:
(type) (version) (msgno) (more) (size)(CRLF) (content) END(CRLF)
where
(type) = MSG | RPY | ERR (version) = (string) (msgno) = 0..2147483647 (more) = . | * (size) = (integer)
Message types MSG
, RPY
, and ERR
correspond to the Ripple message types message
, reply
, and error
.
The version
indicates the Ripple protocol version.
The msgno
must be unique among MSG
-type messages in the connection that have not yet received a complete response. For RPY
and ERR
types, msgno
must be identical to the original MSG
. The host that initiated the connection must use only even-numbered msgno
s and the host that received the connection must use only odd-numbered msgno
s.
If more
is "*", it signifies there are more frames in the message; if it is ".", this is the final frame. This allows a host to chunk messages into discrete bits in order to interleave messages on the same connection. If the connection is dropped before the final frame is received and acknowledged, the message must be disregarded.
size
is the number of content bytes between, but not including, the CRLF
at the end of the header line, and the END
at the end of the frame.
Channels from the BEEP specification are omitted because Ripple interleaving message frames seems to accomplish much the same thing. The seqno
field from BEEP is omitted here because TCP already does its own byte-counting at a lower level.
Errors
If a received frame is not in the correct format, the association must be immediately closed.