# Recover your anti-rewind file

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](/products/custody/v1.15/overview/architecture/security#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](/products/custody/v1.15/system-management/disaster-recovery/register-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](/products/custody/v1.15/support/get-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:

```sh
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:
| Parameter | Default | Required | Description |
|  --- | --- | --- | --- |
| `--db` | N/A | Yes | JDBC connection string including database name |
| `--dbuser` | N/A | Yes | Database user |
| `--dbpassword` | N/A | Yes | Database password |
| `--working-dir` | `state` | No | Non 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](/products/custody/v1.15/api/reference/openapi/systemproperties/getsystemproperties) operation.
This returns, among other things, the following data:

```json
 {
   "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:

```sh
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:
| Parameter | Default | Required | Description |
|  --- | --- | --- | --- |
| `--db` | N/A | Yes | JDBC connection string including database name |
| `--dbuser` | N/A | Yes | Database user |
| `--dbpassword` | N/A | Yes | Database password |
| `--public-key` | N/A | Yes | Base64-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:

```sh
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:

```sh
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:
| Parameter | Default | Required | Description |
|  --- | --- | --- | --- |
| `--db` | N/A | Yes | JDBC connection string including database name |
| `--dbuser` | N/A | Yes | Database user |
| `--dbpassword` | N/A | Yes | Database password |
| `--specific-collections-to-recover` | N/A | No | Specifies comma separated collections keys to recover. If not specified, a manifest for recovering all collection keys will be generated. |
| `--valid-until` | 30 days from now | No | Validity period of the manifest. Accepts ISO 8601 timestamp format. |
| `--working-dir` | `/manifest` | No | Directory for generated files: manifest and its signature. |
| `--manifest-file-name` | `manifest.json` | No | Name for the manifest file (including json file extension) |
| `--output-sig` | `manifest-signature` | No | Name for the file with manifest signature. |
| `--signing-key-path` | N/A | Yes | Path to base64-encoded private key used for manifest signature. |
| `--signing-key-type` | N/A | Yes | Type 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:

```sh

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.