Skip to content

Commit

Permalink
Version cut v1.2.0
Browse files Browse the repository at this point in the history
  • Loading branch information
KaloyanTanev committed Dec 9, 2024
1 parent 948323b commit 546c011
Show file tree
Hide file tree
Showing 100 changed files with 9,204 additions and 0 deletions.
7 changes: 7 additions & 0 deletions versioned_docs/version-v1.2.0/adv/_category_.json
Original file line number Diff line number Diff line change
@@ -0,0 +1,7 @@
{
"label": "ADVANCED & TROUBLESHOOTING",
"position": 3,
"collapsed": false,
"collapsible": false,
"className": "menuSection"
}
5 changes: 5 additions & 0 deletions versioned_docs/version-v1.2.0/adv/advanced/_category_.json
Original file line number Diff line number Diff line change
@@ -0,0 +1,5 @@
{
"label": "Advanced Guides",
"position": 1,
"collapsed": true
}
38 changes: 38 additions & 0 deletions versioned_docs/version-v1.2.0/adv/advanced/adv-docker-configs.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,38 @@
---
sidebar_position: 6
description: Use advanced docker-compose features to have more flexibility and power to change the default configuration.
---

# Advanced Docker Configs

:::info
This section is intended for *docker power users*, i.e.: for those who are familiar with working with `docker compose` and want to have more flexibility and power to change the default configuration.
:::

