Accounts

Accounts

Accounts Work Page

An account is a mutual-credit connection between two nodes defined by the following data, a copy of which is kept by the node of each account partner.

Required data:

  • an account ID, which serves as a permanent identifier for the account
  • each node's ID
  • the unit of account (see Units of Account)
  • the number of decimal digits with which to keep this account
  • a credit limit for each node
  • a balance for the account
  • each node's routing information (see Query Routing)
  • an authentication key for each node (see Authentication Keys)

Optional data:

  • interest rate, as a decimal
  • compounding period, in days
  • account agreement, possibly including debt-settlement terms/schedule

Example:

{
  "account": {
    "account_id": "550e8400-e29b-41d4-a716-446655440000",
    "unit": "urn:ripple:units:CAD",
    "precision": 4,
    "initiator": {
      "node_id": "rfugger@ripplepay.com",
      "limit": 100.0000,
      "routing_id": "7136976c-251d-4be4-b6e2-74baf4b4a53c",
      "key": [public key info here],
      "balance": -15.50
    },
    "partner": {
      "node_id": "random@example.com",
      "limit": 200.0000,
      "routing_id": "d699c900-b245-4e3d-a586-eb5743fa24af",
      "key": [public key info here]
    },
    "interest_rate": 0.05,
    "compound_period": 0,
    "agreement": "Both parties agree to pay the outstanding balance in cash on demand.",
}

The JSON structure here is only to show how fields will be addressed in account messages, not to dictate how a node must store its data. The roles of "initiator" node and "partner" node are determined at account creation time, with the node making the initial account offer being deemed the "initiator". These roles stay constant for the life of the account, allowing either node to its node ID.

The balance field may appear in either the "initiator" or "partner" node object, and gives the balance from that node's perspective (negative means owing, positive means owed).

Custom data fields may be added to an account as long as their meaning is understood by both nodes.

Generally a node will want to keep a record of all messages necessary to calculate the current balance on the account, including transaction receipts and changes to the account.

Account Messages

There are two primary account messages: account_request and account_set.

An account_request is to request a new account, or to request a change to one or more account fields that could not be dictated unilaterally by the requesting node. An account_request must be signed unless the request could in other circumstances be imposed unilaterally by the node receiving the request. Otherwise, the requesting node must indicate that it gives permission to make the requested changes by signing the account_request, which allows this permission to be verified at a later date. If a node receives an unsigned message that it feels ought to be signed, it should reply with a Message must be signed error. An implementation may decide to simply sign every account-request.

{
  "account_request": {
    "request_id": (integer),
    "account": {
      "account_id": (string),
      (remaining account data structure containing requested field values)
    },
    "note": (string explaining request)  -- optional
  }
}

To avoid overlap, the "initiator" node uses odd request IDs, and the "partner" node uses even request IDs. Only those account fields that contain new, non-default values, or are to be changed need to be included.

The account_set message is to confirm a new account, accept the changes requested in an account_request, or to unilaterally declare changes to account fields where permitted. While any arrangement may be negotiated between nodes by trial and error, in general, a node may unilaterally dictate values for its own "node_id", "routing_id", and "key", as well as decreases to either node's credit limit. Credit limit increases would generally require an account-request, although when it contains an increase to the other node's limit, the request is better understood as an offer.

An account_set must always be signed.

{
  "account_set": {
    "request_id": (integer),   -- only present on responses to account_requests
    "timestamp": (string with format "2006-11-01 15:02:48.780000"),
    "account": {
      "account_id": (string),
      (remaining account data structure containing requested field values)
    },
  }
}

The request ID is only necessary when the account_set refers to an earlier request. In that case, the account fields must be identical to those in the earlier account-request with the same request ID.

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.

Creating an Account

Accounts are created by one node offering to accept another's IOUs with a signed account_request message containing:

  • a request ID
  • an account ID
  • the offering node's network ID
  • the offering node's routing information
  • the units of account
  • the number of decimal digits with which to keep this account
  • the proposed credit limit for node receiving the offer
  • an initial balance for the new account
  • any other optional data fields desired for this account
{
  "account_request": {
    "request_id": 1,

    "account": {
      "account_id": "550e8400-e29b-41d4-a716-446655440000",
      "unit": "urn:ripple:units:CAD",
      "precision": 4,
      "initiator": {
        "node_id": "rfugger@ripplepay.com",
        "routing_id": "7136976c-251d-4be4-b6e2-74baf4b4a53c",
        "key": [key info here],
        "balance": -15.50
      },
      "partner": {
        "node_id": "random@example.com",
        "limit": 200,
      },
      "interest_rate": 0.05,
      "compound_period": 0,
      "agreement": "Both parties agree to pay any outstanding balance in cash on demand."
    },

    "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 account_set echoing the request ID and the full account data structure in the request, as well as a timestamp which is the official account creation time.

To indicate that the account has been created, the node receiving the account_set responds with an affirmative reply. If the reply is an error, the account is not created.

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 signature with a personal signing key, into the "note" field of the account_request.

Changing Account Data

To declare a change to one or more account data fields, a node sends a signed account_set message to its account partner. An affirmative reply by the other node indicates acceptance of those changes. An error indicates rejection.

To request a change to one or more account data fields, a node sends an account_request message, which need not be signed. An affirmative reply here only indicates that the request has been understood and is being held for approval. The reply need not contain any data nor be signed.

Once the request is approved, the request recipient sends an account-set message echoing back the account fields and values and request ID from the account-request. An affirmative reply to the account_set completes the change.

Account Change Errors

The following errors allow nodes to negotiate between them what are permissible unilateral changes and what aren't in case of disagreement:

Field change by account_request only
Contains path to field that node receiving an account_set deems requires an account_request to change in the manner requested.
Unilateral declaration preferred
Node receiving an account_request deems an account_set preferable for the requested change. (Equally valid is to simply accept the request immediately -- perhaps this error is unnecessary?)

Adding New Fields

To add a new data field to an account, use account_set or account_request as appropriate. If the other node does not understand the field, it will reply with an error, and the field may not be added.

Changing Keys

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.

Verifying Account Data

To request a copy of an account partner's account data for verification, send an account_verify_request message containing the account ID:

{
  "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 account_verify_request as well as a timestamp:

{
  "account_verify": {
    "timestamp": "2006-11-07 02:11:28.401000",
    "account": {
      ...
    }
  }
}

Neither message nor reply must be signed.

Account History

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 account_history_request:

{
  "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.

Closing an Account

To close an account, either party may send an account_close message containing the ID of the account to be closed:

{
  "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. Generally an account may only be closed when the balance is zero. As a precursor to closing an account that is no longer desired, a node would usually set both credit limits to zero, which would only permit transactions that bring the balance closer to zero.

Payment Messages

Several payment messages are also sent over account channels. See the next section for details.

Accounts Work Page