Less Technical
Implementation
Old Stuff
Older Stuff
Oldest Stuff |
Protocol /
PaymentProtocolRipple Payment ProtocolMessagingThe 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. Binding to a Message Transport Layer A Ripple transport layer binding must specify the following:
A message transport layer must distinguish between three message types: 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:
{
"account-request": {
"request-id": 16504,
"account-id": "550e8400-e29b-41d4-a716-446655440000",
"initiator": {
"limit": 500
}
}
}
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. Protocol extensions may add custom fields to Ripple messages, as well as defining their own host and/or node messages. Nonstandard extensions should take care not to duplicate field names of other extensions, by, for example, giving their field names a short common prefix that identifies the protocol extension to which they belong. Protocol extensions must each have a unique name. Hosts can query each other to discover which extensions they support -- see Host Status below. Host MessagesCertain messages are sent to a host, rather than to an individual node on a host. When a connection between two Ripple hosts is established, the host accepting the conection must send a
{
"time": "2006-10-30 18:47:55.356000"
}
The host receiving the time message echoes back its own time message in reply, indicating that it agrees to use the other host's time as the official time for that connection. If it disagrees, it replies with an error and sends its own time message. If that time message is rejected, the connection is closed. There is little reason to disagree with someone's time at the start of a connection, unless you have oustanding open transactions with the other host that are time-sensitive -- simply store the difference from the local host's time and compensate on sent and received messages. During the course of the connection, either host may send a time message to the other to verify the time. If at any point the two hosts fail to agree on the current time, the connection should be closed. Time messages can be used to discover connection latency. They can also act as hearbeat messages to verify the connection. At any time they are connected, a host may request another for the status of its protocol support by sending a
{
"host-status"
}
The host receiving such a message must reply immediately with a list of protocol versions and extensions to each that it understands.
{
"host-status": [
{
"version": "1",
"extensions": [
"ripple-routing",
"ripple-channel",
"ripple-account",
]
}
]
}
Neighbour ConnectionsRipple nodes may connect when one or both accept the other's obligations as valuable. Connected nodes are said to be neighbours. A neighbour connection is a relationship defined by an agreement to participate in Ripple transactions as neighbours, and does not refer to the messaging connection that may exist from time to time between the neighbouring nodes' hosts, and over which the neighbour relationship takes place. The Ripple Payment Protocol involves nodes issuing and accepting obligations of a certain value to and from their neighbours, but doesn't specify how these obligations are recorded or what the terms or limits of these obligations are. Neighbours must agree on an accounting system that will approve potential transactions and record the balance of committed transactions between them. One such system is the Ripple Account Protocol. A neighbour connection consists of nothing other than one or more accounts between the neighbours. The minimal set of data that must be known by two neighbouring nodes in order to participate in Ripple payments is:
The JSON data structure for an account is:
{
"account": {
"account-id": (string),
"unit": (URI),
"account-type": (string),
"initiator": {
"node-id": (Ripple ID),
"key": (public key data structure)
},
"partner": {
"node-id": (Ripple ID),
"key": (public key data structure)
},
}
The roles of The There are two primary account messages: An
{
"account-request": {
"request-id": (integer),
"account": {
"account-id": (string),
(remaining account data structure containing requested field values)
},
"note": (string - optional)
}
}
To avoid overlap, the The An
{
"account-set": {
"request-id": (integer - only present on responses to account-requests),
"timestamp": (date/time string),
"account": {
"account-id": (string),
(remaining account data structure containing requested field values)
},
}
}
The request ID is only necessary when the The timestamp establishes the exact time, measured in connection time, that the changes to the account fields take effect. Account messages, other than at account-creation time, should only alter one account field at a time unless two or more fields must be altered in atomic fashion. Accounts are established by a signed
Example:
{
"account-request": {
"request-id": 1,
"account": {
"account-id": "550e8400-e29b-41d4-a716-446655440000",
"unit": "urn:ripple:units:CAD",
"account-type": (...),
"initiator": {
"node-id": "rfugger@ripplepay.com",
"key": (...),
},
"partner": {
"node-id": "random@example.com",
}
},
"note": "Let's have an account!"
}
}
An affirmative reply means the offer has been understood being held for consideration. If the offer recipient accepts the offer, his node sends back an To indicate that the account has been created, the node receiving the Identification of Account Partner Ripple has no universal mechanism for positively identifying the owner of another node. The owner of a node receiving a new account request should confirm the identity of the owner of the requesting node before assigning it a non-zero credit limit. Even if the node ID in the form node@host.com of the requesting node is familiar to the request recipient, one must ensure that the transport layer has verified positively by some means that the request actually comes from the correct host and that the host is trustworthy before relying solely on that piece of information. The requesting node's owner may put secret, personal, or other information that could help the receiving node's owner identify them, such as a message signed with a personal signing key, into the To declare a change to one or more account data fields, a node sends a signed To request a change to one or more account data fields, a node sends an Once the request is approved, the request recipient sends an The following errors allow nodes to negotiate between them what are permissible unilateral changes and what aren't in case of disagreement:
To add a new data field to an account, use An account message declaring or requesting a key change should be signed by the old key. Subsequent signed messages must be signed by the new key. To request a copy of an account partner's account data for verification, send an Example:
{
"account-verify-request": {
"account-id": "550e8400-e29b-41d4-a716-446655440000"
}
}
The immediate reply must contain the complete account data structure of the node receiving the Example:
{
"account-verify": {
"timestamp": "2006-11-07 02:11:28.401000",
"account": {
(...)
}
}
}
Neither message nor reply must be signed. To request from an account partner a list of every signed message that has changed the value of an account field over a certain period, send an Example:
{
"account-history-request": {
"starting": "2006-01-01 00:00:00.000000",
"ending": "2006-11-07 02:11:28.401000"
}
}
If the "starting" field is omitted, messages from beginning of the account should be included in the reply. If the "ending" field is omitted, messages up to the present should be included. The reply is as follows:
{
"account-history": [
(a chronological order of signed messages sent and received over
this account during the requested period that have changed a piece
of shared account data, in the format they were originally sent or
received, including signatures)
]
}
This account history may be used as an audit to find the source of any data discrepancies between partners. This same output may also be taken for each account by a node owner from her own node in order to backup account data or move a node to a different host. To close an account, either party may send an Example:
{
"account-close": {
"request-id": 14590,
"account-id": "550e8400-e29b-41d4-a716-446655440000"
}
}
An affirmative reply indicates assent to close the account. An error indicates refusal. PaymentsTo allow payments between two nodes that aren't neighbours, Ripple propagates value account-by-account along one or more paths of accounts in the network connecting payer and recipient. The basic payment process consists of:
A node wishing to receive a payment from another node may initiate contact with the potential payer node by sending a
{
"payment-request": {
"payment-id": (string),
"amount": (decimal),
"unit": (URI),
"recipient-node-id": (Ripple ID),
"note": (string)
}
}
The The The payer node contacts recipient node and communicates the following in a
{
"payment-init": {
"payment-id": (string),
"amount": (decimal),
"units": (URI),
"note": (string)
}
}
When generating The recipient may accept the
{
"payment-accept": {
"payment-id": (string),
"amount": (decimal),
"units": (URI),
"note": (string),
"recipient-receipt-key": (public key data structure),
"recipient-certificate": (certificate data structure)
}
}
This must be signed by the recipient's identifying certificate key, whose certificate identifies the recipient in a way acceptable to the payer, such as being issued (i.e., signed) by an authority recognized by the payer. This message serves as evidence that the recipient participated in the transaction. Thus the signature of the recipient's receipt key on the payment receipts can be irrevocably connected the recipient, proving that the payment was indeed received. The explanatory text can contain text linking the payment to a real-world exchange of goods or services, such as "Payment for auction item #12345". The recipient may reject the Making Promises (Commit-Request) To prepare the payment paths, the payer sends a
{
"promise": {
"payment-id": (string),
"path-id": [(ordered list of strings)],
"path-amount": (decimal),
"account-id": (string),
"amount": (decimal),
"onion": (routing onion data structure),
"ttl": (date/time string),
"penalty-deadline": (date/time string),
"penalty-rate": (decimal),
"deadline": (date/time string),
"payer-receipt-key": (public key data structure),
"recipient-receipt-key": (public key data structure),
"timestamp": (date/time string)
}
Since a promise must be fulfilled if a valid Each node that receives a promise message updates its fields and passes it on to the next node in the path, as determined by data gleaned from the routing onion and/or by extension fields that inform a routing system defined in a protocol extension. At each step, the promise message is signed to the next node by the passing node's authentication key. This serves to establish the integrity and non-repudiability of the promise. The The The The As the recipient receives each
{
"promise-received": {
"payment-id": (string),
"path-id": [(ordered list of strings)],
"deadline": (date/time string),
"amount": (decimal)
}
}
The recipient's receipt deadline to the payer should be well before the penalty deadline on the The recipient can cancel the transaction at any time by sending the payer a When the payer receives a satisfactory set of
{
"receipt": {
"payment-id": (string),
"path-id": [(ordered list of strings)],
"path-amount": (decimal)
}
The collection of receipts signed by the payer represents the value of the payment, and once they are given to the recipient, the recipient is considered to have been paid. If any of the receipts is invalid (to be rigorously defined), the amount of that receipt is not considered to have been paid until a valid receipt is issued. The recipient must reply with an error code when receiving an invalid receipt. The recipient redeems receipts with its neighbours that have issued promises to do so. Each receipt may only partially redeem the value of a single promise, and multiple receipts may be redeemed for a single promise. The unredeemed portion of the promise must be released before the penalty deadline or the penalty must be paid. |