We use the "Multiple Compose File" feature which provides a very powerful way to override any configuration in `docker-compose.yml` without needing to modify git-checked-in files since that results in conflicts when upgrading this repo.
See [this](https://docs.docker.com/compose/extends/#multiple-compose-files) for more details.

There are some additional compose files in [this repository](https://github.com/ObolNetwork/charon-distributed-validator-node/), `compose-debug.yml` and `docker-compose.override.yml.sample`, along-with the default `docker-compose.yml` file that you can use for this purpose.

- `compose-debug.yml` contains some additional containers that developers can use for debugging, like `jaeger`. To achieve this, you can run:

```shell
docker compose -f docker-compose.yml -f compose-debug.yml up
```

- `docker-compose.override.yml.sample` is intended to override the default configuration provided in `docker-compose.yml`. This is useful when, for example, you wish to add port mappings or want to disable a container.

- To use it, just copy the sample file to `docker-compose.override.yml` and customise it to your liking. Please create this file ONLY when you want to tweak something. This is because the default override file is empty and docker errors if you provide an empty compose file.

```shell
cp docker-compose.override.yml.sample docker-compose.override.yml

# Tweak docker-compose.override.yml and then run docker compose up
docker compose up
```

- You can also run all these compose files together. This is desirable when you want to use both the features. For example, you may want to have some debugging containers AND also want to override some defaults. To achieve this, you can run:

```shell
docker compose -f docker-compose.yml -f docker-compose.override.yml -f compose-debug.yml up
```
112 changes: 112 additions & 0 deletions versioned_docs/version-v1.2.0/adv/advanced/quickstart-combine.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,112 @@
---
sidebar_position: 4
description: Combine distributed validator private key shares to recover the validator private key.
---

# Combine DV Private Key Shares

:::danger
Reconstituting Distributed Validator private key shares into a standard validator private key is a security risk, and can potentially cause your validator to be slashed.

Only combine private keys as a last resort and do so with extreme caution.
:::

Combine distributed validator private key shares into an Ethereum validator private key.

## Pre-requisites

- Ensure you have the `.charon` directories of at least a threshold of the cluster's node operators.
- Ensure you have [docker](https://docs.docker.com/engine/install/) installed.
- Make sure `docker` is running before executing the commands below.

## Step 1. Set up the key combination directory tree

Rename each cluster node operator `.charon` directory in a different way to avoid folder name conflicts.

We suggest naming them clearly and distinctly, to avoid confusion.

At the end of this process, you should have a tree like this:

```shell
$ tree ./cluster

cluster/
├── node0
│   ├── charon-enr-private-key
│   ├── cluster-lock.json
│   ├── deposit-data.json
│   └── validator_keys
│   ├── keystore-0.json
│   ├── keystore-0.txt
│   ├── keystore-1.json
│   └── keystore-1.txt
├── node1
│   ├── charon-enr-private-key
│   ├── cluster-lock.json
│   ├── deposit-data.json
│   └── validator_keys
│   ├── keystore-0.json
│   ├── keystore-0.txt
│   ├── keystore-1.json
│   └── keystore-1.txt
├── node2
│   ├── charon-enr-private-key
│   ├── cluster-lock.json
│   ├── deposit-data.json
│   └── validator_keys
│   ├── keystore-0.json
│   ├── keystore-0.txt
│   ├── keystore-1.json
│   └── keystore-1.txt
...
└── nodeN
├── charon-enr-private-key
├── cluster-lock.json
├── deposit-data.json
└── validator_keys
├── keystore-0.json
├── keystore-0.txt
├── keystore-1.json
└── keystore-1.txt
```

:::warning
Make sure to never mix the various `.charon` directories with one another.

Doing so can potentially cause the combination process to fail.
:::

## Step 2. Combine the key shares

Run the following command:

```shell
# Combine a clusters private keys
docker run --rm -v "$(pwd):/opt/charon" obolnetwork/charon:v1.2.0 combine --cluster-dir /opt/charon/cluster --output-dir /opt/charon/combined
```

This command will store the combined keys in the `output-dir`, in this case a folder named `combined`.

```shell
$ tree combined
combined
├── keystore-0.json
├── keystore-0.txt
├── keystore-1.json
└── keystore-1.txt
```

We can verify that the directory names are correct by looking at the lock file:

```shell
$ jq .distributed_validators[].distributed_public_key cluster/node0/cluster-lock.json
"0x822c5310674f4fc4ec595642d0eab73d01c62b588f467da6f98564f292a975a0ac4c3a10f1b3a00ccc166a28093c2dcd"
"0x8929b4c8af2d2eb222d377cac2aa7be950e71d2b247507d19b5fdec838f0fb045ea8910075f191fd468da4be29690106"
```

:::info

The generated private keys are in the standard [EIP-2335](https://github.com/ethereum/ercs/blob/master/ERCS/erc-2335.md) format, and can be imported in any Ethereum validator client that supports it.

Ensure your distributed validator cluster is completely shut down before starting a replacement validator or you are likely to be slashed.
:::
129 changes: 129 additions & 0 deletions versioned_docs/version-v1.2.0/adv/advanced/quickstart-sdk.mdx
Original file line number Diff line number Diff line change
@@ -0,0 +1,129 @@
---
sidebar_position: 2
description: Create a DV cluster using the Obol Typescript SDK
---

import Tabs from '@theme/Tabs';
import TabItem from '@theme/TabItem';

# Create a DV Using the SDK

This is a walkthrough of using the [Obol-SDK](https://www.npmjs.com/package/@obolnetwork/obol-sdk) to propose a four-node distributed validator cluster for creation using the [DV Launchpad](../../learn/intro/launchpad.md).

## Pre-requisites

- You have [node.js](https://nodejs.org/en) installed.

## Install the package

Install the Obol-SDK package into your development environment

<Tabs groupId="install-sdk">
<TabItem value="npm" label="NPM" default>
<pre>
<code>npm install --save @obolnetwork/obol-sdk</code>
</pre>
</TabItem>
<TabItem value="yarn" label="Yarn">
<pre>
<code>yarn add @obolnetwork/obol-sdk</code>
</pre>
</TabItem>
</Tabs>

## Instantiate the client

The first thing you need to do is create an instance of the Obol SDK client. The client takes two constructor parameters:

- The `chainID` for the chain you intend to use.
- An ethers.js [signer](https://docs.ethers.org/v6/api/providers/#Signer-signTypedData) object.

```ts
import { Client } from "@obolnetwork/obol-sdk";
import { ethers } from "ethers";

// Create a dummy ethers signer object with a throwaway private key
const mnemonic = ethers.Wallet.createRandom().mnemonic?.phrase || "";
const privateKey = ethers.Wallet.fromPhrase(mnemonic).privateKey;
const wallet = new ethers.Wallet(privateKey);
const signer = wallet.connect(null);

// Instantiate the Obol Client for holesky
const obol = new Client({ chainId: 17000 }, signer);
```

## Propose the cluster

List the Ethereum addresses of participating operators, along with withdrawal and fee recipient address data for each validator you intend for the operators to create.

```ts
// A config hash is a deterministic hash of the proposed DV cluster configuration
const configHash = await obol.createClusterDefinition({
name: "SDK Demo Cluster",
operators: [
{ address: "0xC35CfCd67b9C27345a54EDEcC1033F2284148c81" },
{ address: "0x33807D6F1DCe44b9C599fFE03640762A6F08C496" },
{ address: "0xc6e76F72Ea672FAe05C357157CfC37720F0aF26f" },
{ address: "0x86B8145c98e5BD25BA722645b15eD65f024a87EC" },
],
validators: [
{
fee_recipient_address: "0x3CD4958e76C317abcEA19faDd076348808424F99",
withdrawal_address: "0xE0C5ceA4D3869F156717C66E188Ae81C80914a6e",
},
],
});

console.log(
`Direct the operators to https://holesky.launchpad.obol.org/dv?configHash=${configHash} to complete the key generation process`
);
```

## Invite the Operators to complete the DKG

Once the Obol-API returns a `configHash` string from the `createClusterDefinition` method, you can use this identifier to invite the operators to the [Launchpad](../../learn/intro/launchpad.md) to complete the process

1. Operators navigate to `https://<NETWORK_NAME_HERE>.launchpad.obol.org/dv?configHash=<CONFIG_HASH_HERE>` and complete the [run a DV with others](../../run/start/quickstart_group.mdx) flow.
1. Once the DKG is complete, and operators are using the `--publish` flag, the created cluster details will be posted to the Obol API.
1. The creator will be able to retrieve this data with `obol.getClusterLock(configHash)`, to use for activating the newly created validator.

## Retrieve the created Distributed Validators using the SDK

Once the DKG is complete, the proposer of the cluster can retrieve key data such as the validator public keys and their associated deposit data messages.

```js
const clusterLock = await obol.getClusterLock(configHash);
```

Reference lock files can be found [here](https://github.com/ObolNetwork/charon/tree/main/cluster/testdata).

## Activate the DVs using the deposit contract

In order to activate the distributed validators, the cluster operator can retrieve the validators' associated deposit data from the lock file and use it to craft transactions to the `deposit()` method on the deposit contract.

```js
const validatorDepositData =
clusterLock.distributed_validators[validatorIndex].deposit_data;

const depositContract = new ethers.Contract(
DEPOSIT_CONTRACT_ADDRESS, // 0x00000000219ab540356cBB839Cbe05303d7705Fa for Mainnet, 0xff50ed3d0ec03aC01D4C79aAd74928BFF48a7b2b for Goerli
depositContractABI, // https://etherscan.io/address/0x00000000219ab540356cBB839Cbe05303d7705Fa#code for Mainnet, and replace the address for Goerli
signer
);

const TX_VALUE = ethers.parseEther("32");

const tx = await depositContract.deposit(
validatorDepositData.pubkey,
validatorDepositData.withdrawal_credentials,
validatorDepositData.signature,
validatorDepositData.deposit_data_root,
{ value: TX_VALUE }
);

const txResult = await tx.wait();
```

## Usage Examples

Examples of how our SDK can be used are found [here](https://github.com/ObolNetwork/obol-sdk-examples).
Loading

0 comments on commit 546c011

Please sign in to comment.