# Key Generation in Cluster Mode

When running `keygen` many times between the same group of Vertex instances (i.e. a Cluster), exchanging the `keygen_id` parameter between them for every keygen event is both cumbersome and can potentially decrease security.\
Therefore, in those cases, a Cluster can be set up.\
A Cluster is simply a defined group of Vertex servers that mutually know the domains and `keygen_id`s of each other.\
This makes the `keygen` process much smoother, as well as increases security by only requiring that `keygen_id`s be exchanged securely one time during the Cluster setup.\
Below, the flow of setting up and using a Cluster for key generation is shown.

## Setting Up a Cluster

### Step 1: Gather Persistent Keygen IDs

First, gather the persistent keygen IDs of all parties involved. This can be done using the [`persistent-keygen-id`](https://docs.sodot.dev/vertex-api-reference/#tag/keygenid/GET/cluster/persistent-keygen-id) endpoint:

```bash
curl -L -X GET "https://<YOUR_VERTEX>/cluster/persistent-keygen-id" \
-H "Content-Type: application/json" \
-H "Authorization: <USER_API_KEY>"
```

### Step 2: Register the Other Vertex Servers on the Vertex

For each Vertex in the cluster, register the domain and `persistent_keygen_id` of all other Vertices.\
This can be done using the [`insert-vertex`](https://docs.sodot.dev/vertex-api-reference/#tag/admin/POST/admin/cluster/insert-vertex) endpoint:

```bash
curl -L -X POST "https://<YOUR_VERTEX_1>/admin/cluster/insert-vertex" \
-H 'Content-Type: application/json' \
-H "Authorization: <ADMIN_API_KEY>" \
--data-raw '{
  "domain": "https://vertex2.domain",
  "persistent_keygen_id": "<PERSISTENT_KEYGEN_ID_OF_VERTEX_2>"
}'

curl -L -X POST "https://<YOUR_VERTEX_1>/admin/cluster/insert-vertex" \
-H 'Content-Type: application/json' \
-H "Authorization: <ADMIN_API_KEY>" \
--data-raw '{
  "domain": "https://vertex3.domain",
  "persistent_keygen_id": "<PERSISTENT_KEYGEN_ID_OF_VERTEX_3>"
}'
```

### Step 3: Create a Cluster

Next, a `SystemAdmin` needs to create a cluster using the gathered `persistent_keygen_id`s. This can be done using the [`create-cluster`](https://docs.sodot.dev/vertex-api-reference/#tag/admin/POST/admin/cluster/create-cluster) endpoint:

```bash
curl -L -X POST "https://<YOUR_VERTEX_1>/admin/cluster/create-cluster" \
-H "Content-Type: application/json" \
-H "Authorization: <ADMIN_API_KEY>" \
--data-raw '{
    "name": "my_cluster",
    "vertices_domains": [
        "https://vertex2.domain",
        "https://vertex3.domain"
    ]
}'
```

## Perform Key Generation Using the Cluster

Once the cluster is created, each Vertex instance that is part of the cluster can perform an MPC key generation using the cluster name.\
Users can simply reference the Cluster in their operations.

Use the relevant keygen endpoints for your chosen algorithm:

* [Ed25519 Keygen](https://docs.sodot.dev/vertex-api-reference/#tag/ed25519/POST/cluster/ed25519/keygen)
* [BIP340 Keygen](https://docs.sodot.dev/vertex-api-reference/#tag/bip340/POST/cluster/bip340/keygen)
* [ECDSA Keygen](https://docs.sodot.dev/vertex-api-reference/#tag/ecdsa/POST/cluster/ecdsa/keygen)
* [Sr25519 Keygen](https://docs.sodot.dev/vertex-api-reference/#tag/sr25519/POST/cluster/sr25519/keygen)

Each MPC key generation still requires a Relay Room, which can be created using the [`create-room`](https://docs.sodot.dev/vertex-api-reference/#tag/common/POST/create-room) endpoint.

Example request for Ed25519:

```bash
curl -L -X POST "https://<YOUR_VERTEX>/cluster/ed25519/keygen" \
-H "Content-Type: application/json" \
-H "Authorization: <USER_API_KEY>" \
--data-raw '{
  "cluster_name": "my_cluster",
  "room_uuid": "<ROOM_UUID>",
  "num_parties": 3,
  "threshold": 2
}'
```
