Skip to content

You create your initial Ripple Custody environment setup with the genesis API operation.

The input request body contains two sections:

  • rootDomainSetup: A standard new domain creation payload.
  • cryptoSetup: The cryptographic algorithms Ripple Custody will use.

For an example request body and detailed descriptions of each section, see Run the setup operation on this page.

You can only run this process once. The system is equipped with an anti-rewind mechanism that blocks any attempt to rerun the genesis operation.

After system setup, any further updates fall under the normal system update process of intents and the governance workflow. Therefore, it is important to consider what you want to include in your initial system setup.

For more information on how to design a Ripple Custody environment that meets your governance needs, see Design your governance model.

Prerequisites

Before you run system setup, you need:

  • The URL of your Ripple Custody API instance, which you can obtain from your Ripple liaison.
  • The public keys of users you want to create.
    For more information on user key generation, see Generate a key pair and share the public key.

Run the setup operation

It is mandatory to define at least a primary (or root) domain, one user, and one policy during system setup, but you can also set up more.

To set up your system, call the Genesis API operation with a request body similar to the example below. You do not any authentication information, since the system has no active users at this stage.

Request body example

Example genesis request body
{
    "rootDomainSetup": {
        "id": "e7eb7b63-d63b-4c30-9cca-d3b1ea7e46ad",
        "alias": "Root domain",
        "lock": "Unlocked",
        "governingStrategy": "CoerceDescendants",
        "permissions": {
            "readAccess": {
                "domains": [
                    "operator"
                ],
                "users": [
                    "operator"
                ],
                "endpoints": [
                    "operator"
                ],
                "policies": [
                    "operator"
                ],
                "accounts": [
                    "operator"
                ],
                "transactions": [
                    "operator"
                ],
                "requests": [
                    "operator"
                ],
                "events": [
                    "operator"
                ]
            }
        },
        "description": "A genesis payload for the creation of the root domain",
        "customProperties": {},
        "users": [
            {
                "id": "e1fe3431-f899-427b-9e67-a75fb9fe5e57",
                "alias": "operator@company.com",
                "publicKey": "MFkw...NfPfw/q9YW74Q==",
                "roles": [
                    "manager"
                ],
                "loginIds": [
                    {
                        "id": "op1@company.com",
                        "providerId": "harmonize"
                    },
                    {
                        "id": "op1@company.com",
                        "providerId": "azure-ad"
                    }
                ],
                "lock": "Unlocked",
                "description": "A manager user",
                "customProperties": {}
            }
        ],
        "policies": [
            {
                "id": "00000000-0000-0000-0000-000000000000",
                "alias": "Catch-All Policy",
                "rank": 20,
                "intentTypes": null,
                "scope": "Self",
                "scriptingEngine": "Javascript_v0",
                "condition": {
                    "expression": "context.request.author.id == 'e1fe3431-f899-427b-9e67-a75fb9fe5e57'",
                    "type": "Expression"
                },
                "workflow": [
                    {
                        "role": "manager",
                        "quorum": 1,
                        "type": "RoleQuorum"
                    }
                ],
                "lock": "Unlocked",
                "description": "Policy for exception handling",
                "customProperties": {}
            }
        ],
        "descendants": [{. . .}]]
    },
    "cryptoSetup": {
        "apiSigning": "Secp256r1",
        "collectionSigning": "Secp256r1",
        "messageSigning": "Ed25519"
    },
    "tickers": [
        {
            "id": "688b48e3-8ce1-4e01-b242-96f03ecb554a",
            "ledgerId": "bitcoin-testnet",
            "kind": "Native",
            "name": "Bitcoin testnet",
            "decimals": 8,
            "symbol": "tBTC",
            "ledgerDetails": {
                "properties": {
                    "type": "Native"
                },
                "type": "Bitcoin"
            },
            "lock": "Unlocked",
            "description": null,
            "customProperties": {}
        },
        {
            "id": "1e94173d-fafb-4e76-ae01-dbc11e4eaa17",
            "ledgerId": "ethereum-testnet",
            "kind": "Native",
            "name": "Ethereum testnet",
            "decimals": 18,
            "symbol": "tETH",
            "ledgerDetails": {
                "properties": {
                    "type": "Native"
                },
                "type": "Ethereum"
            },
            "lock": "Unlocked",
            "description": null,
            "customProperties": {}
        }
    ],
    "systemProperties": [
        {
            "value": {
                "publicKey": {
                    "value": "MFkw...HdVNyxTyl1plgAfh/Yg=="
                }
            },
            "type": "StateReviewAuthorityProperty"
        }
    ]
}

The main sections are described below.

Root domain setup

This is the only mandatory section.

The rootDomainSetup section is similar to a standard new domain creation payload, where you specify the read permissions, users, and policies to be created in the newly created Ripple Custody instance. You can change the rootDomainSetup section to deploy new policies and users, together with their properties.

