Skip to content

If the ARF is lost or corrupted, you need to rebuild the file in a secure manner.

For more information about the ARF, see Anti-rewind file.

Prerequisites

In a disaster scenario, the private key associated with the public key of the state review authority operator is used to sign a manifest. As this recovery operation is security sensitive, the operator in charge of recovery, along with their associated public key, must exist in Ripple Custody.

For more information, see Register the state review authority public key.

You also need access to Docker on a machine that can access the Ripple Custody database.

Restore your ARF

This procedure is for operators acting as state review authority.

To obtain the state-review-tool CLI tool to help with data export and review, contact Ripple support.

To restore your ARF, perform the following steps:

  1. On a local, disconnected, machine restore a dump of the latest secure copy of the Ripple Custody database.

  2. Extract the list of collections from the node table in the database copy:

    docker run --rm -it --network host -v $PWD/state:/state -v $PWD/state/log:/opt/state-review-tool/log state-review-tool \
    export --db "jdbc:postgresql://localhost:5432/database_name" --dbuser postgres --dbpassword m3t4c0

    Parameters:

    ParameterDefaultRequiredDescription
    --dbN/AYesJDBC connection string including database name
    --dbuserN/AYesDatabase user
    --dbpasswordN/AYesDatabase password
    --working-dirstateNoNon existing directory, which will be used as target for all data files.

    The generated files are not used during the validation phase; they are only to assist you with data review.

  3. Verify the integrity and versioning of the collections.

  4. To retrieve the public key for governance engine collection signature that was generated by Ripple Custody during system setup, call the List system properties operation.

    This returns, among other things, the following data:

     {
       "data": {
         "id": "<GOVERNANCE_ENGINE_COLLECTION_KEY>",
         "value": {
           "publicKey": {
             "value": "MFkwEwYHKoZIzj0CAQYIKoZIzj0DAQcDQgAERDEHR1wxs2VhnMIHkwi/aVOqIW8PVYndk1V/ZmpRzF+mbc7cjERavruubpRp8uUM77lk9FCwECDgXatwyQgmXw==",
             "type": "PublicKey"
           }
         },
         "metadata": {
           "description": null,
           "revision": 1,
           "createdAt": "2023-07-13T12:58:54.630Z",
           "createdBy": null,
           "lastModifiedAt": "2023-07-13T12:58:54.630Z",
           "lastModifiedBy": null,
           "customProperties": {}
         },
         "type": "NotaryCollectionsKeySystemProperty",
         "access": "ReadOnly"
       },
       "signature": "<SIGNATURE>"
     }
  5. Validate the data and then generate and sign a manifest for all the existing collections:

    docker run --rm -it --network host -v $PWD/state-review-tool-log:/opt/state-review-tool/log state-review-tool \
    validate --db "jdbc:postgresql://localhost:5432/database_name" --dbuser postgres --dbpassword m3t4c0 \
    --public-key [governance_engine_collection_key]

    Parameters:

    ParameterDefaultRequiredDescription
    --dbN/AYesJDBC connection string including database name
    --dbuserN/AYesDatabase user
    --dbpasswordN/AYesDatabase password
    --public-keyN/AYesBase64-encoded public key from key pair used for signing Merkle tree. The required notary_collection_key is a public key belonging to the governance engine, that is generated by Ripple Custody autonomously at genesis time (NOTARY_COLLECTION_KEY from the previous step).

    This takes the root hash of the collections, verifies each node against the root hash, and calculates the cryptographic proof of correctness for these nodes. After validation, you can either generate a manifest or generate and sign it.

    If this returns a failure, it means that the database has been tampered with and cannot be used as a source for regenerating the ARF. In this case, you need to try again with an earlier copy of the database.

  6. If you did not generate the manifest in the previous step, generate and sign the manifest:

    docker run --rm -it --network host -v $PWD/manifest:/manifest -v "$PWD/../pk/Ed25519:/home/root/key" -v $PWD/state-review-tool-log:/opt/state-review-tool/log state-review-tool \
    generate-signed-manifest \
    --db "jdbc:postgresql://localhost:5432/database_name" \
    --dbuser postgres \
    --dbpassword m3t4c0 \
    --signing-key-path /home/root/key \
    --signing-key-type Ed25519 \
    --working-dir /manifest

    Or generate the manifest with no signature, for example, if the private key is stored somewhere else and the manifest cannot be signed directly:

    docker run --rm -it --network host -v $PWD/manifest:/manifest -v $PWD/state-review-tool-log:/opt/state-review-tool/log  state-review-tool \
    generate-manifest --db "jdbc:postgresql://localhost:5432/database_name" --dbuser postgres --dbpassword m3t4c0

    If you do not sign the manifest at this point, you need to use a dedicated signing tool to sign it later.

    Parameters:

    ParameterDefaultRequiredDescription
    --dbN/AYesJDBC connection string including database name
    --dbuserN/AYesDatabase user
    --dbpasswordN/AYesDatabase password
    --specific-collections-to-recoverN/ANoSpecifies comma separated collections keys to recover. If not specified, a manifest for recovering all collection keys will be generated.
    --valid-until30 days from nowNoValidity period of the manifest. Accepts ISO 8601 timestamp format.
    --working-dir/manifestNoDirectory for generated files: manifest and its signature.
    --manifest-file-namemanifest.jsonNoName for the manifest file (including json file extension)
    --output-sigmanifest-signatureNoName for the file with manifest signature.
    --signing-key-pathN/AYesPath to base64-encoded private key used for manifest signature.
    --signing-key-typeN/AYesType of the private key, available values: secp256r1, secp256k1, Ed25519

    The generated manifest, presented as a string in JSON format, is the single source of truth regarding the integrity and versioning of the database (Ripple Custody state) and will be used by the governance engine to regenerate the anti-rewind file.

    This file is very important and must be signed by the state review authority using their private key. The signature must be stored as a base64 value.

  7. Pass the manifest and the signature to the governance engine using the following environment variables:

    • ANTI_REWIND_RECOVERY_STATE_MANIFEST: contains the manifest in a serialized JSON string format
    • ANTI_REWIND_RECOVERY_STATE_MANIFEST_SIGNATURE: contains the signature corresponding to the manifest, encoded in base64 format.
  8. Restart the governance engine to rebuild the ARF.
    The governance engine starts in recovery mode, processes the manifest, rebuilds the corresponding ARF, and contacts Ripple Custody’s bridge to obtain the collections. It then computes the root hash and verifies that the new ARF corresponds to the database state based on the received manifest.
    While in recovery mode, the governance engine does not serve any requests, so no intents can be executed.
    When the governance engine finishes building the ARF, the logs show the following:

    
    Recovery completed, remember to unset ANTI_REWIND_RECOVERY\_\* env variables before running it again
    
  9. Remove the environment variables and restart the governance engine again.

The governance engine is now out of recovery mode and back into regular operation mode. Recovery is complete and operations resume as usual.