-
Notifications
You must be signed in to change notification settings - Fork 47
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
- Loading branch information
1 parent
948323b
commit 546c011
Showing
100 changed files
with
9,204 additions
and
0 deletions.
There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
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" | ||
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
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
38
versioned_docs/version-v1.2.0/adv/advanced/adv-docker-configs.md
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
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
112
versioned_docs/version-v1.2.0/adv/advanced/quickstart-combine.md
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
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
129
versioned_docs/version-v1.2.0/adv/advanced/quickstart-sdk.mdx
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
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). |
Oops, something went wrong.