For more information, see Ripple Custody API > Create domains.

Governing strategy

During domain creation, you need to decide between the following governing strategies:

  • CoerceDescendants: The domain ignores the policies of its subdomains.
  • ConsiderDescendants: The domain considers the policies of its subdomains.

This field is optional. If you do not specify a governing strategy during domain creation, the domain defaults to a ConsiderDescendants strategy. Once a domain is created, the governing strategy cannot be changed.

The governing strategy and the presence of a matching policy for subdomains are evaluated using the domainId of the user submitting the intent. The targetDomainId must be a subdomain of the domain of intent origin. For a coercive intent, the policies of the targetDomainId are entirely ignored.

If the coercive domain doesn't have a policy that is applicable to subdomains matching the intent, the intent is created in the subdomain with status Failed and a NoApplicablePoliciesForDomain error code.

To execute a coercive intent within a locked domain, the domain must be unlocked first.

Permissions

This access management section specifies the user roles that can view different entity types in the domain.

Users

This section is similar to a standard new user creation payload.

You need to create enough users, with appropriate roles, to fulfill the defined policies.

Users are identified by a unique alias and public key combination. These identifiers must respect the following guidelines:

  • Users within the same domain cannot have the same alias.
  • Users that have the same public key in different domains must have the same alias.
Example user with four roles and Azure AD SSO
    "users": [
        {
            "id": "e1fe3431-f899-427b-9e67-a75fb9fe5e57",
            "alias": "operator@ripple.com",
            "publicKey": "MFkw...NfPfw/q9YW74Q==",
            "roles": [
                "manager","compliance","director","operator"
            ],
            "loginIds": [
                {
                    "id": "op1@company.com",
                    "providerId": "harmonize"
                },
                {
                    "id": "op1@company.com",
                    "providerId": "azure-ad"
                }
            ],
            "lock": "Unlocked",
            "description": "A user",
            "customProperties": {}
        }
    ],

Once setup is complete, the initial set of users can log in to and use Ripple Custody.

For a detailed description of the user creation payload, see Ripple Custody API > Create a user.

Policies

This section is similar to a standard new policy creation payload. It is important to include a breakglass policy. For more information, see Breakglass policy.

Example catch-all policy
    "policies": [
        {
            "id": "00000000-0000-0000-0000-000000000000",
            "alias": "Catch-All Policy",
            "rank": 20,
            "intentTypes": null,
            "scope": "Self",
            "scriptingEngine": "Javascript_v0",
            "condition": {
                "expression": "context.request.author.id == 'e1fe3431-f899-427b-9e67-a75fb9fe5e57'",
                "type": "Expression"
            },
            "workflow": [
                {
                    "role": "manager",
                    "quorum": 1,
                    "type": "RoleQuorum"
                }
            ],
            "lock": "Unlocked",
            "description": "Policy for exception handling",
            "customProperties": {}
        }
    ],

For a detailed description of the policy creation payload, see Ripple Custody API > Create policies.

Descendants

This section is optional. You can specify subdomains as an array of domain objects inside the descendants property. For each subdomain, you specify the same information as for the root domain.

Crypto setup

This section is optional.

The cryptoSetup section is used to specify the cryptographic methods (elliptic curves) that the governance engine uses to create and verify signatures, in order to securely exchange information with other parties.

You can specify different elliptic curves for different operations:

  • apiSigning: The curve used to sign payloads returned to users following a GET request.
  • collectionSigning: The curve used for signing the roots of all collections’ Merkle trees, which guarantees tamper-proof storage of the information. For more information about the Merkle tree, see Merkle tree.
  • messageSigning: The curve used to sign internal messages from the governance engine to the vault.

For all types of operations the user can choose between Secp256r1, Secp256k1 and Ed25519 elliptic curves. Recommended values are shown in the example payload above.

For more information, see Digital signature.

Tickers

This section is optional.

The tickers section includes a list of tickers and other assets available for blockchain ledgers. You can use this section to provide a list of pre-validated tickers.

System properties

This section is optional.

In the systemProperties section, you register the public key of the state review authority. This is a public key in a standard Ripple Custody accepted format (secp256k1, secp256r1, or Ed25519) represented as a Base64-encoded string.

The state review authority acts as a trusted party to confirm the authenticity of the system state if the anti-rewind file (ARF) needs to be recovered.

If you do not specify this information during system setup, you need to specify it as soon as possible afterwards, since it allows you to recover your system in a disaster recovery scenario.

For more information, see Disaster recovery.

Event updates

When you run the genesis operation, Ripple Custody includes two properties in the GenesisSucceeded event:

  • genesis: A data structure holding the notary signed original genesis payload.
  • createdEntitiesReferences: Key information on the data created.

For more information, see Event management > Genesis event.